Merge "Revert "Removing AM.getTasks call on UI thread during touch down"" into tm-dev
diff --git a/Android.bp b/Android.bp
index a523a62..b3027bc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -107,7 +107,6 @@
"androidx.cardview_cardview",
"com.google.android.material_material",
"iconloader_base",
- "modules-utils-build",
],
manifest: "AndroidManifest-common.xml",
sdk_version: "current",
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 36c9d13..5b912ad 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -244,8 +244,7 @@
mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS);
mHandler = new Handler(Looper.getMainLooper());
mDeviceProfile = mLauncher.getDeviceProfile();
- mBackAnimationController = new LauncherBackAnimationController(
- mDeviceProfile, mLauncher, this);
+ mBackAnimationController = new LauncherBackAnimationController(mLauncher, this);
Resources res = mLauncher.getResources();
mContentScale = res.getFloat(R.dimen.content_scale);
@@ -1441,6 +1440,10 @@
}
};
anim.addOnUpdateListener(runner);
+ } else {
+ // If no floating icon or widget is present, animate the to the default window
+ // target rect.
+ anim.addOnUpdateListener(new SpringAnimRunner(targets, targetRect, windowTargetBounds));
}
// Use a fixed velocity to start the animation.
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 3b02599..eda0823 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -53,6 +53,7 @@
public class DepthController implements StateHandler<LauncherState>,
BaseActivity.MultiWindowModeChangedListener {
+ private static final boolean OVERLAY_SCROLL_ENABLED = false;
public static final FloatProperty<DepthController> DEPTH =
new FloatProperty<DepthController>("depth") {
@Override
@@ -294,6 +295,9 @@
}
public void onOverlayScrollChanged(float progress) {
+ if (!OVERLAY_SCROLL_ENABLED) {
+ return;
+ }
// Add some padding to the progress, such we don't change the depth on the last frames of
// the animation. It's possible that a user flinging the feed quickly would scroll
// horizontally by accident, causing the device to enter client composition unnecessarily.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index a22398d..89e54b8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -156,14 +156,7 @@
updateIconSize(resources);
mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size);
- // Inflate views.
- mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
- R.layout.taskbar, null, false);
- TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
- TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
- FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
- StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
-
+ // Get display and corners first, as views might use them in constructor.
Display display = windowContext.getDisplay();
Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
? windowContext.getApplicationContext()
@@ -172,6 +165,14 @@
mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+ // Inflate views.
+ mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
+ R.layout.taskbar, null, false);
+ TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
+ TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
+ FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
+ StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
+
mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
// Construct controllers.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
new file mode 100644
index 0000000..1177bdb
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 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.taskbar
+
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Path
+import com.android.launcher3.R
+
+/**
+ * Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners.
+ */
+class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
+
+ val paint: Paint = Paint()
+ var backgroundHeight = context.deviceProfile.taskbarSize.toFloat()
+
+ private val leftCornerRadius = context.leftCornerRadius.toFloat()
+ private val rightCornerRadius = context.rightCornerRadius.toFloat()
+ private val invertedLeftCornerPath: Path = Path()
+ private val invertedRightCornerPath: Path = Path()
+
+ init {
+ paint.color = context.getColor(R.color.taskbar_background)
+ paint.flags = Paint.ANTI_ALIAS_FLAG
+ paint.style = Paint.Style.FILL
+
+ // Create the paths for the inverted rounded corners above the taskbar. Start with a filled
+ // square, and then subtract out a circle from the appropriate corner.
+ val square = Path()
+ square.addRect(0f, 0f, leftCornerRadius, leftCornerRadius, Path.Direction.CW)
+ val circle = Path()
+ circle.addCircle(leftCornerRadius, 0f, leftCornerRadius, Path.Direction.CW)
+ invertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE)
+ square.reset()
+ square.addRect(0f, 0f, rightCornerRadius, rightCornerRadius, Path.Direction.CW)
+ circle.reset()
+ circle.addCircle(0f, 0f, rightCornerRadius, Path.Direction.CW)
+ invertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE)
+ }
+
+ /**
+ * Draws the background with the given paint and height, on the provided canvas.
+ */
+ fun draw(canvas: Canvas) {
+ canvas.save()
+ canvas.translate(0f, canvas.height - backgroundHeight)
+
+ // Draw the background behind taskbar content.
+ canvas.drawRect(0f, 0f, canvas.width.toFloat(), backgroundHeight, paint)
+
+ // Draw the inverted rounded corners above the taskbar.
+ canvas.translate(0f, -leftCornerRadius)
+ canvas.drawPath(invertedLeftCornerPath, paint)
+ canvas.translate(0f, leftCornerRadius)
+ canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
+ canvas.drawPath(invertedRightCornerPath, paint)
+
+ canvas.restore()
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 9ba4a65..5c10565 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -477,7 +477,6 @@
tx.setScale(dragSurface, scale, scale);
tx.setAlpha(dragSurface, alpha);
tx.apply();
- tx.close();
}
});
mReturnAnimator.addListener(new AnimatorListenerAdapter() {
@@ -498,6 +497,7 @@
}
private void cleanUpSurface() {
+ tx.close();
maybeOnDragEnd();
// Synchronize removing the drag surface with the next draw after calling
// maybeOnDragEnd()
@@ -508,7 +508,6 @@
syncer.addToSync(syncId, viewRoot.getView());
syncer.addTransactionToSync(syncId, transaction);
syncer.markSyncReady(syncId);
-
mReturnAnimator = null;
}
});
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 4a80665..089c26d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -20,8 +20,6 @@
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -31,7 +29,6 @@
import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.R;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.views.BaseDragLayer;
@@ -44,13 +41,11 @@
*/
public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
- private final Paint mTaskbarBackgroundPaint;
- private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath;
+ private final TaskbarBackgroundRenderer mBackgroundRenderer;
private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
// Initialized in init.
private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
- private float mLeftCornerRadius, mRightCornerRadius;
private float mTaskbarBackgroundOffset;
@@ -70,35 +65,13 @@
public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, 1 /* alphaChannelCount */);
- mTaskbarBackgroundPaint = new Paint();
- mTaskbarBackgroundPaint.setColor(getResources().getColor(R.color.taskbar_background));
- mTaskbarBackgroundPaint.setAlpha(0);
- mTaskbarBackgroundPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- mTaskbarBackgroundPaint.setStyle(Paint.Style.FILL);
-
- // Will be set in init(), but this ensures they are always non-null.
- mInvertedLeftCornerPath = new Path();
- mInvertedRightCornerPath = new Path();
+ mBackgroundRenderer = new TaskbarBackgroundRenderer(mActivity);
+ mBackgroundRenderer.getPaint().setAlpha(0);
}
public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
mControllerCallbacks = callbacks;
- // Create the paths for the inverted rounded corners above the taskbar. Start with a filled
- // square, and then subtracting out a circle from the appropriate corner.
- mLeftCornerRadius = mActivity.getLeftCornerRadius();
- mRightCornerRadius = mActivity.getRightCornerRadius();
- Path square = new Path();
- square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW);
- Path circle = new Path();
- circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW);
- mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE);
- square.reset();
- square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW);
- circle.reset();
- circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW);
- mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE);
-
recreateControllers();
}
@@ -151,20 +124,8 @@
protected void dispatchDraw(Canvas canvas) {
float backgroundHeight = mControllerCallbacks.getTaskbarBackgroundHeight()
* (1f - mTaskbarBackgroundOffset);
- canvas.save();
- canvas.translate(0, canvas.getHeight() - backgroundHeight);
-
- // Draw the background behind taskbar content.
- canvas.drawRect(0, 0, canvas.getWidth(), backgroundHeight, mTaskbarBackgroundPaint);
-
- // Draw the inverted rounded corners above the taskbar.
- canvas.translate(0, -mLeftCornerRadius);
- canvas.drawPath(mInvertedLeftCornerPath, mTaskbarBackgroundPaint);
- canvas.translate(0, mLeftCornerRadius);
- canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius);
- canvas.drawPath(mInvertedRightCornerPath, mTaskbarBackgroundPaint);
-
- canvas.restore();
+ mBackgroundRenderer.setBackgroundHeight(backgroundHeight);
+ mBackgroundRenderer.draw(canvas);
super.dispatchDraw(canvas);
}
@@ -173,7 +134,7 @@
* @param alpha 0 is fully transparent, 1 is fully opaque.
*/
protected void setTaskbarBackgroundAlpha(float alpha) {
- mTaskbarBackgroundPaint.setAlpha((int) (alpha * 255));
+ mBackgroundRenderer.getPaint().setAlpha((int) (alpha * 255));
invalidate();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
index 94a3307..1d3757f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
@@ -17,22 +17,19 @@
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
+import com.android.launcher3.views.ActivityContext;
+
/**
* View that handles scrimming the taskbar and the inverted corners it draws. The scrim is used
* when bubbles is expanded.
*/
public class TaskbarScrimView extends View {
- private final Paint mTaskbarScrimPaint;
- private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath;
+ private final TaskbarBackgroundRenderer mRenderer;
private boolean mShowScrim;
- private float mLeftCornerRadius, mRightCornerRadius;
- private float mBackgroundHeight;
public TaskbarScrimView(Context context) {
this(context, null);
@@ -49,14 +46,9 @@
public TaskbarScrimView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
-
- mTaskbarScrimPaint = new Paint();
- mTaskbarScrimPaint.setColor(getResources().getColor(android.R.color.system_neutral1_1000));
- mTaskbarScrimPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- mTaskbarScrimPaint.setStyle(Paint.Style.FILL);
-
- mInvertedLeftCornerPath = new Path();
- mInvertedRightCornerPath = new Path();
+ mRenderer = new TaskbarBackgroundRenderer(ActivityContext.lookupContext(context));
+ mRenderer.getPaint().setColor(getResources().getColor(
+ android.R.color.system_neutral1_1000));
}
@Override
@@ -64,31 +56,7 @@
super.onDraw(canvas);
if (mShowScrim) {
- canvas.save();
- canvas.translate(0, canvas.getHeight() - mBackgroundHeight);
-
- // Scrim the taskbar itself.
- canvas.drawRect(0, 0, canvas.getWidth(), mBackgroundHeight, mTaskbarScrimPaint);
-
- // Scrim the inverted rounded corners above the taskbar.
- canvas.translate(0, -mLeftCornerRadius);
- canvas.drawPath(mInvertedLeftCornerPath, mTaskbarScrimPaint);
- canvas.translate(0, mLeftCornerRadius);
- canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius);
- canvas.drawPath(mInvertedRightCornerPath, mTaskbarScrimPaint);
-
- canvas.restore();
- }
- }
-
- /**
- * Sets the height of the taskbar background.
- * @param height the height of the background.
- */
- protected void setBackgroundHeight(float height) {
- mBackgroundHeight = height;
- if (mShowScrim) {
- invalidate();
+ mRenderer.draw(canvas);
}
}
@@ -98,32 +66,7 @@
*/
protected void setScrimAlpha(float alpha) {
mShowScrim = alpha > 0f;
- mTaskbarScrimPaint.setAlpha((int) (alpha * 255));
+ mRenderer.getPaint().setAlpha((int) (alpha * 255));
invalidate();
}
-
- /**
- * Sets the radius of the left and right corners above the taskbar.
- * @param leftCornerRadius the radius of the left corner.
- * @param rightCornerRadius the radius of the right corner.
- */
- protected void setCornerSizes(float leftCornerRadius, float rightCornerRadius) {
- mLeftCornerRadius = leftCornerRadius;
- mRightCornerRadius = rightCornerRadius;
-
- Path square = new Path();
- square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW);
- Path circle = new Path();
- circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW);
- mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE);
- square.reset();
- square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW);
- circle.reset();
- circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW);
- mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE);
-
- if (mShowScrim) {
- invalidate();
- }
- }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 02bbae4..58ace17 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -49,9 +49,6 @@
public TaskbarScrimViewController(TaskbarActivityContext activity, TaskbarScrimView scrimView) {
mActivity = activity;
mScrimView = scrimView;
- mScrimView.setCornerSizes(mActivity.getLeftCornerRadius(),
- mActivity.getRightCornerRadius());
- mScrimView.setBackgroundHeight(mActivity.getDeviceProfile().taskbarSize);
}
/**
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 7abcbdb..cc79f4a 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -25,6 +25,7 @@
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Matrix;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
@@ -33,11 +34,12 @@
import android.util.Pair;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.window.BackEvent;
import android.window.IOnBackInvokedCallback;
import com.android.launcher3.BaseQuickstepLauncher;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -62,34 +64,36 @@
*
*/
public class LauncherBackAnimationController {
- private static final int CANCEL_TRANSITION_DURATION = 150;
+ private static final int CANCEL_TRANSITION_DURATION = 233;
+ private static final float MIN_WINDOW_SCALE = 0.7f;
private static final String TAG = "LauncherBackAnimationController";
- private final DeviceProfile mDeviceProfile;
private final QuickstepTransitionManager mQuickstepTransitionManager;
private final Matrix mTransformMatrix = new Matrix();
- private final RectF mTargetRectF = new RectF();
- private final RectF mStartRectF = new RectF();
+ /** The window position at the beginning of the back animation. */
+ private final Rect mStartRect = new Rect();
+ /** The window position when the back gesture is cancelled. */
+ private final RectF mCancelRect = new RectF();
+ /** The current window position. */
private final RectF mCurrentRect = new RectF();
private final BaseQuickstepLauncher mLauncher;
private final int mWindowScaleMarginX;
- private final int mWindowScaleMarginY;
+ /** Max window translation in the Y axis. */
+ private final int mWindowMaxDeltaY;
private final float mWindowScaleEndCornerRadius;
private final float mWindowScaleStartCornerRadius;
+ private final Interpolator mCancelInterpolator;
+ private final PointF mInitialTouchPos = new PointF();
private RemoteAnimationTargetCompat mBackTarget;
private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
private boolean mSpringAnimationInProgress = false;
private boolean mAnimatorSetInProgress = false;
- @BackEvent.SwipeEdge
- private int mSwipeEdge;
private float mBackProgress = 0;
private boolean mBackInProgress = false;
public LauncherBackAnimationController(
- DeviceProfile deviceProfile,
BaseQuickstepLauncher launcher,
QuickstepTransitionManager quickstepTransitionManager) {
- mDeviceProfile = deviceProfile;
mLauncher = launcher;
mQuickstepTransitionManager = quickstepTransitionManager;
mWindowScaleEndCornerRadius = QuickStepContract.supportsRoundedCornersOnWindows(
@@ -100,8 +104,10 @@
mWindowScaleStartCornerRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
R.dimen.swipe_back_window_scale_x_margin);
- mWindowScaleMarginY = mLauncher.getResources().getDimensionPixelSize(
- R.dimen.swipe_back_window_scale_y_margin);
+ mWindowMaxDeltaY = mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.swipe_back_window_max_delta_y);
+ mCancelInterpolator =
+ AnimationUtils.loadInterpolator(mLauncher, R.interpolator.back_cancel);
}
/**
@@ -136,7 +142,7 @@
if (!mBackInProgress) {
startBack(backEvent);
} else {
- updateBackProgress(mBackProgress);
+ updateBackProgress(mBackProgress, backEvent);
}
}
@@ -145,11 +151,13 @@
}
private void resetPositionAnimated() {
- ValueAnimator cancelAnimator = ValueAnimator.ofFloat(mBackProgress, 0);
+ ValueAnimator cancelAnimator = ValueAnimator.ofFloat(0, 1);
+ mCancelRect.set(mCurrentRect);
cancelAnimator.setDuration(CANCEL_TRANSITION_DURATION);
+ cancelAnimator.setInterpolator(mCancelInterpolator);
cancelAnimator.addUpdateListener(
animation -> {
- updateBackProgress((float) animation.getAnimatedValue());
+ updateCancelProgress((float) animation.getAnimatedValue());
});
cancelAnimator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -179,50 +187,70 @@
mTransaction.show(appTarget.leash).apply();
mTransaction.setAnimationTransaction();
mBackTarget = new RemoteAnimationTargetCompat(appTarget);
- mSwipeEdge = backEvent.getSwipeEdge();
- float screenWidth = mDeviceProfile.widthPx;
- float screenHeight = mDeviceProfile.heightPx;
- float targetHeight = screenHeight - 2 * mWindowScaleMarginY;
- float targetWidth = targetHeight * screenWidth / screenHeight;
- float left;
- if (mSwipeEdge == BackEvent.EDGE_LEFT) {
- left = screenWidth - targetWidth - mWindowScaleMarginX;
- } else {
- left = mWindowScaleMarginX;
- }
- float top = mWindowScaleMarginY;
+ mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY());
+
// TODO(b/218916755): Offset start rectangle in multiwindow mode.
- mStartRectF.set(0, 0, screenWidth, screenHeight);
- mTargetRectF.set(left, top, targetWidth + left, targetHeight + top);
+ mStartRect.set(mBackTarget.windowConfiguration.getMaxBounds());
}
- private void updateBackProgress(float progress) {
+ private void updateBackProgress(float progress, BackEvent event) {
if (mBackTarget == null) {
return;
}
+ float screenWidth = mStartRect.width();
+ float screenHeight = mStartRect.height();
+ float dX = Math.abs(event.getTouchX() - mInitialTouchPos.x);
+ // The 'follow width' is the width of the window if it completely matches
+ // the gesture displacement.
+ float followWidth = screenWidth - dX;
+ // The 'progress width' is the width of the window if it strictly linearly interpolates
+ // to minimum scale base on progress.
+ float progressWidth = MathUtils.lerp(1, MIN_WINDOW_SCALE, progress) * screenWidth;
+ // The final width is derived from interpolating between the follow with and progress width
+ // using gesture progress.
+ float width = MathUtils.lerp(followWidth, progressWidth, progress);
+ float height = screenHeight / screenWidth * width;
+ float deltaYRatio = (event.getTouchY() - mInitialTouchPos.y) / screenHeight;
+ // Base the window movement in the Y axis on the touch movement in the Y axis.
+ float deltaY = (float) Math.sin(deltaYRatio * Math.PI * 0.5f) * mWindowMaxDeltaY;
+ // Move the window along the Y axis.
+ float top = (screenHeight - height) * 0.5f + deltaY;
+ // Move the window along the X axis.
+ float left = event.getSwipeEdge() == BackEvent.EDGE_RIGHT
+ ? progress * mWindowScaleMarginX
+ : screenWidth - progress * mWindowScaleMarginX - width;
- mCurrentRect.set(
- MathUtils.lerp(mStartRectF.left, mTargetRectF.left, progress),
- MathUtils.lerp(mStartRectF.top, mTargetRectF.top, progress),
- MathUtils.lerp(mStartRectF.right, mTargetRectF.right, progress),
- MathUtils.lerp(mStartRectF.bottom, mTargetRectF.bottom, progress));
- SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder builder =
- new SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder(mBackTarget.leash);
-
- Rect currentRect = new Rect();
- mCurrentRect.round(currentRect);
-
- // Scale the target window to match the currentRectF.
- final float scale = mCurrentRect.width() / mStartRectF.width();
- mTransformMatrix.reset();
- mTransformMatrix.setScale(scale, scale);
- mTransformMatrix.postTranslate(mCurrentRect.left, mCurrentRect.top);
- Rect startRect = new Rect();
- mStartRectF.round(startRect);
+ mCurrentRect.set(left, top, left + width, top + height);
float cornerRadius = Utilities.mapRange(
progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
+ applyTransform(mCurrentRect, cornerRadius);
+ }
+
+ private void updateCancelProgress(float progress) {
+ if (mBackTarget == null) {
+ return;
+ }
+ mCurrentRect.set(
+ MathUtils.lerp(mCancelRect.left, mStartRect.left, progress),
+ MathUtils.lerp(mCancelRect.top, mStartRect.top, progress),
+ MathUtils.lerp(mCancelRect.right, mStartRect.right, progress),
+ MathUtils.lerp(mCancelRect.bottom, mStartRect.bottom, progress));
+
+ float cornerRadius = Utilities.mapRange(
+ progress, mWindowScaleEndCornerRadius, mWindowScaleStartCornerRadius);
+ applyTransform(mCurrentRect, cornerRadius);
+ }
+
+ /** Transform the target window to match the target rect. */
+ private void applyTransform(RectF targetRect, float cornerRadius) {
+ SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder builder =
+ new SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder(mBackTarget.leash);
+ final float scale = targetRect.width() / mStartRect.width();
+ mTransformMatrix.reset();
+ mTransformMatrix.setScale(scale, scale);
+ mTransformMatrix.postTranslate(targetRect.left, targetRect.top);
builder.withMatrix(mTransformMatrix)
- .withWindowCrop(startRect)
+ .withWindowCrop(mStartRect)
.withCornerRadius(cornerRadius);
SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams = builder.build();
@@ -263,11 +291,11 @@
mBackTarget = null;
mBackInProgress = false;
mBackProgress = 0;
- mSwipeEdge = BackEvent.EDGE_LEFT;
mTransformMatrix.reset();
- mTargetRectF.setEmpty();
+ mCancelRect.setEmpty();
mCurrentRect.setEmpty();
- mStartRectF.setEmpty();
+ mStartRect.setEmpty();
+ mInitialTouchPos.set(0, 0);
mAnimatorSetInProgress = false;
mSpringAnimationInProgress = false;
SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ed00b8e..e5cbbee 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -106,6 +106,7 @@
import android.widget.ListView;
import android.widget.OverScroller;
import android.widget.Toast;
+import android.window.PictureInPictureSurfaceTransaction;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -161,6 +162,7 @@
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.ViewUtils;
import com.android.quickstep.util.GroupTask;
+import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitScreenBounds;
@@ -4507,6 +4509,18 @@
final SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(getContext());
systemUiProxy.notifySwipeToHomeFinished();
systemUiProxy.setShelfHeight(true, mActivity.getDeviceProfile().hotseatBarSizePx);
+ // Transaction to hide the task to avoid flicker for entering PiP from split-screen.
+ // See also {@link AbsSwipeUpHandler#maybeFinishSwipeToHome}.
+ PictureInPictureSurfaceTransaction tx =
+ new PictureInPictureSurfaceTransaction.Builder()
+ .setAlpha(0f)
+ .build();
+ int[] taskIds =
+ LauncherSplitScreenListener.INSTANCE.getNoCreate().getRunningSplitTaskIds();
+ for (int taskId : taskIds) {
+ mRecentsAnimationController.setFinishTaskTransaction(taskId,
+ tx, null /* overlay */);
+ }
}
mRecentsAnimationController.finish(toRecents, () -> {
if (onFinishComplete != null) {
diff --git a/res/interpolator/back_cancel.xml b/res/interpolator/back_cancel.xml
new file mode 100644
index 0000000..2165457
--- /dev/null
+++ b/res/interpolator/back_cancel.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2022, 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.
+*/
+-->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.2"
+ android:controlY1="0"
+ android:controlX2="0"
+ android:controlY2="1"/>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index 0ed2d85..5ecd929 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -166,6 +166,6 @@
<!-- Swipe back to home related -->
<dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
- <dimen name="swipe_back_window_scale_y_margin">80dp</dimen>
+ <dimen name="swipe_back_window_max_delta_y">160dp</dimen>
<dimen name="swipe_back_window_corner_radius">40dp</dimen>
</resources>
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 6d39857..8358f2a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -53,6 +53,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Message;
@@ -72,6 +73,7 @@
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
+import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
@@ -93,7 +95,6 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.PendingAddShortcutInfo;
-import com.android.modules.utils.build.SdkLevel;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -122,15 +123,20 @@
public static final String[] EMPTY_STRING_ARRAY = new String[0];
public static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.P)
public static final boolean ATLEAST_P = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.Q)
public static final boolean ATLEAST_Q = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
- public static final boolean ATLEAST_R = SdkLevel.isAtLeastR();
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.R)
+ public static final boolean ATLEAST_R = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
- public static final boolean ATLEAST_S = SdkLevel.isAtLeastS();
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.S)
+ public static final boolean ATLEAST_S = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
- public static final boolean ATLEAST_T = SdkLevel.isAtLeastT();
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.TIRAMISU, codename = "T")
+ public static final boolean ATLEAST_T = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
/**
* Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index bcb0d14..6203cea 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -27,6 +27,7 @@
import android.os.UserManager;
import android.util.Log;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
@@ -147,6 +148,9 @@
workFabMarginBottom +=
mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.qsb_widget_height);
}
+ if (!mAllApps.mActivityContext.getDeviceProfile().isGestureMode){
+ workFabMarginBottom += mAllApps.mActivityContext.getDeviceProfile().getInsets().bottom;
+ }
((ViewGroup.MarginLayoutParams) mWorkModeSwitch.getLayoutParams()).bottomMargin =
workFabMarginBottom;
if (mWorkModeSwitch.getParent() != mAllApps) {
@@ -158,7 +162,6 @@
mWorkModeSwitch.updateCurrentState(mCurrentState == STATE_ENABLED);
return true;
}
-
/**
* Removes work profile toggle button from {@link BaseAllAppsContainerView}
*/
diff --git a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
index 74d9a22..6f295e6 100644
--- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
+++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
@@ -20,9 +20,13 @@
import android.annotation.TargetApi;
import android.graphics.Bitmap;
-import android.graphics.Matrix;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Picture;
+import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
@@ -31,10 +35,11 @@
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import com.android.launcher3.Utilities;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
-import com.android.launcher3.graphics.ShiftedBitmapDrawable;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.views.ActivityContext;
@@ -69,79 +74,104 @@
return mBadge;
}
+ @TargetApi(Build.VERSION_CODES.P)
public static @Nullable FolderAdaptiveIcon createFolderAdaptiveIcon(
- ActivityContext activity, int folderId, Point dragViewSize) {
+ ActivityContext activity, int folderId, Point size) {
Preconditions.assertNonUiThread();
+ if (!Utilities.ATLEAST_P) {
+ return null;
+ }
- // Create the actual drawable on the UI thread to avoid race conditions with
+ // assume square
+ if (size.x != size.y) {
+ return null;
+ }
+ int requestedSize = size.x;
+
+ // Only use the size actually needed for drawing the folder icon
+ int drawingSize = activity.getDeviceProfile().folderIconSizePx;
+ int foregroundSize = Math.max(requestedSize, drawingSize);
+ float shift = foregroundSize - requestedSize;
+
+ Picture background = new Picture();
+ Picture foreground = new Picture();
+ Picture badge = new Picture();
+
+ Canvas bgCanvas = background.beginRecording(requestedSize, requestedSize);
+ Canvas badgeCanvas = badge.beginRecording(requestedSize, requestedSize);
+
+ Canvas fgCanvas = foreground.beginRecording(foregroundSize, foregroundSize);
+ fgCanvas.translate(shift, shift);
+
+ // Do not clip the folder drawing since the icon previews extend outside the background.
+ Path mask = new Path();
+ mask.addRect(-shift, -shift, requestedSize + shift, requestedSize + shift,
+ Direction.CCW);
+
+ // Initialize the actual draw commands on the UI thread to avoid race conditions with
// FolderIcon draw pass
try {
- return MAIN_EXECUTOR.submit(() -> {
+ MAIN_EXECUTOR.submit(() -> {
FolderIcon icon = activity.findFolderIcon(folderId);
- return icon == null ? null : createDrawableOnUiThread(icon, dragViewSize);
-
+ if (icon == null) {
+ throw new IllegalArgumentException("Folder not found with id: " + folderId);
+ }
+ initLayersOnUiThread(icon, requestedSize, bgCanvas, fgCanvas, badgeCanvas);
}).get();
} catch (Exception e) {
Log.e(TAG, "Unable to create folder icon", e);
return null;
+ } finally {
+ background.endRecording();
+ foreground.endRecording();
+ badge.endRecording();
}
+
+ // Only convert foreground to a bitmap as it can contain multiple draw commands. Other
+ // layers either draw a nothing or a single draw call.
+ Bitmap fgBitmap = Bitmap.createBitmap(foreground);
+ Paint foregroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ // Do not use PictureDrawable as it moves the picture to the canvas bounds, whereas we want
+ // to draw it at (0,0)
+ return new FolderAdaptiveIcon(
+ new BitmapRendererDrawable(c -> c.drawPicture(background)),
+ new BitmapRendererDrawable(
+ c -> c.drawBitmap(fgBitmap, -shift, -shift, foregroundPaint)),
+ new BitmapRendererDrawable(c -> c.drawPicture(badge)),
+ mask);
}
- private static FolderAdaptiveIcon createDrawableOnUiThread(FolderIcon icon,
- Point dragViewSize) {
- Preconditions.assertUIThread();
-
+ @UiThread
+ private static void initLayersOnUiThread(FolderIcon icon, int size,
+ Canvas backgroundCanvas, Canvas foregroundCanvas, Canvas badgeCanvas) {
icon.getPreviewBounds(sTmpRect);
-
- PreviewBackground bg = icon.getFolderBackground();
-
- // assume square
- assert (dragViewSize.x == dragViewSize.y);
final int previewSize = sTmpRect.width();
- final int margin = (dragViewSize.x - previewSize) / 2;
+ PreviewBackground bg = icon.getFolderBackground();
+ final int margin = (size - previewSize) / 2;
final float previewShiftX = -sTmpRect.left + margin;
final float previewShiftY = -sTmpRect.top + margin;
// Initialize badge, which consists of the outline stroke, shadow and dot; these
// must be rendered above the foreground
- Bitmap badgeBmp = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y,
- (canvas) -> {
- canvas.save();
- canvas.translate(previewShiftX, previewShiftY);
- bg.drawShadow(canvas);
- bg.drawBackgroundStroke(canvas);
- icon.drawDot(canvas);
- canvas.restore();
- });
+ badgeCanvas.save();
+ badgeCanvas.translate(previewShiftX, previewShiftY);
+ icon.drawDot(badgeCanvas);
+ badgeCanvas.restore();
- // Initialize mask
- Path mask = new Path();
- Matrix m = new Matrix();
- m.setTranslate(previewShiftX, previewShiftY);
- bg.getClipPath().transform(m, mask);
+ // Draw foreground
+ foregroundCanvas.save();
+ foregroundCanvas.translate(previewShiftX, previewShiftY);
+ icon.getPreviewItemManager().draw(foregroundCanvas);
+ foregroundCanvas.restore();
- Bitmap previewBitmap = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y,
- (canvas) -> {
- canvas.save();
- canvas.translate(previewShiftX, previewShiftY);
- icon.getPreviewItemManager().draw(canvas);
- canvas.restore();
- });
-
- Bitmap bgBitmap = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y,
- (canvas) -> {
- Paint p = new Paint();
- p.setColor(bg.getBgColor());
-
- canvas.drawCircle(dragViewSize.x / 2f, dragViewSize.y / 2f, bg.getRadius(), p);
- });
-
- ShiftedBitmapDrawable badge = new ShiftedBitmapDrawable(badgeBmp, 0, 0);
- ShiftedBitmapDrawable foreground = new ShiftedBitmapDrawable(previewBitmap, 0, 0);
- ShiftedBitmapDrawable background = new ShiftedBitmapDrawable(bgBitmap, 0, 0);
-
- return new FolderAdaptiveIcon(background, foreground, badge, mask);
+ // Draw background
+ Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ backgroundPaint.setColor(bg.getBgColor());
+ bg.drawShadow(backgroundCanvas);
+ backgroundCanvas.drawCircle(size / 2f, size / 2f, bg.getRadius(), backgroundPaint);
+ bg.drawBackgroundStroke(backgroundCanvas);
}
@Override
@@ -174,4 +204,52 @@
& mBadge.getChangingConfigurations();
}
}
+
+ private static class BitmapRendererDrawable extends Drawable {
+
+ private final BitmapRenderer mRenderer;
+
+ BitmapRendererDrawable(BitmapRenderer renderer) {
+ mRenderer = renderer;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mRenderer.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int i) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public ConstantState getConstantState() {
+ return new MyConstantState(mRenderer);
+ }
+
+ private static class MyConstantState extends ConstantState {
+ private final BitmapRenderer mRenderer;
+
+ MyConstantState(BitmapRenderer renderer) {
+ mRenderer = renderer;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new BitmapRendererDrawable(mRenderer);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return 0;
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java b/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java
deleted file mode 100644
index f8583b8..0000000
--- a/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.graphics;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-
-/**
- * A simple drawable which draws a bitmap at a fixed position irrespective of the bounds
- */
-public class ShiftedBitmapDrawable extends Drawable {
-
- private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
- private final Bitmap mBitmap;
- private float mShiftX;
- private float mShiftY;
-
- private final ConstantState mConstantState;
-
- public ShiftedBitmapDrawable(Bitmap bitmap, float shiftX, float shiftY) {
- mBitmap = bitmap;
- mShiftX = shiftX;
- mShiftY = shiftY;
-
- mConstantState = new MyConstantState(mBitmap, mShiftX, mShiftY);
- }
-
- public float getShiftX() {
- return mShiftX;
- }
-
- public float getShiftY() {
- return mShiftY;
- }
-
- public void setShiftX(float shiftX) {
- mShiftX = shiftX;
- }
-
- public void setShiftY(float shiftY) {
- mShiftY = shiftY;
- }
-
- @Override
- public void draw(Canvas canvas) {
- canvas.drawBitmap(mBitmap, mShiftX, mShiftY, mPaint);
- }
-
- @Override
- public void setAlpha(int i) { }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
- mPaint.setColorFilter(colorFilter);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public ConstantState getConstantState() {
- return mConstantState;
- }
-
- private static class MyConstantState extends ConstantState {
- private final Bitmap mBitmap;
- private float mShiftX;
- private float mShiftY;
-
- MyConstantState(Bitmap bitmap, float shiftX, float shiftY) {
- mBitmap = bitmap;
- mShiftX = shiftX;
- mShiftY = shiftY;
- }
-
- @Override
- public Drawable newDrawable() {
- return new ShiftedBitmapDrawable(mBitmap, mShiftX, mShiftY);
- }
-
- @Override
- public int getChangingConfigurations() {
- return 0;
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/model/StringCache.java b/src/com/android/launcher3/model/StringCache.java
index 2fc852d..663a463 100644
--- a/src/com/android/launcher3/model/StringCache.java
+++ b/src/com/android/launcher3/model/StringCache.java
@@ -16,6 +16,7 @@
package com.android.launcher3.model;
+import android.annotation.SuppressLint;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.Build;
@@ -215,6 +216,7 @@
context, DISABLED_BY_ADMIN_MESSAGE, R.string.msg_disabled_by_admin);
}
+ @SuppressLint("NewApi")
private String getEnterpriseString(
Context context, String updatableStringId, int defaultStringId) {
return Utilities.ATLEAST_T
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index bbeb886..04eb38a 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -35,6 +35,7 @@
import android.util.Pair;
import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -154,14 +155,9 @@
case MSG_NOTIFICATION_FULL_REFRESH:
List<StatusBarNotification> activeNotifications = null;
if (sIsConnected) {
- try {
- activeNotifications = Arrays.stream(getActiveNotifications())
- .filter(this::notificationIsValidForUI)
- .collect(Collectors.toList());
- } catch (SecurityException ex) {
- Log.e(TAG, "SecurityException: failed to fetch notifications");
- activeNotifications = new ArrayList<>();
- }
+ activeNotifications = Arrays.stream(getActiveNotificationsSafely(null))
+ .filter(this::notificationIsValidForUI)
+ .collect(Collectors.toList());
} else {
activeNotifications = new ArrayList<>();
}
@@ -175,7 +171,7 @@
}
case MSG_RANKING_UPDATE: {
String[] keys = ((RankingMap) message.obj).getOrderedKeys();
- for (StatusBarNotification sbn : getActiveNotifications(keys)) {
+ for (StatusBarNotification sbn : getActiveNotificationsSafely(keys)) {
updateGroupKeyIfNecessary(sbn);
}
return true;
@@ -214,6 +210,16 @@
return true;
}
+ private @NonNull StatusBarNotification[] getActiveNotificationsSafely(@Nullable String[] keys) {
+ StatusBarNotification[] result = null;
+ try {
+ result = getActiveNotifications(keys);
+ } catch (SecurityException e) {
+ Log.e(TAG, "SecurityException: failed to fetch notifications");
+ }
+ return result == null ? new StatusBarNotification[0] : result;
+ }
+
@Override
public void onListenerConnected() {
super.onListenerConnected();
@@ -313,9 +319,8 @@
*/
@WorkerThread
public List<StatusBarNotification> getNotificationsForKeys(List<NotificationKeyData> keys) {
- StatusBarNotification[] notifications = getActiveNotifications(
- keys.stream().map(n -> n.notificationKey).toArray(String[]::new));
- return notifications == null ? Collections.emptyList() : Arrays.asList(notifications);
+ return Arrays.asList(getActiveNotificationsSafely(
+ keys.stream().map(n -> n.notificationKey).toArray(String[]::new)));
}
/**
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 56a1d37..babe607 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -49,7 +49,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -413,8 +412,7 @@
@WorkerThread
@SuppressWarnings("WrongThread")
private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) {
- if (!(drawable instanceof AdaptiveIconDrawable)
- || (drawable instanceof FolderAdaptiveIcon)) {
+ if (!(drawable instanceof AdaptiveIconDrawable)) {
return 0;
}
int blurSizeOutline =