Merge qt-r1-dev-plus-aosp-without-vendor (5817612) into stage-aosp-master
Bug: 135460123 Change-Id: Ib65b2e0e55cd046797bf3d60ddcc2a7558553e3a Merged-In: I157ff596deb419a57eca32a9b8d954d76294f627
This commit is contained in:
@@ -21,5 +21,5 @@
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="couldnt_launch" msgid="7873588052226763866">"無法啟動活動"</string>
|
||||
<string name="add_app_shortcut" msgid="2756755330707509435">"新增應用程式捷徑"</string>
|
||||
<string name="set_wallpaper" msgid="6475195450505435904">"設定桌布"</string>
|
||||
<string name="set_wallpaper" msgid="6475195450505435904">"套用桌布"</string>
|
||||
</resources>
|
||||
|
||||
@@ -25,6 +25,7 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MOD
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -151,7 +152,7 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions toActivityOptions(Handler handler, long duration) {
|
||||
public ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
|
||||
LauncherAnimationRunner runner = new LauncherAnimationRunner(handler,
|
||||
false /* startAtFrontOfQueue */) {
|
||||
|
||||
@@ -165,7 +166,7 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple
|
||||
);
|
||||
return;
|
||||
}
|
||||
result.setAnimation(createWindowAnimation(targetCompats));
|
||||
result.setAnimation(createWindowAnimation(targetCompats), context);
|
||||
}
|
||||
};
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(
|
||||
|
||||
@@ -34,6 +34,8 @@ import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
import com.android.systemui.shared.recents.IOverviewProxy;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
|
||||
@@ -137,6 +139,9 @@ public class TouchInteractionService extends Service {
|
||||
return sConnected;
|
||||
}
|
||||
|
||||
public static final LooperExecutor BACKGROUND_EXECUTOR =
|
||||
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
|
||||
|
||||
private RecentsModel mRecentsModel;
|
||||
private OverviewComponentObserver mOverviewComponentObserver;
|
||||
private OverviewCommandHelper mOverviewCommandHelper;
|
||||
@@ -180,4 +185,8 @@ public class TouchInteractionService extends Service {
|
||||
}
|
||||
return mMyBinder;
|
||||
}
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* This class will be moved to androidx library. There shouldn't be any dependency outside
|
||||
@@ -154,7 +155,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
* @param scale returns the scale result from normalization
|
||||
* @return a bitmap suitable for disaplaying as an icon at various system UIs.
|
||||
*/
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, UserHandle user,
|
||||
boolean shrinkNonAdaptiveIcons, boolean isInstantApp, float[] scale) {
|
||||
if (scale == null) {
|
||||
scale = new float[1];
|
||||
@@ -204,8 +205,11 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
mDisableColorExtractor = true;
|
||||
}
|
||||
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, boolean shrinkNonAdaptiveIcons,
|
||||
RectF outIconBounds, float[] outScale) {
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(@NonNull Drawable icon,
|
||||
boolean shrinkNonAdaptiveIcons, RectF outIconBounds, float[] outScale) {
|
||||
if (icon == null) {
|
||||
return null;
|
||||
}
|
||||
float scale = 1f;
|
||||
|
||||
if (shrinkNonAdaptiveIcons && ATLEAST_OREO) {
|
||||
@@ -261,7 +265,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
* @param icon drawable that should be flattened to a bitmap
|
||||
* @param scale the scale to apply before drawing {@param icon} on the canvas
|
||||
*/
|
||||
public Bitmap createIconBitmap(Drawable icon, float scale, int size) {
|
||||
public Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
if (icon == null) {
|
||||
return bitmap;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
package="com.android.launcher3" >
|
||||
|
||||
<uses-permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
|
||||
|
||||
+6
-6
@@ -31,6 +31,9 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
@@ -41,9 +44,6 @@ import com.android.launcher3.allapps.FloatingHeaderView;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* A view which shows a horizontal divider
|
||||
*/
|
||||
@@ -288,10 +288,10 @@ public class AppsDividerView extends View implements LauncherStateManager.StateL
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
|
||||
PropertySetter setter, Interpolator fadeInterpolator) {
|
||||
public void setContentVisibility(boolean hasHeaderExtra, boolean hasAllAppsContent,
|
||||
PropertySetter setter, Interpolator headerFade, Interpolator allAppsFade) {
|
||||
// Don't use setViewAlpha as we want to control the visibility ourselves.
|
||||
setter.setFloat(this, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
|
||||
setter.setFloat(this, ALPHA, hasAllAppsContent ? 1 : 0, allAppsFade);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+28
-21
@@ -32,6 +32,9 @@ import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
@@ -62,9 +65,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class PredictionRowView extends LinearLayout implements
|
||||
LogContainerProvider, OnDeviceProfileChangeListener, FloatingHeaderRow {
|
||||
@@ -80,7 +80,7 @@ public class PredictionRowView extends LinearLayout implements
|
||||
|
||||
@Override
|
||||
public Integer get(PredictionRowView view) {
|
||||
return view.mIconCurrentTextAlpha;
|
||||
return view.mIconLastSetTextAlpha;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,6 +103,8 @@ public class PredictionRowView extends LinearLayout implements
|
||||
|
||||
private final int mIconTextColor;
|
||||
private final int mIconFullTextAlpha;
|
||||
private int mIconLastSetTextAlpha;
|
||||
// Might use mIconFullTextAlpha instead of mIconLastSetTextAlpha if we are translucent.
|
||||
private int mIconCurrentTextAlpha;
|
||||
|
||||
private FloatingHeaderView mParent;
|
||||
@@ -315,14 +317,27 @@ public class PredictionRowView extends LinearLayout implements
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextAlpha(int alpha) {
|
||||
mIconCurrentTextAlpha = alpha;
|
||||
public void setTextAlpha(int textAlpha) {
|
||||
mIconLastSetTextAlpha = textAlpha;
|
||||
if (getAlpha() < 1 && textAlpha > 0) {
|
||||
// If the entire header is translucent, make sure the text is at full opacity so it's
|
||||
// not double-translucent. However, we support keeping the text invisible (alpha == 0).
|
||||
textAlpha = mIconFullTextAlpha;
|
||||
}
|
||||
mIconCurrentTextAlpha = textAlpha;
|
||||
int iconColor = setColorAlphaBound(mIconTextColor, mIconCurrentTextAlpha);
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
((BubbleTextView) getChildAt(i)).setTextColor(iconColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(float alpha) {
|
||||
super.setAlpha(alpha);
|
||||
// Reapply text alpha so that we update it to be full alpha if the row is now translucent.
|
||||
setTextAlpha(mIconLastSetTextAlpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlappingRendering() {
|
||||
return false;
|
||||
@@ -351,23 +366,15 @@ public class PredictionRowView extends LinearLayout implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
|
||||
PropertySetter setter, Interpolator fadeInterpolator) {
|
||||
boolean isDrawn = getAlpha() > 0;
|
||||
int textAlpha = hasHeaderExtra
|
||||
? (hasContent ? mIconFullTextAlpha : 0) // Text follows the content visibility
|
||||
: mIconCurrentTextAlpha; // Leave as before
|
||||
if (!isDrawn) {
|
||||
// If the header is not drawn, no need to animate the text alpha
|
||||
setTextAlpha(textAlpha);
|
||||
} else {
|
||||
setter.setInt(this, TEXT_ALPHA, textAlpha, fadeInterpolator);
|
||||
}
|
||||
|
||||
public void setContentVisibility(boolean hasHeaderExtra, boolean hasAllAppsContent,
|
||||
PropertySetter setter, Interpolator headerFade, Interpolator allAppsFade) {
|
||||
// Text follows all apps visibility
|
||||
int textAlpha = hasHeaderExtra && hasAllAppsContent ? mIconFullTextAlpha : 0;
|
||||
setter.setInt(this, TEXT_ALPHA, textAlpha, allAppsFade);
|
||||
setter.setFloat(mOverviewScrollFactor, AnimatedFloat.VALUE,
|
||||
(hasHeaderExtra && !hasContent) ? 1 : 0, LINEAR);
|
||||
(hasHeaderExtra && !hasAllAppsContent) ? 1 : 0, LINEAR);
|
||||
setter.setFloat(mContentAlphaFactor, AnimatedFloat.VALUE, hasHeaderExtra ? 1 : 0,
|
||||
fadeInterpolator);
|
||||
headerFade);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
@@ -164,6 +164,11 @@ public abstract class RecentsUiFactory {
|
||||
}
|
||||
}
|
||||
|
||||
if (FeatureFlags.PULL_DOWN_STATUS_BAR
|
||||
&& !launcher.getDeviceProfile().isMultiWindowMode) {
|
||||
list.add(new StatusBarTouchController(launcher));
|
||||
}
|
||||
|
||||
list.add(new LauncherTaskViewController(launcher));
|
||||
return list.toArray(new TouchController[list.size()]);
|
||||
}
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
@@ -68,8 +69,8 @@ public class BackgroundAppState extends OverviewState {
|
||||
if (taskCount == 0) {
|
||||
return super.getOverviewScaleAndTranslation(launcher);
|
||||
}
|
||||
TaskView dummyTask = recentsView.getTaskViewAt(Math.max(taskCount - 1,
|
||||
recentsView.getCurrentPage()));
|
||||
TaskView dummyTask = recentsView.getTaskViewAt(Utilities.boundToRange(
|
||||
recentsView.getCurrentPage(), 0, taskCount - 1));
|
||||
return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask)
|
||||
.getScaleAndTranslation();
|
||||
}
|
||||
|
||||
+3
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCRIM_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
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;
|
||||
|
||||
@@ -43,6 +45,7 @@ public class OverviewPeekState extends OverviewState {
|
||||
if (this == OVERVIEW_PEEK && fromState == NORMAL) {
|
||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
||||
builder.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -43,7 +43,6 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.uioverrides.UiFactory;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
@@ -128,14 +127,15 @@ public class OverviewState extends LauncherState {
|
||||
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON;
|
||||
} else {
|
||||
boolean hasAllAppsHeaderExtra = launcher.getAppsView() != null
|
||||
&& launcher.getAppsView().getFloatingHeaderView().hasVisibleContent();
|
||||
return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON |
|
||||
(launcher.getAppsView().getFloatingHeaderView().hasVisibleContent()
|
||||
? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
|
||||
(hasAllAppsHeaderExtra ? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWorkspaceScrimAlpha(Launcher launcher) {
|
||||
public float getOverviewScrimAlpha(Launcher launcher) {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
|
||||
+30
@@ -23,13 +23,17 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
|
||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
|
||||
import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
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.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
|
||||
@@ -43,6 +47,7 @@ import android.view.ViewConfiguration;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.quickstep.OverviewInteractionState;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
@@ -102,6 +107,9 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
||||
mPeekAnim.start();
|
||||
recentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
|
||||
mLauncher.getDragLayer().getScrim().animateToSysuiMultiplier(isPaused ? 0 : 1,
|
||||
peekDuration, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -120,6 +128,13 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
||||
LauncherState toState) {
|
||||
if (fromState == NORMAL && toState == ALL_APPS) {
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
|
||||
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
|
||||
- OVERVIEW.getVerticalProgress(mLauncher);
|
||||
builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(ACCEL,
|
||||
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
|
||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(LINEAR,
|
||||
progressToReachOverview, 1));
|
||||
|
||||
// Get workspace out of the way quickly, to prepare for potential pause.
|
||||
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
|
||||
@@ -167,6 +182,21 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
||||
mMotionPauseDetector.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void goToTargetState(LauncherState targetState, int logAction) {
|
||||
if (mPeekAnim != null && mPeekAnim.isStarted()) {
|
||||
// Don't jump to the target state until overview is no longer peeking.
|
||||
mPeekAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
FlingAndHoldTouchController.super.goToTargetState(targetState, logAction);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
super.goToTargetState(targetState, logAction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateAnimatorBuilderOnReinit(AnimatorSetBuilder builder) {
|
||||
if (handlingOverviewAnim()) {
|
||||
|
||||
+3
-3
@@ -16,10 +16,10 @@
|
||||
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
|
||||
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -266,8 +266,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity);
|
||||
}
|
||||
|
||||
float nextFrameProgress = Utilities.boundToRange(
|
||||
progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f);
|
||||
float nextFrameProgress = Utilities.boundToRange(progress
|
||||
+ velocity * getSingleFrameMs(mActivity) / Math.abs(mEndDisplacement), 0f, 1f);
|
||||
|
||||
mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction));
|
||||
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* 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.os.VibrationEffect.EFFECT_CLICK;
|
||||
import static android.os.VibrationEffect.createPredefined;
|
||||
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
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;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
|
||||
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
|
||||
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
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.anim.Interpolators;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.inputconsumers.InputConsumer;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.RemoteAnimationTargetSet;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
/**
|
||||
* Base class for swipe up handler with some utility methods
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q extends RecentsView>
|
||||
implements SwipeAnimationListener {
|
||||
|
||||
private static final String TAG = "BaseSwipeUpHandler";
|
||||
protected static final Rect TEMP_RECT = new Rect();
|
||||
|
||||
// Start resisting when swiping past this factor of mTransitionDragLength.
|
||||
private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
|
||||
// This is how far down we can scale down, where 0f is full screen and 1f is recents.
|
||||
private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = 1.8f;
|
||||
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
|
||||
|
||||
// The distance needed to drag to reach the task size in recents.
|
||||
protected int mTransitionDragLength;
|
||||
// How much further we can drag past recents, as a factor of mTransitionDragLength.
|
||||
protected float mDragLengthFactor = 1;
|
||||
|
||||
protected final Context mContext;
|
||||
protected final OverviewComponentObserver mOverviewComponentObserver;
|
||||
protected final ActivityControlHelper<T> mActivityControlHelper;
|
||||
protected final RecentsModel mRecentsModel;
|
||||
protected final int mRunningTaskId;
|
||||
|
||||
protected final ClipAnimationHelper mClipAnimationHelper;
|
||||
protected final TransformParams mTransformParams = new TransformParams();
|
||||
|
||||
private final Vibrator mVibrator;
|
||||
protected final Mode mMode;
|
||||
|
||||
// Shift in the range of [0, 1].
|
||||
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
|
||||
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
|
||||
// visible.
|
||||
protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
|
||||
|
||||
protected final ActivityInitListener mActivityInitListener;
|
||||
protected final RecentsAnimationWrapper mRecentsAnimationWrapper;
|
||||
|
||||
protected T mActivity;
|
||||
protected Q mRecentsView;
|
||||
protected DeviceProfile mDp;
|
||||
private final int mPageSpacing;
|
||||
|
||||
protected Runnable mGestureEndCallback;
|
||||
|
||||
protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
|
||||
protected MultiStateCallback mStateCallback;
|
||||
|
||||
protected boolean mCanceled;
|
||||
protected int mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
||||
protected BaseSwipeUpHandler(Context context,
|
||||
OverviewComponentObserver overviewComponentObserver,
|
||||
RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
|
||||
mContext = context;
|
||||
mOverviewComponentObserver = overviewComponentObserver;
|
||||
mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
|
||||
mRecentsModel = recentsModel;
|
||||
mActivityInitListener =
|
||||
mActivityControlHelper.createActivityInitListener(this::onActivityInit);
|
||||
mRunningTaskId = runningTaskId;
|
||||
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
|
||||
this::createNewInputProxyHandler);
|
||||
mMode = SysUINavigationMode.getMode(context);
|
||||
|
||||
mClipAnimationHelper = new ClipAnimationHelper(context);
|
||||
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
mVibrator = context.getSystemService(Vibrator.class);
|
||||
initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
|
||||
.getDeviceProfile(mContext));
|
||||
}
|
||||
|
||||
protected void setStateOnUiThread(int stateFlag) {
|
||||
if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
|
||||
mStateCallback.setState(stateFlag);
|
||||
} else {
|
||||
postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
|
||||
}
|
||||
}
|
||||
|
||||
protected void performHapticFeedback() {
|
||||
if (!mVibrator.hasVibrator()) {
|
||||
return;
|
||||
}
|
||||
if (Settings.System.getInt(
|
||||
mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
VibrationEffect effect = createPredefined(EFFECT_CLICK);
|
||||
if (effect == null) {
|
||||
return;
|
||||
}
|
||||
BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
|
||||
}
|
||||
|
||||
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
|
||||
return mRecentsView != null ? mRecentsView.getEventDispatcher(rotationMode) : null;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void updateDisplacement(float displacement) {
|
||||
// We are moving in the negative x/y direction
|
||||
displacement = -displacement;
|
||||
float shift;
|
||||
if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
|
||||
shift = mDragLengthFactor;
|
||||
} else {
|
||||
float translation = Math.max(displacement, 0);
|
||||
shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
|
||||
if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
|
||||
float pullbackProgress = Utilities.getProgress(shift,
|
||||
DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
|
||||
pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
|
||||
shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
|
||||
* (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentShift.updateValue(shift);
|
||||
}
|
||||
|
||||
public void setGestureEndCallback(Runnable gestureEndCallback) {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
|
||||
public abstract Intent getLaunchIntent();
|
||||
|
||||
protected void linkRecentsViewScroll() {
|
||||
SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
|
||||
mTransformParams.setSyncTransactionApplier(applier);
|
||||
mRecentsAnimationWrapper.runOnInit(() ->
|
||||
mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
|
||||
});
|
||||
|
||||
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
|
||||
if (moveWindowWithRecentsScroll()) {
|
||||
updateFinalShift();
|
||||
}
|
||||
});
|
||||
mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
|
||||
mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
|
||||
}
|
||||
|
||||
protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
|
||||
// Launch the task user scrolled to (mRecentsView.getNextPage()).
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// We finish recents animation inside launchTask() when live tile is enabled.
|
||||
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
|
||||
true /* freezeTaskList */);
|
||||
} else {
|
||||
int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
|
||||
mFinishingRecentsAnimationForNewTaskId = taskId;
|
||||
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
if (nextTask != null) {
|
||||
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
|
||||
success -> {
|
||||
resultCallback.accept(success);
|
||||
if (!success) {
|
||||
mActivityControlHelper.onLaunchTaskFailed(mActivity);
|
||||
nextTask.notifyTaskLaunchFailed(TAG);
|
||||
} else {
|
||||
mActivityControlHelper.onLaunchTaskSuccess(mActivity);
|
||||
}
|
||||
}, mMainThreadHandler);
|
||||
}
|
||||
setStateOnUiThread(successStateFlag);
|
||||
}
|
||||
mCanceled = false;
|
||||
mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
});
|
||||
}
|
||||
TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
|
||||
final Rect overviewStackBounds;
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
|
||||
|
||||
if (targetSet.minimizedHomeBounds != null && runningTaskTarget != null) {
|
||||
overviewStackBounds = mActivityControlHelper
|
||||
.getOverviewWindowBounds(targetSet.minimizedHomeBounds, runningTaskTarget);
|
||||
dp = dp.getMultiWindowProfile(mContext, new Point(
|
||||
overviewStackBounds.width(), overviewStackBounds.height()));
|
||||
} 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(targetSet.homeContentInsets);
|
||||
dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
|
||||
if (runningTaskTarget != null) {
|
||||
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
|
||||
}
|
||||
|
||||
mClipAnimationHelper.prepareAnimation(dp, false /* isOpening */);
|
||||
initTransitionEndpoints(dp);
|
||||
|
||||
mRecentsAnimationWrapper.setController(targetSet);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
mDp = dp;
|
||||
|
||||
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
|
||||
dp, mContext, TEMP_RECT);
|
||||
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.
|
||||
mClipAnimationHelper.updateHomeBounds(getStackBounds(dp));
|
||||
}
|
||||
mClipAnimationHelper.updateTargetRect(TEMP_RECT);
|
||||
if (mMode == Mode.NO_BUTTON) {
|
||||
// We can drag all the way to the top of the screen.
|
||||
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the window should be translated horizontally if the recents view scrolls
|
||||
*/
|
||||
protected abstract boolean moveWindowWithRecentsScroll();
|
||||
|
||||
protected abstract boolean onActivityInit(final T activity, Boolean alreadyOnHome);
|
||||
|
||||
/**
|
||||
* Called to create a input proxy for the running task
|
||||
*/
|
||||
@UiThread
|
||||
protected abstract InputConsumer createNewInputProxyHandler();
|
||||
|
||||
/**
|
||||
* Called when the value of {@link #mCurrentShift} changes
|
||||
*/
|
||||
@UiThread
|
||||
public abstract void updateFinalShift();
|
||||
|
||||
/**
|
||||
* Called when motion pause is detected
|
||||
*/
|
||||
public abstract void onMotionPauseChanged(boolean isPaused);
|
||||
|
||||
@UiThread
|
||||
public void onGestureStarted() { }
|
||||
|
||||
@UiThread
|
||||
public abstract void onGestureCancelled();
|
||||
|
||||
@UiThread
|
||||
public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
|
||||
|
||||
public abstract void onConsumerAboutToBeSwitched(SwipeSharedState sharedState);
|
||||
|
||||
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
|
||||
|
||||
public void initWhenReady() {
|
||||
// Preload the plan
|
||||
mRecentsModel.getTasks(null);
|
||||
|
||||
mActivityInitListener.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the transform on the recents animation without any additional null checks
|
||||
*/
|
||||
protected void applyTransformUnchecked() {
|
||||
float shift = mCurrentShift.value;
|
||||
float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
|
||||
float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
|
||||
mClipAnimationHelper.getTargetRect().width());
|
||||
mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
|
||||
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
|
||||
mTransformParams);
|
||||
}
|
||||
|
||||
private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
|
||||
float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 + mPageSpacing;
|
||||
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
|
||||
return TaskView.getCurveScaleForInterpolation(interpolation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param homeAnimationFactory The home animation factory.
|
||||
*/
|
||||
protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
|
||||
HomeAnimationFactory homeAnimationFactory) {
|
||||
final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet;
|
||||
final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet,
|
||||
mTransformParams.setProgress(startProgress), false /* launcherOnTop */));
|
||||
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
|
||||
|
||||
final View floatingView = homeAnimationFactory.getFloatingView();
|
||||
final boolean isFloatingIconView = floatingView instanceof FloatingIconView;
|
||||
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext.getResources());
|
||||
if (isFloatingIconView) {
|
||||
FloatingIconView fiv = (FloatingIconView) floatingView;
|
||||
anim.addAnimatorListener(fiv);
|
||||
fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
}
|
||||
|
||||
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 = mClipAnimationHelper.getCurrentCornerRadius();
|
||||
float endRadius = startRect.width() / 6f;
|
||||
// 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;
|
||||
anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() {
|
||||
|
||||
// Alpha interpolates between [1, 0] between progress values [start, end]
|
||||
final float start = 0f;
|
||||
final float end = 0.85f;
|
||||
|
||||
private float getWindowAlpha(float progress) {
|
||||
if (progress <= start) {
|
||||
return 1f;
|
||||
}
|
||||
if (progress >= end) {
|
||||
return 0f;
|
||||
}
|
||||
return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(RectF currentRect, float progress) {
|
||||
homeAnim.setPlayFraction(progress);
|
||||
|
||||
mTransformParams.setProgress(progress)
|
||||
.setCurrentRectAndTargetAlpha(currentRect, getWindowAlpha(progress));
|
||||
if (isFloatingIconView) {
|
||||
mTransformParams.setCornerRadius(endRadius * progress + startRadius
|
||||
* (1f - progress));
|
||||
}
|
||||
mClipAnimationHelper.applyTransform(targetSet, mTransformParams,
|
||||
false /* launcherOnTop */);
|
||||
|
||||
if (isFloatingIconView) {
|
||||
((FloatingIconView) floatingView).update(currentRect, 1f, progress,
|
||||
windowAlphaThreshold, mClipAnimationHelper.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();
|
||||
}
|
||||
});
|
||||
return anim;
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
|
||||
BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask,
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask);
|
||||
}
|
||||
|
||||
protected interface RunningWindowAnim {
|
||||
void end();
|
||||
|
||||
void cancel();
|
||||
|
||||
static RunningWindowAnim wrap(Animator animator) {
|
||||
return new RunningWindowAnim() {
|
||||
@Override
|
||||
public void end() {
|
||||
animator.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
animator.cancel();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) {
|
||||
return new RunningWindowAnim() {
|
||||
@Override
|
||||
public void end() {
|
||||
rectFSpringAnim.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
rectFSpringAnim.cancel();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -80,7 +80,9 @@ public final class FallbackActivityControllerHelper implements
|
||||
|
||||
@Override
|
||||
public void onAssistantVisibilityChanged(float visibility) {
|
||||
// TODO:
|
||||
// This class becomes active when the screen is locked.
|
||||
// Rather than having it handle assistant visibility changes, the assistant visibility is
|
||||
// set to zero prior to this class becoming active.
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+1
-10
@@ -151,16 +151,10 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
|
||||
@NonNull
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
final int halfIconSize = dp.iconSizePx / 2;
|
||||
final float targetCenterX = dp.availableWidthPx / 2f;
|
||||
final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
|
||||
|
||||
if (canUseWorkspaceView) {
|
||||
return iconLocation;
|
||||
} else {
|
||||
// Fallback to animate to center of screen.
|
||||
return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
|
||||
targetCenterX + halfIconSize, targetCenterY + halfIconSize);
|
||||
return HomeAnimationFactory.getDefaultWindowTargetRect(dp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,9 +188,6 @@ 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;
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.testing.TestInformationHandler;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class QuickstepTestInformationHandler extends TestInformationHandler {
|
||||
|
||||
public QuickstepTestInformationHandler(Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String method) {
|
||||
final Bundle response = new Bundle();
|
||||
switch (method) {
|
||||
case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
|
||||
final float swipeHeight =
|
||||
OverviewState.getDefaultSwipeHeight(mDeviceProfile);
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
|
||||
final float swipeHeight =
|
||||
LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
|
||||
response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
|
||||
TouchInteractionService.isInitialized());
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_HOTSEAT_TOP: {
|
||||
if (mLauncher == null) return null;
|
||||
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
|
||||
PortraitStatesTouchController.getHotseatTop(mLauncher));
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN: {
|
||||
try {
|
||||
final int leftMargin = new MainThreadExecutor().submit(() ->
|
||||
mLauncher.<RecentsView>getOverviewPanel().getLeftGestureMargin()).get();
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, leftMargin);
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN: {
|
||||
try {
|
||||
final int rightMargin = new MainThreadExecutor().submit(() ->
|
||||
mLauncher.<RecentsView>getOverviewPanel().getRightGestureMargin()).
|
||||
get();
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, rightMargin);
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
return super.call(method);
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,10 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
|
||||
@@ -42,7 +44,9 @@ import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.fallback.RecentsRootView;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.ObjectWrapper;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
@@ -54,6 +58,9 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
*/
|
||||
public final class RecentsActivity extends BaseRecentsActivity {
|
||||
|
||||
public static final String EXTRA_THUMBNAIL = "thumbnailData";
|
||||
public static final String EXTRA_TASK_ID = "taskID";
|
||||
|
||||
private Handler mUiHandler = new Handler(Looper.getMainLooper());
|
||||
private RecentsRootView mRecentsRootView;
|
||||
private FallbackRecentsView mFallbackRecentsView;
|
||||
@@ -78,6 +85,22 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
if (intent.getExtras() != null) {
|
||||
int taskID = intent.getIntExtra(EXTRA_TASK_ID, 0);
|
||||
IBinder thumbnail = intent.getExtras().getBinder(EXTRA_THUMBNAIL);
|
||||
if (taskID != 0 && thumbnail instanceof ObjectWrapper) {
|
||||
ThumbnailData thumbnailData = ((ObjectWrapper<ThumbnailData>) thumbnail).get();
|
||||
mFallbackRecentsView.showCurrentTask(taskID);
|
||||
mFallbackRecentsView.updateThumbnail(taskID, thumbnailData);
|
||||
}
|
||||
}
|
||||
intent.removeExtra(EXTRA_TASK_ID);
|
||||
intent.removeExtra(EXTRA_THUMBNAIL);
|
||||
super.onNewIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleConfigChanged() {
|
||||
super.onHandleConfigChanged();
|
||||
@@ -132,7 +155,7 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
||||
mFallbackRecentsView.resetViewUI();
|
||||
}
|
||||
});
|
||||
result.setAnimation(anim);
|
||||
result.setAnimation(anim, RecentsActivity.this);
|
||||
}
|
||||
};
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
|
||||
@@ -178,6 +201,12 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
||||
mFallbackRecentsView.resetTaskVisuals();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mFallbackRecentsView.reset();
|
||||
}
|
||||
|
||||
public void onTaskLaunched() {
|
||||
mFallbackRecentsView.resetTaskVisuals();
|
||||
}
|
||||
|
||||
+4
-9
@@ -19,12 +19,12 @@ import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Utilities.FLAG_NO_GESTURES;
|
||||
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.quickstep.inputconsumers.InputConsumer;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
@@ -33,8 +33,6 @@ import com.android.systemui.shared.system.InputConsumerController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
/**
|
||||
* Wrapper around RecentsAnimationController to help with some synchronization
|
||||
*/
|
||||
@@ -184,18 +182,15 @@ public class RecentsAnimationWrapper {
|
||||
}
|
||||
}
|
||||
if (mInputConsumer != null) {
|
||||
int flags = ev.getEdgeFlags();
|
||||
ev.setEdgeFlags(flags | FLAG_NO_GESTURES);
|
||||
mInputConsumer.onMotionEvent(ev);
|
||||
ev.setEdgeFlags(flags);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCancelWithDeferredScreenshot(boolean deferredWithScreenshot) {
|
||||
public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
|
||||
if (targetSet != null) {
|
||||
targetSet.controller.setCancelWithDeferredScreenshot(deferredWithScreenshot);
|
||||
targetSet.controller.setDeferCancelUntilNextTransition(defer, screenshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,8 +207,7 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
||||
}
|
||||
};
|
||||
WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
|
||||
future, animStartedListener, mHandler, true /* scaleUp */,
|
||||
v.getDisplay().getDisplayId());
|
||||
future, animStartedListener, mHandler, true /* scaleUp */, displayId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+183
-22
@@ -31,18 +31,22 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_H
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
|
||||
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_QUICK_SETTINGS_EXPANDED;
|
||||
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_OCCLUDED;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.Service;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
@@ -65,6 +69,7 @@ import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
@@ -74,6 +79,9 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.logging.EventLogArray;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.provider.RestoreDbTask;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
@@ -96,8 +104,10 @@ import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
import com.android.systemui.shared.system.RecentsAnimationListener;
|
||||
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
|
||||
|
||||
import com.android.systemui.shared.system.TaskInfoCompat;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
@@ -119,10 +129,6 @@ class ArgList extends LinkedList<String> {
|
||||
public String nextArg() {
|
||||
return pollFirst().toLowerCase();
|
||||
}
|
||||
|
||||
public String nextArgExact() {
|
||||
return pollFirst();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,6 +147,11 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
private static final String TAG = "TouchInteractionService";
|
||||
|
||||
private static final String KEY_BACK_NOTIFICATION_COUNT = "backNotificationCount";
|
||||
private static final String NOTIFY_ACTION_BACK = "com.android.quickstep.action.BACK_GESTURE";
|
||||
private static final int MAX_BACK_NOTIFICATION_COUNT = 3;
|
||||
private int mBackGestureNotificationCounter = -1;
|
||||
|
||||
private final IBinder mMyBinder = new IOverviewProxy.Stub() {
|
||||
|
||||
public void onActiveNavBarRegionChanges(Region region) {
|
||||
@@ -152,6 +163,8 @@ public class TouchInteractionService extends Service implements
|
||||
.asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
|
||||
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
|
||||
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
|
||||
MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
|
||||
sIsInitialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -199,6 +212,10 @@ public class TouchInteractionService extends Service implements
|
||||
mOverviewComponentObserver.getActivityControlHelper();
|
||||
UserEventDispatcher.newInstance(getBaseContext()).logActionBack(completed, downX, downY,
|
||||
isButton, gestureSwipeLeft, activityControl.getContainerType());
|
||||
|
||||
if (completed && !isButton && shouldNotifyBackGesture()) {
|
||||
BACKGROUND_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
|
||||
}
|
||||
}
|
||||
|
||||
public void onSystemUiStateChanged(int stateFlags) {
|
||||
@@ -225,12 +242,17 @@ public class TouchInteractionService extends Service implements
|
||||
};
|
||||
|
||||
private static boolean sConnected = false;
|
||||
private static boolean sIsInitialized = false;
|
||||
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
|
||||
|
||||
public static boolean isConnected() {
|
||||
return sConnected;
|
||||
}
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return sIsInitialized;
|
||||
}
|
||||
|
||||
public static SwipeSharedState getSwipeSharedState() {
|
||||
return sSwipeSharedState;
|
||||
}
|
||||
@@ -238,6 +260,11 @@ public class TouchInteractionService extends Service implements
|
||||
private final InputConsumer mResetGestureInputConsumer =
|
||||
new ResetGestureInputConsumer(sSwipeSharedState);
|
||||
|
||||
private final BaseSwipeUpHandler.Factory mWindowTreansformFactory =
|
||||
this::createWindowTransformSwipeHandler;
|
||||
private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
|
||||
this::createFallbackNoButtonSwipeHandler;
|
||||
|
||||
private ActivityManagerWrapper mAM;
|
||||
private RecentsModel mRecentsModel;
|
||||
private ISystemUiProxy mISystemUiProxy;
|
||||
@@ -319,6 +346,9 @@ public class TouchInteractionService extends Service implements
|
||||
if (mInputEventReceiver != null) {
|
||||
mInputEventReceiver.dispose();
|
||||
mInputEventReceiver = null;
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "disposeEventHandlers");
|
||||
}
|
||||
}
|
||||
if (mInputMonitorCompat != null) {
|
||||
mInputMonitorCompat.dispose();
|
||||
@@ -327,16 +357,25 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
|
||||
private void initInputMonitor() {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 1");
|
||||
}
|
||||
if (!mMode.hasGestures || mISystemUiProxy == null) {
|
||||
return;
|
||||
}
|
||||
disposeEventHandlers();
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 2");
|
||||
}
|
||||
|
||||
try {
|
||||
mInputMonitorCompat = InputMonitorCompat.fromBundle(mISystemUiProxy
|
||||
.monitorGestureInput("swipe-up", mDefaultDisplayId), KEY_EXTRA_INPUT_MONITOR);
|
||||
mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
|
||||
mMainChoreographer, this::onInputEvent);
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 3");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to create input monitor", e);
|
||||
}
|
||||
@@ -394,6 +433,9 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
@Override
|
||||
public void onNavigationModeChanged(Mode newMode) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onNavigationModeChanged " + newMode);
|
||||
}
|
||||
if (mMode.hasGestures != newMode.hasGestures) {
|
||||
if (newMode.hasGestures) {
|
||||
getSystemService(DisplayManager.class).registerDisplayListener(
|
||||
@@ -448,6 +490,8 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
// Temporarily disable model preload
|
||||
// new ModelPreload().start(this);
|
||||
mBackGestureNotificationCounter = Math.max(0, Utilities.getDevicePrefs(this)
|
||||
.getInt(KEY_BACK_NOTIFICATION_COUNT, MAX_BACK_NOTIFICATION_COUNT));
|
||||
|
||||
Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver);
|
||||
}
|
||||
@@ -478,6 +522,7 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
sIsInitialized = false;
|
||||
if (mIsUserUnlocked) {
|
||||
mInputConsumer.unregisterInputConsumer();
|
||||
mOverviewComponentObserver.onDestroy();
|
||||
@@ -502,6 +547,9 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
|
||||
private void onInputEvent(InputEvent ev) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onInputEvent " + ev);
|
||||
}
|
||||
if (!(ev instanceof MotionEvent)) {
|
||||
Log.e(TAG, "Unknown event " + ev);
|
||||
return;
|
||||
@@ -534,6 +582,7 @@ public class TouchInteractionService extends Service implements
|
||||
private boolean validSystemUiFlags() {
|
||||
return (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
|
||||
&& (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
|
||||
&& (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0
|
||||
&& ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
|
||||
|| (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0);
|
||||
}
|
||||
@@ -553,7 +602,7 @@ public class TouchInteractionService extends Service implements
|
||||
if (isInValidSystemUiState) {
|
||||
// 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).
|
||||
return createDeviceLockedInputConsumer(mAM.getRunningTask(0));
|
||||
return createDeviceLockedInputConsumer(mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
|
||||
} else {
|
||||
return mResetGestureInputConsumer;
|
||||
}
|
||||
@@ -591,7 +640,7 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
|
||||
private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
|
||||
final RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
|
||||
RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
|
||||
if (!useSharedState) {
|
||||
sSwipeSharedState.clearAllState(false /* finishAnimation */);
|
||||
}
|
||||
@@ -603,6 +652,19 @@ public class TouchInteractionService extends Service implements
|
||||
final ActivityControlHelper activityControl =
|
||||
mOverviewComponentObserver.getActivityControlHelper();
|
||||
|
||||
boolean forceOverviewInputConsumer = false;
|
||||
if (isExcludedAssistant(runningTaskInfo)) {
|
||||
// In the case where we are in the excluded assistant state, ignore it and treat the
|
||||
// running activity as the task behind the assistant
|
||||
runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
|
||||
if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
|
||||
final ComponentName homeComponent =
|
||||
mOverviewComponentObserver.getHomeIntent().getComponent();
|
||||
forceOverviewInputConsumer =
|
||||
runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
|
||||
}
|
||||
}
|
||||
|
||||
if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
|
||||
&& !sSwipeSharedState.recentsAnimationFinishInterrupted) {
|
||||
return mResetGestureInputConsumer;
|
||||
@@ -612,22 +674,25 @@ public class TouchInteractionService extends Service implements
|
||||
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||
info.id = sSwipeSharedState.nextRunningTaskId;
|
||||
return createOtherActivityInputConsumer(event, info);
|
||||
} else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()) {
|
||||
} else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()
|
||||
|| forceOverviewInputConsumer) {
|
||||
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 mResetGestureInputConsumer;
|
||||
} else if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||
return new FallbackNoButtonInputConsumer(this, activityControl,
|
||||
mInputMonitorCompat, sSwipeSharedState, mSwipeTouchRegion,
|
||||
mOverviewComponentObserver, disableHorizontalSwipe(event), runningTaskInfo);
|
||||
} else {
|
||||
return createOtherActivityInputConsumer(event, runningTaskInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExcludedAssistant(TaskInfo info) {
|
||||
return info != null
|
||||
&& TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
|
||||
&& (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
|
||||
}
|
||||
|
||||
private boolean disableHorizontalSwipe(MotionEvent event) {
|
||||
// mExclusionRegion can change on binder thread, use a local instance here.
|
||||
Region exclusionRegion = mExclusionRegion;
|
||||
@@ -635,17 +700,25 @@ public class TouchInteractionService extends Service implements
|
||||
&& exclusionRegion.contains((int) event.getX(), (int) event.getY());
|
||||
}
|
||||
|
||||
private OtherActivityInputConsumer createOtherActivityInputConsumer(MotionEvent event,
|
||||
private InputConsumer createOtherActivityInputConsumer(MotionEvent event,
|
||||
RunningTaskInfo runningTaskInfo) {
|
||||
final ActivityControlHelper activityControl =
|
||||
mOverviewComponentObserver.getActivityControlHelper();
|
||||
boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
|
||||
|
||||
return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
|
||||
mOverviewComponentObserver.getOverviewIntent(), activityControl,
|
||||
shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive,
|
||||
final boolean shouldDefer;
|
||||
final BaseSwipeUpHandler.Factory factory;
|
||||
|
||||
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||
shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
|
||||
factory = mFallbackNoButtonFactory;
|
||||
} else {
|
||||
shouldDefer = mOverviewComponentObserver.getActivityControlHelper()
|
||||
.deferStartingActivity(mActiveNavBarRegion, event);
|
||||
factory = mWindowTreansformFactory;
|
||||
}
|
||||
|
||||
return new OtherActivityInputConsumer(this, runningTaskInfo,
|
||||
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
|
||||
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
|
||||
disableHorizontalSwipe(event));
|
||||
disableHorizontalSwipe(event), factory);
|
||||
}
|
||||
|
||||
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
|
||||
@@ -669,7 +742,7 @@ public class TouchInteractionService extends Service implements
|
||||
return new OverviewInputConsumer(activity, mInputMonitorCompat,
|
||||
false /* startingInActivityBounds */);
|
||||
} else {
|
||||
return new OverviewWithoutFocusInputConsumer(this, mInputMonitorCompat,
|
||||
return new OverviewWithoutFocusInputConsumer(activity, mInputMonitorCompat,
|
||||
disableHorizontalSwipe(event));
|
||||
}
|
||||
}
|
||||
@@ -684,6 +757,60 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
}
|
||||
|
||||
private void preloadOverview(boolean fromInit) {
|
||||
if (!mIsUserUnlocked) {
|
||||
return;
|
||||
}
|
||||
if (!mMode.hasGestures && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||
// Prevent the overview from being started before the real home on first boot.
|
||||
return;
|
||||
}
|
||||
|
||||
if (RestoreDbTask.isPending(this)) {
|
||||
// Preloading while a restore is pending may cause launcher to start the restore
|
||||
// too early.
|
||||
return;
|
||||
}
|
||||
|
||||
final ActivityControlHelper<BaseDraggingActivity> activityControl =
|
||||
mOverviewComponentObserver.getActivityControlHelper();
|
||||
if (activityControl.getCreatedActivity() == null) {
|
||||
// Make sure that UI states will be initialized.
|
||||
activityControl.createActivityInitListener((activity, wasVisible) -> {
|
||||
AppLaunchTracker.INSTANCE.get(activity);
|
||||
return false;
|
||||
}).register();
|
||||
} else if (fromInit) {
|
||||
// The activity has been created before the initialization of overview service. It is
|
||||
// usually happens when booting or launcher is the top activity, so we should already
|
||||
// have the latest state.
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass null animation handler to indicate this start is preload.
|
||||
startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
if (!mIsUserUnlocked) {
|
||||
return;
|
||||
}
|
||||
final ActivityControlHelper activityControl =
|
||||
mOverviewComponentObserver.getActivityControlHelper();
|
||||
final BaseDraggingActivity activity = activityControl.getCreatedActivity();
|
||||
if (activity == null || activity.isStarted()) {
|
||||
// We only care about the existing background activity.
|
||||
return;
|
||||
}
|
||||
if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
|
||||
activity.getResources().getConfiguration().diff(newConfig))) {
|
||||
return;
|
||||
}
|
||||
|
||||
preloadOverview(false /* fromInit */);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
|
||||
if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) {
|
||||
@@ -708,8 +835,9 @@ public class TouchInteractionService extends Service implements
|
||||
pw.println(" assistantAvailable=" + mAssistantAvailable);
|
||||
pw.println(" assistantDisabled="
|
||||
+ QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
|
||||
pw.println(" resumed="
|
||||
+ mOverviewComponentObserver.getActivityControlHelper().isResumed());
|
||||
boolean resumed = mOverviewComponentObserver != null
|
||||
&& mOverviewComponentObserver.getActivityControlHelper().isResumed();
|
||||
pw.println(" resumed=" + resumed);
|
||||
pw.println(" useSharedState=" + mConsumer.useSharedSwipeState());
|
||||
if (mConsumer.useSharedSwipeState()) {
|
||||
sSwipeSharedState.dump(" ", pw);
|
||||
@@ -739,4 +867,37 @@ public class TouchInteractionService extends Service implements
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createWindowTransformSwipeHandler(RunningTaskInfo runningTask,
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
|
||||
return new WindowTransformSwipeHandler(runningTask, this, touchTimeMs,
|
||||
mOverviewComponentObserver, continuingLastGesture, mInputConsumer, mRecentsModel);
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(RunningTaskInfo runningTask,
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
|
||||
return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask,
|
||||
mRecentsModel, mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
|
||||
}
|
||||
|
||||
protected boolean shouldNotifyBackGesture() {
|
||||
return mBackGestureNotificationCounter > 0 &&
|
||||
mGestureBlockingActivity != null;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
protected void tryNotifyBackGesture() {
|
||||
if (shouldNotifyBackGesture()) {
|
||||
mBackGestureNotificationCounter--;
|
||||
Utilities.getDevicePrefs(this).edit()
|
||||
.putInt(KEY_BACK_NOTIFICATION_COUNT, mBackGestureNotificationCounter).apply();
|
||||
sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(
|
||||
mGestureBlockingActivity.getPackageName()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
|
||||
BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
||||
.startRecentsActivity(intent, null, listener, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
+93
-359
@@ -17,22 +17,18 @@ 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.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
|
||||
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;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
|
||||
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
|
||||
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
|
||||
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
|
||||
@@ -43,65 +39,49 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_O
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
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;
|
||||
import android.view.View.OnApplyWindowInsetsListener;
|
||||
import android.view.ViewTreeObserver.OnDrawListener;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
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.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
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;
|
||||
import com.android.launcher3.util.RaceConditionTracker;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
|
||||
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
|
||||
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.inputconsumers.InputConsumer;
|
||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.RemoteAnimationTargetSet;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
|
||||
import com.android.quickstep.views.LiveTileOverlay;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
@@ -109,19 +89,14 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.LatencyTrackerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
import com.android.systemui.shared.system.WindowCallbacksCompat;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
implements SwipeAnimationListener, OnApplyWindowInsetsListener {
|
||||
extends BaseSwipeUpHandler<T, RecentsView>
|
||||
implements OnApplyWindowInsetsListener {
|
||||
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
|
||||
|
||||
private static final Rect TEMP_RECT = new Rect();
|
||||
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
|
||||
|
||||
private static int getFlagForIndex(int index, String name) {
|
||||
@@ -220,64 +195,30 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
private static final long SHELF_ANIM_DURATION = 240;
|
||||
public static final long RECENTS_ATTACH_DURATION = 300;
|
||||
|
||||
// Start resisting when swiping past this factor of mTransitionDragLength.
|
||||
private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
|
||||
// This is how far down we can scale down, where 0f is full screen and 1f is recents.
|
||||
private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = 1.8f;
|
||||
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
|
||||
|
||||
/**
|
||||
* Used as the page index for logging when we return to the last task at the end of the gesture.
|
||||
*/
|
||||
private static final int LOG_NO_OP_PAGE_INDEX = -1;
|
||||
|
||||
private final ClipAnimationHelper mClipAnimationHelper;
|
||||
private final ClipAnimationHelper.TransformParams mTransformParams;
|
||||
|
||||
private Runnable mGestureEndCallback;
|
||||
private GestureEndTarget mGestureEndTarget;
|
||||
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
|
||||
private RunningWindowAnim mRunningWindowAnim;
|
||||
private boolean mIsShelfPeeking;
|
||||
private DeviceProfile mDp;
|
||||
// The distance needed to drag to reach the task size in recents.
|
||||
private int mTransitionDragLength;
|
||||
// How much further we can drag past recents, as a factor of mTransitionDragLength.
|
||||
private float mDragLengthFactor = 1;
|
||||
|
||||
// Shift in the range of [0, 1].
|
||||
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
|
||||
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
|
||||
// visible.
|
||||
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
|
||||
private boolean mContinuingLastGesture;
|
||||
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
|
||||
private float mShiftAtGestureStart = 0;
|
||||
|
||||
private final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
|
||||
|
||||
private final Context mContext;
|
||||
private final ActivityControlHelper<T> mActivityControlHelper;
|
||||
private final ActivityInitListener mActivityInitListener;
|
||||
|
||||
private final SysUINavigationMode.Mode mMode;
|
||||
|
||||
private final int mRunningTaskId;
|
||||
private ThumbnailData mTaskSnapshot;
|
||||
|
||||
private MultiStateCallback mStateCallback;
|
||||
// Used to control launcher components throughout the swipe gesture.
|
||||
private AnimatorPlaybackController mLauncherTransitionController;
|
||||
private boolean mHasLauncherTransitionControllerStarted;
|
||||
|
||||
private T mActivity;
|
||||
private RecentsView mRecentsView;
|
||||
private AnimationFactory mAnimationFactory = (t) -> { };
|
||||
private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
|
||||
|
||||
private boolean mCanceled;
|
||||
private boolean mWasLauncherAlreadyVisible;
|
||||
private int mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
||||
private boolean mPassedOverviewThreshold;
|
||||
private boolean mGestureStarted;
|
||||
@@ -286,31 +227,17 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
private PointF mDownPos;
|
||||
private boolean mIsLikelyToStartNewTask;
|
||||
|
||||
private final RecentsAnimationWrapper mRecentsAnimationWrapper;
|
||||
|
||||
private final long mTouchTimeMs;
|
||||
private long mLauncherFrameDrawnTime;
|
||||
|
||||
public WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
|
||||
long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
|
||||
InputConsumerController inputConsumer) {
|
||||
mContext = context;
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
long touchTimeMs, OverviewComponentObserver overviewComponentObserver,
|
||||
boolean continuingLastGesture,
|
||||
InputConsumerController inputConsumer, RecentsModel recentsModel) {
|
||||
super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mActivityControlHelper = controller;
|
||||
mActivityInitListener = mActivityControlHelper
|
||||
.createActivityInitListener(this::onActivityInit);
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
|
||||
this::createNewInputProxyHandler);
|
||||
mClipAnimationHelper = new ClipAnimationHelper(context);
|
||||
mTransformParams = new ClipAnimationHelper.TransformParams();
|
||||
|
||||
mMode = SysUINavigationMode.getMode(context);
|
||||
initStateCallbacks();
|
||||
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
|
||||
initTransitionEndpoints(dp);
|
||||
}
|
||||
|
||||
private void initStateCallbacks() {
|
||||
@@ -373,44 +300,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
}
|
||||
}
|
||||
|
||||
private void setStateOnUiThread(int stateFlag) {
|
||||
if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
|
||||
mStateCallback.setState(stateFlag);
|
||||
} else {
|
||||
postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
|
||||
}
|
||||
}
|
||||
|
||||
private void initTransitionEndpoints(DeviceProfile dp) {
|
||||
mDp = dp;
|
||||
|
||||
Rect tempRect = new Rect();
|
||||
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
|
||||
dp, mContext, tempRect);
|
||||
mClipAnimationHelper.updateTargetRect(tempRect);
|
||||
if (mMode == Mode.NO_BUTTON) {
|
||||
// We can drag all the way to the top of the screen.
|
||||
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
|
||||
}
|
||||
}
|
||||
|
||||
private long getFadeInDuration() {
|
||||
if (mCurrentShift.getCurrentAnimation() != null) {
|
||||
ObjectAnimator anim = mCurrentShift.getCurrentAnimation();
|
||||
long theirDuration = anim.getDuration() - anim.getCurrentPlayTime();
|
||||
|
||||
// TODO: Find a better heuristic
|
||||
return Math.min(MAX_SWIPE_DURATION, Math.max(theirDuration, MIN_SWIPE_DURATION));
|
||||
} else {
|
||||
return MAX_SWIPE_DURATION;
|
||||
}
|
||||
}
|
||||
|
||||
public void initWhenReady() {
|
||||
mActivityInitListener.register();
|
||||
}
|
||||
|
||||
private boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
|
||||
@Override
|
||||
protected boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
|
||||
if (mActivity == activity) {
|
||||
return true;
|
||||
}
|
||||
@@ -431,19 +322,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
}
|
||||
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
|
||||
mTransformParams.setSyncTransactionApplier(applier);
|
||||
mRecentsAnimationWrapper.runOnInit(() ->
|
||||
mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
|
||||
});
|
||||
|
||||
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
|
||||
if (mGestureEndTarget != HOME) {
|
||||
updateFinalShift();
|
||||
}
|
||||
});
|
||||
mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
|
||||
mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
|
||||
linkRecentsViewScroll();
|
||||
mRecentsView.setLiveTileOverlay(mLiveTileOverlay);
|
||||
mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
|
||||
|
||||
@@ -458,33 +337,23 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mGestureEndTarget != HOME;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -494,14 +363,8 @@ 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();
|
||||
}
|
||||
}
|
||||
@@ -577,30 +440,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
return TaskView.getCurveScaleForInterpolation(interpolation);
|
||||
}
|
||||
|
||||
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
|
||||
return mRecentsView != null ? mRecentsView.getEventDispatcher(rotationMode) : null;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void updateDisplacement(float displacement) {
|
||||
// We are moving in the negative x/y direction
|
||||
displacement = -displacement;
|
||||
if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
|
||||
mCurrentShift.updateValue(mDragLengthFactor);
|
||||
} else {
|
||||
float translation = Math.max(displacement, 0);
|
||||
float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
|
||||
if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
|
||||
float pullbackProgress = Utilities.getProgress(shift,
|
||||
DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
|
||||
pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
|
||||
shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
|
||||
* (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
|
||||
}
|
||||
mCurrentShift.updateValue(shift);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
|
||||
}
|
||||
@@ -651,6 +491,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
|
||||
if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
|
||||
mIsLikelyToStartNewTask = isLikelyToStartNewTask;
|
||||
@@ -666,9 +507,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
if (mIsShelfPeeking != wasShelfPeeking) {
|
||||
maybeUpdateRecentsAttachedState();
|
||||
}
|
||||
if (mRecentsView != null && shelfState.shouldPreformHaptic) {
|
||||
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
if (shelfState.shouldPreformHaptic) {
|
||||
performHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,19 +537,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void updateFinalShift() {
|
||||
float shift = mCurrentShift.value;
|
||||
@Override
|
||||
public Intent getLaunchIntent() {
|
||||
return mOverviewComponentObserver.getOverviewIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
|
||||
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
|
||||
if (controller != null) {
|
||||
float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
|
||||
float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
|
||||
mClipAnimationHelper.getTargetRect().width());
|
||||
mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
|
||||
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
|
||||
mTransformParams);
|
||||
updateSysUiFlags(shift);
|
||||
applyTransformUnchecked();
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
}
|
||||
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
@@ -722,9 +561,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
|
||||
if (passed != mPassedOverviewThreshold) {
|
||||
mPassedOverviewThreshold = passed;
|
||||
if (mRecentsView != null && mMode != Mode.NO_BUTTON) {
|
||||
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
if (mMode != Mode.NO_BUTTON) {
|
||||
performHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,39 +605,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
|
||||
final Rect overviewStackBounds;
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
|
||||
|
||||
if (targetSet.minimizedHomeBounds != null && runningTaskTarget != null) {
|
||||
overviewStackBounds = mActivityControlHelper
|
||||
.getOverviewWindowBounds(targetSet.minimizedHomeBounds, runningTaskTarget);
|
||||
dp = dp.getMultiWindowProfile(mContext, new Point(
|
||||
targetSet.minimizedHomeBounds.width(), targetSet.minimizedHomeBounds.height()));
|
||||
dp.updateInsets(targetSet.homeContentInsets);
|
||||
} else {
|
||||
if (mActivity != null) {
|
||||
int loc[] = new int[2];
|
||||
View rootView = mActivity.getRootView();
|
||||
rootView.getLocationOnScreen(loc);
|
||||
overviewStackBounds = new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(),
|
||||
loc[1] + rootView.getHeight());
|
||||
} else {
|
||||
overviewStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx);
|
||||
}
|
||||
// If we are not in multi-window mode, home insets should be same as system insets.
|
||||
dp = dp.copy(mContext);
|
||||
dp.updateInsets(targetSet.homeContentInsets);
|
||||
}
|
||||
dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
|
||||
|
||||
if (runningTaskTarget != null) {
|
||||
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
|
||||
}
|
||||
mClipAnimationHelper.prepareAnimation(dp, false /* isOpening */);
|
||||
initTransitionEndpoints(dp);
|
||||
|
||||
mRecentsAnimationWrapper.setController(targetSet);
|
||||
super.onRecentsAnimationStart(targetSet);
|
||||
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimationCallback", targetSet.apps.length);
|
||||
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
|
||||
@@ -814,7 +620,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
TOUCH_INTERACTION_LOG.addLog("cancelRecentsAnimation");
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public void onGestureStarted() {
|
||||
notifyGestureStartedAsync();
|
||||
mShiftAtGestureStart = mCurrentShift.value;
|
||||
@@ -838,7 +644,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
/**
|
||||
* Called as a result on ACTION_CANCEL to return the UI to the start state.
|
||||
*/
|
||||
@UiThread
|
||||
@Override
|
||||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
@@ -851,7 +657,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
* @param velocity The x and y components of the velocity when the gesture ends.
|
||||
* @param downPos The x and y value of where the gesture started.
|
||||
*/
|
||||
@UiThread
|
||||
@Override
|
||||
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
|
||||
float flingThreshold = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
@@ -869,9 +675,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private InputConsumer createNewInputProxyHandler() {
|
||||
endRunningWindowAnim();
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
endRunningWindowAnim(mGestureEndTarget == HOME /* cancel */);
|
||||
endLauncherTransitionController();
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// Hide the task view, if not already hidden
|
||||
@@ -883,9 +689,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
? InputConsumer.NO_OP : new OverviewInputConsumer(activity, null, true);
|
||||
}
|
||||
|
||||
private void endRunningWindowAnim() {
|
||||
private void endRunningWindowAnim(boolean cancel) {
|
||||
if (mRunningWindowAnim != null) {
|
||||
mRunningWindowAnim.end();
|
||||
if (cancel) {
|
||||
mRunningWindowAnim.cancel();
|
||||
} else {
|
||||
mRunningWindowAnim.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -926,18 +736,19 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
: LAST_TASK;
|
||||
}
|
||||
} else {
|
||||
if (mMode == Mode.NO_BUTTON && endVelocity < 0 && !mIsShelfPeeking) {
|
||||
// If swiping at a diagonal, base end target on the faster velocity.
|
||||
boolean isSwipeUp = endVelocity < 0;
|
||||
boolean willGoToNewTaskOnSwipeUp =
|
||||
goingToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity);
|
||||
|
||||
if (mMode == Mode.NO_BUTTON && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
|
||||
endTarget = HOME;
|
||||
} else if (mMode == Mode.NO_BUTTON && isSwipeUp && !mIsShelfPeeking) {
|
||||
// If swiping at a diagonal, base end target on the faster velocity.
|
||||
endTarget = goingToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity)
|
||||
? NEW_TASK : HOME;
|
||||
} else if (endVelocity < 0) {
|
||||
if (reachedOverviewThreshold) {
|
||||
endTarget = RECENTS;
|
||||
} else {
|
||||
// If swiping at a diagonal, base end target on the faster velocity.
|
||||
endTarget = goingToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity)
|
||||
? NEW_TASK : RECENTS;
|
||||
}
|
||||
endTarget = NEW_TASK;
|
||||
} else if (isSwipeUp) {
|
||||
endTarget = !reachedOverviewThreshold && willGoToNewTaskOnSwipeUp
|
||||
? NEW_TASK : RECENTS;
|
||||
} else {
|
||||
endTarget = goingToNewTask ? NEW_TASK : LAST_TASK;
|
||||
}
|
||||
@@ -970,14 +781,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
|
||||
} else {
|
||||
startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
|
||||
* SINGLE_FRAME_MS / mTransitionDragLength, 0, mDragLengthFactor);
|
||||
* getSingleFrameMs(mContext) / mTransitionDragLength, 0, mDragLengthFactor);
|
||||
float minFlingVelocity = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_min_velocity);
|
||||
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
|
||||
if (endTarget == RECENTS && mMode != Mode.NO_BUTTON) {
|
||||
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
|
||||
startShift, endShift, endShift, velocityPxPerMs.y,
|
||||
mTransitionDragLength);
|
||||
startShift, endShift, endShift, endVelocity / 1000,
|
||||
mTransitionDragLength, mContext);
|
||||
endShift = overshoot.end;
|
||||
interpolator = overshoot.interpolator;
|
||||
duration = Utilities.boundToRange(overshoot.duration, MIN_OVERSHOOT_DURATION,
|
||||
@@ -1151,57 +962,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
|
||||
* @param homeAnimationFactory The home animation factory.
|
||||
*/
|
||||
private RectFSpringAnim createWindowAnimationToHome(float startProgress,
|
||||
@Override
|
||||
protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
|
||||
HomeAnimationFactory homeAnimationFactory) {
|
||||
final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet;
|
||||
final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet,
|
||||
mTransformParams.setProgress(startProgress), false /* launcherOnTop */));
|
||||
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
|
||||
|
||||
final View floatingView = homeAnimationFactory.getFloatingView();
|
||||
final boolean isFloatingIconView = floatingView instanceof FloatingIconView;
|
||||
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mActivity.getResources());
|
||||
if (isFloatingIconView) {
|
||||
FloatingIconView fiv = (FloatingIconView) floatingView;
|
||||
anim.addAnimatorListener(fiv);
|
||||
fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
}
|
||||
|
||||
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 = mClipAnimationHelper.getCurrentCornerRadius();
|
||||
float endRadius = startRect.width() / 6f;
|
||||
// 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;
|
||||
anim.addOnUpdateListener((currentRect, progress) -> {
|
||||
homeAnim.setPlayFraction(progress);
|
||||
|
||||
float alphaProgress = ACCEL_1_5.getInterpolation(progress);
|
||||
float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0,
|
||||
windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1);
|
||||
mTransformParams.setProgress(progress)
|
||||
.setCurrentRectAndTargetAlpha(currentRect, windowAlpha);
|
||||
if (isFloatingIconView) {
|
||||
mTransformParams.setCornerRadius(endRadius * progress + startRadius
|
||||
* (1f - progress));
|
||||
}
|
||||
mClipAnimationHelper.applyTransform(targetSet, mTransformParams,
|
||||
false /* launcherOnTop */);
|
||||
|
||||
if (isFloatingIconView) {
|
||||
((FloatingIconView) floatingView).update(currentRect, 1f, progress,
|
||||
windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false);
|
||||
}
|
||||
|
||||
updateSysUiFlags(Math.max(progress, mCurrentShift.value));
|
||||
});
|
||||
RectFSpringAnim anim =
|
||||
super.createWindowAnimationToHome(startProgress, homeAnimationFactory);
|
||||
anim.addOnUpdateListener((r, p) -> updateSysUiFlags(Math.max(p, mCurrentShift.value)));
|
||||
anim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
homeAnim.dispatchOnStart();
|
||||
if (mActivity != null) {
|
||||
mActivity.getRootView().getOverlay().remove(mLiveTileOverlay);
|
||||
}
|
||||
@@ -1209,7 +978,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
homeAnim.getAnimationPlayer().end();
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.post(mRecentsView::resetTaskVisuals);
|
||||
}
|
||||
@@ -1221,11 +989,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The GestureEndTarget if the gesture has ended, else null.
|
||||
*/
|
||||
public @Nullable GestureEndTarget getGestureEndTarget() {
|
||||
return mGestureEndTarget;
|
||||
@Override
|
||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
||||
if (mGestureEndTarget != null) {
|
||||
sharedState.canGestureBeContinued = mGestureEndTarget.canBeContinued;
|
||||
sharedState.goingToLauncher = mGestureEndTarget.isLauncher;
|
||||
}
|
||||
|
||||
if (sharedState.canGestureBeContinued) {
|
||||
cancelCurrentAnimation(sharedState);
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -1238,43 +1013,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
|
||||
@UiThread
|
||||
private void startNewTask() {
|
||||
// Launch the task user scrolled to (mRecentsView.getNextPage()).
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// We finish recents animation inside launchTask() when live tile is enabled.
|
||||
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
|
||||
true /* freezeTaskList */);
|
||||
} else {
|
||||
int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
|
||||
mFinishingRecentsAnimationForNewTaskId = taskId;
|
||||
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
if (nextTask != null) {
|
||||
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
|
||||
success -> {
|
||||
if (!success) {
|
||||
// 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();
|
||||
mActivityControlHelper.onLaunchTaskFailed(mActivity);
|
||||
nextTask.notifyTaskLaunchFailed(TAG);
|
||||
updateSysUiFlags(1 /* windowProgress == overview */);
|
||||
} else {
|
||||
mActivityControlHelper.onLaunchTaskSuccess(mActivity);
|
||||
}
|
||||
}, mMainThreadHandler);
|
||||
doLogGesture(NEW_TASK);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
mCanceled = false;
|
||||
mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
});
|
||||
}
|
||||
TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
|
||||
startNewTask(STATE_HANDLER_INVALIDATED, success -> {
|
||||
if (!success) {
|
||||
// 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();
|
||||
updateSysUiFlags(1 /* windowProgress == overview */);
|
||||
}
|
||||
doLogGesture(NEW_TASK);
|
||||
});
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
private void reset() {
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
@@ -1282,7 +1032,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
* Cancels any running animation so that the active target can be overriden by a new swipe
|
||||
* handle (in case of quick switch).
|
||||
*/
|
||||
public void cancelCurrentAnimation(SwipeSharedState sharedState) {
|
||||
private void cancelCurrentAnimation(SwipeSharedState sharedState) {
|
||||
mCanceled = true;
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mLauncherTransitionController != null && mLauncherTransitionController
|
||||
@@ -1305,7 +1055,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
}
|
||||
|
||||
private void invalidateHandler() {
|
||||
endRunningWindowAnim();
|
||||
endRunningWindowAnim(false /* cancel */);
|
||||
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
@@ -1436,7 +1186,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
private void setupLauncherUiAfterSwipeUpToRecentsAnimation() {
|
||||
endLauncherTransitionController();
|
||||
mActivityControlHelper.onSwipeUpToRecentsComplete(mActivity);
|
||||
mRecentsAnimationWrapper.setCancelWithDeferredScreenshot(true);
|
||||
mRecentsAnimationWrapper.setDeferCancelUntilNextTransition(true /* defer */,
|
||||
true /* screenshot */);
|
||||
mRecentsView.onSwipeUpAnimationSuccess();
|
||||
|
||||
RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG);
|
||||
@@ -1445,17 +1196,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
reset();
|
||||
}
|
||||
|
||||
public void setGestureEndCallback(Runnable gestureEndCallback) {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
|
||||
private void setTargetAlphaProvider(
|
||||
BiFunction<RemoteAnimationTargetCompat, Float, Float> provider) {
|
||||
private void setTargetAlphaProvider(TargetAlphaProvider provider) {
|
||||
mClipAnimationHelper.setTaskAlphaCallback(provider);
|
||||
updateFinalShift();
|
||||
}
|
||||
|
||||
public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, Float expectedAlpha) {
|
||||
public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, float expectedAlpha) {
|
||||
if (!isNotInRecents(app)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1466,16 +1212,4 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
return app.isNotInRecents
|
||||
|| app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
}
|
||||
|
||||
private interface RunningWindowAnim {
|
||||
void end();
|
||||
|
||||
static RunningWindowAnim wrap(Animator animator) {
|
||||
return animator::end;
|
||||
}
|
||||
|
||||
static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) {
|
||||
return rectFSpringAnim::end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+56
@@ -17,6 +17,7 @@ package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
@@ -31,6 +32,10 @@ import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
|
||||
@@ -54,6 +59,8 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
private float mZoomScale = 1f;
|
||||
private float mZoomTranslationY = 0f;
|
||||
|
||||
private RunningTaskInfo mRunningTaskInfo;
|
||||
|
||||
public FallbackRecentsView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
@@ -87,6 +94,12 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
resetViewUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
|
||||
LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
|
||||
@@ -114,6 +127,12 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -139,4 +158,41 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
TRANSLATION_Y.set(this, Utilities.mapRange(mZoomInProgress, 0, mZoomTranslationY));
|
||||
FULLSCREEN_PROGRESS.set(this, mZoomInProgress);
|
||||
}
|
||||
|
||||
public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
|
||||
mRunningTaskInfo = runningTaskInfo;
|
||||
onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentTask(int runningTaskId) {
|
||||
super.setCurrentTask(runningTaskId);
|
||||
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId != runningTaskId) {
|
||||
mRunningTaskInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyLoadPlan(ArrayList<Task> tasks) {
|
||||
// When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
|
||||
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
|
||||
// track the index of the next task appropriately, as it we are switching on any other app.
|
||||
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
|
||||
// Check if the task list has running task
|
||||
boolean found = false;
|
||||
for (Task t : tasks) {
|
||||
if (t.key.id == mRunningTaskId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ArrayList<Task> newList = new ArrayList<>(tasks.size() + 1);
|
||||
newList.addAll(tasks);
|
||||
newList.add(Task.from(new TaskKey(mRunningTaskInfo), mRunningTaskInfo, false));
|
||||
tasks = newList;
|
||||
}
|
||||
}
|
||||
super.applyLoadPlan(tasks);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-5
@@ -23,6 +23,7 @@ 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.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -44,8 +45,6 @@ import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.RecentsAnimationListenerSet;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
@@ -209,9 +208,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
|
||||
mInputMonitorCompat.pilferPointers();
|
||||
BackgroundExecutor.get().submit(
|
||||
() -> ActivityManagerWrapper.getInstance().startRecentsActivity(
|
||||
intent, null, newListenerSet, null, null));
|
||||
startRecentsActivityAsync(intent, newListenerSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+379
-280
@@ -15,344 +15,443 @@
|
||||
*/
|
||||
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_POINTER_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.MotionEvent.INVALID_POINTER_ID;
|
||||
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.MAX_SWIPE_DURATION;
|
||||
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.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_SWIPE_DURATION;
|
||||
import static com.android.quickstep.inputconsumers.OtherActivityInputConsumer.QUICKSTEP_TOUCH_SLOP_RATIO;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.ActivityControlHelper;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.BaseSwipeUpHandler;
|
||||
import com.android.quickstep.MultiStateCallback;
|
||||
import com.android.quickstep.OverviewComponentObserver;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.NavBarPosition;
|
||||
import com.android.quickstep.util.RecentsAnimationListenerSet;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.ObjectWrapper;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
|
||||
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.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
|
||||
public class FallbackNoButtonInputConsumer implements InputConsumer, SwipeAnimationListener {
|
||||
public class FallbackNoButtonInputConsumer extends
|
||||
BaseSwipeUpHandler<RecentsActivity, FallbackRecentsView> {
|
||||
|
||||
private static final int STATE_NOT_FINISHED = 0;
|
||||
private static final int STATE_FINISHED_TO_HOME = 1;
|
||||
private static final int STATE_FINISHED_TO_APP = 2;
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
|
||||
|
||||
private static final float PROGRESS_TO_END_GESTURE = -2;
|
||||
private static int getFlagForIndex(int index, String name) {
|
||||
if (DEBUG_STATES) {
|
||||
STATE_NAMES[index] = name;
|
||||
}
|
||||
return 1 << index;
|
||||
}
|
||||
|
||||
private final ActivityControlHelper mActivityControlHelper;
|
||||
private final InputMonitorCompat mInputMonitor;
|
||||
private final Context mContext;
|
||||
private final NavBarPosition mNavBarPosition;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
private final OverviewComponentObserver mOverviewComponentObserver;
|
||||
private final int mRunningTaskId;
|
||||
private static final int STATE_RECENTS_PRESENT =
|
||||
getFlagForIndex(0, "STATE_RECENTS_PRESENT");
|
||||
private static final int STATE_HANDLER_INVALIDATED =
|
||||
getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
|
||||
|
||||
private final ClipAnimationHelper mClipAnimationHelper;
|
||||
private final TransformParams mTransformParams = new TransformParams();
|
||||
private final float mTransitionDragLength;
|
||||
private final DeviceProfile mDP;
|
||||
private static final int STATE_GESTURE_CANCELLED =
|
||||
getFlagForIndex(2, "STATE_GESTURE_CANCELLED");
|
||||
private static final int STATE_GESTURE_COMPLETED =
|
||||
getFlagForIndex(3, "STATE_GESTURE_COMPLETED");
|
||||
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
||||
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
|
||||
|
||||
private final RectF mSwipeTouchRegion;
|
||||
private final boolean mDisableHorizontalSwipe;
|
||||
public enum GestureEndTarget {
|
||||
HOME(3, 100, 1),
|
||||
RECENTS(1, 300, 0),
|
||||
LAST_TASK(0, 150, 1),
|
||||
NEW_TASK(0, 150, 1);
|
||||
|
||||
private final PointF mDownPos = new PointF();
|
||||
private final PointF mLastPos = new PointF();
|
||||
private final float mEndProgress;
|
||||
private final long mDurationMultiplier;
|
||||
private final float mLauncherAlpha;
|
||||
|
||||
private int mActivePointerId = -1;
|
||||
// Slop used to determine when we say that the gesture has started.
|
||||
private boolean mPassedPilferInputSlop;
|
||||
GestureEndTarget(float endProgress, long durationMultiplier, float launcherAlpha) {
|
||||
mEndProgress = endProgress;
|
||||
mDurationMultiplier = durationMultiplier;
|
||||
mLauncherAlpha = launcherAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
private VelocityTracker mVelocityTracker;
|
||||
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
|
||||
|
||||
// Distance after which we start dragging the window.
|
||||
private final float mTouchSlop;
|
||||
private boolean mIsMotionPaused = false;
|
||||
private GestureEndTarget mEndTarget;
|
||||
|
||||
// Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
|
||||
private float mStartDisplacement;
|
||||
private SwipeAnimationTargetSet mSwipeAnimationTargetSet;
|
||||
private float mProgress;
|
||||
private final boolean mInQuickSwitchMode;
|
||||
private final boolean mContinuingLastGesture;
|
||||
private final boolean mRunningOverHome;
|
||||
private final boolean mSwipeUpOverHome;
|
||||
|
||||
private int mState = STATE_NOT_FINISHED;
|
||||
private final RunningTaskInfo mRunningTaskInfo;
|
||||
|
||||
private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
|
||||
private RunningWindowAnim mFinishAnimation;
|
||||
|
||||
public FallbackNoButtonInputConsumer(Context context,
|
||||
ActivityControlHelper activityControlHelper, InputMonitorCompat inputMonitor,
|
||||
SwipeSharedState swipeSharedState, RectF swipeTouchRegion,
|
||||
OverviewComponentObserver overviewComponentObserver,
|
||||
boolean disableHorizontalSwipe, RunningTaskInfo runningTaskInfo) {
|
||||
mContext = context;
|
||||
mActivityControlHelper = activityControlHelper;
|
||||
mInputMonitor = inputMonitor;
|
||||
mOverviewComponentObserver = overviewComponentObserver;
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
RunningTaskInfo runningTaskInfo, RecentsModel recentsModel,
|
||||
InputConsumerController inputConsumer,
|
||||
boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
|
||||
super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
|
||||
mLauncherAlpha.value = 1;
|
||||
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
mSwipeTouchRegion = swipeTouchRegion;
|
||||
mDisableHorizontalSwipe = disableHorizontalSwipe;
|
||||
mRunningTaskInfo = runningTaskInfo;
|
||||
mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mRunningOverHome = ActivityManagerWrapper.isHomeTask(runningTaskInfo);
|
||||
mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
|
||||
|
||||
mNavBarPosition = new NavBarPosition(context);
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
|
||||
mTouchSlop = QUICKSTEP_TOUCH_SLOP_RATIO
|
||||
* ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
|
||||
mClipAnimationHelper = new ClipAnimationHelper(context);
|
||||
|
||||
mDP = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context).copy(context);
|
||||
Rect tempRect = new Rect();
|
||||
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
|
||||
mDP, context, tempRect);
|
||||
mClipAnimationHelper.updateTargetRect(tempRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return TYPE_FALLBACK_NO_BUTTON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionEvent(MotionEvent ev) {
|
||||
if (mVelocityTracker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVelocityTracker.addMovement(ev);
|
||||
if (ev.getActionMasked() == ACTION_POINTER_UP) {
|
||||
mVelocityTracker.clear();
|
||||
}
|
||||
|
||||
switch (ev.getActionMasked()) {
|
||||
case ACTION_DOWN: {
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
mDownPos.set(ev.getX(), ev.getY());
|
||||
mLastPos.set(mDownPos);
|
||||
break;
|
||||
}
|
||||
case ACTION_POINTER_DOWN: {
|
||||
if (!mPassedPilferInputSlop) {
|
||||
// Cancel interaction in case of multi-touch interaction
|
||||
int ptrIdx = ev.getActionIndex();
|
||||
if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
|
||||
forceCancelGesture(ev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_POINTER_UP: {
|
||||
int ptrIdx = ev.getActionIndex();
|
||||
int ptrId = ev.getPointerId(ptrIdx);
|
||||
if (ptrId == mActivePointerId) {
|
||||
final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
|
||||
mDownPos.set(
|
||||
ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
|
||||
ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
|
||||
mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
|
||||
mActivePointerId = ev.getPointerId(newPointerIdx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_MOVE: {
|
||||
int pointerIndex = ev.findPointerIndex(mActivePointerId);
|
||||
if (pointerIndex == INVALID_POINTER_ID) {
|
||||
break;
|
||||
}
|
||||
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
|
||||
float displacement = getDisplacement(ev);
|
||||
|
||||
if (!mPassedPilferInputSlop) {
|
||||
if (mDisableHorizontalSwipe && Math.abs(mLastPos.x - mDownPos.x)
|
||||
> Math.abs(mLastPos.y - mDownPos.y)) {
|
||||
// Horizontal gesture is not allowed in this region
|
||||
forceCancelGesture(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Math.abs(displacement) >= mTouchSlop) {
|
||||
mPassedPilferInputSlop = true;
|
||||
|
||||
// Deferred gesture, start the animation and gesture tracking once
|
||||
// we pass the actual touch slop
|
||||
startTouchTrackingForWindowAnimation(displacement);
|
||||
}
|
||||
} else {
|
||||
updateDisplacement(displacement - mStartDisplacement);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_CANCEL:
|
||||
case ACTION_UP: {
|
||||
finishTouchTracking(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startTouchTrackingForWindowAnimation(float displacement) {
|
||||
mStartDisplacement = Math.min(displacement, -mTouchSlop);
|
||||
|
||||
RecentsAnimationListenerSet listenerSet =
|
||||
mSwipeSharedState.newRecentsAnimationListenerSet();
|
||||
listenerSet.addListener(this);
|
||||
Intent homeIntent = mOverviewComponentObserver.getHomeIntent();
|
||||
BackgroundExecutor.get().submit(
|
||||
() -> ActivityManagerWrapper.getInstance().startRecentsActivity(
|
||||
homeIntent, null, listenerSet, null, null));
|
||||
|
||||
ActivityManagerWrapper.getInstance().closeSystemWindows(
|
||||
CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
|
||||
mInputMonitor.pilferPointers();
|
||||
}
|
||||
|
||||
private void updateDisplacement(float displacement) {
|
||||
mProgress = displacement / mTransitionDragLength;
|
||||
mTransformParams.setProgress(mProgress);
|
||||
|
||||
if (mSwipeAnimationTargetSet != null) {
|
||||
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
|
||||
}
|
||||
}
|
||||
|
||||
private void forceCancelGesture(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
ev.setAction(ACTION_CANCEL);
|
||||
finishTouchTracking(ev);
|
||||
ev.setAction(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the gesture has ended. Does not correlate to the completion of the interaction as
|
||||
* the animation can still be running.
|
||||
*/
|
||||
private void finishTouchTracking(MotionEvent ev) {
|
||||
if (ev.getAction() == ACTION_CANCEL) {
|
||||
mState = STATE_FINISHED_TO_APP;
|
||||
if (mSwipeUpOverHome) {
|
||||
mClipAnimationHelper.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
|
||||
} else {
|
||||
mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
||||
}
|
||||
|
||||
initStateCallbacks();
|
||||
}
|
||||
|
||||
private void initStateCallbacks() {
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES);
|
||||
|
||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidated);
|
||||
mStateCallback.addCallback(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidatedWithRecents);
|
||||
|
||||
mStateCallback.addCallback(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSetAnimationComplete);
|
||||
|
||||
if (mInQuickSwitchMode) {
|
||||
mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
|
||||
| STATE_RECENTS_PRESENT,
|
||||
this::finishAnimationTargetSet);
|
||||
} else {
|
||||
mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSet);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLauncherAlphaChanged() {
|
||||
if (mRecentsAnimationWrapper.targetSet != null && mEndTarget == null) {
|
||||
applyTransformUnchecked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onActivityInit(final RecentsActivity activity, Boolean alreadyOnHome) {
|
||||
mActivity = activity;
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
linkRecentsViewScroll();
|
||||
mRecentsView.setDisallowScrollToClearAll(true);
|
||||
mRecentsView.getClearAllButton().setVisibilityAlpha(0);
|
||||
|
||||
mRecentsView.setZoomProgress(1);
|
||||
|
||||
if (!mContinuingLastGesture) {
|
||||
if (mRunningOverHome) {
|
||||
mRecentsView.onGestureAnimationStart(mRunningTaskInfo);
|
||||
} else {
|
||||
mRecentsView.onGestureAnimationStart(mRunningTaskId);
|
||||
}
|
||||
}
|
||||
setStateOnUiThread(STATE_RECENTS_PRESENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mInQuickSwitchMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initWhenReady() {
|
||||
if (mInQuickSwitchMode) {
|
||||
// Only init if we are in quickswitch mode
|
||||
super.initWhenReady();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplacement(float displacement) {
|
||||
if (!mInQuickSwitchMode) {
|
||||
super.updateDisplacement(displacement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
// Just consume all input on the active task
|
||||
return InputConsumer.NO_OP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
if (!mInQuickSwitchMode) {
|
||||
mIsMotionPaused = isPaused;
|
||||
mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
|
||||
.setDuration(150).start();
|
||||
performHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getLaunchIntent() {
|
||||
if (mInQuickSwitchMode || mSwipeUpOverHome) {
|
||||
return mOverviewComponentObserver.getOverviewIntent();
|
||||
} else {
|
||||
return mOverviewComponentObserver.getHomeIntent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
mTransformParams.setProgress(mCurrentShift.value);
|
||||
mRecentsAnimationWrapper.setWindowThresholdCrossed(!mInQuickSwitchMode
|
||||
&& (mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD));
|
||||
if (mRecentsAnimationWrapper.targetSet != null) {
|
||||
applyTransformUnchecked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
mEndTarget = LAST_TASK;
|
||||
setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
|
||||
mEndVelocityPxPerMs.set(0, velocity.y / 1000);
|
||||
if (mInQuickSwitchMode) {
|
||||
// For now set it to non-null, it will be reset before starting the animation
|
||||
mEndTarget = LAST_TASK;
|
||||
} else {
|
||||
mVelocityTracker.computeCurrentVelocity(1000,
|
||||
ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
|
||||
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
|
||||
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
|
||||
float velocity = mNavBarPosition.isRightEdge() ? velocityX
|
||||
: mNavBarPosition.isLeftEdge() ? -velocityX
|
||||
: velocityY;
|
||||
float flingThreshold = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = Math.abs(velocity) > flingThreshold;
|
||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||
|
||||
boolean goingHome;
|
||||
if (!isFling) {
|
||||
goingHome = -mProgress >= MIN_PROGRESS_FOR_OVERVIEW;
|
||||
if (isFling) {
|
||||
mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
|
||||
} else if (mIsMotionPaused) {
|
||||
mEndTarget = RECENTS;
|
||||
} else {
|
||||
goingHome = velocity < 0;
|
||||
mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
|
||||
}
|
||||
}
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
||||
if (mInQuickSwitchMode && mEndTarget != null) {
|
||||
sharedState.canGestureBeContinued = true;
|
||||
sharedState.goingToLauncher = false;
|
||||
|
||||
mCanceled = true;
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mFinishAnimation != null) {
|
||||
mFinishAnimation.cancel();
|
||||
}
|
||||
|
||||
if (goingHome) {
|
||||
mState = STATE_FINISHED_TO_HOME;
|
||||
} else {
|
||||
mState = STATE_FINISHED_TO_APP;
|
||||
if (mRecentsView != null) {
|
||||
if (mFinishingRecentsAnimationForNewTaskId != -1) {
|
||||
TaskView newRunningTaskView = mRecentsView.getTaskView(
|
||||
mFinishingRecentsAnimationForNewTaskId);
|
||||
int newRunningTaskId = newRunningTaskView != null
|
||||
? newRunningTaskView.getTask().key.id
|
||||
: -1;
|
||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||
sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
|
||||
}
|
||||
mRecentsView.setOnScrollChangeListener(null);
|
||||
}
|
||||
} else {
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandlerInvalidated() {
|
||||
mActivityInitListener.unregister();
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
if (mFinishAnimation != null) {
|
||||
mFinishAnimation.end();
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandlerInvalidatedWithRecents() {
|
||||
mRecentsView.onGestureAnimationEnd();
|
||||
mRecentsView.setDisallowScrollToClearAll(false);
|
||||
mRecentsView.getClearAllButton().setVisibilityAlpha(1);
|
||||
}
|
||||
|
||||
private void finishAnimationTargetSetAnimationComplete() {
|
||||
switch (mEndTarget) {
|
||||
case HOME: {
|
||||
if (mSwipeUpOverHome) {
|
||||
mRecentsAnimationWrapper.finish(false, null, false);
|
||||
// Send a home intent to clear the task stack
|
||||
mContext.startActivity(mOverviewComponentObserver.getHomeIntent());
|
||||
} else {
|
||||
mRecentsAnimationWrapper.finish(true, null, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LAST_TASK:
|
||||
mRecentsAnimationWrapper.finish(false, null, false);
|
||||
break;
|
||||
case RECENTS: {
|
||||
if (mSwipeUpOverHome) {
|
||||
mRecentsAnimationWrapper.finish(true, null, true);
|
||||
break;
|
||||
}
|
||||
|
||||
ThumbnailData thumbnail =
|
||||
mRecentsAnimationWrapper.targetSet.controller.screenshotTask(mRunningTaskId);
|
||||
mRecentsAnimationWrapper.setDeferCancelUntilNextTransition(true /* defer */,
|
||||
false /* screenshot */);
|
||||
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
ActivityOptionsCompat.setFreezeRecentTasksList(options);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
|
||||
extras.putInt(EXTRA_TASK_ID, mRunningTaskId);
|
||||
|
||||
Intent intent = new Intent(mOverviewComponentObserver.getOverviewIntent())
|
||||
.putExtras(extras);
|
||||
mContext.startActivity(intent, options.toBundle());
|
||||
mRecentsAnimationWrapper.targetSet.controller.cleanupScreenshot();
|
||||
break;
|
||||
}
|
||||
case NEW_TASK: {
|
||||
startNewTask(STATE_HANDLER_INVALIDATED, b -> {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSwipeAnimationTargetSet != null) {
|
||||
finishAnimationTargetSet();
|
||||
}
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
private void finishAnimationTargetSet() {
|
||||
if (mState == STATE_FINISHED_TO_APP) {
|
||||
mSwipeAnimationTargetSet.finishController(false, null, false);
|
||||
} else {
|
||||
if (mProgress < PROGRESS_TO_END_GESTURE) {
|
||||
mSwipeAnimationTargetSet.finishController(true, null, true);
|
||||
if (mInQuickSwitchMode) {
|
||||
// Recalculate the end target, some views might have been initialized after
|
||||
// gesture has ended.
|
||||
if (mRecentsView == null || !mRecentsAnimationWrapper.hasTargets()) {
|
||||
mEndTarget = LAST_TASK;
|
||||
} else {
|
||||
long duration = (long) (Math.min(mProgress - PROGRESS_TO_END_GESTURE, 1)
|
||||
* MAX_SWIPE_DURATION / Math.abs(PROGRESS_TO_END_GESTURE));
|
||||
if (duration < 0) {
|
||||
duration = MIN_SWIPE_DURATION;
|
||||
}
|
||||
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(mProgress, PROGRESS_TO_END_GESTURE);
|
||||
anim.addUpdateListener(a -> {
|
||||
float p = (Float) anim.getAnimatedValue();
|
||||
mTransformParams.setProgress(p);
|
||||
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
|
||||
});
|
||||
anim.setDuration(duration);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mSwipeAnimationTargetSet.finishController(true, null, true);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||
final int taskToLaunch = mRecentsView.getNextPage();
|
||||
mEndTarget = (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||
? NEW_TASK : LAST_TASK;
|
||||
}
|
||||
}
|
||||
|
||||
float endProgress = mEndTarget.mEndProgress;
|
||||
long duration = (long) (mEndTarget.mDurationMultiplier *
|
||||
Math.abs(endProgress - mCurrentShift.value));
|
||||
if (mRecentsView != null) {
|
||||
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
|
||||
}
|
||||
if (mCurrentShift.value != endProgress || mInQuickSwitchMode) {
|
||||
AnimationSuccessListener endListener = new AnimationSuccessListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
mFinishAnimation = null;
|
||||
}
|
||||
};
|
||||
|
||||
if (mEndTarget == HOME && !mRunningOverHome) {
|
||||
RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration);
|
||||
anim.addAnimatorListener(endListener);
|
||||
anim.start(mEndVelocityPxPerMs);
|
||||
mFinishAnimation = RunningWindowAnim.wrap(anim);
|
||||
} else {
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(mLauncherAlpha.animateToValue(
|
||||
mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
|
||||
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
|
||||
|
||||
anim.setDuration(duration);
|
||||
anim.addListener(endListener);
|
||||
anim.start();
|
||||
mFinishAnimation = RunningWindowAnim.wrap(anim);
|
||||
}
|
||||
|
||||
} else {
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
|
||||
mSwipeAnimationTargetSet = targetSet;
|
||||
Rect overviewStackBounds = new Rect(0, 0, mDP.widthPx, mDP.heightPx);
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
|
||||
super.onRecentsAnimationStart(targetSet);
|
||||
mRecentsAnimationWrapper.enableInputConsumer();
|
||||
|
||||
mDP.updateIsSeascape(mContext.getSystemService(WindowManager.class));
|
||||
if (runningTaskTarget != null) {
|
||||
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
|
||||
if (mRunningOverHome) {
|
||||
mClipAnimationHelper.prepareAnimation(mDp, true);
|
||||
}
|
||||
mClipAnimationHelper.prepareAnimation(mDP, false /* isOpening */);
|
||||
applyTransformUnchecked();
|
||||
|
||||
overviewStackBounds
|
||||
.inset(-overviewStackBounds.width() / 5, -overviewStackBounds.height() / 5);
|
||||
mClipAnimationHelper.updateTargetRect(overviewStackBounds);
|
||||
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
|
||||
|
||||
if (mState != STATE_NOT_FINISHED) {
|
||||
finishAnimationTargetSet();
|
||||
}
|
||||
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled() { }
|
||||
|
||||
private float getDisplacement(MotionEvent ev) {
|
||||
if (mNavBarPosition.isRightEdge()) {
|
||||
return ev.getX() - mDownPos.x;
|
||||
} else if (mNavBarPosition.isLeftEdge()) {
|
||||
return mDownPos.x - ev.getX();
|
||||
} else {
|
||||
return ev.getY() - mDownPos.y;
|
||||
}
|
||||
public void onRecentsAnimationCanceled() {
|
||||
mRecentsAnimationWrapper.setController(null);
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInterceptByParent() {
|
||||
return !mPassedPilferInputSlop;
|
||||
/**
|
||||
* 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() {
|
||||
return HomeAnimationFactory.getDefaultWindowTargetRect(mDp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(mLauncherAlpha.animateToValue(mLauncherAlpha.value, 1));
|
||||
anim.setDuration(duration);
|
||||
return AnimatorPlaybackController.wrap(anim, duration);
|
||||
}
|
||||
};
|
||||
return createWindowAnimationToHome(startProgress, factory);
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -33,7 +33,6 @@ public interface InputConsumer {
|
||||
int TYPE_SCREEN_PINNED = 1 << 6;
|
||||
int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
|
||||
int TYPE_RESET_GESTURE = 1 << 8;
|
||||
int TYPE_FALLBACK_NO_BUTTON = 1 << 9;
|
||||
|
||||
String[] NAMES = new String[] {
|
||||
"TYPE_NO_OP", // 0
|
||||
@@ -45,7 +44,6 @@ public interface InputConsumer {
|
||||
"TYPE_SCREEN_PINNED", // 6
|
||||
"TYPE_OVERVIEW_WITHOUT_FOCUS", // 7
|
||||
"TYPE_RESET_GESTURE", // 8
|
||||
"TYPE_FALLBACK_NO_BUTTON", // 9
|
||||
};
|
||||
|
||||
InputConsumer NO_OP = () -> TYPE_NO_OP;
|
||||
|
||||
+30
-50
@@ -28,13 +28,13 @@ import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
|
||||
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
|
||||
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
|
||||
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
@@ -48,21 +48,16 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.launcher3.util.RaceConditionTracker;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.ActivityControlHelper;
|
||||
import com.android.quickstep.BaseSwipeUpHandler;
|
||||
import com.android.quickstep.OverviewCallbacks;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
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;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -83,16 +78,14 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
|
||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||
private final RunningTaskInfo mRunningTask;
|
||||
private final RecentsModel mRecentsModel;
|
||||
private final Intent mHomeIntent;
|
||||
private final ActivityControlHelper mActivityControlHelper;
|
||||
private final OverviewCallbacks mOverviewCallbacks;
|
||||
private final InputConsumerController mInputConsumer;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
private final InputMonitorCompat mInputMonitorCompat;
|
||||
private final SysUINavigationMode.Mode mMode;
|
||||
private final RectF mSwipeTouchRegion;
|
||||
|
||||
private final BaseSwipeUpHandler.Factory mHandlerFactory;
|
||||
|
||||
private final NavBarPosition mNavBarPosition;
|
||||
|
||||
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
|
||||
@@ -100,7 +93,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
private final float mMotionPauseMinDisplacement;
|
||||
private VelocityTracker mVelocityTracker;
|
||||
|
||||
private WindowTransformSwipeHandler mInteractionHandler;
|
||||
private BaseSwipeUpHandler mInteractionHandler;
|
||||
|
||||
private final boolean mIsDeferredDownTarget;
|
||||
private final PointF mDownPos = new PointF();
|
||||
@@ -114,7 +107,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
private final boolean mDisableHorizontalSwipe;
|
||||
|
||||
// Slop used to check when we start moving window.
|
||||
private boolean mPaddedWindowMoveSlop;
|
||||
private boolean mPassedWindowMoveSlop;
|
||||
// Slop used to determine when we say that the gesture has started.
|
||||
private boolean mPassedPilferInputSlop;
|
||||
|
||||
@@ -128,20 +121,18 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
};
|
||||
|
||||
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
|
||||
RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
|
||||
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
|
||||
InputConsumerController inputConsumer,
|
||||
Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
||||
RectF swipeTouchRegion, boolean disableHorizontalSwipe) {
|
||||
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
|
||||
BaseSwipeUpHandler.Factory handlerFactory) {
|
||||
super(base);
|
||||
|
||||
mMainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
mRunningTask = runningTaskInfo;
|
||||
mRecentsModel = recentsModel;
|
||||
mHomeIntent = homeIntent;
|
||||
mMode = SysUINavigationMode.getMode(base);
|
||||
mSwipeTouchRegion = swipeTouchRegion;
|
||||
mHandlerFactory = handlerFactory;
|
||||
|
||||
mMotionPauseDetector = new MotionPauseDetector(base);
|
||||
mMotionPauseMinDisplacement = base.getResources().getDimension(
|
||||
@@ -150,11 +141,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
mInputMonitorCompat = inputMonitorCompat;
|
||||
|
||||
mActivityControlHelper = activityControl;
|
||||
boolean continuingPreviousGesture = swipeSharedState.getActiveListener() != null;
|
||||
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
|
||||
mOverviewCallbacks = overviewCallbacks;
|
||||
mInputConsumer = inputConsumer;
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
|
||||
mNavBarPosition = new NavBarPosition(base);
|
||||
@@ -163,7 +152,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
float slop = QUICKSTEP_TOUCH_SLOP_RATIO * mTouchSlop;
|
||||
mSquaredTouchSlop = slop * slop;
|
||||
|
||||
mPassedPilferInputSlop = mPaddedWindowMoveSlop = continuingPreviousGesture;
|
||||
mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
|
||||
mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
|
||||
}
|
||||
|
||||
@@ -186,7 +175,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
}
|
||||
|
||||
// Proxy events to recents view
|
||||
if (mPaddedWindowMoveSlop && mInteractionHandler != null
|
||||
if (mPassedWindowMoveSlop && mInteractionHandler != null
|
||||
&& !mRecentsViewDispatcher.hasConsumer()) {
|
||||
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
|
||||
mNavBarPosition.getRotationMode()));
|
||||
@@ -213,7 +202,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
// Start the window animation on down to give more time for launcher to draw if the
|
||||
// user didn't start the gesture over the back button
|
||||
if (!mIsDeferredDownTarget) {
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime(), false);
|
||||
}
|
||||
|
||||
RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
|
||||
@@ -251,17 +240,21 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
float displacement = getDisplacement(ev);
|
||||
float displacementX = mLastPos.x - mDownPos.x;
|
||||
|
||||
if (!mPaddedWindowMoveSlop) {
|
||||
if (!mPassedWindowMoveSlop) {
|
||||
if (!mIsDeferredDownTarget) {
|
||||
// Normal gesture, ensure we pass the drag slop before we start tracking
|
||||
// the gesture
|
||||
if (Math.abs(displacement) > mTouchSlop) {
|
||||
mPaddedWindowMoveSlop = true;
|
||||
mPassedWindowMoveSlop = true;
|
||||
mStartDisplacement = Math.min(displacement, -mTouchSlop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float horizontalDist = Math.abs(displacementX);
|
||||
float upDist = -displacement;
|
||||
boolean isLikelyToStartNewTask = horizontalDist > upDist;
|
||||
|
||||
if (!mPassedPilferInputSlop) {
|
||||
float displacementY = mLastPos.y - mDownPos.y;
|
||||
if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
|
||||
@@ -277,10 +270,11 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
if (mIsDeferredDownTarget) {
|
||||
// Deferred gesture, start the animation and gesture tracking once
|
||||
// we pass the actual touch slop
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
startTouchTrackingForWindowAnimation(
|
||||
ev.getEventTime(), isLikelyToStartNewTask);
|
||||
}
|
||||
if (!mPaddedWindowMoveSlop) {
|
||||
mPaddedWindowMoveSlop = true;
|
||||
if (!mPassedWindowMoveSlop) {
|
||||
mPassedWindowMoveSlop = true;
|
||||
mStartDisplacement = Math.min(displacement, -mTouchSlop);
|
||||
|
||||
}
|
||||
@@ -289,15 +283,12 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
}
|
||||
|
||||
if (mInteractionHandler != null) {
|
||||
if (mPaddedWindowMoveSlop) {
|
||||
if (mPassedWindowMoveSlop) {
|
||||
// Move
|
||||
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
|
||||
}
|
||||
|
||||
if (mMode == Mode.NO_BUTTON) {
|
||||
float horizontalDist = Math.abs(displacementX);
|
||||
float upDist = -displacement;
|
||||
boolean isLikelyToStartNewTask = horizontalDist > upDist;
|
||||
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|
||||
|| isLikelyToStartNewTask);
|
||||
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
|
||||
@@ -329,16 +320,14 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
mInteractionHandler.onGestureStarted();
|
||||
}
|
||||
|
||||
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
|
||||
private void startTouchTrackingForWindowAnimation(
|
||||
long touchTimeMs, boolean isLikelyToStartNewTask) {
|
||||
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
|
||||
|
||||
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
|
||||
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
|
||||
mRunningTask, this, touchTimeMs, mActivityControlHelper,
|
||||
listenerSet != null, mInputConsumer);
|
||||
final BaseSwipeUpHandler handler = mHandlerFactory.newHandler(mRunningTask, touchTimeMs,
|
||||
listenerSet != null, isLikelyToStartNewTask);
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.getTasks(null);
|
||||
mInteractionHandler = handler;
|
||||
handler.setGestureEndCallback(this::onInteractionGestureFinished);
|
||||
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
|
||||
@@ -352,9 +341,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
RecentsAnimationListenerSet newListenerSet =
|
||||
mSwipeSharedState.newRecentsAnimationListenerSet();
|
||||
newListenerSet.addListener(handler);
|
||||
BackgroundExecutor.get().submit(
|
||||
() -> ActivityManagerWrapper.getInstance().startRecentsActivity(
|
||||
mHomeIntent, null, newListenerSet, null, null));
|
||||
startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +353,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
RaceConditionTracker.onEvent(UP_EVT, ENTER);
|
||||
TraceHelper.endSection("TouchInt");
|
||||
|
||||
if (mPaddedWindowMoveSlop && mInteractionHandler != null) {
|
||||
if (mPassedWindowMoveSlop && mInteractionHandler != null) {
|
||||
if (ev.getActionMasked() == ACTION_CANCEL) {
|
||||
mInteractionHandler.onGestureCancelled();
|
||||
} else {
|
||||
@@ -409,14 +396,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
// The consumer is being switched while we are active. Set up the shared state to be
|
||||
// used by the next animation
|
||||
removeListener();
|
||||
GestureEndTarget endTarget = mInteractionHandler.getGestureEndTarget();
|
||||
mSwipeSharedState.canGestureBeContinued = endTarget != null && endTarget.canBeContinued;
|
||||
mSwipeSharedState.goingToLauncher = endTarget != null && endTarget.isLauncher;
|
||||
if (mSwipeSharedState.canGestureBeContinued) {
|
||||
mInteractionHandler.cancelCurrentAnimation(mSwipeSharedState);
|
||||
} else {
|
||||
mInteractionHandler.reset();
|
||||
}
|
||||
mInteractionHandler.onConsumerAboutToBeSwitched(mSwipeSharedState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -19,6 +19,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
|
||||
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
|
||||
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;
|
||||
|
||||
@@ -26,6 +27,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.OverviewCallbacks;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
|
||||
+15
@@ -30,7 +30,13 @@ import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.logging.StatsLogUtils;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.quickstep.OverviewCallbacks;
|
||||
import com.android.quickstep.util.NavBarPosition;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
@@ -131,12 +137,14 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer {
|
||||
? -velocityX : (mNavBarPosition.isLeftEdge() ? velocityX : -velocityY);
|
||||
|
||||
final boolean triggerQuickstep;
|
||||
int touch = Touch.FLING;
|
||||
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;
|
||||
touch = Touch.SWIPE;
|
||||
}
|
||||
|
||||
if (triggerQuickstep) {
|
||||
@@ -144,6 +152,13 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer {
|
||||
ActivityManagerWrapper.getInstance()
|
||||
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
|
||||
TOUCH_INTERACTION_LOG.addLog("startQuickstep");
|
||||
BaseActivity activity = BaseDraggingActivity.fromContext(mContext);
|
||||
int pageIndex = -1; // This number doesn't reflect workspace page index.
|
||||
// It only indicates that launcher client screen was shown.
|
||||
int containerType = StatsLogUtils.getContainerTypeFromState(activity.getCurrentState());
|
||||
activity.getUserEventDispatcher().logActionOnContainer(
|
||||
touch, Direction.UP, containerType, pageIndex);
|
||||
activity.getUserEventDispatcher().setPreviousHomeGesture(true);
|
||||
} else {
|
||||
// ignore
|
||||
}
|
||||
|
||||
+24
-10
@@ -99,8 +99,8 @@ public class ClipAnimationHelper {
|
||||
// Whether to boost the opening animation target layers, or the closing
|
||||
private int mBoostModeTargetLayers = -1;
|
||||
|
||||
private BiFunction<RemoteAnimationTargetCompat, Float, Float> mTaskAlphaCallback =
|
||||
(t, a1) -> a1;
|
||||
private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
|
||||
private TargetAlphaProvider mBaseAlphaCallback = (t, a) -> 1;
|
||||
|
||||
public ClipAnimationHelper(Context context) {
|
||||
mWindowCornerRadius = getWindowCornerRadius(context.getResources());
|
||||
@@ -119,8 +119,12 @@ public class ClipAnimationHelper {
|
||||
}
|
||||
|
||||
public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
|
||||
mHomeStackBounds.set(homeStackBounds);
|
||||
updateSourceStack(target);
|
||||
updateHomeBounds(homeStackBounds);
|
||||
}
|
||||
|
||||
public void updateHomeBounds(Rect homeStackBounds) {
|
||||
mHomeStackBounds.set(homeStackBounds);
|
||||
}
|
||||
|
||||
public void updateTargetRect(Rect targetRect) {
|
||||
@@ -187,12 +191,12 @@ public class ClipAnimationHelper {
|
||||
Rect crop = mTmpRect;
|
||||
crop.set(app.sourceContainerBounds);
|
||||
crop.offsetTo(0, 0);
|
||||
float alpha = 1f;
|
||||
float alpha;
|
||||
int layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
|
||||
float cornerRadius = 0f;
|
||||
float scale = Math.max(params.currentRect.width(), mTargetRect.width()) / crop.width();
|
||||
if (app.mode == targetSet.targetMode) {
|
||||
alpha = mTaskAlphaCallback.apply(app, params.targetAlpha);
|
||||
alpha = mTaskAlphaCallback.getAlpha(app, params.targetAlpha);
|
||||
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL);
|
||||
mTmpMatrix.postTranslate(app.position.x, app.position.y);
|
||||
@@ -214,9 +218,12 @@ public class ClipAnimationHelper {
|
||||
// home target.
|
||||
alpha = 1 - (progress * params.targetAlpha);
|
||||
}
|
||||
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && launcherOnTop) {
|
||||
crop = null;
|
||||
layer = Integer.MAX_VALUE;
|
||||
} else {
|
||||
alpha = mBaseAlphaCallback.getAlpha(app, progress);
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && launcherOnTop) {
|
||||
crop = null;
|
||||
layer = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Since radius is in Surface space, but we draw the rounded corners in screen space, we
|
||||
@@ -247,11 +254,14 @@ public class ClipAnimationHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void setTaskAlphaCallback(
|
||||
BiFunction<RemoteAnimationTargetCompat, Float, Float> callback) {
|
||||
public void setTaskAlphaCallback(TargetAlphaProvider callback) {
|
||||
mTaskAlphaCallback = callback;
|
||||
}
|
||||
|
||||
public void setBaseAlphaCallback(TargetAlphaProvider callback) {
|
||||
mBaseAlphaCallback = callback;
|
||||
}
|
||||
|
||||
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
|
||||
fromTaskThumbnailView(ttv, rv, null);
|
||||
}
|
||||
@@ -357,6 +367,10 @@ public class ClipAnimationHelper {
|
||||
return mCurrentCornerRadius;
|
||||
}
|
||||
|
||||
public interface TargetAlphaProvider {
|
||||
float getAlpha(RemoteAnimationTargetCompat target, float expectedAlpha);
|
||||
}
|
||||
|
||||
public static class TransformParams {
|
||||
float progress;
|
||||
public float offsetX;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Utility class to pass non-parcealable objects within same process using parcealable payload.
|
||||
*
|
||||
* It wraps the object in a binder as binders are singleton within a process
|
||||
*/
|
||||
public class ObjectWrapper<T> extends Binder {
|
||||
|
||||
private final T mObject;
|
||||
|
||||
public ObjectWrapper(T object) {
|
||||
mObject = object;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return mObject;
|
||||
}
|
||||
|
||||
public static IBinder wrap(Object obj) {
|
||||
return new ObjectWrapper<>(obj);
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,18 @@ public class RectFSpringAnim {
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (mAnimsStarted) {
|
||||
for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
|
||||
onUpdateListener.onCancel();
|
||||
}
|
||||
}
|
||||
end();
|
||||
}
|
||||
|
||||
public interface OnUpdateListener {
|
||||
void onUpdate(RectF currentRect, float progress);
|
||||
|
||||
default void onCancel() { }
|
||||
}
|
||||
}
|
||||
|
||||
+55
-16
@@ -15,7 +15,14 @@
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.Animator.AnimatorListener;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -29,18 +36,15 @@ import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.anim.SpringObjectAnimator;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
/**
|
||||
* Creates an animation where all the workspace items are moved into their final location,
|
||||
* staggered row by row from the bottom up.
|
||||
@@ -79,9 +83,19 @@ public class StaggeredWorkspaceAnim {
|
||||
.getDimensionPixelSize(R.dimen.swipe_up_max_workspace_trans_y);
|
||||
|
||||
DeviceProfile grid = launcher.getDeviceProfile();
|
||||
ShortcutAndWidgetContainer currentPage = ((CellLayout) launcher.getWorkspace()
|
||||
.getChildAt(launcher.getWorkspace().getCurrentPage()))
|
||||
.getShortcutsAndWidgets();
|
||||
Workspace workspace = launcher.getWorkspace();
|
||||
CellLayout cellLayout = (CellLayout) workspace.getChildAt(workspace.getCurrentPage());
|
||||
ShortcutAndWidgetContainer currentPage = cellLayout.getShortcutsAndWidgets();
|
||||
|
||||
boolean workspaceClipChildren = workspace.getClipChildren();
|
||||
boolean workspaceClipToPadding = workspace.getClipToPadding();
|
||||
boolean cellLayoutClipChildren = cellLayout.getClipChildren();
|
||||
boolean cellLayoutClipToPadding = cellLayout.getClipToPadding();
|
||||
|
||||
workspace.setClipChildren(false);
|
||||
workspace.setClipToPadding(false);
|
||||
cellLayout.setClipChildren(false);
|
||||
cellLayout.setClipToPadding(false);
|
||||
|
||||
// Hotseat and QSB takes up two additional rows.
|
||||
int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
|
||||
@@ -109,8 +123,29 @@ public class StaggeredWorkspaceAnim {
|
||||
addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
|
||||
}
|
||||
|
||||
addWorkspaceScrimAnimationForState(launcher, BACKGROUND_APP, 0);
|
||||
addWorkspaceScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
|
||||
addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
|
||||
addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
|
||||
|
||||
AnimatorListener resetClipListener = new AnimatorListenerAdapter() {
|
||||
int numAnimations = mAnimators.size();
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
numAnimations--;
|
||||
if (numAnimations > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
workspace.setClipChildren(workspaceClipChildren);
|
||||
workspace.setClipToPadding(workspaceClipToPadding);
|
||||
cellLayout.setClipChildren(cellLayoutClipChildren);
|
||||
cellLayout.setClipToPadding(cellLayoutClipToPadding);
|
||||
}
|
||||
};
|
||||
|
||||
for (Animator a : mAnimators) {
|
||||
a.addListener(resetClipListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,10 +169,6 @@ public class StaggeredWorkspaceAnim {
|
||||
* @param totalRows Total number of rows.
|
||||
*/
|
||||
private void addStaggeredAnimationForView(View v, int row, int totalRows) {
|
||||
if (v == mViewToIgnore) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Invert the rows, because we stagger starting from the bottom of the screen.
|
||||
int invertedRow = totalRows - row;
|
||||
// Add 1 to the inverted row so that the bottom most row has a start delay.
|
||||
@@ -149,6 +180,10 @@ public class StaggeredWorkspaceAnim {
|
||||
springTransY.setStartDelay(startDelay);
|
||||
mAnimators.add(springTransY);
|
||||
|
||||
if (v == mViewToIgnore) {
|
||||
return;
|
||||
}
|
||||
|
||||
v.setAlpha(0);
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
|
||||
alpha.setInterpolator(LINEAR);
|
||||
@@ -157,13 +192,17 @@ public class StaggeredWorkspaceAnim {
|
||||
mAnimators.add(alpha);
|
||||
}
|
||||
|
||||
private void addWorkspaceScrimAnimationForState(Launcher launcher, LauncherState state,
|
||||
long duration) {
|
||||
private void addScrimAnimationForState(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());
|
||||
Animator fadeOverviewScrim = ObjectAnimator.ofFloat(
|
||||
launcher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
|
||||
state.getOverviewScrimAlpha(launcher));
|
||||
fadeOverviewScrim.setDuration(duration);
|
||||
mAnimators.add(fadeOverviewScrim);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
||||
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
|
||||
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
@@ -72,6 +73,7 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.ListView;
|
||||
@@ -108,7 +110,6 @@ import com.android.quickstep.util.ClipAnimationHelper;
|
||||
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.BackgroundExecutor;
|
||||
import com.android.systemui.shared.system.LauncherEventUtil;
|
||||
import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
@@ -226,7 +227,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return;
|
||||
}
|
||||
|
||||
BackgroundExecutor.get().submit(() -> {
|
||||
BACKGROUND_EXECUTOR.execute(() -> {
|
||||
TaskView taskView = getTaskView(taskId);
|
||||
if (taskView == null) {
|
||||
return;
|
||||
@@ -269,7 +270,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
private int mTaskListChangeId = -1;
|
||||
|
||||
// Only valid until the launcher state changes to NORMAL
|
||||
private int mRunningTaskId = -1;
|
||||
protected int mRunningTaskId = -1;
|
||||
private boolean mRunningTaskTileHidden;
|
||||
private Task mTmpRunningTask;
|
||||
|
||||
@@ -289,7 +290,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private float mContentAlpha = 1;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private float mFullscreenProgress = 0;
|
||||
protected float mFullscreenProgress = 0;
|
||||
|
||||
// Keeps track of task id whose visual state should not be reset
|
||||
private int mIgnoreResetTaskId = -1;
|
||||
@@ -527,7 +528,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyLoadPlan(ArrayList<Task> tasks) {
|
||||
protected void applyLoadPlan(ArrayList<Task> tasks) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.addEndListener((onEndListener) -> applyLoadPlan(tasks));
|
||||
return;
|
||||
@@ -599,6 +600,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
TaskView taskView = (TaskView) getChildAt(i);
|
||||
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
|
||||
taskView.resetVisualProperties();
|
||||
taskView.setStableAlpha(mContentAlpha);
|
||||
}
|
||||
}
|
||||
if (mRunningTaskTileHidden) {
|
||||
@@ -848,12 +850,14 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
* is called. Also scrolls the view to this task.
|
||||
*/
|
||||
public void showCurrentTask(int runningTaskId) {
|
||||
if (getChildCount() == 0) {
|
||||
if (getTaskView(runningTaskId) == null) {
|
||||
boolean wasEmpty = getChildCount() == 0;
|
||||
// Add an empty view for now until the task plan is loaded and applied
|
||||
final TaskView taskView = mTaskViewPool.getView();
|
||||
addView(taskView);
|
||||
addView(mClearAllButton);
|
||||
|
||||
addView(taskView, 0);
|
||||
if (wasEmpty) {
|
||||
addView(mClearAllButton);
|
||||
}
|
||||
// The temporary running task is only used for the duration between the start of the
|
||||
// gesture and the task list is loaded and applied
|
||||
mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(),
|
||||
@@ -1687,6 +1691,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
* @return How many pixels the running task is offset on the x-axis due to the current scrollX.
|
||||
*/
|
||||
public float getScrollOffset() {
|
||||
if (getRunningTaskIndex() == -1) {
|
||||
return 0;
|
||||
}
|
||||
int startScroll = getScrollForPage(getRunningTaskIndex());
|
||||
int offsetX = startScroll - getScrollX();
|
||||
offsetX *= getScaleX();
|
||||
@@ -1733,4 +1740,14 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
updateEnabledOverlays();
|
||||
}
|
||||
}
|
||||
|
||||
public int getLeftGestureMargin() {
|
||||
final WindowInsets insets = getRootWindowInsets();
|
||||
return Math.max(insets.getSystemGestureInsets().left, insets.getSystemWindowInsetLeft());
|
||||
}
|
||||
|
||||
public int getRightGestureMargin() {
|
||||
final WindowInsets insets = getRootWindowInsets();
|
||||
return Math.max(insets.getSystemGestureInsets().right, insets.getSystemWindowInsetRight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,4 +410,11 @@ public class TaskThumbnailView extends View {
|
||||
|
||||
return new ColorMatrixColorFilter(COLOR_MATRIX);
|
||||
}
|
||||
|
||||
public Bitmap getThumbnail() {
|
||||
if (mThumbnailData == null) {
|
||||
return null;
|
||||
}
|
||||
return mThumbnailData.thumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +192,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mActivity = BaseDraggingActivity.fromContext(context);
|
||||
setOnClickListener((view) -> {
|
||||
if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TASK_TAG, "TaskView onClick");
|
||||
}
|
||||
if (getTask() == null) {
|
||||
return;
|
||||
}
|
||||
@@ -291,9 +288,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
|
||||
public void launchTask(boolean animate, boolean freezeTaskList, Consumer<Boolean> resultCallback,
|
||||
Handler resultCallbackHandler) {
|
||||
if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TASK_TAG, "launchTask");
|
||||
}
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (isRunningTask()) {
|
||||
getRecentsView().finishRecentsAnimation(false /* toRecents */,
|
||||
@@ -308,9 +302,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
|
||||
private void launchTaskInternal(boolean animate, boolean freezeTaskList,
|
||||
Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
|
||||
if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TASK_TAG, "launchTaskInternal");
|
||||
}
|
||||
if (mTask != null) {
|
||||
final ActivityOptions opts;
|
||||
if (animate) {
|
||||
|
||||
@@ -33,5 +33,5 @@
|
||||
<string name="time_left_for_app" msgid="3111996412933644358">"Encore <xliff:g id="TIME">%1$s</xliff:g> aujourd\'hui"</string>
|
||||
<string name="title_app_suggestions" msgid="4185902664111965088">"Suggestions d\'applications"</string>
|
||||
<string name="all_apps_label" msgid="8542784161730910663">"Toutes les applications"</string>
|
||||
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Vos applications prévues"</string>
|
||||
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Applications prévues pour vous"</string>
|
||||
</resources>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<string name="accessibility_close_task" msgid="5354563209433803643">"बंद करें"</string>
|
||||
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
|
||||
<string name="recents_clear_all" msgid="5328176793634888831">"सभी ऐप्लिकेशन बंद करें"</string>
|
||||
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए एेप्लिकेशन"</string>
|
||||
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन"</string>
|
||||
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
|
||||
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"<1 मिनट"</string>
|
||||
<string name="time_left_for_app" msgid="3111996412933644358">"आज <xliff:g id="TIME">%1$s</xliff:g> और चलेगा"</string>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<string name="accessibility_close_task" msgid="5354563209433803643">"बंद"</string>
|
||||
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अॅप वापर सेटिंग्ज"</string>
|
||||
<string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
|
||||
<string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
|
||||
<string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
|
||||
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
|
||||
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"१मिहून कमी"</string>
|
||||
<string name="time_left_for_app" msgid="3111996412933644358">"आज <xliff:g id="TIME">%1$s</xliff:g>शिल्लक आहे"</string>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities
|
||||
.postAtFrontOfQueueAsynchronously;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
|
||||
@@ -66,7 +67,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
|
||||
/**
|
||||
* Called on the UI thread when the animation targets are received. The implementation must
|
||||
* call {@link AnimationResult#setAnimation(AnimatorSet)} with the target animation to be run.
|
||||
* call {@link AnimationResult#setAnimation} with the target animation to be run.
|
||||
*/
|
||||
@UiThread
|
||||
public abstract void onCreateAnimation(
|
||||
@@ -110,7 +111,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void setAnimation(AnimatorSet animation) {
|
||||
public void setAnimation(AnimatorSet animation, Context context) {
|
||||
if (mInitialized) {
|
||||
throw new IllegalStateException("Animation already initialized");
|
||||
}
|
||||
@@ -134,7 +135,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
|
||||
// Because t=0 has the app icon in its original spot, we can skip the
|
||||
// first frame and have the same movement one frame earlier.
|
||||
mAnimator.setCurrentPlayTime(SINGLE_FRAME_MS);
|
||||
mAnimator.setCurrentPlayTime(getSingleFrameMs(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class LauncherInitListener extends InternalStateHandler implements Activi
|
||||
|
||||
register();
|
||||
|
||||
Bundle options = animProvider.toActivityOptions(handler, duration).toBundle();
|
||||
Bundle options = animProvider.toActivityOptions(handler, duration, context).toBundle();
|
||||
context.startActivity(addToIntent(new Intent((intent))), options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
||||
anim.addListener(mForceInvisibleListener);
|
||||
}
|
||||
|
||||
result.setAnimation(anim);
|
||||
result.setAnimation(anim, mLauncher);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -822,7 +822,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
|
||||
}
|
||||
|
||||
mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
|
||||
result.setAnimation(anim);
|
||||
result.setAnimation(anim, mLauncher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-2
@@ -19,16 +19,20 @@ package com.android.launcher3.uioverrides;
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCRIM_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
|
||||
|
||||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
@@ -36,8 +40,7 @@ import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
|
||||
/**
|
||||
* State handler for recents view. Manages UI changes and animations for recents view based off the
|
||||
@@ -67,6 +70,8 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
||||
mRecentsView.setTranslationX(translationX);
|
||||
mRecentsView.setTranslationY(scaleAndTranslation.translationY);
|
||||
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
|
||||
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
|
||||
SCRIM_PROGRESS.set(scrim, state.getOverviewScrimAlpha(mLauncher));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,6 +115,9 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
||||
translateYInterpolator);
|
||||
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
|
||||
builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
||||
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
|
||||
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
|
||||
builder.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-3
@@ -51,7 +51,6 @@ import com.android.quickstep.OverviewInteractionState;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
|
||||
/**
|
||||
* Touch controller for handling various state transitions in portrait UI.
|
||||
@@ -63,7 +62,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
/**
|
||||
* The progress at which all apps content will be fully visible when swiping up from overview.
|
||||
*/
|
||||
private static final float ALL_APPS_CONTENT_FADE_THRESHOLD = 0.08f;
|
||||
protected static final float ALL_APPS_CONTENT_FADE_THRESHOLD = 0.08f;
|
||||
|
||||
/**
|
||||
* The progress at which recents will begin fading out when swiping up from overview.
|
||||
@@ -296,9 +295,13 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
* @return true if the event is over the hotseat
|
||||
*/
|
||||
static boolean isTouchOverHotseat(Launcher launcher, MotionEvent ev) {
|
||||
return (ev.getY() >= getHotseatTop(launcher));
|
||||
}
|
||||
|
||||
public static int getHotseatTop(Launcher launcher) {
|
||||
DeviceProfile dp = launcher.getDeviceProfile();
|
||||
int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
|
||||
return (ev.getY() >= (launcher.getDragLayer().getHeight() - hotseatHeight));
|
||||
return launcher.getDragLayer().getHeight() - hotseatHeight;
|
||||
}
|
||||
|
||||
private static class InterpolatorWrapper implements Interpolator {
|
||||
|
||||
+58
-17
@@ -17,17 +17,25 @@ package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.touch.TouchEventTranslator;
|
||||
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.TouchController;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
@@ -36,18 +44,29 @@ import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* TouchController for handling touch events that get sent to the StatusBar. Once the
|
||||
* Once the event delta y passes the touch slop, the events start getting forwarded.
|
||||
* Once the event delta mDownY passes the touch slop, the events start getting forwarded.
|
||||
* All events are offset by initial Y value of the pointer.
|
||||
*/
|
||||
public class StatusBarTouchController implements TouchController {
|
||||
|
||||
private static final String TAG = "StatusBarController";
|
||||
|
||||
/**
|
||||
* Window flag: Enable touches to slide out of a window into neighboring
|
||||
* windows in mid-gesture instead of being captured for the duration of
|
||||
* the gesture.
|
||||
*
|
||||
* This flag changes the behavior of touch focus for this window only.
|
||||
* Touches can slide out of the window but they cannot necessarily slide
|
||||
* back in (unless the other window with touch focus permits it).
|
||||
*/
|
||||
private static final int FLAG_SLIPPERY = 0x20000000;
|
||||
|
||||
protected final Launcher mLauncher;
|
||||
protected final TouchEventTranslator mTranslator;
|
||||
private final float mTouchSlop;
|
||||
private ISystemUiProxy mSysUiProxy;
|
||||
private int mLastAction;
|
||||
private final SparseArray<PointF> mDownEvents;
|
||||
|
||||
/* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/
|
||||
private boolean mCanIntercept;
|
||||
@@ -56,7 +75,7 @@ public class StatusBarTouchController implements TouchController {
|
||||
mLauncher = l;
|
||||
// Guard against TAPs by increasing the touch slop.
|
||||
mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop();
|
||||
mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev));
|
||||
mDownEvents = new SparseArray<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,7 +83,6 @@ public class StatusBarTouchController implements TouchController {
|
||||
writer.println(prefix + "mCanIntercept:" + mCanIntercept);
|
||||
writer.println(prefix + "mLastAction:" + MotionEvent.actionToString(mLastAction));
|
||||
writer.println(prefix + "mSysUiProxy available:" + (mSysUiProxy != null));
|
||||
|
||||
}
|
||||
|
||||
private void dispatchTouchEvent(MotionEvent ev) {
|
||||
@@ -81,26 +99,31 @@ public class StatusBarTouchController implements TouchController {
|
||||
@Override
|
||||
public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
int action = ev.getActionMasked();
|
||||
int idx = ev.getActionIndex();
|
||||
int pid = ev.getPointerId(idx);
|
||||
if (action == ACTION_DOWN) {
|
||||
mCanIntercept = canInterceptTouch(ev);
|
||||
if (!mCanIntercept) {
|
||||
return false;
|
||||
}
|
||||
mTranslator.reset();
|
||||
mTranslator.setDownParameters(0, ev);
|
||||
mDownEvents.put(pid, new PointF(ev.getX(), ev.getY()));
|
||||
} else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
// Check!! should only set it only when threshold is not entered.
|
||||
mTranslator.setDownParameters(ev.getActionIndex(), ev);
|
||||
// Check!! should only set it only when threshold is not entered.
|
||||
mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx)));
|
||||
}
|
||||
if (!mCanIntercept) {
|
||||
return false;
|
||||
}
|
||||
if (action == ACTION_MOVE) {
|
||||
float dy = ev.getY() - mTranslator.getDownY();
|
||||
float dx = ev.getX() - mTranslator.getDownX();
|
||||
if (dy > mTouchSlop && dy > Math.abs(dx)) {
|
||||
mTranslator.dispatchDownEvents(ev);
|
||||
mTranslator.processMotionEvent(ev);
|
||||
float dy = ev.getY(idx) - mDownEvents.get(pid).y;
|
||||
float dx = ev.getX(idx) - mDownEvents.get(pid).x;
|
||||
// Currently input dispatcher will not do touch transfer if there are more than
|
||||
// one touch pointer. Hence, even if slope passed, only set the slippery flag
|
||||
// when there is single touch event. (context: InputDispatcher.cpp line 1445)
|
||||
if (dy > mTouchSlop && dy > Math.abs(dx) && ev.getPointerCount() == 1) {
|
||||
ev.setAction(ACTION_DOWN);
|
||||
dispatchTouchEvent(ev);
|
||||
setWindowSlippery(true);
|
||||
return true;
|
||||
}
|
||||
if (Math.abs(dx) > mTouchSlop) {
|
||||
@@ -110,13 +133,31 @@ public class StatusBarTouchController implements TouchController {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean onControllerTouchEvent(MotionEvent ev) {
|
||||
mTranslator.processMotionEvent(ev);
|
||||
int action = ev.getAction();
|
||||
if (action == ACTION_UP || action == ACTION_CANCEL) {
|
||||
dispatchTouchEvent(ev);
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(action == ACTION_UP ?
|
||||
Touch.FLING : Touch.SWIPE, Direction.DOWN, ContainerType.WORKSPACE,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
setWindowSlippery(false);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setWindowSlippery(boolean enable) {
|
||||
Window w = mLauncher.getWindow();
|
||||
WindowManager.LayoutParams wlp = w.getAttributes();
|
||||
if (enable) {
|
||||
wlp.flags |= FLAG_SLIPPERY;
|
||||
} else {
|
||||
wlp.flags &= ~FLAG_SLIPPERY;
|
||||
}
|
||||
w.setAttributes(wlp);
|
||||
}
|
||||
|
||||
private boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (!mLauncher.isInState(LauncherState.NORMAL) ||
|
||||
AbstractFloatingView.getTopOpenViewWithType(mLauncher,
|
||||
@@ -132,4 +173,4 @@ public class StatusBarTouchController implements TouchController {
|
||||
mSysUiProxy = RecentsModel.INSTANCE.get(mLauncher).getSystemUiProxy();
|
||||
return mSysUiProxy != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,5 +152,15 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
|
||||
default void playAtomicAnimation(float velocity) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
static RectF getDefaultWindowTargetRect(DeviceProfile dp) {
|
||||
final int halfIconSize = dp.iconSizePx / 2;
|
||||
final float targetCenterX = dp.availableWidthPx / 2f;
|
||||
final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
|
||||
// Fallback to animate to center of screen.
|
||||
return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
|
||||
targetCenterX + halfIconSize, targetCenterY + halfIconSize);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,15 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class to keep track of the current overview component based off user preferences and app updates
|
||||
@@ -53,22 +57,41 @@ public final class OverviewComponentObserver {
|
||||
}
|
||||
};
|
||||
private final Context mContext;
|
||||
private final ComponentName mMyHomeComponent;
|
||||
private final Intent mCurrentHomeIntent;
|
||||
private final Intent mMyHomeIntent;
|
||||
private final Intent mFallbackIntent;
|
||||
private final SparseIntArray mConfigChangesMap = new SparseIntArray();
|
||||
private String mUpdateRegisteredPackage;
|
||||
private ActivityControlHelper mActivityControlHelper;
|
||||
private Intent mOverviewIntent;
|
||||
private Intent mHomeIntent;
|
||||
private int mSystemUiStateFlags;
|
||||
private boolean mIsHomeAndOverviewSame;
|
||||
private boolean mIsDefaultHome;
|
||||
|
||||
public OverviewComponentObserver(Context context) {
|
||||
mContext = context;
|
||||
|
||||
Intent myHomeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
mCurrentHomeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setPackage(mContext.getPackageName());
|
||||
ResolveInfo info = context.getPackageManager().resolveActivity(myHomeIntent, 0);
|
||||
mMyHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name);
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName());
|
||||
ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0);
|
||||
ComponentName myHomeComponent =
|
||||
new ComponentName(context.getPackageName(), info.activityInfo.name);
|
||||
mMyHomeIntent.setComponent(myHomeComponent);
|
||||
mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges);
|
||||
|
||||
ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class);
|
||||
mFallbackIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
.setComponent(fallbackComponent)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
try {
|
||||
ActivityInfo fallbackInfo = context.getPackageManager().getActivityInfo(
|
||||
mFallbackIntent.getComponent(), 0 /* flags */);
|
||||
mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges);
|
||||
} catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ }
|
||||
|
||||
mContext.registerReceiver(mUserPreferenceChangeReceiver,
|
||||
new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED));
|
||||
@@ -92,17 +115,22 @@ public final class OverviewComponentObserver {
|
||||
ComponentName defaultHome = PackageManagerWrapper.getInstance()
|
||||
.getHomeActivities(new ArrayList<>());
|
||||
|
||||
final String overviewIntentCategory;
|
||||
ComponentName overviewComponent;
|
||||
mHomeIntent = null;
|
||||
mIsDefaultHome = Objects.equals(mMyHomeIntent.getComponent(), defaultHome);
|
||||
|
||||
if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 &&
|
||||
(defaultHome == null || mMyHomeComponent.equals(defaultHome))) {
|
||||
// Set assistant visibility to 0 from launcher's perspective, ensures any elements that
|
||||
// launcher made invisible become visible again before the new activity control helper
|
||||
// becomes active.
|
||||
if (mActivityControlHelper != null) {
|
||||
mActivityControlHelper.onAssistantVisibilityChanged(0.f);
|
||||
}
|
||||
|
||||
if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
|
||||
&& (defaultHome == null || mIsDefaultHome)) {
|
||||
// User default home is same as out home app. Use Overview integrated in Launcher.
|
||||
overviewComponent = mMyHomeComponent;
|
||||
mActivityControlHelper = new LauncherActivityControllerHelper();
|
||||
mIsHomeAndOverviewSame = true;
|
||||
overviewIntentCategory = Intent.CATEGORY_HOME;
|
||||
mOverviewIntent = mMyHomeIntent;
|
||||
mCurrentHomeIntent.setComponent(mMyHomeIntent.getComponent());
|
||||
|
||||
if (mUpdateRegisteredPackage != null) {
|
||||
// Remove any update listener as we don't care about other packages.
|
||||
@@ -111,14 +139,12 @@ public final class OverviewComponentObserver {
|
||||
}
|
||||
} else {
|
||||
// The default home app is a different launcher. Use the fallback Overview instead.
|
||||
overviewComponent = new ComponentName(mContext, RecentsActivity.class);
|
||||
|
||||
mActivityControlHelper = new FallbackActivityControllerHelper();
|
||||
mIsHomeAndOverviewSame = false;
|
||||
overviewIntentCategory = Intent.CATEGORY_DEFAULT;
|
||||
mOverviewIntent = mFallbackIntent;
|
||||
mCurrentHomeIntent.setComponent(defaultHome);
|
||||
|
||||
mHomeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setComponent(defaultHome);
|
||||
// User's default home app can change as a result of package updates of this app (such
|
||||
// as uninstalling the app or removing the "Launcher" feature in an update).
|
||||
// Listen for package updates of this app (and remove any previously attached
|
||||
@@ -138,14 +164,6 @@ public final class OverviewComponentObserver {
|
||||
ACTION_PACKAGE_REMOVED));
|
||||
}
|
||||
}
|
||||
|
||||
mOverviewIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(overviewIntentCategory)
|
||||
.setComponent(overviewComponent)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (mHomeIntent == null) {
|
||||
mHomeIntent = mOverviewIntent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,6 +178,32 @@ public final class OverviewComponentObserver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the overview component is able to handle the configuration changes.
|
||||
*/
|
||||
boolean canHandleConfigChanges(ComponentName component, int changes) {
|
||||
final int orientationChange =
|
||||
ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
if ((changes & orientationChange) == orientationChange) {
|
||||
// This is just an approximate guess for simple orientation change because the changes
|
||||
// may contain non-public bits (e.g. window configuration).
|
||||
return true;
|
||||
}
|
||||
|
||||
int configMask = mConfigChangesMap.get(component.hashCode());
|
||||
return configMask != 0 && (~configMask & changes) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the intent for overview activity. It is used when lockscreen is shown and home was died
|
||||
* in background, we still want to restart the one that will be used after unlock.
|
||||
*
|
||||
* @return the overview intent
|
||||
*/
|
||||
Intent getOverviewIntentIgnoreSysUiState() {
|
||||
return mIsDefaultHome ? mMyHomeIntent : mOverviewIntent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current intent for going to the overview activity.
|
||||
*
|
||||
@@ -173,7 +217,7 @@ public final class OverviewComponentObserver {
|
||||
* Get the current intent for going to the home activity.
|
||||
*/
|
||||
public Intent getHomeIntent() {
|
||||
return mHomeIntent;
|
||||
return mCurrentHomeIntent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserManager;
|
||||
@@ -23,29 +22,17 @@ import android.util.Log;
|
||||
|
||||
import com.android.launcher3.BuildConfig;
|
||||
import com.android.launcher3.MainProcessInitializer;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.systemui.shared.system.ThreadedRendererCompat;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class QuickstepProcessInitializer extends MainProcessInitializer {
|
||||
|
||||
private static final String TAG = "QuickstepProcessInitializer";
|
||||
private static final int HEAP_LIMIT_MB = 250;
|
||||
|
||||
public QuickstepProcessInitializer(Context context) { }
|
||||
|
||||
@Override
|
||||
protected void init(Context context) {
|
||||
if (Utilities.IS_DEBUG_DEVICE) {
|
||||
try {
|
||||
// Trigger a heap dump if the PSS reaches beyond the target heap limit
|
||||
final ActivityManager am = context.getSystemService(ActivityManager.class);
|
||||
am.setWatchHeapLimit(HEAP_LIMIT_MB * 1024 * 1024);
|
||||
} catch (SecurityException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for b/120550382, an external app can cause the launcher process to start for
|
||||
// a work profile user which we do not support. Disable the application immediately when we
|
||||
// detect this to be the case.
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.launcher3.testing.TestInformationHandler;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
|
||||
public class QuickstepTestInformationHandler extends TestInformationHandler {
|
||||
|
||||
public QuickstepTestInformationHandler(Context context) { }
|
||||
|
||||
@Override
|
||||
public Bundle call(String method) {
|
||||
final Bundle response = new Bundle();
|
||||
switch (method) {
|
||||
case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
|
||||
final float swipeHeight =
|
||||
OverviewState.getDefaultSwipeHeight(mDeviceProfile);
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
|
||||
final float swipeHeight =
|
||||
LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
return super.call(method);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
@@ -25,10 +27,7 @@ import android.util.SparseBooleanArray;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
import com.android.systemui.shared.system.KeyguardManagerCompat;
|
||||
import com.android.systemui.shared.system.RecentTaskInfoCompat;
|
||||
import com.android.systemui.shared.system.TaskDescriptionCompat;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -43,7 +42,6 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
|
||||
private final KeyguardManagerCompat mKeyguardManager;
|
||||
private final MainThreadExecutor mMainThreadExecutor;
|
||||
private final BackgroundExecutor mBgThreadExecutor;
|
||||
|
||||
// The list change id, increments as the task list changes in the system
|
||||
private int mChangeId;
|
||||
@@ -56,7 +54,6 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
|
||||
public RecentTasksList(Context context) {
|
||||
mMainThreadExecutor = new MainThreadExecutor();
|
||||
mBgThreadExecutor = BackgroundExecutor.get();
|
||||
mKeyguardManager = new KeyguardManagerCompat(context);
|
||||
mChangeId = 1;
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
|
||||
@@ -67,7 +64,7 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
*/
|
||||
public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
|
||||
// Kick off task loading in the background
|
||||
mBgThreadExecutor.submit(() -> {
|
||||
BACKGROUND_EXECUTOR.execute(() -> {
|
||||
ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
|
||||
mMainThreadExecutor.execute(() -> callback.accept(tasks));
|
||||
});
|
||||
@@ -87,13 +84,14 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
: () -> callback.accept(copyOf(mTasks));
|
||||
|
||||
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
|
||||
// The list is up to date, callback with the same list
|
||||
mMainThreadExecutor.execute(resultCallback);
|
||||
// The list is up to date, send the callback on the next frame,
|
||||
// so that requestID can be returned first.
|
||||
mMainThreadExecutor.getHandler().post(resultCallback);
|
||||
return requestLoadId;
|
||||
}
|
||||
|
||||
// Kick off task loading in the background
|
||||
mBgThreadExecutor.submit(() -> {
|
||||
BACKGROUND_EXECUTOR.execute(() -> {
|
||||
ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
|
||||
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
@@ -121,12 +119,7 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(int taskId) {
|
||||
for (int i = mTasks.size() - 1; i >= 0; i--) {
|
||||
if (mTasks.get(i).key.id == taskId) {
|
||||
mTasks.remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mTasks = loadTasksInBackground(Integer.MAX_VALUE, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,15 +159,11 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
int taskCount = rawTasks.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
ActivityManager.RecentTaskInfo rawTask = rawTasks.get(i);
|
||||
RecentTaskInfoCompat t = new RecentTaskInfoCompat(rawTask);
|
||||
Task.TaskKey taskKey = new Task.TaskKey(rawTask);
|
||||
Task task;
|
||||
if (!loadKeysOnly) {
|
||||
ActivityManager.TaskDescription rawTd = t.getTaskDescription();
|
||||
TaskDescriptionCompat td = new TaskDescriptionCompat(rawTd);
|
||||
boolean isLocked = tmpLockedUsers.get(t.getUserId());
|
||||
task = new Task(taskKey, td.getPrimaryColor(), td.getBackgroundColor(),
|
||||
t.supportsSplitScreenMultiWindow(), isLocked, rawTd, t.getTopActivity());
|
||||
boolean isLocked = tmpLockedUsers.get(taskKey.userId);
|
||||
task = Task.from(taskKey, rawTask, isLocked);
|
||||
} else {
|
||||
task = new Task(taskKey);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class RecentsActivityTracker<T extends BaseRecentsActivity> implements Ac
|
||||
Context context, Handler handler, long duration) {
|
||||
register();
|
||||
|
||||
Bundle options = animProvider.toActivityOptions(handler, duration).toBundle();
|
||||
Bundle options = animProvider.toActivityOptions(handler, duration, context).toBundle();
|
||||
context.startActivity(intent, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.quickstep.util;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.android.launcher3.LauncherAnimationRunner;
|
||||
@@ -32,14 +33,14 @@ public interface RemoteAnimationProvider {
|
||||
|
||||
AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targets);
|
||||
|
||||
default ActivityOptions toActivityOptions(Handler handler, long duration) {
|
||||
default ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
|
||||
LauncherAnimationRunner runner = new LauncherAnimationRunner(handler,
|
||||
false /* startAtFrontOfQueue */) {
|
||||
|
||||
@Override
|
||||
public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
|
||||
AnimationResult result) {
|
||||
result.setAnimation(createWindowAnimation(targetCompats));
|
||||
result.setAnimation(createWindowAnimation(targetCompats), context);
|
||||
}
|
||||
};
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(
|
||||
|
||||
@@ -74,6 +74,9 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
|
||||
private int mMidAlpha;
|
||||
private float mMidProgress;
|
||||
|
||||
// The progress at which the drag handle starts moving up with the shelf.
|
||||
private float mDragHandleProgress;
|
||||
|
||||
private Interpolator mBeforeMidProgressColorInterpolator = ACCEL;
|
||||
private Interpolator mAfterMidProgressColorInterpolator = ACCEL;
|
||||
|
||||
@@ -95,7 +98,7 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
|
||||
|
||||
public ShelfScrimView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mMaxScrimAlpha = Math.round(OVERVIEW.getWorkspaceScrimAlpha(mLauncher) * 255);
|
||||
mMaxScrimAlpha = Math.round(OVERVIEW.getOverviewScrimAlpha(mLauncher) * 255);
|
||||
|
||||
mEndAlpha = Color.alpha(mEndScrim);
|
||||
mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context);
|
||||
@@ -150,15 +153,16 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
|
||||
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) == 0) {
|
||||
mMidProgress = 1;
|
||||
mDragHandleProgress = 1;
|
||||
mMidAlpha = 0;
|
||||
} else {
|
||||
mMidAlpha = Themes.getAttrInteger(getContext(), R.attr.allAppsInterimScrimAlpha);
|
||||
mMidProgress = OVERVIEW.getVerticalProgress(mLauncher);
|
||||
Rect hotseatPadding = dp.getHotseatLayoutPadding();
|
||||
int hotseatSize = dp.hotseatBarSizePx + dp.getInsets().bottom
|
||||
- hotseatPadding.bottom - hotseatPadding.top;
|
||||
float arrowTop = Math.min(hotseatSize, OverviewState.getDefaultSwipeHeight(dp));
|
||||
mMidProgress = 1 - (arrowTop / mShiftRange);
|
||||
|
||||
float dragHandleTop = Math.min(hotseatSize, OverviewState.getDefaultSwipeHeight(dp));
|
||||
mDragHandleProgress = 1 - (dragHandleTop / mShiftRange);
|
||||
}
|
||||
mTopOffset = dp.getInsets().top - mShelfOffset;
|
||||
mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
|
||||
@@ -199,8 +203,6 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
|
||||
mProgress, mMidProgress, 1, mMidAlpha, 0, mBeforeMidProgressColorInterpolator));
|
||||
mShelfColor = setColorAlphaBound(mEndScrim, alpha);
|
||||
} else {
|
||||
mDragHandleOffset += mShiftRange * (mMidProgress - mProgress);
|
||||
|
||||
// Note that these ranges and interpolators are inverted because progress goes 1 to 0.
|
||||
int alpha = Math.round(
|
||||
Utilities.mapToRange(mProgress, (float) 0, mMidProgress, (float) mEndAlpha,
|
||||
@@ -212,6 +214,10 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
|
||||
(float) 0, LINEAR));
|
||||
mRemainingScreenColor = setColorAlphaBound(mScrimColor, remainingScrimAlpha);
|
||||
}
|
||||
|
||||
if (mProgress < mDragHandleProgress) {
|
||||
mDragHandleOffset += mShiftRange * (mDragHandleProgress - mProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -88,7 +88,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
|
||||
*/
|
||||
@Test
|
||||
public void testPredictionExistsInAllApps() {
|
||||
mActivityMonitor.startLauncher();
|
||||
mDevice.pressHome();
|
||||
mLauncher.pressHome().switchToAllApps();
|
||||
|
||||
// Dispatch an update
|
||||
@@ -103,7 +103,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
|
||||
*/
|
||||
@Test
|
||||
public void testPredictionsDeferredUntilHome() {
|
||||
mActivityMonitor.startLauncher();
|
||||
mDevice.pressHome();
|
||||
sendPredictionUpdate(mSampleApp1, mSampleApp2);
|
||||
mLauncher.pressHome().switchToAllApps();
|
||||
waitForLauncherCondition("Predictions were not updated in loading state",
|
||||
@@ -120,7 +120,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
|
||||
|
||||
@Test
|
||||
public void testPredictionsDisabled() {
|
||||
mActivityMonitor.startLauncher();
|
||||
mDevice.pressHome();
|
||||
sendPredictionUpdate();
|
||||
mLauncher.pressHome().switchToAllApps();
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public class DigitalWellBeingToastTest extends AbstractQuickStepTest {
|
||||
mLauncher.pressHome();
|
||||
final DigitalWellBeingToast toast = getToast();
|
||||
|
||||
assertTrue("Toast is not visible", toast.hasLimit());
|
||||
waitForLauncherCondition("Toast is not visible", launcher -> toast.hasLimit());
|
||||
assertEquals("Toast text: ", "5 minutes left today", toast.getText());
|
||||
|
||||
// Unset time limit for app.
|
||||
|
||||
@@ -27,6 +27,7 @@ import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_
|
||||
import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_GESTURAL_OVERLAY;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
@@ -80,6 +81,7 @@ public class NavigationModeSwitchRule implements TestRule {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
mLauncher.enableDebugTracing();
|
||||
final Context context = getInstrumentation().getContext();
|
||||
final int currentInteractionMode =
|
||||
LauncherInstrumentation.getCurrentInteractionMode(context);
|
||||
@@ -101,35 +103,55 @@ public class NavigationModeSwitchRule implements TestRule {
|
||||
if (mode == THREE_BUTTON || mode == ALL) {
|
||||
evaluateWithThreeButtons();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Exception", e);
|
||||
throw e;
|
||||
} finally {
|
||||
setActiveOverlay(prevOverlayPkg, originalMode);
|
||||
Assert.assertTrue(setActiveOverlay(prevOverlayPkg, originalMode));
|
||||
}
|
||||
}
|
||||
|
||||
public void evaluateWithoutChangingSetting(Statement base) throws Throwable {
|
||||
base.evaluate();
|
||||
mLauncher.disableDebugTracing();
|
||||
}
|
||||
|
||||
private void evaluateWithThreeButtons() throws Throwable {
|
||||
setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY,
|
||||
LauncherInstrumentation.NavigationModel.THREE_BUTTON);
|
||||
evaluateWithoutChangingSetting(base);
|
||||
if (setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY,
|
||||
LauncherInstrumentation.NavigationModel.THREE_BUTTON)) {
|
||||
base.evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
private void evaluateWithTwoButtons() throws Throwable {
|
||||
setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY,
|
||||
LauncherInstrumentation.NavigationModel.TWO_BUTTON);
|
||||
base.evaluate();
|
||||
if (setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY,
|
||||
LauncherInstrumentation.NavigationModel.TWO_BUTTON)) {
|
||||
base.evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
private void evaluateWithZeroButtons() throws Throwable {
|
||||
setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY,
|
||||
LauncherInstrumentation.NavigationModel.ZERO_BUTTON);
|
||||
base.evaluate();
|
||||
if (setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY,
|
||||
LauncherInstrumentation.NavigationModel.ZERO_BUTTON)) {
|
||||
base.evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
private void setActiveOverlay(String overlayPackage,
|
||||
private boolean packageExists(String packageName) {
|
||||
try {
|
||||
PackageManager pm = getInstrumentation().getContext().getPackageManager();
|
||||
if (pm.getApplicationInfo(packageName, 0 /* flags */) == null) {
|
||||
return false;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setActiveOverlay(String overlayPackage,
|
||||
LauncherInstrumentation.NavigationModel expectedMode) throws Exception {
|
||||
if (!packageExists(overlayPackage)) {
|
||||
Log.d(TAG, "setActiveOverlay: " + overlayPackage + " pkg does not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
setOverlayPackageEnabled(NAV_BAR_MODE_3BUTTON_OVERLAY,
|
||||
overlayPackage == NAV_BAR_MODE_3BUTTON_OVERLAY);
|
||||
setOverlayPackageEnabled(NAV_BAR_MODE_2BUTTON_OVERLAY,
|
||||
@@ -173,6 +195,7 @@ public class NavigationModeSwitchRule implements TestRule {
|
||||
Assert.assertTrue("Switching nav mode: " + error, error == null);
|
||||
|
||||
Thread.sleep(5000);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setOverlayPackageEnabled(String overlayPackage, boolean enable)
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.tapl.LauncherInstrumentation;
|
||||
import com.android.launcher3.util.RaceConditionReproducer;
|
||||
import com.android.quickstep.NavigationModeSwitchRule.Mode;
|
||||
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
|
||||
@@ -79,6 +80,8 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
|
||||
@Test
|
||||
@NavigationModeSwitch
|
||||
public void testStressPressHome() {
|
||||
if (LauncherInstrumentation.isAvd()) return; // b/136278866
|
||||
|
||||
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
|
||||
// Destroy Launcher activity.
|
||||
closeLauncherActivity();
|
||||
@@ -91,6 +94,8 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
|
||||
@Test
|
||||
@NavigationModeSwitch
|
||||
public void testStressSwipeToOverview() {
|
||||
if (LauncherInstrumentation.isAvd()) return; // b/136278866
|
||||
|
||||
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
|
||||
// Destroy Launcher activity.
|
||||
closeLauncherActivity();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -208,7 +207,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
|
||||
|
||||
@Test
|
||||
@NavigationModeSwitch
|
||||
// @PortraitLandscape
|
||||
@PortraitLandscape
|
||||
public void testBackground() throws Exception {
|
||||
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
|
||||
final Background background = mLauncher.getBackground();
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<string name="notification_dots_title" msgid="9062440428204120317">"Punts de notificació"</string>
|
||||
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activats"</string>
|
||||
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Desactivats"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cal que tingui accés a les notificacions"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cal accés a les notificacions"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per veure els punts de notificació, activa les notificacions de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Canvia la configuració"</string>
|
||||
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra els punts de notificació"</string>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<string name="notification_dots_title" msgid="9062440428204120317">"नई सूचनाएं बताने वाला गोल निशान"</string>
|
||||
<string name="notification_dots_desc_on" msgid="1679848116452218908">"चालू"</string>
|
||||
<string name="notification_dots_desc_off" msgid="1760796511504341095">"चालू"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचना के एक्सेस की ज़रूरत है"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचना के ऐक्सेस की ज़रूरत है"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदु दिखाने के लिए, <xliff:g id="NAME">%1$s</xliff:g> के ऐप्लिकेशन सूचना चालू करें"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग बदलें"</string>
|
||||
<string name="notification_dots_service_title" msgid="4284221181793592871">"नई सूचनाएं बताने वाला गोल निशान दिखाएं"</string>
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
<string name="home_screen" msgid="806512411299847073">"Layar utama"</string>
|
||||
<string name="custom_actions" msgid="3747508247759093328">"Tindakan khusus"</string>
|
||||
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh lama untuk memilih widget."</string>
|
||||
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"Tap dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus."</string>
|
||||
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ketuk dua kali & tahan untuk mengambil widget atau menggunakan tindakan khusus."</string>
|
||||
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
|
||||
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"lebar %1$d x tinggi %2$d"</string>
|
||||
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"Tap lama untuk menempatkan secara manual"</string>
|
||||
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"Sentuh lama untuk menempatkan secara manual"</string>
|
||||
<string name="place_automatically" msgid="8064208734425456485">"Tambahkan otomatis"</string>
|
||||
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Telusuri aplikasi"</string>
|
||||
<string name="all_apps_loading_message" msgid="5813968043155271636">"Memuat aplikasi…"</string>
|
||||
@@ -41,8 +41,8 @@
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Telusuri aplikasi lainnya"</string>
|
||||
<string name="label_application" msgid="8531721983832654978">"Aplikasi"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notifikasi"</string>
|
||||
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tap lama untuk memilih pintasan."</string>
|
||||
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Tap dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."</string>
|
||||
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Sentuh lama untuk memilih pintasan."</string>
|
||||
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Ketuk dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."</string>
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Tidak ada ruang lagi pada layar Utama ini."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tidak ada ruang tersisa di baki Favorit"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Daftar aplikasi"</string>
|
||||
@@ -73,8 +73,8 @@
|
||||
<string name="workspace_scroll_format" msgid="8458889198184077399">"Layar utama %1$d dari %2$d"</string>
|
||||
<string name="workspace_new_page" msgid="257366611030256142">"Halaman layar utama baru"</string>
|
||||
<string name="folder_opened" msgid="94695026776264709">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
|
||||
<string name="folder_tap_to_close" msgid="4625795376335528256">"Tap untuk menutup folder"</string>
|
||||
<string name="folder_tap_to_rename" msgid="4017685068016979677">"Tap untuk menyimpan ganti nama"</string>
|
||||
<string name="folder_tap_to_close" msgid="4625795376335528256">"Ketuk untuk menutup folder"</string>
|
||||
<string name="folder_tap_to_rename" msgid="4017685068016979677">"Ketuk untuk menyimpan ganti nama"</string>
|
||||
<string name="folder_closed" msgid="4100806530910930934">"Folder ditutup"</string>
|
||||
<string name="folder_renamed" msgid="1794088362165669656">"Folder diganti namanya menjadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
|
||||
@@ -35,18 +35,18 @@
|
||||
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d रूंद बाय %2$d उंच"</string>
|
||||
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा"</string>
|
||||
<string name="place_automatically" msgid="8064208734425456485">"आपोआप जोडा"</string>
|
||||
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"अॅप्स शोधा"</string>
|
||||
<string name="all_apps_loading_message" msgid="5813968043155271636">"अॅप्स लोड करत आहे…"</string>
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"अधिक अॅप्स शोधा"</string>
|
||||
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"अॅप्स शोधा"</string>
|
||||
<string name="all_apps_loading_message" msgid="5813968043155271636">"अॅप्स लोड करत आहे…"</string>
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"अधिक अॅप्स शोधा"</string>
|
||||
<string name="label_application" msgid="8531721983832654978">"ॲप"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"सूचना"</string>
|
||||
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
|
||||
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."</string>
|
||||
<string name="out_of_space" msgid="4691004494942118364">"या मुख्य स्क्रीनवर आणखी जागा नाही."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"आवडीच्या ट्रे मध्ये आणखी जागा नाही"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"अॅप्स सूची"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"वैयक्तिक अॅप्स सूची"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"अॅप्स सूची"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"वैयक्तिक अॅप्स सूची"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"कामाच्या ठिकाणी वापरली जाणाऱ्या अॅप्सची सूची"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"होम"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"काढा"</string>
|
||||
@@ -136,7 +136,7 @@
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"कामाची अॅप्स येथे मिळवा"</string>
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"प्रत्येक कार्य अॅपला एक बॅज असतो आणि तो तुमच्या संस्थेकडून सुरक्षित ठेवला जातो. अधिक सहज अॅक्सेससाठी अॅप्स तुमच्या होम स्क्रीनवर हलवा."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"तुमच्या संस्थेकडून व्यवस्थापित"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"सूचना आणि अॅप्स बंद आहेत"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"सूचना आणि अॅप्स बंद आहेत"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"बंद करा"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"बंद केले"</string>
|
||||
<string name="remote_action_failed" msgid="1383965239183576790">"हे करता आले नाही: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<string name="notification_dots_title" msgid="9062440428204120317">"Значки уведомлений"</string>
|
||||
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Включены"</string>
|
||||
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Отключены"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Нет доступа к уведомлениям"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Нужен доступ к уведомлениям"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Чтобы показывать значки уведомлений, включите уведомления в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Изменить настройки"</string>
|
||||
<string name="notification_dots_service_title" msgid="4284221181793592871">"Показывать значки уведомлений"</string>
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<string name="notification_dots_desc_on" msgid="1679848116452218908">"ஆன்"</string>
|
||||
<string name="notification_dots_desc_off" msgid="1760796511504341095">"ஆஃப்"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"அறிவிப்பிற்கான அணுகல் தேவை"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"அறிவிப்புப் புள்ளிகளைக் காட்ட, <xliff:g id="NAME">%1$s</xliff:g> இன் பயன்பாட்டு அறிவிப்புகளை இயக்கவும்"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"அறிவிப்புப் புள்ளிகளைக் காட்ட, <xliff:g id="NAME">%1$s</xliff:g> இன் ஆப்ஸ் அறிவிப்புகளை இயக்கவும்"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"அமைப்புகளை மாற்று"</string>
|
||||
<string name="notification_dots_service_title" msgid="4284221181793592871">"அறிவிப்புப் புள்ளிகளைக் காட்டு"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"முகப்புத் திரையில் ஐகானைச் சேர்"</string>
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark">
|
||||
<item name="android:colorControlHighlight">#75212121</item>
|
||||
<item name="allAppsInterimScrimAlpha">25</item>
|
||||
<item name="folderFillColor">#CDFFFFFF</item>
|
||||
<item name="folderTextColor">?attr/workspaceTextColor</item>
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.database.Cursor;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.LoaderTask;
|
||||
import com.android.launcher3.provider.RestoreDbTask;
|
||||
@@ -18,6 +19,8 @@ import com.android.launcher3.util.ContentWriter;
|
||||
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import static android.os.Process.myUserHandle;
|
||||
|
||||
public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "AWRestoredReceiver";
|
||||
@@ -77,9 +80,14 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
|
||||
state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
|
||||
}
|
||||
|
||||
String[] widgetIdParams = new String[] { Integer.toString(oldWidgetIds[i]) };
|
||||
// b/135926478: Work profile widget restore is broken in platform. This forces us to
|
||||
// recreate the widget during loading with the correct host provider.
|
||||
long mainProfileId = UserManagerCompat.getInstance(context)
|
||||
.getSerialNumberForUser(myUserHandle());
|
||||
String oldWidgetId = Integer.toString(oldWidgetIds[i]);
|
||||
int result = new ContentWriter(context, new ContentWriter.CommitParams(
|
||||
"appWidgetId=? and (restored & 1) = 1", widgetIdParams))
|
||||
"appWidgetId=? and (restored & 1) = 1 and profileId=?",
|
||||
new String[] { oldWidgetId, Long.toString(mainProfileId) }))
|
||||
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
|
||||
.put(LauncherSettings.Favorites.RESTORED, state)
|
||||
.commit();
|
||||
@@ -87,7 +95,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
|
||||
if (result == 0) {
|
||||
Cursor cursor = cr.query(Favorites.CONTENT_URI,
|
||||
new String[] {Favorites.APPWIDGET_ID},
|
||||
"appWidgetId=?", widgetIdParams, null);
|
||||
"appWidgetId=?", new String[] { oldWidgetId }, null);
|
||||
try {
|
||||
if (!cursor.moveToFirst()) {
|
||||
// The widget no long exists.
|
||||
|
||||
@@ -135,10 +135,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TAG,
|
||||
"startActivitySafely 1");
|
||||
}
|
||||
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
|
||||
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
@@ -162,10 +158,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
|
||||
} else if (user == null || user.equals(Process.myUserHandle())) {
|
||||
// Could be launching some bookkeeping activity
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TAG,
|
||||
"startActivitySafely 2");
|
||||
}
|
||||
startActivity(intent, optsBundle);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
|
||||
Process.myUserHandle(), sourceContainer);
|
||||
@@ -178,7 +170,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
getUserEventDispatcher().logAppLaunch(v, intent);
|
||||
getStatsLogManager().logAppLaunch(v, intent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException|SecurityException e) {
|
||||
} catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
|
||||
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
|
||||
}
|
||||
|
||||
@@ -319,9 +319,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_TAG, "BubbleTextView.onTouchEvent " + event);
|
||||
}
|
||||
// Call the superclass onTouchEvent first, because sometimes it changes the state to
|
||||
// isPressed() on an ACTION_UP
|
||||
boolean result = super.onTouchEvent(event);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
@@ -108,17 +108,20 @@ public class FirstFrameAnimatorHelper implements OnDrawListener, OnAttachStateCh
|
||||
// For the second frame, if the first frame took more than 16ms,
|
||||
// adjust the start time and pretend it took only 16ms anyway. This
|
||||
// prevents a large jump in the animation due to an expensive first frame
|
||||
} else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY &&
|
||||
!mAdjustedSecondFrameTime &&
|
||||
currentTime > mStartTime + SINGLE_FRAME_MS &&
|
||||
currentPlayTime > SINGLE_FRAME_MS) {
|
||||
animation.setCurrentPlayTime(SINGLE_FRAME_MS);
|
||||
mAdjustedSecondFrameTime = true;
|
||||
} else {
|
||||
if (frameNum > 1) {
|
||||
mRootView.post(() -> animation.removeUpdateListener(this));
|
||||
int singleFrameMS = getSingleFrameMs(mRootView.getContext());
|
||||
if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY &&
|
||||
!mAdjustedSecondFrameTime &&
|
||||
currentTime > mStartTime + singleFrameMS &&
|
||||
currentPlayTime > singleFrameMS) {
|
||||
animation.setCurrentPlayTime(singleFrameMS);
|
||||
mAdjustedSecondFrameTime = true;
|
||||
} else {
|
||||
if (frameNum > 1) {
|
||||
mRootView.post(() -> animation.removeUpdateListener(this));
|
||||
}
|
||||
if (DEBUG) print(animation);
|
||||
}
|
||||
if (DEBUG) print(animation);
|
||||
}
|
||||
mHandlingOnAnimationUpdate = false;
|
||||
} else {
|
||||
|
||||
@@ -890,9 +890,6 @@ 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) {
|
||||
@@ -1809,11 +1806,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TAG,
|
||||
"startActivitySafely outer");
|
||||
}
|
||||
|
||||
if (!hasBeenResumed()) {
|
||||
// Workaround an issue where the WM launch animation is clobbered when finishing the
|
||||
// recents animation into launcher. Defer launching the activity until Launcher is
|
||||
@@ -1904,6 +1896,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
if (mPendingExecutor != null) {
|
||||
mPendingExecutor.markCompleted();
|
||||
mPendingExecutor = null;
|
||||
|
||||
// We might have set this flag previously and forgot to clear it.
|
||||
mAppsView.getAppsStore()
|
||||
.disableDeferUpdatesSilently(AllAppsStore.DEFER_UPDATES_NEXT_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2257,9 +2253,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
|
||||
@Override
|
||||
public void executeOnNextDraw(ViewOnDrawExecutor executor) {
|
||||
if (mPendingExecutor != null) {
|
||||
mPendingExecutor.markCompleted();
|
||||
}
|
||||
clearPendingBinds();
|
||||
mPendingExecutor = executor;
|
||||
if (!isInState(ALL_APPS)) {
|
||||
mAppsView.getAppsStore().enableDeferUpdates(AllAppsStore.DEFER_UPDATES_NEXT_DRAW);
|
||||
|
||||
@@ -243,6 +243,10 @@ public class LauncherState {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float getOverviewScrimAlpha(Launcher launcher) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getDescription(Launcher launcher) {
|
||||
return launcher.getWorkspace().getCurrentPageDescription();
|
||||
}
|
||||
|
||||
@@ -403,10 +403,6 @@ public class LauncherStateManager {
|
||||
}
|
||||
|
||||
private void onStateTransitionStart(LauncherState state) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"onStateTransitionStart");
|
||||
}
|
||||
if (mState != state) {
|
||||
mState.onStateDisabled(mLauncher);
|
||||
}
|
||||
@@ -429,11 +425,6 @@ public class LauncherStateManager {
|
||||
// Only change the stable states after the transitions have finished
|
||||
if (state != mCurrentStableState) {
|
||||
mLastStableState = state.getHistoryForState(mCurrentStableState);
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG,
|
||||
"mCurrentStableState = " + state.getClass().getSimpleName() + " @ " +
|
||||
android.util.Log.getStackTraceString(new Throwable()));
|
||||
}
|
||||
mCurrentStableState = state;
|
||||
}
|
||||
|
||||
@@ -580,10 +571,6 @@ public class LauncherStateManager {
|
||||
private final AnimatorSet mAnim;
|
||||
|
||||
public StartAnimRunnable(AnimatorSet anim) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"StartAnimRunnable");
|
||||
}
|
||||
mAnim = anim;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.Utilities.shouldDisableGestures;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
|
||||
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
|
||||
@@ -48,6 +47,7 @@ import android.view.animation.Interpolator;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.pageindicators.PageIndicator;
|
||||
import com.android.launcher3.touch.OverScroll;
|
||||
@@ -368,6 +368,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
*/
|
||||
protected void onPageEndTransition() {
|
||||
mWasInOverscroll = false;
|
||||
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
|
||||
}
|
||||
|
||||
protected int getUnboundedScrollX() {
|
||||
@@ -847,7 +848,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
*/
|
||||
|
||||
// Skip touch handling if there are no pages to swipe
|
||||
if (getChildCount() <= 0 || shouldDisableGestures(ev)) return false;
|
||||
if (getChildCount() <= 0) return false;
|
||||
|
||||
acquireVelocityTrackerAndAddMovement(ev);
|
||||
|
||||
@@ -1095,7 +1096,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
// Skip touch handling if there are no pages to swipe
|
||||
if (getChildCount() <= 0 || shouldDisableGestures(ev)) return false;
|
||||
if (getChildCount() <= 0) return false;
|
||||
|
||||
acquireVelocityTrackerAndAddMovement(ev);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
@@ -92,8 +94,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
|
||||
|
||||
/**
|
||||
* Various utilities shared amongst the Launcher's classes.
|
||||
*/
|
||||
@@ -127,16 +127,6 @@ public final class Utilities {
|
||||
*/
|
||||
public static final int EDGE_NAV_BAR = 1 << 8;
|
||||
|
||||
/**
|
||||
* Set on a motion event do disallow any gestures and only handle touch.
|
||||
* See {@link MotionEvent#setEdgeFlags(int)}.
|
||||
*/
|
||||
public static final int FLAG_NO_GESTURES = 1 << 9;
|
||||
|
||||
public static boolean shouldDisableGestures(MotionEvent ev) {
|
||||
return (ev.getEdgeFlags() & FLAG_NO_GESTURES) == FLAG_NO_GESTURES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the device has a debug build. Should only be used to store additional info or
|
||||
* add extra logging and not for changing the app behavior.
|
||||
|
||||
@@ -81,10 +81,10 @@ import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.WorkspaceTouchListener;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
@@ -370,10 +370,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
@Override
|
||||
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"onDragStart 1");
|
||||
}
|
||||
if (ENFORCE_DRAG_EVENT_ORDER) {
|
||||
enforceDragParity("onDragStart", 0, 0);
|
||||
}
|
||||
@@ -424,10 +420,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
}
|
||||
|
||||
// Always enter the spring loaded mode
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"onDragStart 2");
|
||||
}
|
||||
mLauncher.getStateManager().goToState(SPRING_LOADED);
|
||||
}
|
||||
|
||||
@@ -1061,8 +1053,11 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
// Not announcing the overlay page for accessibility since it announces itself.
|
||||
} else if (Float.compare(scroll, 0f) == 0) {
|
||||
if (mOverlayShown) {
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
|
||||
UserEventDispatcher ued = mLauncher.getUserEventDispatcher();
|
||||
if (!ued.isPreviousHomeGesture()) {
|
||||
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
|
||||
Action.Direction.RIGHT, ContainerType.WORKSPACE, -1);
|
||||
}
|
||||
} else if (Float.compare(mOverlayTranslation, 0f) != 0) {
|
||||
// When arriving to 0 overscroll from non-zero overscroll, announce page for
|
||||
// accessibility since default announcements were disabled while in overscroll
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.keyboard.FocusedItemDecorator;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
@@ -297,7 +298,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
|
||||
@Override
|
||||
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
|
||||
// This is filled in {@link AllAppsRecyclerView}
|
||||
if (getApps().hasFilter()) {
|
||||
targetParent.containerType = ContainerType.SEARCHRESULT;
|
||||
} else {
|
||||
targetParent.containerType = ContainerType.ALLAPPS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -626,9 +631,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_TAG, "AllAppsContainerView.dispatchTouchEvent " + ev);
|
||||
}
|
||||
final boolean result = super.dispatchTouchEvent(ev);
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
|
||||
@@ -80,6 +80,10 @@ public class AllAppsStore {
|
||||
}
|
||||
}
|
||||
|
||||
public void disableDeferUpdatesSilently(int flag) {
|
||||
mDeferUpdatesFlags &= ~flag;
|
||||
}
|
||||
|
||||
public int getDeferUpdatesFlags() {
|
||||
return mDeferUpdatesFlags;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
@@ -168,10 +169,6 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
||||
@Override
|
||||
public void setStateWithAnimation(LauncherState toState,
|
||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG,
|
||||
"setStateWithAnimation " + toState.getClass().getSimpleName());
|
||||
}
|
||||
float targetProgress = toState.getVerticalProgress(mLauncher);
|
||||
if (Float.compare(mProgress, targetProgress) == 0) {
|
||||
setAlphas(toState, config, builder);
|
||||
@@ -212,13 +209,14 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
||||
PropertySetter setter = config == null ? NO_ANIM_PROPERTY_SETTER
|
||||
: config.getPropertySetter(builder);
|
||||
boolean hasHeaderExtra = (visibleElements & ALL_APPS_HEADER_EXTRA) != 0;
|
||||
boolean hasContent = (visibleElements & ALL_APPS_CONTENT) != 0;
|
||||
boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0;
|
||||
|
||||
Interpolator allAppsFade = builder.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
|
||||
setter.setViewAlpha(mAppsView.getContentView(), hasContent ? 1 : 0, allAppsFade);
|
||||
setter.setViewAlpha(mAppsView.getScrollBar(), hasContent ? 1 : 0, allAppsFade);
|
||||
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasContent, setter,
|
||||
allAppsFade);
|
||||
Interpolator headerFade = builder.getInterpolator(ANIM_ALL_APPS_HEADER_FADE, allAppsFade);
|
||||
setter.setViewAlpha(mAppsView.getContentView(), hasAllAppsContent ? 1 : 0, allAppsFade);
|
||||
setter.setViewAlpha(mAppsView.getScrollBar(), hasAllAppsContent ? 1 : 0, allAppsFade);
|
||||
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasAllAppsContent,
|
||||
setter, headerFade, allAppsFade);
|
||||
mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
|
||||
|
||||
setter.setInt(mScrimView, ScrimView.DRAG_HANDLE_ALPHA,
|
||||
|
||||
@@ -301,11 +301,6 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
||||
}
|
||||
|
||||
private void refreshRecyclerView() {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_START_TAG,
|
||||
"refreshRecyclerView @ " + android.util.Log.getStackTraceString(
|
||||
new Throwable()));
|
||||
}
|
||||
if (mAdapter != null) {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ public interface FloatingHeaderRow {
|
||||
*/
|
||||
boolean hasVisibleContent();
|
||||
|
||||
void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
|
||||
PropertySetter setter, Interpolator fadeInterpolator);
|
||||
void setContentVisibility(boolean hasHeaderExtra, boolean hasAllAppsContent,
|
||||
PropertySetter setter, Interpolator headerFade, Interpolator allAppsFade);
|
||||
|
||||
/**
|
||||
* Scrolls the content vertically.
|
||||
|
||||
@@ -27,6 +27,10 @@ import android.view.ViewGroup;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.Launcher;
|
||||
@@ -40,10 +44,6 @@ import com.android.systemui.plugins.PluginListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class FloatingHeaderView extends LinearLayout implements
|
||||
ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
|
||||
OnHeightUpdatedListener {
|
||||
@@ -363,14 +363,14 @@ public class FloatingHeaderView extends LinearLayout implements
|
||||
p.y = getTop() - mCurrentRV.getTop() - mParent.getTop();
|
||||
}
|
||||
|
||||
public void setContentVisibility(boolean hasHeader, boolean hasContent, PropertySetter setter,
|
||||
Interpolator fadeInterpolator) {
|
||||
public void setContentVisibility(boolean hasHeader, boolean hasAllAppsContent,
|
||||
PropertySetter setter, Interpolator headerFade, Interpolator allAppsFade) {
|
||||
for (FloatingHeaderRow row : mAllRows) {
|
||||
row.setContentVisibility(hasHeader, hasContent, setter, fadeInterpolator);
|
||||
row.setContentVisibility(hasHeader, hasAllAppsContent, setter, headerFade, allAppsFade);
|
||||
}
|
||||
|
||||
allowTouchForwarding(hasContent);
|
||||
setter.setFloat(mTabLayout, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
|
||||
allowTouchForwarding(hasAllAppsContent);
|
||||
setter.setFloat(mTabLayout, ALPHA, hasAllAppsContent ? 1 : 0, headerFade);
|
||||
}
|
||||
|
||||
protected void allowTouchForwarding(boolean allow) {
|
||||
|
||||
@@ -64,10 +64,10 @@ public class PluginHeaderRow implements FloatingHeaderRow {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
|
||||
PropertySetter setter, Interpolator fadeInterpolator) {
|
||||
public void setContentVisibility(boolean hasHeaderExtra, boolean hasAllAppsContent,
|
||||
PropertySetter setter, Interpolator headerFade, Interpolator allAppsFade) {
|
||||
// Don't use setViewAlpha as we want to control the visibility ourselves.
|
||||
setter.setFloat(mView, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
|
||||
setter.setFloat(mView, ALPHA, hasAllAppsContent ? 1 : 0, headerFade);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,6 +39,8 @@ public class AnimatorSetBuilder {
|
||||
public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
|
||||
public static final int ANIM_OVERVIEW_FADE = 9;
|
||||
public static final int ANIM_ALL_APPS_FADE = 10;
|
||||
public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
|
||||
public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
|
||||
|
||||
public static final int FLAG_DONT_ANIMATE_OVERVIEW = 1 << 0;
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
package com.android.launcher3.anim;
|
||||
|
||||
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Path;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
@@ -144,7 +145,8 @@ public class Interpolators {
|
||||
public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
|
||||
float upperBound) {
|
||||
if (upperBound <= lowerBound) {
|
||||
throw new IllegalArgumentException("lowerBound must be less than upperBound");
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"lowerBound (%f) must be less than upperBound (%f)", lowerBound, upperBound));
|
||||
}
|
||||
return t -> {
|
||||
if (t < lowerBound) {
|
||||
@@ -187,13 +189,13 @@ public class Interpolators {
|
||||
* @param totalDistancePx The distance against which progress is calculated.
|
||||
*/
|
||||
public OvershootParams(float startProgress, float overshootPastProgress,
|
||||
float endProgress, float velocityPxPerMs, int totalDistancePx) {
|
||||
float endProgress, float velocityPxPerMs, int totalDistancePx, Context context) {
|
||||
velocityPxPerMs = Math.abs(velocityPxPerMs);
|
||||
start = startProgress;
|
||||
int startPx = (int) (start * totalDistancePx);
|
||||
// Overshoot by about half a frame.
|
||||
float overshootBy = OVERSHOOT_FACTOR * velocityPxPerMs *
|
||||
SINGLE_FRAME_MS / totalDistancePx / 2;
|
||||
getSingleFrameMs(context) / totalDistancePx / 2;
|
||||
overshootBy = Utilities.boundToRange(overshootBy, 0.02f, 0.15f);
|
||||
end = overshootPastProgress + overshootBy;
|
||||
int endPx = (int) (end * totalDistancePx);
|
||||
|
||||
@@ -96,7 +96,10 @@ public class SpringObjectAnimator<T> extends ValueAnimator {
|
||||
}
|
||||
});
|
||||
|
||||
mSpring.addUpdateListener((animation, value, velocity) -> mSpringEnded = false);
|
||||
mSpring.addUpdateListener((animation, value, velocity) -> {
|
||||
mSpringEnded = false;
|
||||
mEnded = false;
|
||||
});
|
||||
mSpring.addEndListener((animation, canceled, value, velocity) -> {
|
||||
mSpringEnded = true;
|
||||
tryEnding();
|
||||
|
||||
@@ -53,9 +53,6 @@ public class AccessibilityManagerCompat {
|
||||
}
|
||||
|
||||
public static void sendStateEventToTest(Context context, int stateOrdinal) {
|
||||
if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
|
||||
android.util.Log.e(TestProtocol.NO_ALLAPPS_EVENT_TAG, "sendStateEventToTest");
|
||||
}
|
||||
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
|
||||
if (accessibilityManager == null) return;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.launcher3.compat;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -48,6 +49,11 @@ public abstract class PackageInstallerCompat {
|
||||
*/
|
||||
public abstract HashMap<String, PackageInstaller.SessionInfo> updateAndGetActiveSessionCache();
|
||||
|
||||
/**
|
||||
* @return an active SessionInfo for {@param pkg} or null if none exists.
|
||||
*/
|
||||
public abstract PackageInstaller.SessionInfo getActiveSessionInfo(UserHandle user, String pkg);
|
||||
|
||||
public abstract void onStop();
|
||||
|
||||
public static final class PackageInstallInfo {
|
||||
|
||||
@@ -64,9 +64,9 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
|
||||
@Override
|
||||
public HashMap<String, SessionInfo> updateAndGetActiveSessionCache() {
|
||||
HashMap<String, SessionInfo> activePackages = new HashMap<>();
|
||||
UserHandle user = Process.myUserHandle();
|
||||
UserHandle primaryUser = Process.myUserHandle();
|
||||
for (SessionInfo info : getAllVerifiedSessions()) {
|
||||
addSessionInfoToCache(info, user);
|
||||
addSessionInfoToCache(info, Utilities.ATLEAST_Q ? info.getUser() : primaryUser);
|
||||
if (info.getAppPackageName() != null) {
|
||||
activePackages.put(info.getAppPackageName(), info);
|
||||
mActiveSessions.put(info.getSessionId(), info.getAppPackageName());
|
||||
@@ -75,6 +75,19 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
|
||||
return activePackages;
|
||||
}
|
||||
|
||||
public SessionInfo getActiveSessionInfo(UserHandle user, String pkg) {
|
||||
for (SessionInfo info : getAllVerifiedSessions()) {
|
||||
boolean match = pkg.equals(info.getAppPackageName());
|
||||
if (Utilities.ATLEAST_Q && !user.equals(info.getUser())) {
|
||||
match = false;
|
||||
}
|
||||
if (match) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Thunk void addSessionInfoToCache(SessionInfo info, UserHandle user) {
|
||||
String packageName = info.getAppPackageName();
|
||||
if (packageName != null) {
|
||||
|
||||
@@ -153,16 +153,6 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
||||
PinItemDragListener listener = new PinItemDragListener(mRequest, bounds,
|
||||
img.getBitmap().getWidth(), img.getWidth());
|
||||
|
||||
Intent homeIntent = listener.addToIntent(
|
||||
new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setPackage(getPackageName())
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
|
||||
listener.initWhenReady();
|
||||
startActivity(homeIntent,
|
||||
ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out).toBundle());
|
||||
mFinishOnPause = true;
|
||||
|
||||
// Start a system drag and drop. We use a transparent bitmap as preview for system drag
|
||||
// as the preview is handled internally by launcher.
|
||||
@@ -179,6 +169,18 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
||||
outShadowTouchPoint.set(SHADOW_SIZE / 2, SHADOW_SIZE / 2);
|
||||
}
|
||||
}, null, View.DRAG_FLAG_GLOBAL);
|
||||
|
||||
|
||||
Intent homeIntent = listener.addToIntent(
|
||||
new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setPackage(getPackageName())
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
|
||||
listener.initWhenReady();
|
||||
startActivity(homeIntent,
|
||||
ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out).toBundle());
|
||||
mFinishOnPause = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,9 +137,6 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen
|
||||
|
||||
@Override
|
||||
public boolean shouldStartDrag(double distanceDragged) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_DRAG_TAG, "BIDL.shouldStartDrag");
|
||||
}
|
||||
// Stay in pre-drag mode, if workspace is locked.
|
||||
return !mLauncher.isWorkspaceLocked();
|
||||
}
|
||||
|
||||
@@ -474,10 +474,6 @@ public class DragController implements DragDriver.EventListener, TouchController
|
||||
}
|
||||
|
||||
private void handleMoveEvent(int x, int y) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"handleMoveEvent 1");
|
||||
}
|
||||
mDragObject.dragView.move(x, y);
|
||||
|
||||
// Drop on someone?
|
||||
@@ -492,22 +488,8 @@ 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) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"handleMoveEvent 2");
|
||||
}
|
||||
callOnDragStart();
|
||||
}
|
||||
}
|
||||
@@ -545,10 +527,6 @@ public class DragController implements DragDriver.EventListener, TouchController
|
||||
* Call this from a drag source view.
|
||||
*/
|
||||
public boolean onControllerTouchEvent(MotionEvent ev) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
android.util.Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"onControllerTouchEvent");
|
||||
}
|
||||
if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,12 +48,13 @@ import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DropTargetBar;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.uioverrides.UiFactory;
|
||||
@@ -92,7 +93,8 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
|
||||
// Related to adjacent page hints
|
||||
private final ViewGroupFocusHelper mFocusIndicatorHelper;
|
||||
private final WorkspaceAndHotseatScrim mScrim;
|
||||
private final WorkspaceAndHotseatScrim mWorkspaceScrim;
|
||||
private final OverviewScrim mOverviewScrim;
|
||||
|
||||
/**
|
||||
* Used to create a new DragLayer from XML.
|
||||
@@ -108,12 +110,13 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
setChildrenDrawingOrderEnabled(true);
|
||||
|
||||
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
|
||||
mScrim = new WorkspaceAndHotseatScrim(this);
|
||||
mWorkspaceScrim = new WorkspaceAndHotseatScrim(this);
|
||||
mOverviewScrim = new OverviewScrim(this);
|
||||
}
|
||||
|
||||
public void setup(DragController dragController, Workspace workspace) {
|
||||
mDragController = dragController;
|
||||
mScrim.setWorkspace(workspace);
|
||||
mWorkspaceScrim.setWorkspace(workspace);
|
||||
recreateControllers();
|
||||
}
|
||||
|
||||
@@ -529,25 +532,39 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
// Draw the background below children.
|
||||
mScrim.draw(canvas);
|
||||
mWorkspaceScrim.draw(canvas);
|
||||
mOverviewScrim.updateCurrentScrimmedView(this);
|
||||
mFocusIndicatorHelper.draw(canvas);
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||
if (child == mOverviewScrim.getScrimmedView()) {
|
||||
mOverviewScrim.draw(canvas);
|
||||
}
|
||||
return super.drawChild(canvas, child, drawingTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
mScrim.setSize(w, h);
|
||||
mWorkspaceScrim.setSize(w, h);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
super.setInsets(insets);
|
||||
mScrim.onInsetsChanged(insets);
|
||||
mWorkspaceScrim.onInsetsChanged(insets);
|
||||
mOverviewScrim.onInsetsChanged(insets);
|
||||
}
|
||||
|
||||
public WorkspaceAndHotseatScrim getScrim() {
|
||||
return mScrim;
|
||||
return mWorkspaceScrim;
|
||||
}
|
||||
|
||||
public OverviewScrim getOverviewScrim() {
|
||||
return mOverviewScrim;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,8 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.R;
|
||||
@@ -66,15 +68,19 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
|
||||
return mBadge;
|
||||
}
|
||||
|
||||
public static FolderAdaptiveIcon createFolderAdaptiveIcon(
|
||||
public static @Nullable FolderAdaptiveIcon createFolderAdaptiveIcon(
|
||||
Launcher launcher, int folderId, Point dragViewSize) {
|
||||
Preconditions.assertNonUiThread();
|
||||
int margin = launcher.getResources()
|
||||
.getDimensionPixelSize(R.dimen.blur_size_medium_outline);
|
||||
|
||||
// Allocate various bitmaps on the background thread, because why not!
|
||||
final Bitmap badge = Bitmap.createBitmap(
|
||||
dragViewSize.x - margin, dragViewSize.y - margin, Bitmap.Config.ARGB_8888);
|
||||
int width = dragViewSize.x - margin;
|
||||
int height = dragViewSize.y - margin;
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
final Bitmap badge = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
|
||||
// Create the actual drawable on the UI thread to avoid race conditions with
|
||||
// FolderIcon draw pass
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.os.Handler;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
@@ -87,6 +88,9 @@ public class DragPreviewProvider {
|
||||
Rect bounds = getDrawableBounds(d);
|
||||
destCanvas.translate(blurSizeOutline / 2 - bounds.left,
|
||||
blurSizeOutline / 2 - bounds.top);
|
||||
if (d instanceof FastBitmapDrawable) {
|
||||
((FastBitmapDrawable) d).setScale(1);
|
||||
}
|
||||
d.draw(destCanvas);
|
||||
} else {
|
||||
final Rect clipRect = mTempRect;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.launcher3.graphics;
|
||||
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* View scrim which draws behind overview (recent apps).
|
||||
*/
|
||||
public class OverviewScrim extends Scrim {
|
||||
|
||||
private @NonNull View mStableScrimmedView;
|
||||
// Might be higher up if mStableScrimmedView is invisible.
|
||||
private @Nullable View mCurrentScrimmedView;
|
||||
|
||||
public OverviewScrim(View view) {
|
||||
super(view);
|
||||
mStableScrimmedView = mCurrentScrimmedView = mLauncher.getOverviewPanel();
|
||||
|
||||
onExtractedColorsChanged(mWallpaperColorInfo);
|
||||
}
|
||||
|
||||
public void onInsetsChanged(Rect insets) {
|
||||
mStableScrimmedView = (OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0
|
||||
? mLauncher.getHotseat()
|
||||
: mLauncher.getOverviewPanel();
|
||||
}
|
||||
|
||||
public void updateCurrentScrimmedView(ViewGroup root) {
|
||||
// Find the lowest view that is at or above the view we want to show the scrim behind.
|
||||
mCurrentScrimmedView = mStableScrimmedView;
|
||||
int currentIndex = root.indexOfChild(mCurrentScrimmedView);
|
||||
final int childCount = root.getChildCount();
|
||||
while (mCurrentScrimmedView.getVisibility() != VISIBLE && currentIndex < childCount) {
|
||||
currentIndex++;
|
||||
mCurrentScrimmedView = root.getChildAt(currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The view to draw the scrim behind.
|
||||
*/
|
||||
public View getScrimmedView() {
|
||||
return mCurrentScrimmedView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.launcher3.graphics;
|
||||
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
|
||||
/**
|
||||
* Contains general scrim properties such as wallpaper-extracted color that subclasses can use.
|
||||
*/
|
||||
public class Scrim implements View.OnAttachStateChangeListener,
|
||||
WallpaperColorInfo.OnChangeListener {
|
||||
|
||||
public static Property<Scrim, Float> SCRIM_PROGRESS =
|
||||
new Property<Scrim, Float>(Float.TYPE, "scrimProgress") {
|
||||
@Override
|
||||
public Float get(Scrim scrim) {
|
||||
return scrim.mScrimProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Scrim scrim, Float value) {
|
||||
scrim.setScrimProgress(value);
|
||||
}
|
||||
};
|
||||
|
||||
protected final Launcher mLauncher;
|
||||
protected final WallpaperColorInfo mWallpaperColorInfo;
|
||||
protected final View mRoot;
|
||||
|
||||
protected float mScrimProgress;
|
||||
protected int mScrimColor;
|
||||
protected int mScrimAlpha = 0;
|
||||
|
||||
public Scrim(View view) {
|
||||
mRoot = view;
|
||||
mLauncher = Launcher.getLauncher(view.getContext());
|
||||
mWallpaperColorInfo = WallpaperColorInfo.getInstance(mLauncher);
|
||||
|
||||
view.addOnAttachStateChangeListener(this);
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawColor(setColorAlphaBound(mScrimColor, mScrimAlpha));
|
||||
}
|
||||
|
||||
private void setScrimProgress(float progress) {
|
||||
if (mScrimProgress != progress) {
|
||||
mScrimProgress = progress;
|
||||
mScrimAlpha = Math.round(255 * mScrimProgress);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
mWallpaperColorInfo.addOnChangeListener(this);
|
||||
onExtractedColorsChanged(mWallpaperColorInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
mWallpaperColorInfo.removeOnChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
|
||||
mScrimColor = wallpaperColorInfo.getMainColor();
|
||||
if (mScrimAlpha > 0) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
mRoot.invalidate();
|
||||
}
|
||||
}
|
||||
@@ -40,34 +40,19 @@ import android.util.DisplayMetrics;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
/**
|
||||
* View scrim which draws behind hotseat and workspace
|
||||
*/
|
||||
public class WorkspaceAndHotseatScrim implements
|
||||
View.OnAttachStateChangeListener, WallpaperColorInfo.OnChangeListener {
|
||||
|
||||
public static Property<WorkspaceAndHotseatScrim, Float> SCRIM_PROGRESS =
|
||||
new Property<WorkspaceAndHotseatScrim, Float>(Float.TYPE, "scrimProgress") {
|
||||
@Override
|
||||
public Float get(WorkspaceAndHotseatScrim scrim) {
|
||||
return scrim.mScrimProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(WorkspaceAndHotseatScrim scrim, Float value) {
|
||||
scrim.setScrimProgress(value);
|
||||
}
|
||||
};
|
||||
public class WorkspaceAndHotseatScrim extends Scrim {
|
||||
|
||||
public static Property<WorkspaceAndHotseatScrim, Float> SYSUI_PROGRESS =
|
||||
new Property<WorkspaceAndHotseatScrim, Float>(Float.TYPE, "sysUiProgress") {
|
||||
@@ -117,9 +102,6 @@ public class WorkspaceAndHotseatScrim implements
|
||||
private static final int ALPHA_MASK_WIDTH_DP = 2;
|
||||
|
||||
private final Rect mHighlightRect = new Rect();
|
||||
private final Launcher mLauncher;
|
||||
private final WallpaperColorInfo mWallpaperColorInfo;
|
||||
private final View mRoot;
|
||||
|
||||
private Workspace mWorkspace;
|
||||
|
||||
@@ -132,11 +114,6 @@ public class WorkspaceAndHotseatScrim implements
|
||||
|
||||
private final Drawable mTopScrim;
|
||||
|
||||
private int mFullScrimColor;
|
||||
|
||||
private float mScrimProgress;
|
||||
private int mScrimAlpha = 0;
|
||||
|
||||
private float mSysUiProgress = 1;
|
||||
private boolean mHideSysUiScrim;
|
||||
|
||||
@@ -144,9 +121,7 @@ public class WorkspaceAndHotseatScrim implements
|
||||
private float mSysUiAnimMultiplier = 1;
|
||||
|
||||
public WorkspaceAndHotseatScrim(View view) {
|
||||
mRoot = view;
|
||||
mLauncher = Launcher.getLauncher(view.getContext());
|
||||
mWallpaperColorInfo = WallpaperColorInfo.getInstance(mLauncher);
|
||||
super(view);
|
||||
|
||||
mMaskHeight = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_DP,
|
||||
view.getResources().getDisplayMetrics());
|
||||
@@ -154,7 +129,6 @@ public class WorkspaceAndHotseatScrim implements
|
||||
mBottomMask = mTopScrim == null ? null : createDitheredAlphaMask();
|
||||
mHideSysUiScrim = mTopScrim == null;
|
||||
|
||||
view.addOnAttachStateChangeListener(this);
|
||||
onExtractedColorsChanged(mWallpaperColorInfo);
|
||||
}
|
||||
|
||||
@@ -176,7 +150,7 @@ public class WorkspaceAndHotseatScrim implements
|
||||
canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
|
||||
}
|
||||
|
||||
canvas.drawColor(setColorAlphaBound(mFullScrimColor, mScrimAlpha));
|
||||
super.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@@ -190,11 +164,8 @@ public class WorkspaceAndHotseatScrim implements
|
||||
mSysUiAnimMultiplier = 0;
|
||||
reapplySysUiAlphaNoInvalidate();
|
||||
|
||||
ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, 1);
|
||||
anim.setAutoCancel(true);
|
||||
anim.setDuration(600);
|
||||
anim.setStartDelay(mLauncher.getWindow().getTransitionBackgroundFadeDuration());
|
||||
anim.start();
|
||||
animateToSysuiMultiplier(1, 600,
|
||||
mLauncher.getWindow().getTransitionBackgroundFadeDuration());
|
||||
mAnimateScrimOnNextDraw = false;
|
||||
}
|
||||
|
||||
@@ -207,24 +178,24 @@ public class WorkspaceAndHotseatScrim implements
|
||||
}
|
||||
}
|
||||
|
||||
public void animateToSysuiMultiplier(float toMultiplier, long duration,
|
||||
long startDelay) {
|
||||
ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, toMultiplier);
|
||||
anim.setAutoCancel(true);
|
||||
anim.setDuration(duration);
|
||||
anim.setStartDelay(startDelay);
|
||||
anim.start();
|
||||
}
|
||||
|
||||
public void onInsetsChanged(Rect insets) {
|
||||
mDrawTopScrim = mTopScrim != null && insets.top > 0;
|
||||
mDrawBottomScrim = mBottomMask != null &&
|
||||
!mLauncher.getDeviceProfile().isVerticalBarLayout();
|
||||
}
|
||||
|
||||
private void setScrimProgress(float progress) {
|
||||
if (mScrimProgress != progress) {
|
||||
mScrimProgress = progress;
|
||||
mScrimAlpha = Math.round(255 * mScrimProgress);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
mWallpaperColorInfo.addOnChangeListener(this);
|
||||
onExtractedColorsChanged(mWallpaperColorInfo);
|
||||
super.onViewAttachedToWindow(view);
|
||||
|
||||
if (mTopScrim != null) {
|
||||
IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
|
||||
@@ -235,7 +206,7 @@ public class WorkspaceAndHotseatScrim implements
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
mWallpaperColorInfo.removeOnChangeListener(this);
|
||||
super.onViewDetachedFromWindow(view);
|
||||
if (mTopScrim != null) {
|
||||
mRoot.getContext().unregisterReceiver(mReceiver);
|
||||
}
|
||||
@@ -248,10 +219,7 @@ public class WorkspaceAndHotseatScrim implements
|
||||
mBottomMaskPaint.setColor(ColorUtils.compositeColors(DARK_SCRIM_COLOR,
|
||||
wallpaperColorInfo.getMainColor()));
|
||||
reapplySysUiAlpha();
|
||||
mFullScrimColor = wallpaperColorInfo.getMainColor();
|
||||
if (mScrimAlpha > 0) {
|
||||
invalidate();
|
||||
}
|
||||
super.onExtractedColorsChanged(wallpaperColorInfo);
|
||||
}
|
||||
|
||||
public void setSize(int w, int h) {
|
||||
@@ -291,10 +259,6 @@ public class WorkspaceAndHotseatScrim implements
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
mRoot.invalidate();
|
||||
}
|
||||
|
||||
public Bitmap createDitheredAlphaMask() {
|
||||
DisplayMetrics dm = mLauncher.getResources().getDisplayMetrics();
|
||||
int width = ResourceUtils.pxFromDp(ALPHA_MASK_WIDTH_DP, dm);
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.android.launcher3.logging;
|
||||
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.DEFAULT_CONTAINERTYPE;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -64,4 +67,20 @@ public class StatsLogUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getContainerTypeFromState(int state) {
|
||||
int containerType = DEFAULT_CONTAINERTYPE;
|
||||
switch (state) {
|
||||
case StatsLogUtils.LAUNCHER_STATE_ALLAPPS:
|
||||
containerType = ContainerType.ALLAPPS;
|
||||
break;
|
||||
case StatsLogUtils.LAUNCHER_STATE_HOME:
|
||||
containerType = ContainerType.WORKSPACE;
|
||||
break;
|
||||
case StatsLogUtils.LAUNCHER_STATE_OVERVIEW:
|
||||
containerType = ContainerType.OVERVIEW;
|
||||
break;
|
||||
}
|
||||
return containerType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ public class UserEventDispatcher implements ResourceBasedOverride {
|
||||
protected InstantAppResolver mInstantAppResolver;
|
||||
private boolean mAppOrTaskLaunch;
|
||||
private UserEventDelegate mDelegate;
|
||||
private boolean mPreviousHomeGesture;
|
||||
|
||||
// APP_ICON SHORTCUT WIDGET
|
||||
// --------------------------------------------------------------
|
||||
@@ -399,11 +400,22 @@ public class UserEventDispatcher implements ResourceBasedOverride {
|
||||
mElapsedContainerMillis = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
public final void setPreviousHomeGesture(boolean homeGesture) {
|
||||
mPreviousHomeGesture = homeGesture;
|
||||
}
|
||||
|
||||
public final boolean isPreviousHomeGesture() {
|
||||
return mPreviousHomeGesture;
|
||||
}
|
||||
|
||||
public final void resetActionDurationMillis() {
|
||||
mActionDurationMillis = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
|
||||
if (mPreviousHomeGesture) {
|
||||
mPreviousHomeGesture = false;
|
||||
}
|
||||
mAppOrTaskLaunch = false;
|
||||
ev.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
||||
ev.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
||||
@@ -426,6 +438,7 @@ public class UserEventDispatcher implements ResourceBasedOverride {
|
||||
ev.actionDurationMillis);
|
||||
log += "\n\n";
|
||||
Log.d(TAG, log);
|
||||
return;
|
||||
}
|
||||
|
||||
private static String getTargetsStr(Target[] targets) {
|
||||
|
||||
@@ -449,11 +449,6 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
|
||||
|
||||
@Override
|
||||
public boolean shouldStartDrag(double distanceDragged) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_DRAG_TAG,
|
||||
"createPreDragCondition().shouldStartDrag " + distanceDragged + ", "
|
||||
+ mStartDragThreshold);
|
||||
}
|
||||
return distanceDragged > mStartDragThreshold;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user