From fbd77c48cc147ae71ba0da4d89e5f21df2fcfc3f Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 23 Jul 2019 16:58:45 -0700 Subject: [PATCH 01/15] Distinguish mDragHandleProgress from mMidProgress mMidProgress is intended to be the point at which we reach Overview when swiping up and thus start scrimming it as All Apps shows above it. For that reason, mMidProgress needs to match OverviewState's progress. In contrast, the drag handle (accessibility arrow) can move up sooner to avoid overlapping with the QSB; for this, we added mDragHandleProgress. Bug: 136800511 Change-Id: I2825ff798707530420855257350e492b4b9b77dc --- .../android/quickstep/views/ShelfScrimView.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index 63c8023f6d..5a2f5c162a 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -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; @@ -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 From 4e6c45bcd3717af05a892a92565d55aa20728644 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 23 Jul 2019 11:26:38 -0700 Subject: [PATCH 02/15] Using the first frame delay based on the display refresh rate instead of hardcoding it to 16ms > Creating a utility class for caching display property changes Bug: 128940249 Change-Id: I6f9a214548de65bd1c8530508d665ee88312da4a --- .../AppToOverviewAnimationProvider.java | 5 +- .../TaskViewTouchController.java | 6 +- .../android/quickstep/RecentsActivity.java | 2 +- .../WindowTransformSwipeHandler.java | 6 +- .../launcher3/LauncherAnimationRunner.java | 9 +- .../launcher3/LauncherInitListener.java | 2 +- .../QuickstepAppTransitionManagerImpl.java | 4 +- .../quickstep/RecentsActivityTracker.java | 2 +- .../util/RemoteAnimationProvider.java | 5 +- .../launcher3/FirstFrameAnimatorHelper.java | 23 +-- .../android/launcher3/anim/Interpolators.java | 7 +- .../AbstractStateChangeTouchController.java | 12 +- .../launcher3/util/DefaultDisplay.java | 166 ++++++++++++++++++ .../launcher3/views/BaseDragLayer.java | 5 +- 14 files changed, 212 insertions(+), 42 deletions(-) create mode 100644 src/com/android/launcher3/util/DefaultDisplay.java diff --git a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java index fe159b5f02..92900f2168 100644 --- a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -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 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 imple ); return; } - result.setAnimation(createWindowAnimation(targetCompats)); + result.setAnimation(createWindowAnimation(targetCompats), context); } }; return ActivityOptionsCompat.makeRemoteAnimation( diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index 8e32bb370e..00e4f58e92 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -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 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)); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java index 60e7b12ec4..f08ae4a827 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java @@ -155,7 +155,7 @@ public final class RecentsActivity extends BaseRecentsActivity { mFallbackRecentsView.resetViewUI(); } }); - result.setAnimation(anim); + result.setAnimation(anim, RecentsActivity.this); } }; return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index cc9719b418..363e4cc6be 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -17,12 +17,12 @@ 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.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; @@ -780,14 +780,14 @@ public class WindowTransformSwipeHandler 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, endVelocity / 1000, - mTransitionDragLength); + mTransitionDragLength, mContext); endShift = overshoot.end; interpolator = overshoot.interpolator; duration = Utilities.boundToRange(overshoot.duration, MIN_OVERSHOOT_DURATION, diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java index 78f6ffa88c..a8e29569b1 100644 --- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java +++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java @@ -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)); } } } diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java index c5c5323ec5..b9ce1ceee5 100644 --- a/quickstep/src/com/android/launcher3/LauncherInitListener.java +++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java @@ -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); } } diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index 44324cb2e4..fc8d02a713 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -218,7 +218,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans anim.addListener(mForceInvisibleListener); } - result.setAnimation(anim); + result.setAnimation(anim, mLauncher); } }; @@ -819,7 +819,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans } mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL); - result.setAnimation(anim); + result.setAnimation(anim, mLauncher); } } } diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java index 0822e6199b..f9d2f11cba 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java +++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java @@ -68,7 +68,7 @@ public class RecentsActivityTracker 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); } diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java index a7e6d74f02..4503a43542 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java @@ -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( diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java index c967a96e48..6c5bc40b3e 100644 --- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java +++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java @@ -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 { diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java index 8443231e8d..c45cd85aad 100644 --- a/src/com/android/launcher3/anim/Interpolators.java +++ b/src/com/android/launcher3/anim/Interpolators.java @@ -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; @@ -188,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); diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index ae69f3b32d..49f515ad4b 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -22,9 +22,9 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherStateManager.ANIM_ALL; import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_SCALE_COMPONENT; import static com.android.launcher3.LauncherStateManager.NON_ATOMIC_COMPONENT; -import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; 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; @@ -55,8 +55,6 @@ import com.android.launcher3.util.TouchController; public abstract class AbstractStateChangeTouchController implements TouchController, SwipeDetector.Listener { - private static final String TAG = "ASCTouchController"; - // Progress after which the transition is assumed to be a success in case user does not fling public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f; @@ -396,8 +394,8 @@ public abstract class AbstractStateChangeTouchController duration = 0; startProgress = 1; } else { - startProgress = Utilities.boundToRange( - progress + velocity * SINGLE_FRAME_MS * mProgressMultiplier, 0f, 1f); + startProgress = Utilities.boundToRange(progress + + velocity * getSingleFrameMs(mLauncher) * mProgressMultiplier, 0f, 1f); duration = SwipeDetector.calculateDuration(velocity, endProgress - Math.max(progress, 0)) * durationMultiplier; } @@ -414,8 +412,8 @@ public abstract class AbstractStateChangeTouchController duration = 0; startProgress = 0; } else { - startProgress = Utilities.boundToRange( - progress + velocity * SINGLE_FRAME_MS * mProgressMultiplier, 0f, 1f); + startProgress = Utilities.boundToRange(progress + + velocity * getSingleFrameMs(mLauncher) * mProgressMultiplier, 0f, 1f); duration = SwipeDetector.calculateDuration(velocity, Math.min(progress, 1) - endProgress) * durationMultiplier; } diff --git a/src/com/android/launcher3/util/DefaultDisplay.java b/src/com/android/launcher3/util/DefaultDisplay.java new file mode 100644 index 0000000000..7719f084d7 --- /dev/null +++ b/src/com/android/launcher3/util/DefaultDisplay.java @@ -0,0 +1,166 @@ +/* + * 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.util; + +import android.content.Context; +import android.graphics.Point; +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManager.DisplayListener; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.Display; +import android.view.WindowManager; + +import java.util.ArrayList; + +/** + * Utility class to cache properties of default display to avoid a system RPC on every call. + */ +public class DefaultDisplay implements DisplayListener { + + public static final MainThreadInitializedObject INSTANCE = + new MainThreadInitializedObject<>(DefaultDisplay::new); + + private static final String TAG = "DefaultDisplay"; + + public static final int CHANGE_SIZE = 1 << 0; + public static final int CHANGE_ROTATION = 1 << 1; + public static final int CHANGE_FRAME_DELAY = 1 << 2; + + private final Context mContext; + private final int mId; + private final ArrayList mListeners = new ArrayList<>(); + private final Handler mChangeHandler; + private Info mInfo; + + private DefaultDisplay(Context context) { + mContext = context; + mInfo = new Info(context); + mId = mInfo.id; + mChangeHandler = new Handler(this::onChange); + + context.getSystemService(DisplayManager.class) + .registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper())); + } + + @Override + public final void onDisplayAdded(int displayId) { } + + @Override + public final void onDisplayRemoved(int displayId) { } + + @Override + public final void onDisplayChanged(int displayId) { + if (displayId != mId) { + return; + } + + Info oldInfo = mInfo; + Info info = new Info(mContext); + + int change = 0; + if (info.hasDifferentSize(oldInfo)) { + change |= CHANGE_SIZE; + } + if (oldInfo.rotation != info.rotation) { + change |= CHANGE_ROTATION; + } + if (info.singleFrameMs != oldInfo.singleFrameMs) { + change |= CHANGE_FRAME_DELAY; + } + + if (change != 0) { + mInfo = info; + mChangeHandler.sendEmptyMessage(change); + } + } + + public static int getSingleFrameMs(Context context) { + return INSTANCE.get(context).getInfo().singleFrameMs; + } + + public Info getInfo() { + return mInfo; + } + + public void addChangeListener(DisplayInfoChangeListener listener) { + mListeners.add(listener); + } + + public void removeChangeListener(DisplayInfoChangeListener listener) { + mListeners.remove(listener); + } + + private boolean onChange(Message msg) { + for (int i = mListeners.size() - 1; i >= 0; i--) { + mListeners.get(i).onDisplayInfoChanged(mInfo, msg.what); + } + return true; + } + + public static class Info { + + public final int id; + public final int rotation; + public final int singleFrameMs; + + public final Point realSize; + public final Point smallestSize; + public final Point largestSize; + + private Info(Context context) { + Display display = context.getSystemService(WindowManager.class).getDefaultDisplay(); + + id = display.getDisplayId(); + rotation = display.getRotation(); + + float refreshRate = display.getRefreshRate(); + singleFrameMs = refreshRate > 0 ? (int) (1000 / refreshRate) : 16; + + realSize = new Point(); + smallestSize = new Point(); + largestSize = new Point(); + display.getRealSize(realSize); + display.getCurrentSizeRange(smallestSize, largestSize); + } + + private boolean hasDifferentSize(Info info) { + if (!realSize.equals(info.realSize) + && !realSize.equals(info.realSize.y, info.realSize.x)) { + Log.d(TAG, String.format("Display size changed from %s to %s", + info.realSize, realSize)); + return true; + } + + if (!smallestSize.equals(info.smallestSize) || !largestSize.equals(info.largestSize)) { + Log.d(TAG, String.format("Available size changed from [%s, %s] to [%s, %s]", + smallestSize, largestSize, info.smallestSize, info.largestSize)); + return true; + } + + return false; + } + } + + /** + * Interface for listening for display changes + */ + public interface DisplayInfoChangeListener { + + void onDisplayInfoChanged(Info info, int flags); + } +} diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index f2f2f3b537..799762d8fe 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -20,7 +20,7 @@ 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.SINGLE_FRAME_MS; +import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs; import android.annotation.TargetApi; import android.content.Context; @@ -41,7 +41,6 @@ import android.widget.FrameLayout; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.Utilities; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.TouchController; @@ -219,7 +218,7 @@ public abstract class BaseDragLayer // This can happen if something goes wrong during a state change/transition. AbstractFloatingView floatingView = (AbstractFloatingView) child; if (floatingView.isOpen()) { - postDelayed(() -> floatingView.close(false), SINGLE_FRAME_MS); + postDelayed(() -> floatingView.close(false), getSingleFrameMs(getContext())); } } } From 0832d4778136d66062dc36e4f092920e0da0ac93 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Wed, 24 Jul 2019 17:20:18 -0700 Subject: [PATCH 03/15] Folder text should show dark highlight when longpressed Broken only on dark theme + super bright wallpaper Bug: 138245847 Change-Id: Ib8627ebd49ac2b31bbd747c15ae6b55eb22efffa --- res/values/styles.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/res/values/styles.xml b/res/values/styles.xml index 881f65d276..339aef5b60 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -104,6 +104,7 @@