Snap for 12445464 from 17b246a556 to 25Q1-release
Change-Id: Id9550bc05cc13a98d51afd7e7c7f88040909da77
This commit is contained in:
@@ -139,8 +139,7 @@
|
||||
<string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
|
||||
<string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
|
||||
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
|
||||
<!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
|
||||
<skip />
|
||||
<string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Taskbar overflow"</string>
|
||||
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
|
||||
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
|
||||
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{more app}other{more apps}}"</string>
|
||||
|
||||
@@ -24,6 +24,7 @@ import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_FOR_BUBBLES;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.UNLOCK_TRANSITION_MEMOIZATION_MS;
|
||||
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
|
||||
import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_IN_ANIM_ALPHA_DURATION_MS;
|
||||
import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_OUT_ANIM_POSITION_DURATION_MS;
|
||||
@@ -167,7 +168,12 @@ public class TaskbarLauncherStateController {
|
||||
private boolean mSkipNextRecentsAnimEnd;
|
||||
|
||||
// Time when FLAG_TASKBAR_HIDDEN was last cleared, SystemClock.elapsedRealtime (milliseconds).
|
||||
private long mLastUnlockTimeMs = 0;
|
||||
private long mLastRemoveTaskbarHiddenTimeMs = 0;
|
||||
/**
|
||||
* Time when FLAG_DEVICE_LOCKED was last cleared, plus
|
||||
* {@link TaskbarStashController#UNLOCK_TRANSITION_MEMOIZATION_MS}
|
||||
*/
|
||||
private long mLastUnlockTransitionTimeout;
|
||||
|
||||
private @Nullable TaskBarRecentsAnimationListener mTaskBarRecentsAnimationListener;
|
||||
|
||||
@@ -535,7 +541,7 @@ public class TaskbarLauncherStateController {
|
||||
|
||||
if (hasAnyFlag(changedFlags, FLAG_TASKBAR_HIDDEN) && !hasAnyFlag(FLAG_TASKBAR_HIDDEN)) {
|
||||
// Take note of the current time, as the taskbar is made visible again.
|
||||
mLastUnlockTimeMs = SystemClock.elapsedRealtime();
|
||||
mLastRemoveTaskbarHiddenTimeMs = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
boolean isHidden = hasAnyFlag(FLAG_TASKBAR_HIDDEN);
|
||||
@@ -561,7 +567,8 @@ public class TaskbarLauncherStateController {
|
||||
// with a fingerprint reader. This should only be done when the device was woken
|
||||
// up via fingerprint reader, however since this information is currently not
|
||||
// available, opting to always delay the fade-in a bit.
|
||||
long durationSinceLastUnlockMs = SystemClock.elapsedRealtime() - mLastUnlockTimeMs;
|
||||
long durationSinceLastUnlockMs = SystemClock.elapsedRealtime()
|
||||
- mLastRemoveTaskbarHiddenTimeMs;
|
||||
taskbarVisibility.setStartDelay(
|
||||
Math.max(0, TASKBAR_SHOW_DELAY_MS - durationSinceLastUnlockMs));
|
||||
}
|
||||
@@ -631,6 +638,15 @@ public class TaskbarLauncherStateController {
|
||||
boolean isUnlockTransition =
|
||||
hasAnyFlag(changedFlags, FLAG_DEVICE_LOCKED) && !hasAnyFlag(FLAG_DEVICE_LOCKED);
|
||||
if (isUnlockTransition) {
|
||||
// the launcher might not be resumed at the time the device is considered
|
||||
// unlocked (when the keyguard goes away), but possibly shortly afterwards.
|
||||
// To play the unlock transition at the time the unstash animation actually happens,
|
||||
// this memoizes the state transition for UNLOCK_TRANSITION_MEMOIZATION_MS.
|
||||
mLastUnlockTransitionTimeout =
|
||||
SystemClock.elapsedRealtime() + UNLOCK_TRANSITION_MEMOIZATION_MS;
|
||||
}
|
||||
boolean isInUnlockTimeout = SystemClock.elapsedRealtime() < mLastUnlockTransitionTimeout;
|
||||
if (isUnlockTransition || isInUnlockTimeout) {
|
||||
// When transitioning to unlocked, ensure the hotseat is fully visible from the
|
||||
// beginning. The hotseat itself is animated by LauncherUnlockAnimationController.
|
||||
mIconAlignment.cancelAnimation();
|
||||
|
||||
@@ -191,7 +191,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
|
||||
// Duration for which an unlock event is considered "current", as other events are received
|
||||
// asynchronously.
|
||||
private static final long UNLOCK_TRANSITION_MEMOIZATION_MS = 200;
|
||||
public static final long UNLOCK_TRANSITION_MEMOIZATION_MS = 200;
|
||||
|
||||
/**
|
||||
* The default stash animation, morphing the taskbar into the navbar.
|
||||
|
||||
@@ -329,7 +329,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
*/
|
||||
public void setRecentsButtonDisabled(boolean isDisabled) {
|
||||
// TODO: check TaskbarStashController#supportsStashing(), to stash instead of setting alpha.
|
||||
mTaskbarIconAlpha.get(ALPHA_INDEX_RECENTS_DISABLED).setValue(isDisabled ? 0 : 1);
|
||||
mTaskbarIconAlpha.get(ALPHA_INDEX_RECENTS_DISABLED).animateToValue(isDisabled ? 0 : 1)
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
@@ -39,4 +39,13 @@ interface BubbleBarFlyoutPositioner {
|
||||
|
||||
/** The color of the flyout when collapsed. */
|
||||
val collapsedColor: Int
|
||||
|
||||
/** The elevation of the flyout when collapsed. */
|
||||
val collapsedElevation: Float
|
||||
|
||||
/**
|
||||
* The distance the flyout must pass from its collapsed position until it can start revealing
|
||||
* the triangle.
|
||||
*/
|
||||
val distanceToRevealTriangle: Float
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
ConstraintLayout(context) {
|
||||
|
||||
private companion object {
|
||||
// the minimum progress of the expansion animation before the triangle is made visible.
|
||||
const val MIN_EXPANSION_PROGRESS_FOR_TRIANGLE = 0.1f
|
||||
// the minimum progress of the expansion animation before the content starts fading in.
|
||||
const val MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA = 0.75f
|
||||
}
|
||||
@@ -92,6 +90,11 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_max_width)
|
||||
}
|
||||
|
||||
private val flyoutElevation by
|
||||
lazy(LazyThreadSafetyMode.NONE) {
|
||||
context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_elevation).toFloat()
|
||||
}
|
||||
|
||||
/** The bounds of the background rect. */
|
||||
private val backgroundRect = RectF()
|
||||
private val cornerRadius: Float
|
||||
@@ -108,6 +111,10 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
private var collapsedCornerRadius = 0f
|
||||
/** The color of the flyout when collapsed. */
|
||||
private var collapsedColor = 0
|
||||
/** The elevation of the flyout when collapsed. */
|
||||
private var collapsedElevation = 0f
|
||||
/** The minimum progress of the expansion animation before the triangle is made visible. */
|
||||
private var minExpansionProgressForTriangle = 0f
|
||||
|
||||
/** The corner radius of the background according to the progress of the animation. */
|
||||
private val currentCornerRadius
|
||||
@@ -141,8 +148,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
val padding = context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_padding)
|
||||
// add extra padding to the bottom of the view to include the triangle
|
||||
setPadding(padding, padding, padding, padding + triangleHeight - triangleOverlap)
|
||||
translationZ =
|
||||
context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_elevation).toFloat()
|
||||
translationZ = flyoutElevation
|
||||
|
||||
RoundedArrowDrawable.addDownPointingRoundedTriangleToPath(
|
||||
triangleWidth.toFloat(),
|
||||
@@ -182,6 +188,12 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
collapsedSize = positioner.collapsedSize
|
||||
collapsedCornerRadius = collapsedSize / 2
|
||||
collapsedColor = positioner.collapsedColor
|
||||
collapsedElevation = positioner.collapsedElevation
|
||||
|
||||
// calculate the expansion progress required before we start showing the triangle as part of
|
||||
// the expansion animation
|
||||
minExpansionProgressForTriangle =
|
||||
positioner.distanceToRevealTriangle / tyToCollapsedPosition
|
||||
|
||||
// post the request to start the expand animation to the looper so the view can measure
|
||||
// itself
|
||||
@@ -240,6 +252,9 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
message.alpha = alpha
|
||||
avatar.alpha = alpha
|
||||
|
||||
translationZ =
|
||||
collapsedElevation + (flyoutElevation - collapsedElevation) * expansionProgress
|
||||
|
||||
invalidate()
|
||||
}
|
||||
|
||||
@@ -275,7 +290,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
currentCornerRadius,
|
||||
backgroundPaint,
|
||||
)
|
||||
if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) {
|
||||
if (expansionProgress >= minExpansionProgressForTriangle) {
|
||||
drawTriangle(canvas)
|
||||
}
|
||||
canvas.restore()
|
||||
@@ -291,9 +306,20 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
} else {
|
||||
width - currentCornerRadius - triangleWidth
|
||||
}
|
||||
// instead of scaling the triangle, increasingly reveal it from the background, starting
|
||||
// with half the size. this has the effect of the triangle scaling.
|
||||
val triangleY = height - triangleHeight - 0.5f * triangleHeight * (1 - expansionProgress)
|
||||
// instead of scaling the triangle, increasingly reveal it from the background. this has the
|
||||
// effect of the triangle scaling.
|
||||
|
||||
// the translation y of the triangle before we start revealing it. align its bottom with the
|
||||
// bottom of the rect
|
||||
val triangleYCollapsed = height - triangleHeight - (triangleHeight - triangleOverlap)
|
||||
// the translation y of the triangle when it's fully revealed
|
||||
val triangleYExpanded = height - triangleHeight
|
||||
val interpolatedExpansion =
|
||||
((expansionProgress - minExpansionProgressForTriangle) /
|
||||
(1 - minExpansionProgressForTriangle))
|
||||
.coerceIn(0f, 1f)
|
||||
val triangleY =
|
||||
triangleYCollapsed + (triangleYExpanded - triangleYCollapsed) * interpolatedExpansion
|
||||
canvas.translate(triangleX, triangleY)
|
||||
canvas.drawPath(triangle, backgroundPaint)
|
||||
triangleOutline.setPath(triangle)
|
||||
@@ -309,7 +335,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly
|
||||
currentCornerRadius,
|
||||
Path.Direction.CW,
|
||||
)
|
||||
if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) {
|
||||
if (expansionProgress >= minExpansionProgressForTriangle) {
|
||||
path.addPath(triangleOutline.mPath)
|
||||
}
|
||||
outline.setPath(path)
|
||||
|
||||
@@ -1149,12 +1149,18 @@ public abstract class AbsSwipeUpHandler<
|
||||
|
||||
if (endTarget != NEW_TASK) {
|
||||
InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_QUICK_SWITCH);
|
||||
} else {
|
||||
InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_QUICK_SWITCH);
|
||||
}
|
||||
if (endTarget != HOME) {
|
||||
InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME);
|
||||
} else {
|
||||
InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME);
|
||||
}
|
||||
if (endTarget != RECENTS) {
|
||||
InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS);
|
||||
} else {
|
||||
InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS);
|
||||
}
|
||||
|
||||
switch (endTarget) {
|
||||
|
||||
@@ -52,7 +52,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
@@ -610,8 +609,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
|
||||
private void updateDrawables() {
|
||||
if (mContext != null) {
|
||||
mTutorialFragment.getRootView().setBackground(AppCompatResources.getDrawable(
|
||||
mContext, getMockWallpaperResId()));
|
||||
mTutorialFragment.getRootView()
|
||||
.setBackground(mContext.getDrawable(getMockWallpaperResId()));
|
||||
mTutorialFragment.updateFeedbackAnimation();
|
||||
mFakeLauncherView.setBackgroundColor(getFakeLauncherColor());
|
||||
updateFakeViewLayout(mFakeHotseatView, getMockHotseatResId());
|
||||
@@ -619,9 +618,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
mFakeTaskView.animate().alpha(1).setListener(
|
||||
AnimatorListeners.forSuccessCallback(() -> mFakeTaskView.animate().cancel()));
|
||||
mFakePreviousTaskView.setFakeTaskViewFillColor(getMockPreviousAppTaskThumbnailColor());
|
||||
mFakeIconView.setBackground(AppCompatResources.getDrawable(
|
||||
mContext, getMockAppIconResId()));
|
||||
|
||||
mFakeIconView.setBackground(mContext.getDrawable(getMockAppIconResId()));
|
||||
mExitingAppView.setBackgroundColor(getExitingAppColor());
|
||||
mFakeTaskView.setBackgroundColor(getFakeTaskViewColor());
|
||||
updateHotseatChildViewColor(mHotseatIconView);
|
||||
|
||||
@@ -22,8 +22,6 @@ import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
@@ -91,9 +89,8 @@ public class TutorialStepIndicator extends LinearLayout {
|
||||
int inactiveStepIndicatorColor = GraphicsUtils.getAttrColor(
|
||||
getContext(), android.R.attr.textColorSecondaryInverse);
|
||||
for (int i = 0; i < mTotalSteps; i++) {
|
||||
Drawable pageIndicatorPillDrawable = AppCompatResources.getDrawable(
|
||||
getContext(), R.drawable.tutorial_step_indicator_pill);
|
||||
|
||||
Drawable pageIndicatorPillDrawable =
|
||||
getContext().getDrawable(R.drawable.tutorial_step_indicator_pill);
|
||||
if (i >= getChildCount()) {
|
||||
ImageView pageIndicatorPill = new ImageView(getContext());
|
||||
pageIndicatorPill.setImageDrawable(pageIndicatorPillDrawable);
|
||||
|
||||
@@ -113,6 +113,12 @@ class RecentsViewUtils {
|
||||
it.isVisibleInCarousel(runningTaskView, nonRunningTaskCarouselHidden)
|
||||
}
|
||||
|
||||
/** Returns if any small tasks are fully visible */
|
||||
fun isAnySmallTaskFullyVisible(
|
||||
taskViews: Iterable<TaskView>,
|
||||
isTaskViewFullyVisible: (TaskView) -> Boolean,
|
||||
): Boolean = taskViews.any { !it.isLargeTile && isTaskViewFullyVisible(it) }
|
||||
|
||||
/** Returns the current list of [TaskView] children. */
|
||||
fun getTaskViews(taskViewCount: Int, requireTaskViewAt: (Int) -> TaskView): Iterable<TaskView> =
|
||||
(0 until taskViewCount).map(requireTaskViewAt)
|
||||
|
||||
@@ -238,7 +238,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
|
||||
taskViewHeight,
|
||||
)
|
||||
val snapshotViewSize =
|
||||
if (isPrimaryTaskSplitting) primarySnapshotViewSize else secondarySnapshotViewSize
|
||||
if (isPrimaryTaskSplitting) secondarySnapshotViewSize else primarySnapshotViewSize
|
||||
if (deviceProfile.isLeftRightSplit) {
|
||||
// Center view first so scaling happens uniformly, alternatively we can move pivotX to 0
|
||||
val centerThumbnailTranslationX: Float = (taskViewWidth - snapshotViewSize.x) / 2f
|
||||
|
||||
@@ -1706,10 +1706,11 @@ public abstract class RecentsView<
|
||||
return;
|
||||
}
|
||||
TaskView taskView = getTaskViewAt(mNextPage);
|
||||
// Snap to fully visible focused task and clear all button.
|
||||
boolean shouldSnapToLargeTask = taskView != null && taskView.isLargeTile()
|
||||
&& isTaskViewFullyVisible(taskView);
|
||||
&& !mUtils.isAnySmallTaskFullyVisible(getTaskViews(),
|
||||
this::isTaskViewFullyVisible);
|
||||
boolean shouldSnapToClearAll = mNextPage == indexOfChild(mClearAllButton);
|
||||
// Snap to large tile when grid tasks aren't fully visible or the clear all button.
|
||||
if (!shouldSnapToLargeTask && !shouldSnapToClearAll) {
|
||||
return;
|
||||
}
|
||||
@@ -3611,10 +3612,10 @@ public abstract class RecentsView<
|
||||
float dismissedTaskWidth = 0;
|
||||
float nextFocusedTaskWidth = 0;
|
||||
|
||||
// Non-grid specific properties.
|
||||
int[] oldScroll = new int[count];
|
||||
int[] newScroll = new int[count];
|
||||
int scrollDiffPerPage = 0;
|
||||
// Non-grid specific properties.
|
||||
boolean needsCurveUpdates = false;
|
||||
|
||||
if (showAsGrid) {
|
||||
@@ -3644,13 +3645,13 @@ public abstract class RecentsView<
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
|
||||
getPageScrolls(newScroll, false,
|
||||
v -> v.getVisibility() != GONE && v != dismissedTaskView);
|
||||
if (count > 1) {
|
||||
scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
|
||||
}
|
||||
}
|
||||
|
||||
getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
|
||||
getPageScrolls(newScroll, false,
|
||||
v -> v.getVisibility() != GONE && v != dismissedTaskView);
|
||||
if (count > 1) {
|
||||
scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
|
||||
}
|
||||
|
||||
float dismissTranslationInterpolationEnd = 1;
|
||||
@@ -3802,7 +3803,9 @@ public abstract class RecentsView<
|
||||
addDismissedTaskAnimations(dismissedTaskView, duration, anim);
|
||||
}
|
||||
}
|
||||
} else if (!showAsGrid) {
|
||||
} else if (!showAsGrid || (enableLargeDesktopWindowingTile()
|
||||
&& dismissedTaskView.isLargeTile()
|
||||
&& nextFocusedTaskView == null)) {
|
||||
int offset = getOffsetToDismissedTask(scrollDiffPerPage, dismissedIndex, taskCount);
|
||||
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
|
||||
if (scrollDiff != 0) {
|
||||
@@ -3814,18 +3817,16 @@ public abstract class RecentsView<
|
||||
splitTimings);
|
||||
needsCurveUpdates = true;
|
||||
}
|
||||
} else if (child instanceof TaskView) {
|
||||
TaskView taskView = (TaskView) child;
|
||||
} else if (child instanceof TaskView taskView) {
|
||||
if (isFocusedTaskDismissed) {
|
||||
if (nextFocusedTaskView != null &&
|
||||
!isSameGridRow(taskView, nextFocusedTaskView)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
|
||||
continue;
|
||||
}
|
||||
} else if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Animate task with index >= dismissed index and in the same row as the
|
||||
// dismissed index or next focused index. Offset successive task dismissal
|
||||
// durations for a staggered effect.
|
||||
@@ -4136,15 +4137,18 @@ public abstract class RecentsView<
|
||||
* - Dragging an adjacent page on the left side (right side for RTL)
|
||||
*/
|
||||
private int getOffsetToDismissedTask(int scrollDiffPerPage, int dismissedIndex, int taskCount) {
|
||||
// When mCurrentPage is ClearAllButton, use the last TaskView instead to calculate
|
||||
// offset.
|
||||
int currentPage = mCurrentPage == taskCount ? taskCount - 1 : mCurrentPage;
|
||||
int offset = mIsRtl ? scrollDiffPerPage : 0;
|
||||
if (mCurrentPage == dismissedIndex) {
|
||||
if (currentPage == dismissedIndex) {
|
||||
int lastPage = taskCount - 1;
|
||||
if (mCurrentPage == lastPage) {
|
||||
if (currentPage == lastPage) {
|
||||
offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
|
||||
}
|
||||
} else {
|
||||
// Dismissing an adjacent page.
|
||||
int negativeAdjacent = mCurrentPage - 1; // (Right in RTL, left in LTR)
|
||||
int negativeAdjacent = currentPage - 1; // (Right in RTL, left in LTR)
|
||||
if (dismissedIndex == negativeAdjacent) {
|
||||
offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
|
||||
}
|
||||
|
||||
+4
-2
@@ -224,7 +224,7 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) {
|
||||
BubbleBarFlyoutMessage(
|
||||
senderAvatar = ColorDrawable(Color.RED),
|
||||
senderName = "sender",
|
||||
message = "collapsed 90% on left",
|
||||
message = "expanded 90% on left",
|
||||
isGroupChat = true,
|
||||
)
|
||||
) {}
|
||||
@@ -249,7 +249,7 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) {
|
||||
BubbleBarFlyoutMessage(
|
||||
senderAvatar = ColorDrawable(Color.RED),
|
||||
senderName = "sender",
|
||||
message = "collapsed 80% on right",
|
||||
message = "expanded 80% on right",
|
||||
isGroupChat = true,
|
||||
)
|
||||
) {}
|
||||
@@ -265,5 +265,7 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) {
|
||||
override val targetTy = 0f
|
||||
override val collapsedSize = 30f
|
||||
override val collapsedColor = Color.BLUE
|
||||
override val collapsedElevation = 1f
|
||||
override val distanceToRevealTriangle = 10f
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -55,6 +55,8 @@ class BubbleBarFlyoutControllerTest {
|
||||
override val distanceToCollapsedPosition = PointF(100f, 200f)
|
||||
override val collapsedSize = 30f
|
||||
override val collapsedColor = Color.BLUE
|
||||
override val collapsedElevation = 1f
|
||||
override val distanceToRevealTriangle = 50f
|
||||
}
|
||||
flyoutController = BubbleBarFlyoutController(flyoutContainer, positioner)
|
||||
}
|
||||
|
||||
+1
-1
@@ -240,7 +240,7 @@ class TransientBubbleStashControllerTest {
|
||||
mTransientBubbleStashController.isStashed = false
|
||||
whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
|
||||
|
||||
// When unstash
|
||||
// When stash
|
||||
getInstrumentation().runOnMainSync {
|
||||
mTransientBubbleStashController.updateStashedAndExpandedState(
|
||||
stash = true,
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
|
||||
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
|
||||
<string name="split_app_usage_settings" msgid="7214375263347964093">"Usage settings for %1$s"</string>
|
||||
<!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
|
||||
<skip />
|
||||
<string name="new_window_option_taskbar" msgid="6448780542727767211">"New window"</string>
|
||||
<string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
|
||||
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
|
||||
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
|
||||
|
||||
@@ -66,6 +66,7 @@ import com.android.launcher3.BuildConfig;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Flags;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatedPropertySetter;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
@@ -699,7 +700,9 @@ public class PrivateProfileManager extends UserProfileManager {
|
||||
mAllApps.mAH.get(MAIN).mRecyclerView.removeItemDecoration(
|
||||
mPrivateAppsSectionDecorator);
|
||||
// Call onAppsUpdated() because it may be canceled when this animation occurs.
|
||||
mAllApps.getPersonalAppList().onAppsUpdated();
|
||||
if (!Utilities.isRunningInTestHarness()) {
|
||||
mAllApps.getPersonalAppList().onAppsUpdated();
|
||||
}
|
||||
if (isPrivateSpaceHidden()) {
|
||||
// TODO (b/325455879): Figure out if we can avoid this.
|
||||
getMainRecyclerView().getAdapter().notifyDataSetChanged();
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.dagger;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
import com.android.launcher3.util.DaggerSingletonTracker;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
@@ -32,6 +33,8 @@ import dagger.BindsInstance;
|
||||
*/
|
||||
public interface LauncherBaseAppComponent {
|
||||
DaggerSingletonTracker getDaggerSingletonTracker();
|
||||
InstallSessionHelper getInstallSessionHelper();
|
||||
|
||||
/** Builder for LauncherBaseAppComponent. */
|
||||
interface Builder {
|
||||
@BindsInstance Builder appContext(@ApplicationContext Context context);
|
||||
|
||||
@@ -31,12 +31,17 @@ import androidx.annotation.WorkerThread;
|
||||
import com.android.launcher3.Flags;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.SessionCommitReceiver;
|
||||
import com.android.launcher3.dagger.ApplicationContext;
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton;
|
||||
import com.android.launcher3.dagger.LauncherBaseAppComponent;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.model.ItemInstallQueue;
|
||||
import com.android.launcher3.util.ApplicationInfoWrapper;
|
||||
import com.android.launcher3.util.DaggerSingletonObject;
|
||||
import com.android.launcher3.util.DaggerSingletonTracker;
|
||||
import com.android.launcher3.util.ExecutorUtil;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
@@ -47,10 +52,13 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Utility class to tracking install sessions
|
||||
*/
|
||||
@SuppressWarnings("NewApi")
|
||||
@LauncherAppSingleton
|
||||
public class InstallSessionHelper implements SafeCloseable {
|
||||
|
||||
@NonNull
|
||||
@@ -64,8 +72,8 @@ public class InstallSessionHelper implements SafeCloseable {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@NonNull
|
||||
public static final MainThreadInitializedObject<InstallSessionHelper> INSTANCE =
|
||||
new MainThreadInitializedObject<>(InstallSessionHelper::new);
|
||||
public static final DaggerSingletonObject<InstallSessionHelper> INSTANCE =
|
||||
new DaggerSingletonObject<>(LauncherBaseAppComponent::getInstallSessionHelper);
|
||||
|
||||
@Nullable
|
||||
private final LauncherApps mLauncherApps;
|
||||
@@ -82,10 +90,13 @@ public class InstallSessionHelper implements SafeCloseable {
|
||||
@Nullable
|
||||
private IntSet mPromiseIconIds;
|
||||
|
||||
public InstallSessionHelper(@NonNull final Context context) {
|
||||
@Inject
|
||||
public InstallSessionHelper(@NonNull @ApplicationContext final Context context,
|
||||
DaggerSingletonTracker tracker) {
|
||||
mInstaller = context.getPackageManager().getPackageInstaller();
|
||||
mAppContext = context.getApplicationContext();
|
||||
mLauncherApps = context.getSystemService(LauncherApps.class);
|
||||
ExecutorUtil.executeSyncOnMainOrFail(() -> tracker.addCloseable(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.launcher3.LauncherPrefs
|
||||
import com.android.launcher3.LauncherPrefs.Companion.PROMISE_ICON_IDS
|
||||
import com.android.launcher3.util.DaggerSingletonTracker
|
||||
import com.android.launcher3.util.Executors.MODEL_EXECUTOR
|
||||
import com.android.launcher3.util.IntArray
|
||||
import com.android.launcher3.util.LauncherModelHelper
|
||||
@@ -53,6 +54,7 @@ class InstallSessionHelperTest {
|
||||
private val expectedAppPackage = "expectedAppPackage"
|
||||
private val expectedInstallerPackage = "expectedInstallerPackage"
|
||||
private val mockPackageInstaller: PackageInstaller = mock()
|
||||
private val mTracker: DaggerSingletonTracker = mock()
|
||||
|
||||
private lateinit var installSessionHelper: InstallSessionHelper
|
||||
private lateinit var launcherApps: LauncherApps
|
||||
@@ -62,7 +64,7 @@ class InstallSessionHelperTest {
|
||||
whenever(packageManager.packageInstaller).thenReturn(mockPackageInstaller)
|
||||
whenever(sandboxContext.packageName).thenReturn(expectedInstallerPackage)
|
||||
launcherApps = sandboxContext.spyService(LauncherApps::class.java)
|
||||
installSessionHelper = InstallSessionHelper(sandboxContext)
|
||||
installSessionHelper = InstallSessionHelper(sandboxContext, mTracker)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,6 +26,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -103,6 +104,8 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
|
||||
public static final long DEFAULT_UI_TIMEOUT = TestUtil.DEFAULT_UI_TIMEOUT;
|
||||
private static final String TAG = "AbstractLauncherUiTest";
|
||||
|
||||
private static final long BYTES_PER_MEGABYTE = 1 << 20;
|
||||
|
||||
private static boolean sDumpWasGenerated = false;
|
||||
private static boolean sActivityLeakReported = false;
|
||||
private static boolean sSeenKeyguard = false;
|
||||
@@ -124,6 +127,10 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
|
||||
protected String mTargetPackage;
|
||||
private int mLauncherPid;
|
||||
|
||||
private final ActivityManager.MemoryInfo mMemoryInfo = new ActivityManager.MemoryInfo();
|
||||
private final ActivityManager mActivityManager;
|
||||
private long mMemoryBefore;
|
||||
|
||||
/** Detects activity leaks and throws an exception if a leak is found. */
|
||||
public static void checkDetectedLeaks(LauncherInstrumentation launcher) {
|
||||
checkDetectedLeaks(launcher, false);
|
||||
@@ -192,6 +199,8 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
|
||||
}
|
||||
|
||||
protected AbstractLauncherUiTest() {
|
||||
mActivityManager = InstrumentationRegistry.getContext()
|
||||
.getSystemService(ActivityManager.class);
|
||||
mLauncher.enableCheckEventsForSuccessfulGestures();
|
||||
mLauncher.setAnomalyChecker(AbstractLauncherUiTest::verifyKeyguardInvisible);
|
||||
try {
|
||||
@@ -311,6 +320,26 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
|
||||
initialize(this);
|
||||
}
|
||||
|
||||
private long getAvailableMemory() {
|
||||
mActivityManager.getMemoryInfo(mMemoryInfo);
|
||||
|
||||
return Math.divideExact(mMemoryInfo.availMem, BYTES_PER_MEGABYTE);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void saveMemoryBefore() {
|
||||
mMemoryBefore = getAvailableMemory();
|
||||
}
|
||||
|
||||
@After
|
||||
public void logMemoryAfter() {
|
||||
long memoryAfter = getAvailableMemory();
|
||||
|
||||
Log.d(TAG, "Available memory: before=" + mMemoryBefore
|
||||
+ "MB, after=" + memoryAfter
|
||||
+ "MB, delta=" + (memoryAfter - mMemoryBefore) + "MB");
|
||||
}
|
||||
|
||||
/** Method that should be called when a test starts. */
|
||||
public static void onTestStart() {
|
||||
waitForSetupWizardDismissal();
|
||||
|
||||
Reference in New Issue
Block a user