Snap for 11399958 from cac7c6f682 to 24Q2-release
Change-Id: I9a5c16bf02104ffbb1e47a8b3e9b0f340f44955c
This commit is contained in:
@@ -71,6 +71,7 @@ import com.android.launcher3.taskbar.TaskbarControllers;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.Executors.SimpleThreadFactory;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.wm.shell.Flags;
|
||||
import com.android.wm.shell.bubbles.IBubblesListener;
|
||||
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
|
||||
import com.android.wm.shell.common.bubbles.BubbleInfo;
|
||||
@@ -101,8 +102,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
|
||||
*
|
||||
* @see #onTaskbarRecreated()
|
||||
*/
|
||||
private static boolean sBubbleBarEnabled =
|
||||
SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
|
||||
private static boolean sBubbleBarEnabled = Flags.enableBubbleBar()
|
||||
|| SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
|
||||
|
||||
/** Whether showing bubbles in the launcher bubble bar is enabled. */
|
||||
public static boolean isBubbleBarEnabled() {
|
||||
@@ -111,8 +112,10 @@ public class BubbleBarController extends IBubblesListener.Stub {
|
||||
|
||||
/** Re-reads the value of the flag from SystemProperties when taskbar is recreated. */
|
||||
public static void onTaskbarRecreated() {
|
||||
sBubbleBarEnabled = SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
|
||||
sBubbleBarEnabled = Flags.enableBubbleBar()
|
||||
|| SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
|
||||
}
|
||||
|
||||
private static final int MASK_HIDE_BUBBLE_BAR = SYSUI_STATE_BOUNCER_SHOWING
|
||||
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
|
||||
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
|
||||
|
||||
@@ -28,10 +28,8 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.Toast;
|
||||
import android.window.SplashScreen;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -63,8 +61,7 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler {
|
||||
// Log metric
|
||||
StatsLogManager.StatsLogger logger = mLauncher.getStatsLogManager().logger();
|
||||
logger.log(LAUNCHER_SPLIT_WIDGET_ATTEMPT);
|
||||
Toast.makeText(hostView.getContext(), R.string.split_widgets_not_supported,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
mLauncher.handleIncorrectSplitTargetSelection();
|
||||
return true;
|
||||
}
|
||||
Pair<Intent, ActivityOptions> options = remoteResponse.getLaunchOptions(view);
|
||||
|
||||
@@ -36,6 +36,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||
import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
|
||||
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
|
||||
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
|
||||
@@ -676,7 +677,7 @@ public class QuickstepLauncher extends Launcher {
|
||||
splitSelectSource.alreadyRunningTaskId = taskWasFound
|
||||
? foundTask.key.id
|
||||
: INVALID_TASK_ID;
|
||||
if (FeatureFlags.enableSplitContextually()) {
|
||||
if (enableSplitContextually()) {
|
||||
startSplitToHome(splitSelectSource);
|
||||
} else {
|
||||
recentsView.initiateSplitSelect(splitSelectSource);
|
||||
@@ -761,7 +762,7 @@ public class QuickstepLauncher extends Launcher {
|
||||
|
||||
super.onPause();
|
||||
|
||||
if (FeatureFlags.enableSplitContextually()) {
|
||||
if (enableSplitContextually()) {
|
||||
// If Launcher pauses before both split apps are selected, exit split screen.
|
||||
if (!mSplitSelectStateController.isBothSplitAppsConfirmed() &&
|
||||
!mSplitSelectStateController.isLaunchingFirstAppFullscreen()) {
|
||||
@@ -1352,6 +1353,15 @@ public class QuickstepLauncher extends Launcher {
|
||||
return (mTaskbarUIController != null && mTaskbarUIController.hasBubbles());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleIncorrectSplitTargetSelection() {
|
||||
if (enableSplitContextually() && !mSplitSelectStateController.isSplitSelectActive()) {
|
||||
return false;
|
||||
}
|
||||
mSplitSelectStateController.getSplitInstructionsView().goBoing();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final class LauncherTaskViewController extends
|
||||
TaskViewTouchController<Launcher> {
|
||||
|
||||
|
||||
@@ -371,8 +371,8 @@ public class FallbackSwipeHandler extends
|
||||
if (mSpringAnim != null) {
|
||||
mSpringAnim.onTargetPositionChanged();
|
||||
}
|
||||
mOnFinishCallback = data.getParcelable(EXTRA_ON_FINISH_CALLBACK);
|
||||
}
|
||||
mOnFinishCallback = data.getParcelable(EXTRA_ON_FINISH_CALLBACK);
|
||||
maybeSendEndMessage();
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Flags.enableCursorHoverStates;
|
||||
import static com.android.launcher3.Flags.useActivityOverlay;
|
||||
import static com.android.launcher3.Launcher.INTENT_ACTION_ALL_APPS_TOGGLE;
|
||||
import static com.android.launcher3.LauncherPrefs.backedUpItem;
|
||||
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
|
||||
@@ -1159,6 +1160,14 @@ public class TouchInteractionService extends Service {
|
||||
boolean launcherResumedThroughShellTransition =
|
||||
gestureState.getActivityInterface().isResumed()
|
||||
&& !previousGestureState.isRecentsAnimationRunning();
|
||||
// If a task fragment within Launcher is resumed
|
||||
boolean launcherChildActivityResumed = useActivityOverlay()
|
||||
&& runningTask != null
|
||||
&& runningTask.isHomeTask()
|
||||
&& mOverviewComponentObserver.isHomeAndOverviewSame()
|
||||
&& !launcherResumedThroughShellTransition
|
||||
&& !previousGestureState.isRecentsAnimationRunning();
|
||||
|
||||
if (gestureState.getActivityInterface().isInLiveTileMode()) {
|
||||
return createOverviewInputConsumer(
|
||||
previousGestureState,
|
||||
@@ -1185,9 +1194,11 @@ public class TouchInteractionService extends Service {
|
||||
? "launcher resumed through a shell transition"
|
||||
: "forceOverviewInputConsumer == true"))
|
||||
.append(", trying to use overview input consumer"));
|
||||
} else if (mDeviceState.isGestureBlockedTask(runningTask)) {
|
||||
} else if (mDeviceState.isGestureBlockedTask(runningTask) || launcherChildActivityResumed) {
|
||||
return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
|
||||
.append("is gesture-blocked task, trying to use default input consumer"));
|
||||
.append(launcherChildActivityResumed
|
||||
? "is launcher child-task, trying to use default input consumer"
|
||||
: "is gesture-blocked task, trying to use default input consumer"));
|
||||
} else {
|
||||
reasonString.append(SUBSTRING_PREFIX)
|
||||
.append("using OtherActivityInputConsumer");
|
||||
|
||||
@@ -86,6 +86,7 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
private final int mMinIconBackgroundHeight;
|
||||
private final int mMaxIconBackgroundCornerRadius;
|
||||
private final float mMinIconBackgroundCornerRadius;
|
||||
private AnimatorSet mAnimator;
|
||||
|
||||
private int mMaxWidth = Integer.MAX_VALUE;
|
||||
|
||||
@@ -316,11 +317,13 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
}
|
||||
|
||||
protected void revealAnim(boolean isRevealing) {
|
||||
cancelInProgressAnimations();
|
||||
|
||||
if (isRevealing) {
|
||||
boolean isRtl = isLayoutRtl();
|
||||
bringToFront();
|
||||
((AnimatedVectorDrawable) mIconArrowView.getDrawable()).start();
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
mAnimator = new AnimatorSet();
|
||||
float backgroundScaleY = mMaxIconBackgroundHeight / (float) mMinIconBackgroundHeight;
|
||||
float maxCornerSize = Math.min(mMaxIconBackgroundHeight / 2f,
|
||||
mMaxIconBackgroundCornerRadius);
|
||||
@@ -341,7 +344,7 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
mIconTextMaxWidth + maxCornerSize);
|
||||
}
|
||||
});
|
||||
anim.playTogether(
|
||||
mAnimator.playTogether(
|
||||
expandedTextRevealAnim,
|
||||
ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_Y,
|
||||
backgroundScaleY),
|
||||
@@ -367,9 +370,9 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
ObjectAnimator.ofFloat(mIconTextExpandedView, ALPHA, 1),
|
||||
ObjectAnimator.ofFloat(mIconArrowView, TRANSLATION_X,
|
||||
isRtl ? -arrowTranslationX : arrowTranslationX));
|
||||
anim.setDuration(MENU_BACKGROUND_REVEAL_DURATION);
|
||||
anim.setInterpolator(EMPHASIZED);
|
||||
anim.start();
|
||||
mAnimator.setDuration(MENU_BACKGROUND_REVEAL_DURATION);
|
||||
mAnimator.setInterpolator(EMPHASIZED);
|
||||
mAnimator.start();
|
||||
} else {
|
||||
((AnimatedVectorDrawable) mIconArrowView.getDrawable()).reverse();
|
||||
float maxCornerSize = Math.min(mMaxIconBackgroundHeight / 2f,
|
||||
@@ -386,8 +389,8 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
mIconTextExpandedView.getHeight() / 2f, 0);
|
||||
}
|
||||
});
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.playTogether(
|
||||
mAnimator = new AnimatorSet();
|
||||
mAnimator.playTogether(
|
||||
expandedTextClipAnim,
|
||||
ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_X, 1),
|
||||
ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_Y, 1),
|
||||
@@ -403,9 +406,9 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
ObjectAnimator.ofFloat(mIconTextCollapsedView, ALPHA, 1),
|
||||
ObjectAnimator.ofFloat(mIconTextExpandedView, ALPHA, 0),
|
||||
ObjectAnimator.ofFloat(mIconArrowView, TRANSLATION_X, 0));
|
||||
anim.setDuration(MENU_BACKGROUND_HIDE_DURATION);
|
||||
anim.setInterpolator(EMPHASIZED);
|
||||
anim.start();
|
||||
mAnimator.setDuration(MENU_BACKGROUND_HIDE_DURATION);
|
||||
mAnimator.setInterpolator(EMPHASIZED);
|
||||
mAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,6 +428,16 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
|
||||
mIconTextExpandedView.setAlpha(0);
|
||||
mIconArrowView.setTranslationX(0);
|
||||
((AnimatedVectorDrawable) mIconArrowView.getDrawable()).reset();
|
||||
mAnimator = null;
|
||||
}
|
||||
|
||||
private void cancelInProgressAnimations() {
|
||||
// We null the `AnimatorSet` because it holds references to the `Animators` which aren't
|
||||
// expecting to be mutable and will cause a crash if they are re-used.
|
||||
if (mAnimator != null && mAnimator.isStarted()) {
|
||||
mAnimator.cancel();
|
||||
mAnimator = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
@@ -69,6 +70,8 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
private TextView mTaskName;
|
||||
@Nullable
|
||||
private AnimatorSet mOpenCloseAnimator;
|
||||
@Nullable
|
||||
private ValueAnimator mRevealAnimator;
|
||||
@Nullable private Runnable mOnClosingStartCallback;
|
||||
private TaskView mTaskView;
|
||||
private TaskIdAttributeContainer mTaskContainer;
|
||||
@@ -290,13 +293,18 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
|
||||
private void animateOpenOrClosed(boolean closing) {
|
||||
if (mOpenCloseAnimator != null && mOpenCloseAnimator.isRunning()) {
|
||||
mOpenCloseAnimator.end();
|
||||
mOpenCloseAnimator.cancel();
|
||||
}
|
||||
mOpenCloseAnimator = new AnimatorSet();
|
||||
|
||||
final Animator revealAnimator = createOpenCloseOutlineProvider()
|
||||
.createRevealAnimator(this, closing);
|
||||
revealAnimator.setInterpolator(enableOverviewIconMenu() ? Interpolators.EMPHASIZED
|
||||
// If we're opening, we just start from the beginning as a new `TaskMenuView` is created
|
||||
// each time we do the open animation so there will never be a partial value here.
|
||||
float revealAnimationStartProgress = 0f;
|
||||
if (closing && mRevealAnimator != null) {
|
||||
revealAnimationStartProgress = 1f - mRevealAnimator.getAnimatedFraction();
|
||||
}
|
||||
mRevealAnimator = createOpenCloseOutlineProvider()
|
||||
.createRevealAnimator(this, closing, revealAnimationStartProgress);
|
||||
mRevealAnimator.setInterpolator(enableOverviewIconMenu() ? Interpolators.EMPHASIZED
|
||||
: Interpolators.DECELERATE);
|
||||
|
||||
if (enableOverviewIconMenu()) {
|
||||
@@ -349,7 +357,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
mOpenCloseAnimator.playTogether(translationXAnim, menuTranslationXAnim);
|
||||
}
|
||||
|
||||
mOpenCloseAnimator.playTogether(revealAnimator,
|
||||
mOpenCloseAnimator.playTogether(mRevealAnimator,
|
||||
ObjectAnimator.ofFloat(
|
||||
mTaskContainer.getThumbnailView(), DIM_ALPHA,
|
||||
closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
|
||||
@@ -378,6 +386,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
mIsOpen = false;
|
||||
resetOverviewIconMenu();
|
||||
mActivity.getDragLayer().removeView(this);
|
||||
mRevealAnimator = null;
|
||||
}
|
||||
|
||||
private void resetOverviewIconMenu() {
|
||||
|
||||
@@ -1137,9 +1137,8 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
DeviceProfile dp = mActivity.getDeviceProfile();
|
||||
if (enableOverviewIconMenu() && iconView instanceof IconAppChipView) {
|
||||
((IconAppChipView) iconView).revealAnim(/* isRevealing= */ true);
|
||||
return TaskMenuView.showForTask(menuContainer, () -> {
|
||||
((IconAppChipView) iconView).revealAnim(/* isRevealing= */ false);
|
||||
});
|
||||
return TaskMenuView.showForTask(menuContainer,
|
||||
() -> ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ false));
|
||||
} else if (dp.isTablet) {
|
||||
int alignedOptionIndex = 0;
|
||||
if (getRecentsView().isOnGridBottomRow(menuContainer.getTaskView()) && dp.isLandscape) {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<!-- App Widget resize frame -->
|
||||
<dimen name="widget_handle_margin">13dp</dimen>
|
||||
<dimen name="resize_frame_background_padding">24dp</dimen>
|
||||
<dimen name="resize_frame_margin">22dp</dimen>
|
||||
<dimen name="resize_frame_margin">23dp</dimen>
|
||||
<dimen name="resize_frame_invalid_drag_across_two_panel_opacity_margin">24dp</dimen>
|
||||
|
||||
<!-- App widget reconfigure button -->
|
||||
@@ -196,6 +196,8 @@
|
||||
<dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
|
||||
<dimen name="widget_list_entry_spacing">2dp</dimen>
|
||||
<dimen name="widget_list_horizontal_margin">16dp</dimen>
|
||||
<!-- Margin applied to the recycler view with search bar & the list of widget apps below it. -->
|
||||
<dimen name="widget_list_left_pane_horizontal_margin">0dp</dimen>
|
||||
<dimen name="widget_list_horizontal_margin_two_pane">24dp</dimen>
|
||||
|
||||
<dimen name="widget_preview_shadow_blur">0.5dp</dimen>
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.style.SuggestionSpan;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
@@ -42,6 +43,7 @@ public class AllAppsSearchBarController
|
||||
implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener,
|
||||
OnFocusChangeListener {
|
||||
|
||||
private static final String TAG = "AllAppsSearchBarController";
|
||||
protected ActivityContext mLauncher;
|
||||
protected SearchCallback<AdapterItem> mCallback;
|
||||
protected ExtendedEditText mInput;
|
||||
@@ -122,6 +124,7 @@ public class AllAppsSearchBarController
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO) {
|
||||
Log.i(TAG, "User tapped ime search button");
|
||||
// selectFocusedView should return SearchTargetEvent that is passed onto onClick
|
||||
return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
|
||||
}
|
||||
|
||||
@@ -800,6 +800,14 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
return;
|
||||
}
|
||||
|
||||
int size = getIconsInReadingOrder().size();
|
||||
if (size <= 1) {
|
||||
Log.d(TAG, "Couldn't animate folder closed because there's " + size + " icons");
|
||||
closeComplete(false);
|
||||
post(this::announceAccessibilityChanges);
|
||||
return;
|
||||
}
|
||||
|
||||
mContent.completePendingPageChanges();
|
||||
mContent.snapToPageImmediately(mContent.getDestinationPage());
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemFactory;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
@@ -102,6 +103,11 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
|
||||
Objects.requireNonNull(item.getIntent()))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item instanceof ItemInfoWithIcon
|
||||
&& ((ItemInfoWithIcon) item).isArchived()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
|
||||
|
||||
@@ -18,10 +18,12 @@ package com.android.launcher3.model;
|
||||
|
||||
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
|
||||
|
||||
import static com.android.launcher3.Flags.enableSupportForArchiving;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
|
||||
import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ARCHIVED;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
@@ -276,6 +278,7 @@ public class ItemInstallQueue {
|
||||
return intent;
|
||||
}
|
||||
|
||||
@SuppressWarnings("NewApi")
|
||||
public Pair<ItemInfo, Object> getItemInfo(Context context) {
|
||||
switch (itemType) {
|
||||
case ITEM_TYPE_APPLICATION: {
|
||||
@@ -297,6 +300,9 @@ public class ItemInstallQueue {
|
||||
} else {
|
||||
lai = laiList.get(0);
|
||||
si.intent = makeLaunchIntent(lai);
|
||||
if (enableSupportForArchiving() && lai.getActivityInfo().isArchived) {
|
||||
si.runtimeStatusFlags |= FLAG_ARCHIVED;
|
||||
}
|
||||
}
|
||||
LauncherAppState.getInstance(context).getIconCache()
|
||||
.getTitleAndIcon(si, () -> lai, usePackageIcon, false);
|
||||
|
||||
@@ -150,6 +150,12 @@ public class TestInformationHandler implements ResourceBasedOverride {
|
||||
}, this::getCurrentActivity);
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_CELL_LAYOUT_BOARDER_HEIGHT: {
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
|
||||
mDeviceProfile.cellLayoutBorderSpacePx.y);
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_SYSTEM_GESTURE_REGION: {
|
||||
return getUIProperty(Bundle::putParcelable, activity -> {
|
||||
WindowInsetsCompat insets = WindowInsetsCompat.toWindowInsetsCompat(
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import static com.android.launcher3.Flags.enableSupportForArchiving;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -112,8 +114,7 @@ public class PackageManagerHelper {
|
||||
@NonNull final UserHandle user, final int flags) {
|
||||
try {
|
||||
ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
|
||||
return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 || !info.enabled
|
||||
? null : info;
|
||||
return !isPackageInstalledOrArchived(info) || !info.enabled ? null : info;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -253,4 +254,11 @@ public class PackageManagerHelper {
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
/** Returns true in case app is installed on the device or in archived state. */
|
||||
@SuppressWarnings("NewApi")
|
||||
private boolean isPackageInstalledOrArchived(ApplicationInfo info) {
|
||||
return (info.flags & ApplicationInfo.FLAG_INSTALLED) != 0 || (
|
||||
enableSupportForArchiving() && info.isArchived);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,19 @@ public interface ActivityContext {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle user tapping on unsupported target when in split selection mode.
|
||||
* See {@link #isSplitSelectionActive()}
|
||||
*
|
||||
* @return {@code true} if this method will handle the incorrect target selection,
|
||||
* {@code false} if it could not be handled or if not possible to handle based on
|
||||
* current split state
|
||||
*/
|
||||
default boolean handleIncorrectSplitTargetSelection() {
|
||||
// Overridden
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The root view to support drag-and-drop and popup support.
|
||||
*/
|
||||
|
||||
@@ -175,7 +175,6 @@ public class FloatingSurfaceView extends AbstractFloatingView implements
|
||||
|
||||
if (!mTmpPosition.equals(mIconPosition)) {
|
||||
mIconPosition.set(mTmpPosition);
|
||||
sendIconInfo();
|
||||
|
||||
LayoutParams lp = (LayoutParams) mSurfaceView.getLayoutParams();
|
||||
lp.width = Math.round(mIconPosition.width());
|
||||
@@ -184,6 +183,9 @@ public class FloatingSurfaceView extends AbstractFloatingView implements
|
||||
lp.topMargin = Math.round(mIconPosition.top);
|
||||
}
|
||||
}
|
||||
|
||||
sendIconInfo();
|
||||
|
||||
if (mIcon != null && iconChanged && !mIconBounds.isEmpty()) {
|
||||
// Record the icon display
|
||||
setCurrentIconVisible(true);
|
||||
@@ -197,7 +199,7 @@ public class FloatingSurfaceView extends AbstractFloatingView implements
|
||||
}
|
||||
|
||||
private void sendIconInfo() {
|
||||
if (mContract != null && !mIconPosition.isEmpty()) {
|
||||
if (mContract != null) {
|
||||
mContract.sendEndPosition(mIconPosition, mLauncher, mSurfaceView.getSurfaceControl());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,14 +72,21 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<BaseActivity>
|
||||
|
||||
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContentHorizontalMargin = getResources().getDimensionPixelSize(
|
||||
R.dimen.widget_list_horizontal_margin);
|
||||
mContentHorizontalMargin = getWidgetListHorizontalMargin();
|
||||
mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
|
||||
R.dimen.widget_cell_horizontal_padding);
|
||||
mNavBarScrimPaint = new Paint();
|
||||
mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the margins to be applied to the left and right of the widget apps list.
|
||||
*/
|
||||
protected int getWidgetListHorizontalMargin() {
|
||||
return getResources().getDimensionPixelSize(
|
||||
R.dimen.widget_list_horizontal_margin);
|
||||
}
|
||||
|
||||
protected int getScrimColor(Context context) {
|
||||
return context.getResources().getColor(R.color.widgets_picker_scrim);
|
||||
}
|
||||
@@ -142,8 +149,7 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<BaseActivity>
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
mInsets.set(insets);
|
||||
@Px int contentHorizontalMargin = getResources().getDimensionPixelSize(
|
||||
R.dimen.widget_list_horizontal_margin);
|
||||
@Px int contentHorizontalMargin = getWidgetListHorizontalMargin();
|
||||
if (contentHorizontalMargin != mContentHorizontalMargin) {
|
||||
onContentHorizontalMarginChanged(contentHorizontalMargin);
|
||||
mContentHorizontalMargin = contentHorizontalMargin;
|
||||
|
||||
@@ -302,6 +302,12 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getWidgetListHorizontalMargin() {
|
||||
return getResources().getDimensionPixelSize(
|
||||
R.dimen.widget_list_left_pane_horizontal_margin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isTwoPane() {
|
||||
return true;
|
||||
|
||||
@@ -176,6 +176,7 @@ android_library {
|
||||
name: "launcher-testing-shared",
|
||||
srcs: [
|
||||
"multivalentTests/shared/com/android/launcher3/testing/shared/**/*.java",
|
||||
"multivalentTests/shared/com/android/launcher3/testing/shared/**/*.kt"
|
||||
],
|
||||
resource_dirs: [],
|
||||
manifest: "multivalentTests/shared/AndroidManifest.xml",
|
||||
|
||||
@@ -121,6 +121,7 @@ public final class TestProtocol {
|
||||
public static final String REQUEST_IS_TABLET = "is-tablet";
|
||||
public static final String REQUEST_NUM_ALL_APPS_COLUMNS = "num-all-apps-columns";
|
||||
public static final String REQUEST_IS_TWO_PANELS = "is-two-panel";
|
||||
public static final String REQUEST_CELL_LAYOUT_BOARDER_HEIGHT = "cell-layout-boarder-height";
|
||||
public static final String REQUEST_START_DRAG_THRESHOLD = "start-drag-threshold";
|
||||
public static final String REQUEST_SHELL_DRAG_READY = "shell-drag-ready";
|
||||
public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT =
|
||||
|
||||
+3
-3
@@ -66,7 +66,7 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
|
||||
}
|
||||
|
||||
public CellLayoutBoard(int width, int height) {
|
||||
mWidget = new char[width + 1][height + 1];
|
||||
mWidget = new char[width][height];
|
||||
this.mWidth = width;
|
||||
this.mHeight = height;
|
||||
for (int x = 0; x < mWidget.length; x++) {
|
||||
@@ -371,8 +371,8 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
|
||||
s.append("\n");
|
||||
maxX = Math.min(maxX, mWidget.length);
|
||||
maxY = Math.min(maxY, mWidget[0].length);
|
||||
for (int y = 0; y <= maxY; y++) {
|
||||
for (int x = 0; x <= maxX; x++) {
|
||||
for (int y = 0; y < maxY; y++) {
|
||||
for (int x = 0; x < maxX; x++) {
|
||||
s.append(mWidget[x][y]);
|
||||
}
|
||||
s.append('\n');
|
||||
|
||||
+3
-3
@@ -27,7 +27,7 @@ open class RandomBoardGenerator(generator: Random) : DeterministicRandomGenerato
|
||||
* usually less than 100.
|
||||
* @return a randomly generated board filled with icons and widgets.
|
||||
*/
|
||||
open fun generateBoard(width: Int, height: Int, remainingEmptySpaces: Int): CellLayoutBoard? {
|
||||
open fun generateBoard(width: Int, height: Int, remainingEmptySpaces: Int): CellLayoutBoard {
|
||||
val cellLayoutBoard = CellLayoutBoard(width, height)
|
||||
return fillBoard(cellLayoutBoard, Rect(0, 0, width, height), remainingEmptySpaces)
|
||||
}
|
||||
@@ -39,8 +39,8 @@ open class RandomBoardGenerator(generator: Random) : DeterministicRandomGenerato
|
||||
): CellLayoutBoard {
|
||||
var remainingEmptySpaces = remainingEmptySpacesArg
|
||||
if (area.height() * area.width() <= 0) return board
|
||||
val width = getRandom(1, area.width() - 1)
|
||||
val height = getRandom(1, area.height() - 1)
|
||||
val width = getRandom(1, area.width())
|
||||
val height = getRandom(1, area.height())
|
||||
val x = area.left + getRandom(0, area.width() - width)
|
||||
val y = area.top + getRandom(0, area.height() - height)
|
||||
if (remainingEmptySpaces > 0) {
|
||||
|
||||
@@ -405,6 +405,11 @@ public final class LauncherInstrumentation {
|
||||
.getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
|
||||
int getCellLayoutBoarderHeight() {
|
||||
return getTestInfo(TestProtocol.REQUEST_CELL_LAYOUT_BOARDER_HEIGHT)
|
||||
.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
|
||||
int getFocusedTaskHeightForTablet() {
|
||||
return getTestInfo(TestProtocol.REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET).getInt(
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
|
||||
@@ -57,7 +57,8 @@ public class WidgetResizeFrame {
|
||||
Rect originalWidgetSize = widget.getVisibleBounds();
|
||||
Point targetStart = bottomResizeHandle.getVisibleCenter();
|
||||
Point targetDest = bottomResizeHandle.getVisibleCenter();
|
||||
targetDest.offset(0, originalWidgetSize.height());
|
||||
targetDest.offset(0,
|
||||
originalWidgetSize.height() + mLauncher.getCellLayoutBoarderHeight());
|
||||
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetStart,
|
||||
|
||||
@@ -62,5 +62,6 @@ public class TaplAllAppsIconsWorkingTest extends AbstractLauncherUiTest {
|
||||
} finally {
|
||||
allApps.unfreeze();
|
||||
}
|
||||
mLauncher.goHome();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.celllayout
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Point
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.core.view.get
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.launcher3.CellLayout
|
||||
import com.android.launcher3.celllayout.board.CellLayoutBoard
|
||||
import com.android.launcher3.celllayout.board.IconPoint
|
||||
import com.android.launcher3.celllayout.board.PermutedBoardComparator
|
||||
import com.android.launcher3.celllayout.board.WidgetRect
|
||||
import com.android.launcher3.celllayout.testgenerator.RandomBoardGenerator
|
||||
import com.android.launcher3.util.ActivityContextWrapper
|
||||
import com.android.launcher3.views.DoubleShadowBubbleTextView
|
||||
import java.util.Random
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
private class HotseatReorderTestCase(
|
||||
val startBoard: CellLayoutBoard,
|
||||
val endBoard: CellLayoutBoard
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "$startBoard#endBoard:\n$endBoard"
|
||||
}
|
||||
}
|
||||
|
||||
class HotseatReorderUnitTest {
|
||||
|
||||
private val applicationContext: Context =
|
||||
ActivityContextWrapper(ApplicationProvider.getApplicationContext())
|
||||
|
||||
@JvmField @Rule var cellLayoutBuilder = UnitTestCellLayoutBuilderRule()
|
||||
|
||||
/**
|
||||
* This test generates random CellLayout configurations and then try to reorder it and makes
|
||||
* sure the result is a valid board meaning it didn't remove any widget or icon.
|
||||
*/
|
||||
@Test
|
||||
fun generateValidTests() {
|
||||
val generator = Random(Companion.SEED.toLong())
|
||||
for (i in 0 until Companion.TOTAL_OF_CASES_GENERATED) {
|
||||
// Using a new seed so that we can replicate the same test cases.
|
||||
val seed = generator.nextInt()
|
||||
Log.d(Companion.TAG, "Seed = $seed")
|
||||
|
||||
val testCase: HotseatReorderTestCase =
|
||||
generateRandomTestCase(RandomBoardGenerator(Random(seed.toLong())))
|
||||
Log.d(Companion.TAG, "testCase = $testCase")
|
||||
|
||||
Assert.assertTrue(
|
||||
"invalid case $i",
|
||||
PermutedBoardComparator().compare(testCase.startBoard, testCase.endBoard) == 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addViewInCellLayout(
|
||||
cellLayout: CellLayout,
|
||||
cellX: Int,
|
||||
cellY: Int,
|
||||
spanX: Int,
|
||||
spanY: Int,
|
||||
isWidget: Boolean
|
||||
) {
|
||||
val cell =
|
||||
if (isWidget) View(applicationContext)
|
||||
else DoubleShadowBubbleTextView(applicationContext)
|
||||
cell.layoutParams = CellLayoutLayoutParams(cellX, cellY, spanX, spanY)
|
||||
cellLayout.addViewToCellLayout(
|
||||
cell,
|
||||
-1,
|
||||
cell.id,
|
||||
cell.layoutParams as CellLayoutLayoutParams,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
private fun solve(board: CellLayoutBoard): CellLayout {
|
||||
val cl = cellLayoutBuilder.createCellLayout(board.width, board.height, false)
|
||||
// The views have to be sorted or the result can vary
|
||||
board.icons
|
||||
.map(IconPoint::getCoord)
|
||||
.sortedWith(
|
||||
Comparator.comparing { p: Any -> (p as Point).x }
|
||||
.thenComparing { p: Any -> (p as Point).y }
|
||||
)
|
||||
.forEach { p ->
|
||||
addViewInCellLayout(
|
||||
cellLayout = cl,
|
||||
cellX = p.x,
|
||||
cellY = p.y,
|
||||
spanX = 1,
|
||||
spanY = 1,
|
||||
isWidget = false
|
||||
)
|
||||
}
|
||||
board.widgets
|
||||
.sortedWith(
|
||||
Comparator.comparing(WidgetRect::getCellX).thenComparing(WidgetRect::getCellY)
|
||||
)
|
||||
.forEach { widget ->
|
||||
addViewInCellLayout(
|
||||
cl,
|
||||
widget.cellX,
|
||||
widget.cellY,
|
||||
widget.spanX,
|
||||
widget.spanY,
|
||||
isWidget = true
|
||||
)
|
||||
}
|
||||
if (cl.makeSpaceForHotseatMigration(true)) {
|
||||
commitTempPosition(cl)
|
||||
}
|
||||
return cl
|
||||
}
|
||||
|
||||
private fun commitTempPosition(cellLayout: CellLayout) {
|
||||
val count = cellLayout.shortcutsAndWidgets.childCount
|
||||
for (i in 0 until count) {
|
||||
val params = cellLayout.shortcutsAndWidgets[i].layoutParams as CellLayoutLayoutParams
|
||||
params.cellX = params.tmpCellX
|
||||
params.cellY = params.tmpCellY
|
||||
}
|
||||
}
|
||||
|
||||
private fun boardFromCellLayout(cellLayout: CellLayout): CellLayoutBoard {
|
||||
val views = mutableListOf<View>()
|
||||
for (i in 0 until cellLayout.shortcutsAndWidgets.childCount) {
|
||||
views.add(cellLayout.shortcutsAndWidgets.getChildAt(i))
|
||||
}
|
||||
return CellLayoutTestUtils.viewsToBoard(views, cellLayout.countX, cellLayout.countY)
|
||||
}
|
||||
|
||||
private fun generateRandomTestCase(
|
||||
boardGenerator: RandomBoardGenerator
|
||||
): HotseatReorderTestCase {
|
||||
val width: Int = boardGenerator.getRandom(3, Companion.MAX_BOARD_SIZE)
|
||||
val height: Int = boardGenerator.getRandom(3, Companion.MAX_BOARD_SIZE)
|
||||
val targetWidth: Int = boardGenerator.getRandom(1, width - 2)
|
||||
val targetHeight: Int = boardGenerator.getRandom(1, height - 2)
|
||||
val board: CellLayoutBoard =
|
||||
boardGenerator.generateBoard(width, height, targetWidth * targetHeight)
|
||||
val finishBoard: CellLayoutBoard = boardFromCellLayout(solve(board))
|
||||
return HotseatReorderTestCase(board, finishBoard)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MAX_BOARD_SIZE = 13
|
||||
|
||||
/**
|
||||
* There is nothing special about this numbers, the random seed is just to be able to
|
||||
* reproduce the test cases and the height and width is a random number similar to what
|
||||
* users expect on their devices
|
||||
*/
|
||||
private const val SEED = -194162315
|
||||
private const val TOTAL_OF_CASES_GENERATED = 300
|
||||
private const val TAG = "HotseatReorderUnitTest"
|
||||
}
|
||||
}
|
||||
@@ -161,11 +161,12 @@ public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest {
|
||||
|
||||
public int getWidgetId() throws InterruptedException {
|
||||
Intent intent = blockingGetExtraIntent();
|
||||
assertNotNull(intent);
|
||||
assertEquals(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, intent.getAction());
|
||||
assertNotNull("Null EXTRA_INTENT", intent);
|
||||
assertEquals("Intent action is not ACTION_APPWIDGET_CONFIGURE",
|
||||
AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, intent.getAction());
|
||||
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
LauncherAppWidgetInfo.NO_ID);
|
||||
assertNotSame(widgetId, LauncherAppWidgetInfo.NO_ID);
|
||||
assertNotSame("Widget id is NO_ID", widgetId, LauncherAppWidgetInfo.NO_ID);
|
||||
return widgetId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import static com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserHandle;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Unit tests for {@link PackageManagerHelper}. */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class PackageManagerHelperTest {
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
|
||||
private static final String TEST_PACKAGE = "com.android.test.package";
|
||||
private static final int TEST_USER = 2;
|
||||
|
||||
private Context mContext;
|
||||
private LauncherApps mLauncherApps;
|
||||
private PackageManagerHelper mPackageManagerHelper;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mContext = mock(Context.class);
|
||||
mLauncherApps = mock(LauncherApps.class);
|
||||
when(mContext.getSystemService(eq(LauncherApps.class))).thenReturn(mLauncherApps);
|
||||
mPackageManagerHelper = new PackageManagerHelper(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(FLAG_ENABLE_SUPPORT_FOR_ARCHIVING)
|
||||
public void getApplicationInfo_archivedApp_appInfoIsNotNull()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||
applicationInfo.isArchived = true;
|
||||
when(mLauncherApps.getApplicationInfo(TEST_PACKAGE, 0 /* flags */,
|
||||
UserHandle.of(TEST_USER)))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
assertThat(mPackageManagerHelper.getApplicationInfo(TEST_PACKAGE, UserHandle.of(TEST_USER),
|
||||
0 /* flags */))
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user