Snap for 12445464 from 17b246a556 to 25Q1-release

Change-Id: Id9550bc05cc13a98d51afd7e7c7f88040909da77
This commit is contained in:
Android Build Coastguard Worker
2024-10-02 23:22:45 +00:00
21 changed files with 171 additions and 59 deletions
+1 -2
View File
@@ -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();
}
/**
@@ -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;
}
@@ -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
}
}
@@ -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)
}
@@ -240,7 +240,7 @@ class TransientBubbleStashControllerTest {
mTransientBubbleStashController.isStashed = false
whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
// When unstash
// When stash
getInstrumentation().runOnMainSync {
mTransientBubbleStashController.updateStashedAndExpandedState(
stash = true,
+1 -2
View File
@@ -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();