Snap for 11517216 from 3fb35d3fb8 to 24Q3-release
Change-Id: I07b469add09c5942370d1884f382fe0b2a45782a
This commit is contained in:
@@ -120,6 +120,16 @@
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/action_save_app_pair"
|
||||
style="@style/GoOverviewActionButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_save_app_pair"
|
||||
android:text="@string/action_save_app_pair"
|
||||
android:theme="@style/ThemeControlHighlightWorkspaceColor"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.quickstep.views.GoOverviewActionsView>
|
||||
@@ -55,6 +55,15 @@
|
||||
android:theme="@style/ThemeControlHighlightWorkspaceColor"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/action_save_app_pair"
|
||||
style="@style/OverviewActionButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/action_save_app_pair"
|
||||
android:theme="@style/ThemeControlHighlightWorkspaceColor"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
|
||||
@@ -230,6 +230,8 @@
|
||||
<string name="action_screenshot">Screenshot</string>
|
||||
<!-- Label for a button that enters split screen selection mode. [CHAR_LIMIT=20] -->
|
||||
<string name="action_split">Split</string>
|
||||
<!-- Label for a button that saves a new app pair. [CHAR_LIMIT=20] -->
|
||||
<string name="action_save_app_pair">Save app pair</string>
|
||||
<!-- Label for toast with instructions for split screen selection mode. [CHAR_LIMIT=50] -->
|
||||
<string name="toast_split_select_app">Tap another app to use split screen</string>
|
||||
<string name="toast_contextual_split_select_app">Choose another app to use split screen</string>
|
||||
|
||||
@@ -206,19 +206,12 @@ public class TaskbarModelCallbacks implements
|
||||
|
||||
if (mDeferUpdatesForSUW) {
|
||||
ItemInfo[] finalHotseatItemInfos = hotseatItemInfos;
|
||||
mDeferredUpdates = () -> {
|
||||
updateHotseatItemsAndBackground(finalHotseatItemInfos);
|
||||
};
|
||||
mDeferredUpdates = () -> mContainer.updateHotseatItems(finalHotseatItemInfos);
|
||||
} else {
|
||||
updateHotseatItemsAndBackground(hotseatItemInfos);
|
||||
mContainer.updateHotseatItems(hotseatItemInfos);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHotseatItemsAndBackground(ItemInfo[] hotseatItemInfos) {
|
||||
mContainer.updateHotseatItems(hotseatItemInfos);
|
||||
mControllers.taskbarViewController.updateIconsBackground();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to defer UI updates after SUW builds the unstash animation.
|
||||
* @param defer if true, defers updates to the UI
|
||||
|
||||
@@ -52,7 +52,6 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.apppairs.AppPairIcon;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.icons.ThemedIconDrawable;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
@@ -60,7 +59,6 @@ import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.LauncherBindableItemsContainer;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.DoubleShadowBubbleTextView;
|
||||
import com.android.launcher3.views.IconButtonView;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
@@ -409,21 +407,6 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse all the child views and change the background of themeIcons
|
||||
**/
|
||||
public void setThemedIconsBackgroundColor(int color) {
|
||||
for (View icon : getIconViews()) {
|
||||
if (icon instanceof DoubleShadowBubbleTextView) {
|
||||
DoubleShadowBubbleTextView textView = ((DoubleShadowBubbleTextView) icon);
|
||||
if (textView.getIcon() != null
|
||||
&& textView.getIcon() instanceof ThemedIconDrawable) {
|
||||
((ThemedIconDrawable) textView.getIcon()).changeBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets OnClickListener and OnLongClickListener for the given view.
|
||||
*/
|
||||
|
||||
@@ -45,7 +45,6 @@ import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.view.OneShotPreDrawListener;
|
||||
|
||||
import com.android.app.animation.Interpolators;
|
||||
@@ -62,7 +61,6 @@ import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.anim.RevealOutlineAnimation;
|
||||
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.icons.ThemedIconDrawable;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
@@ -93,8 +91,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
public static final int ALPHA_INDEX_SMALL_SCREEN = 6;
|
||||
private static final int NUM_ALPHA_CHANNELS = 7;
|
||||
|
||||
private static final float TASKBAR_DARK_THEME_ICONS_BACKGROUND_LUMINANCE = 0.30f;
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final TaskbarView mTaskbarView;
|
||||
private final MultiValueAlpha mTaskbarIconAlpha;
|
||||
@@ -125,12 +121,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
|
||||
private int mTaskbarBottomMargin;
|
||||
private final int mStashedHandleHeight;
|
||||
private final int mLauncherThemedIconsBackgroundColor;
|
||||
private final int mTaskbarThemedIconsBackgroundColor;
|
||||
|
||||
/** Progress from {@code 0} for Launcher's color to {@code 1} for Taskbar's color. */
|
||||
private final AnimatedFloat mThemedIconsBackgroundProgress = new AnimatedFloat(
|
||||
this::updateIconsBackground);
|
||||
|
||||
private final TaskbarModelCallbacks mModelCallbacks;
|
||||
|
||||
@@ -173,16 +163,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
mTaskbarBottomMargin = activity.getDeviceProfile().taskbarBottomMargin;
|
||||
mStashedHandleHeight = activity.getResources()
|
||||
.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_height);
|
||||
mLauncherThemedIconsBackgroundColor = ThemedIconDrawable.getColors(mActivity)[0];
|
||||
if (!Utilities.isDarkTheme(mActivity)) {
|
||||
mTaskbarThemedIconsBackgroundColor = mLauncherThemedIconsBackgroundColor;
|
||||
} else {
|
||||
// Increase luminance for dark themed icons given they are on a dark Taskbar background.
|
||||
float[] colorHSL = new float[3];
|
||||
ColorUtils.colorToHSL(mLauncherThemedIconsBackgroundColor, colorHSL);
|
||||
colorHSL[2] = TASKBAR_DARK_THEME_ICONS_BACKGROUND_LUMINANCE;
|
||||
mTaskbarThemedIconsBackgroundColor = ColorUtils.HSLToColor(colorHSL);
|
||||
}
|
||||
|
||||
mIsRtl = Utilities.isRtl(mTaskbarView.getResources());
|
||||
mTaskbarLeftRightMargin = mActivity.getResources().getDimensionPixelSize(
|
||||
R.dimen.transient_taskbar_padding);
|
||||
@@ -470,18 +451,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
return taskbarIconTranslationYForPinningValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Taskbar's themed icons background according to the progress between in-app/home.
|
||||
*/
|
||||
protected void updateIconsBackground() {
|
||||
mTaskbarView.setThemedIconsBackgroundColor(
|
||||
ColorUtils.blendARGB(
|
||||
mLauncherThemedIconsBackgroundColor,
|
||||
mTaskbarThemedIconsBackgroundColor,
|
||||
mThemedIconsBackgroundProgress.value
|
||||
));
|
||||
}
|
||||
|
||||
private ValueAnimator createRevealAnimForView(View view, boolean isStashed, float newWidth,
|
||||
boolean isQsb, boolean dispatchOnAnimationStart) {
|
||||
Rect viewBounds = new Rect(0, 0, view.getWidth(), view.getHeight());
|
||||
@@ -679,10 +648,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
setter.setFloat(mTaskbarNavButtonTranslationY, VALUE, -offsetY, interpolator);
|
||||
setter.setFloat(mTaskbarNavButtonTranslationYForInAppDisplay, VALUE, offsetY, interpolator);
|
||||
|
||||
if (Utilities.isDarkTheme(mTaskbarView.getContext())) {
|
||||
setter.addFloat(mThemedIconsBackgroundProgress, VALUE, 1f, 0f, LINEAR);
|
||||
}
|
||||
|
||||
int collapsedHeight = mActivity.getDefaultTaskbarWindowSize();
|
||||
int expandedHeight = Math.max(collapsedHeight, taskbarDp.taskbarHeight + offsetY);
|
||||
setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowSize(
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.launcher3.util.ResourceBasedOverride;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.Snackbar;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.views.GroupedTaskView;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskThumbnailView;
|
||||
@@ -210,13 +211,19 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
||||
}
|
||||
}
|
||||
|
||||
private void enterSplitSelect() {
|
||||
protected void enterSplitSelect() {
|
||||
RecentsView overviewPanel = mThumbnailView.getTaskView().getRecentsView();
|
||||
// Task has already been dismissed
|
||||
if (overviewPanel == null) return;
|
||||
overviewPanel.initiateSplitSelect(mThumbnailView.getTaskView());
|
||||
}
|
||||
|
||||
protected void saveAppPair() {
|
||||
GroupedTaskView taskView = (GroupedTaskView) mThumbnailView.getTaskView();
|
||||
taskView.getRecentsView().getSplitSelectController().getAppPairsController()
|
||||
.saveAppPair(taskView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the overlay is no longer used.
|
||||
*/
|
||||
@@ -329,6 +336,10 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
||||
public void onSplit() {
|
||||
endLiveTileMode(TaskOverlay.this::enterSplitSelect);
|
||||
}
|
||||
|
||||
public void onSaveAppPair() {
|
||||
endLiveTileMode(TaskOverlay.this::saveAppPair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,5 +353,8 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
||||
|
||||
/** User wants to start split screen with current app. */
|
||||
void onSplit();
|
||||
|
||||
/** User wants to save an app pair with current group of apps. */
|
||||
void onSaveAppPair();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,9 +311,21 @@ public interface TaskShortcutFactory {
|
||||
@Override
|
||||
public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
|
||||
TaskIdAttributeContainer taskContainer) {
|
||||
DeviceProfile deviceProfile = activity.getDeviceProfile();
|
||||
final TaskView taskView = taskContainer.getTaskView();
|
||||
final RecentsView recentsView = taskView.getRecentsView();
|
||||
boolean isLargeTileFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
|
||||
boolean isInExpectedScrollPosition =
|
||||
recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
|
||||
boolean shouldShowActionsButtonInstead =
|
||||
isLargeTileFocusedTask && isInExpectedScrollPosition;
|
||||
|
||||
if (!FeatureFlags.enableAppPairs() || !taskView.containsMultipleTasks()) {
|
||||
// No "save app pair" menu item if:
|
||||
// - app pairs feature is not enabled
|
||||
// - the task in question is a single task
|
||||
// - the Overview Actions Button should be visible
|
||||
if (!FeatureFlags.enableAppPairs() || !taskView.containsMultipleTasks()
|
||||
|| shouldShowActionsButtonInstead) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.android.internal.jank.Cuj;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.CancellableTask;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
@@ -40,11 +41,11 @@ import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
|
||||
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
|
||||
import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
|
||||
*
|
||||
@@ -382,7 +383,11 @@ public class GroupedTaskView extends TaskView {
|
||||
|
||||
@Override
|
||||
public void setOverlayEnabled(boolean overlayEnabled) {
|
||||
// Intentional no-op to prevent setting smart actions overlay on thumbnails
|
||||
if (FeatureFlags.enableAppPairs()) {
|
||||
super.setOverlayEnabled(overlayEnabled);
|
||||
} else {
|
||||
// Intentional no-op to prevent setting smart actions overlay on thumbnails
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Flags;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
@@ -92,14 +93,28 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
private static final int INDEX_SCROLL_ALPHA = 5;
|
||||
private static final int NUM_ALPHAS = 6;
|
||||
|
||||
public @interface ScreenshotButtonHiddenFlags { }
|
||||
public static final int FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT = 1 << 0;
|
||||
|
||||
public @interface SplitButtonHiddenFlags { }
|
||||
public static final int FLAG_IS_NOT_TABLET = 1 << 0;
|
||||
public static final int FLAG_SMALL_SCREEN_HIDE_SPLIT = 1 << 0;
|
||||
public static final int FLAG_MULTIPLE_TASKS_HIDE_SPLIT = 1 << 1;
|
||||
|
||||
public @interface SplitButtonDisabledFlags { }
|
||||
public static final int FLAG_SINGLE_TASK = 1 << 0;
|
||||
public static final int FLAG_SINGLE_TASK_DISABLE_SPLIT = 1 << 0;
|
||||
|
||||
public @interface AppPairButtonHiddenFlags { }
|
||||
public static final int FLAG_SINGLE_TASK_HIDE_APP_PAIR = 1 << 0;
|
||||
public static final int FLAG_SMALL_SCREEN_HIDE_APP_PAIR = 1 << 1;
|
||||
|
||||
private MultiValueAlpha mMultiValueAlpha;
|
||||
|
||||
// The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is an
|
||||
// ImageButton in go launcher (does not share a common class with Button). Take care when
|
||||
// casting this.
|
||||
private View mScreenshotButton;
|
||||
private Button mSplitButton;
|
||||
private Button mSaveAppPairButton;
|
||||
|
||||
@ActionsHiddenFlags
|
||||
private int mHiddenFlags;
|
||||
@@ -107,11 +122,14 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
@ActionsDisabledFlags
|
||||
protected int mDisabledFlags;
|
||||
|
||||
@ScreenshotButtonHiddenFlags
|
||||
private int mScreenshotButtonHiddenFlags;
|
||||
|
||||
@SplitButtonHiddenFlags
|
||||
private int mSplitButtonHiddenFlags;
|
||||
|
||||
@SplitButtonDisabledFlags
|
||||
private int mSplitButtonDisabledFlags;
|
||||
@AppPairButtonHiddenFlags
|
||||
private int mAppPairButtonHiddenFlags;
|
||||
|
||||
@Nullable
|
||||
protected T mCallbacks;
|
||||
@@ -138,9 +156,12 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
mMultiValueAlpha = new MultiValueAlpha(findViewById(R.id.action_buttons), NUM_ALPHAS);
|
||||
mMultiValueAlpha.setUpdateVisibility(true);
|
||||
|
||||
findViewById(R.id.action_screenshot).setOnClickListener(this);
|
||||
mScreenshotButton = findViewById(R.id.action_screenshot);
|
||||
mScreenshotButton.setOnClickListener(this);
|
||||
mSplitButton = findViewById(R.id.action_split);
|
||||
mSplitButton.setOnClickListener(this);
|
||||
mSaveAppPairButton = findViewById(R.id.action_save_app_pair);
|
||||
mSaveAppPairButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,6 +183,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
mCallbacks.onScreenshot();
|
||||
} else if (id == R.id.action_split) {
|
||||
mCallbacks.onSplit();
|
||||
} else if (id == R.id.action_save_app_pair) {
|
||||
mCallbacks.onSaveAppPair();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +227,49 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
}
|
||||
boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
|
||||
LayoutUtils.setViewEnabled(this, isEnabled);
|
||||
updateSplitButtonEnabledState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a batch of flags to hide and show actions buttons when a grouped task (split screen)
|
||||
* is focused.
|
||||
* @param isGroupedTask True if the focused task is a grouped task.
|
||||
*/
|
||||
public void updateForGroupedTask(boolean isGroupedTask) {
|
||||
// Update flags to see if split button should be hidden.
|
||||
updateSplitButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SPLIT, isGroupedTask);
|
||||
// Update flags to see if screenshot button should be hidden.
|
||||
updateScreenshotButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT, isGroupedTask);
|
||||
// Update flags to see if save app pair button should be hidden.
|
||||
updateAppPairButtonHiddenFlags(FLAG_SINGLE_TASK_HIDE_APP_PAIR, !isGroupedTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a batch of flags to hide and show actions buttons for tablet/non tablet case.
|
||||
* @param isSmallScreen True if the current display is a small screen.
|
||||
*/
|
||||
public void updateForSmallScreen(boolean isSmallScreen) {
|
||||
// Update flags to see if split button should be hidden.
|
||||
updateSplitButtonHiddenFlags(FLAG_SMALL_SCREEN_HIDE_SPLIT, isSmallScreen);
|
||||
// Update flags to see if save app pair button should be hidden.
|
||||
updateAppPairButtonHiddenFlags(FLAG_SMALL_SCREEN_HIDE_APP_PAIR, isSmallScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the proper flags to indicate whether the "Screenshot" button should be hidden.
|
||||
*
|
||||
* @param flag The flag to update.
|
||||
* @param enable Whether to enable the hidden flag: True will cause view to be hidden.
|
||||
*/
|
||||
private void updateScreenshotButtonHiddenFlags(@ScreenshotButtonHiddenFlags int flag,
|
||||
boolean enable) {
|
||||
if (mScreenshotButton == null) return;
|
||||
if (enable) {
|
||||
mScreenshotButtonHiddenFlags |= flag;
|
||||
} else {
|
||||
mScreenshotButtonHiddenFlags &= ~flag;
|
||||
}
|
||||
int desiredVisibility = mScreenshotButtonHiddenFlags == 0 ? VISIBLE : GONE;
|
||||
mScreenshotButton.setVisibility(desiredVisibility);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,16 +278,17 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
* @param flag The flag to update.
|
||||
* @param enable Whether to enable the hidden flag: True will cause view to be hidden.
|
||||
*/
|
||||
public void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag, boolean enable) {
|
||||
void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag,
|
||||
boolean enable) {
|
||||
if (mSplitButton == null) return;
|
||||
if (enable) {
|
||||
mSplitButtonHiddenFlags |= flag;
|
||||
} else {
|
||||
mSplitButtonHiddenFlags &= ~flag;
|
||||
}
|
||||
if (mSplitButton == null) return;
|
||||
boolean shouldBeVisible = mSplitButtonHiddenFlags == 0;
|
||||
mSplitButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
|
||||
findViewById(R.id.action_split_space).setVisibility(shouldBeVisible ? VISIBLE : GONE);
|
||||
int desiredVisibility = mSplitButtonHiddenFlags == 0 ? VISIBLE : GONE;
|
||||
mSplitButton.setVisibility(desiredVisibility);
|
||||
findViewById(R.id.action_split_space).setVisibility(desiredVisibility);
|
||||
|
||||
String callStack = Arrays.stream(
|
||||
Log.getStackTraceString(new Exception("thread stacktrace"))
|
||||
@@ -232,23 +298,30 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
.collect(Collectors.joining("\n"));
|
||||
Log.d("b/321291049", "updateSplitButtonHiddenFlags called with flag: " + flag
|
||||
+ " enabled: " + enable
|
||||
+ " shouldBeVisible: " + shouldBeVisible
|
||||
+ " visibility: " + desiredVisibility
|
||||
+ " partial trace: \n" + callStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the proper flags to indicate whether the "Split screen" button should be disabled.
|
||||
* Updates the proper flags to indicate whether the "Save app pair" button should be disabled.
|
||||
*
|
||||
* @param flag The flag to update.
|
||||
* @param enable Whether to enable the disable flag: True will cause view to be disabled.
|
||||
* @param enable Whether to enable the hidden flag: True will cause view to be hidden.
|
||||
*/
|
||||
public void updateSplitButtonDisabledFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
|
||||
if (enable) {
|
||||
mSplitButtonDisabledFlags |= flag;
|
||||
} else {
|
||||
mSplitButtonDisabledFlags &= ~flag;
|
||||
private void updateAppPairButtonHiddenFlags(
|
||||
@AppPairButtonHiddenFlags int flag, boolean enable) {
|
||||
if (!FeatureFlags.enableAppPairs()) {
|
||||
return;
|
||||
}
|
||||
updateSplitButtonEnabledState();
|
||||
|
||||
if (mSaveAppPairButton == null) return;
|
||||
if (enable) {
|
||||
mAppPairButtonHiddenFlags |= flag;
|
||||
} else {
|
||||
mAppPairButtonHiddenFlags &= ~flag;
|
||||
}
|
||||
int desiredVisibility = mAppPairButtonHiddenFlags == 0 ? VISIBLE : GONE;
|
||||
mSaveAppPairButton.setVisibility(desiredVisibility);
|
||||
}
|
||||
|
||||
public MultiProperty getContentAlpha() {
|
||||
@@ -326,19 +399,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
? R.drawable.ic_split_horizontal
|
||||
: R.drawable.ic_split_vertical;
|
||||
mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds(splitIconRes, 0, 0, 0);
|
||||
mSaveAppPairButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
R.drawable.ic_save_app_pair, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables the "Split" button based on the status of mSplitButtonDisabledFlags and
|
||||
* mDisabledFlags.
|
||||
*/
|
||||
private void updateSplitButtonEnabledState() {
|
||||
if (mSplitButton == null) {
|
||||
return;
|
||||
}
|
||||
boolean isParentEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
|
||||
boolean shouldBeEnabled = mSplitButtonDisabledFlags == 0 && isParentEnabled;
|
||||
mSplitButton.setEnabled(shouldBeEnabled);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,8 +62,6 @@ import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_TAB;
|
||||
import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_UP;
|
||||
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
|
||||
import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
|
||||
import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
|
||||
import static com.android.quickstep.views.OverviewActionsView.FLAG_SINGLE_TASK;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
|
||||
@@ -493,9 +491,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
private final Rect mClearAllButtonDeadZoneRect = new Rect();
|
||||
private final Rect mTaskViewDeadZoneRect = new Rect();
|
||||
/**
|
||||
* Reflects if Recents is currently in the middle of a gesture
|
||||
* Reflects if Recents is currently in the middle of a gesture, and if so, which tasks are
|
||||
* running. If a gesture is not in progress, this will be null.
|
||||
*/
|
||||
private boolean mGestureActive;
|
||||
private @Nullable Task[] mActiveGestureRunningTasks;
|
||||
|
||||
// Keeps track of the previously known visible tasks for purposes of loading/unloading task data
|
||||
private final SparseBooleanArray mHasVisibleTaskData = new SparseBooleanArray();
|
||||
@@ -1841,7 +1840,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
if (newRunningTaskView != null) {
|
||||
mRunningTaskViewId = newRunningTaskView.getTaskViewId();
|
||||
} else {
|
||||
mRunningTaskViewId = INVALID_TASK_ID;
|
||||
if (mActiveGestureRunningTasks != null) {
|
||||
// This will update mRunningTaskViewId and create a stub view if necessary.
|
||||
// We try to avoid this because it can cause a scroll jump, but it is needed
|
||||
// for cases where the running task isn't included in this load plan (e.g. if
|
||||
// the current running task is excludedFromRecents.)
|
||||
showCurrentTask(mActiveGestureRunningTasks);
|
||||
} else {
|
||||
mRunningTaskViewId = INVALID_TASK_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1909,10 +1916,17 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
|
||||
private void removeTasksViewsAndClearAllButton() {
|
||||
// This handles an edge case where applyLoadPlan happens during a gesture when the
|
||||
// only Task is one with excludeFromRecents, in which case we should not remove it.
|
||||
final int stubRunningTaskIndex = isGestureActive() ? getRunningTaskIndex() : -1;
|
||||
|
||||
for (int i = getTaskViewCount() - 1; i >= 0; i--) {
|
||||
if (i == stubRunningTaskIndex) {
|
||||
continue;
|
||||
}
|
||||
removeView(requireTaskViewAt(i));
|
||||
}
|
||||
if (indexOfChild(mClearAllButton) != -1) {
|
||||
if (getTaskViewCount() == 0 && indexOfChild(mClearAllButton) != -1) {
|
||||
removeView(mClearAllButton);
|
||||
}
|
||||
}
|
||||
@@ -2375,7 +2389,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// Ignore thumbnail update if it's current running task during the gesture
|
||||
// We snapshot at end of gesture, it will update then
|
||||
int changes = dataChanges;
|
||||
if (taskView == getRunningTaskView() && mGestureActive) {
|
||||
if (taskView == getRunningTaskView() && isGestureActive()) {
|
||||
changes &= ~TaskView.FLAG_UPDATE_THUMBNAIL;
|
||||
}
|
||||
taskView.onTaskListVisibilityChanged(true /* visible */, changes);
|
||||
@@ -2587,7 +2601,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
*/
|
||||
public void onGestureAnimationStart(
|
||||
Task[] runningTasks, RotationTouchHelper rotationTouchHelper) {
|
||||
mGestureActive = true;
|
||||
mActiveGestureRunningTasks = runningTasks;
|
||||
// This needs to be called before the other states are set since it can create the task view
|
||||
if (mOrientationState.setGestureActive(true)) {
|
||||
setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
|
||||
@@ -2597,13 +2611,17 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
updateSizeAndPadding();
|
||||
}
|
||||
|
||||
showCurrentTask(runningTasks);
|
||||
showCurrentTask(mActiveGestureRunningTasks);
|
||||
setEnableFreeScroll(false);
|
||||
setEnableDrawingLiveTile(false);
|
||||
setRunningTaskHidden(true);
|
||||
setTaskIconScaledDown(true);
|
||||
}
|
||||
|
||||
private boolean isGestureActive() {
|
||||
return mActiveGestureRunningTasks != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only when a swipe-up gesture from an app has completed. Only called after
|
||||
* {@link #onGestureAnimationStart} and {@link #onGestureAnimationEnd()}.
|
||||
@@ -2712,7 +2730,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
* Called when a gesture from an app has finished, and the animation to the target has ended.
|
||||
*/
|
||||
public void onGestureAnimationEnd() {
|
||||
mGestureActive = false;
|
||||
mActiveGestureRunningTasks = null;
|
||||
if (mOrientationState.setGestureActive(false)) {
|
||||
updateOrientationHandler(/* forceRecreateDragLayerControllers = */ false);
|
||||
}
|
||||
@@ -3987,18 +4005,24 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides all overview actions if current page is for split apps, shows otherwise
|
||||
* If actions are showing, we only show split option if
|
||||
* Hides all overview actions if user is halfway through split selection, shows otherwise.
|
||||
* We only show split option if:
|
||||
* * Focused view is a single app
|
||||
* * Device is large screen
|
||||
* * There are at least 2 tasks to invoke split
|
||||
*/
|
||||
private void updateCurrentTaskActionsVisibility() {
|
||||
boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
|
||||
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
|
||||
// Update flags to see if entire actions bar should be hidden.
|
||||
if (!FeatureFlags.enableAppPairs()) {
|
||||
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
|
||||
}
|
||||
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
|
||||
mActionsView.updateSplitButtonHiddenFlags(FLAG_IS_NOT_TABLET,
|
||||
!mActivity.getDeviceProfile().isTablet);
|
||||
mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK, /*enable=*/ false);
|
||||
// Update flags to see if actions bar should show buttons for a single task or a pair of
|
||||
// tasks.
|
||||
mActionsView.updateForGroupedTask(isCurrentSplit);
|
||||
// Update flags to see if actions bar should show buttons for tablets or phones.
|
||||
mActionsView.updateForSmallScreen(!mActivity.getDeviceProfile().isTablet);
|
||||
|
||||
if (isDesktopModeSupported()) {
|
||||
boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
|
||||
mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
|
||||
|
||||
@@ -21,11 +21,9 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -141,32 +139,6 @@ public class SplitInstructionsView extends LinearLayout {
|
||||
mLauncher.getStateManager().goToState(LauncherState.NORMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
if (!FeatureFlags.enableSplitContextually()) {
|
||||
return;
|
||||
}
|
||||
|
||||
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
|
||||
R.string.toast_split_select_cont_desc,
|
||||
getResources().getString(R.string.toast_split_select_cont_desc)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||
if (!FeatureFlags.enableSplitContextually()) {
|
||||
return super.performAccessibilityAction(action, arguments);
|
||||
}
|
||||
|
||||
if (action == R.string.toast_split_select_cont_desc) {
|
||||
exitSplitSelection();
|
||||
return true;
|
||||
}
|
||||
return super.performAccessibilityAction(action, arguments);
|
||||
}
|
||||
|
||||
void ensureProperRotation() {
|
||||
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler()
|
||||
.setSplitInstructionsParams(
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<!-- Hotseat -->
|
||||
<dimen name="dynamic_grid_hotseat_bottom_tall_padding">0dp</dimen>
|
||||
<dimen name="spring_loaded_hotseat_top_margin">76dp</dimen>
|
||||
<dimen name="spring_loaded_hotseat_top_margin_wide_portrait">64dp</dimen>
|
||||
|
||||
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
|
||||
|
||||
@@ -47,6 +48,7 @@
|
||||
<dimen name="drop_target_vertical_gap">20dp</dimen>
|
||||
<dimen name="drop_target_top_margin">32dp</dimen>
|
||||
<dimen name="drop_target_bottom_margin">16dp</dimen>
|
||||
<dimen name="drop_target_bottom_margin_wide_portrait">32dp</dimen>
|
||||
|
||||
<!-- App Widget resize frame -->
|
||||
<!-- Button drop target bar -->
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
<!-- App pair default title -->
|
||||
<string name="app_pair_default_title"><xliff:g id="app1" example="Chrome">%1$s</xliff:g> | <xliff:g id="app2" example="YouTube">%2$s</xliff:g></string>
|
||||
<!-- Displayed when an app pair can't launch at this screen size [CHAR_LIMIT=none] -->
|
||||
<string name="app_pair_unlaunchable_at_screen_size">This pair isn\'t supported at this screen size</string>
|
||||
<string name="app_pair_unlaunchable_at_screen_size">This app pair isn\'t supported on this device</string>
|
||||
<!-- Displayed when an app pair can't launch at this screen size, but user can unfold device to restore functionality [CHAR_LIMIT=none] -->
|
||||
<string name="app_pair_needs_unfold">Unfold your device to use this pair</string>
|
||||
<string name="app_pair_needs_unfold">Unfold device to use this app pair</string>
|
||||
|
||||
<!-- Widgets -->
|
||||
<!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
|
||||
@@ -326,6 +326,8 @@
|
||||
<string name="app_downloading_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> downloading, <xliff:g id="progress" example="30%">%2$s</xliff:g> complete</string>
|
||||
<!-- Title for an app whose download has been started. -->
|
||||
<string name="app_waiting_download_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> waiting to install</string>
|
||||
<!-- Title for an app which is archived. -->
|
||||
<string name="app_archived_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> is archived. Tap to download.</string>
|
||||
|
||||
|
||||
<!-- Title shown on the alert dialog prompting the user to update the application in market
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.ACTIVITY_NOT_RESUMED_AFTER_BACK;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.sDebugTracing;
|
||||
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
|
||||
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
|
||||
@@ -310,9 +308,6 @@ public abstract class BaseActivity extends Activity implements ActivityContext {
|
||||
* Sets the activity to appear as paused.
|
||||
*/
|
||||
public void setPaused() {
|
||||
if (sDebugTracing) {
|
||||
Log.d(ACTIVITY_NOT_RESUMED_AFTER_BACK, "Activity setPaused: " + this, new Throwable());
|
||||
}
|
||||
removeActivityFlags(ACTIVITY_STATE_RESUMED | ACTIVITY_STATE_DEFERRED_RESUMED);
|
||||
}
|
||||
|
||||
@@ -320,7 +315,6 @@ public abstract class BaseActivity extends Activity implements ActivityContext {
|
||||
* Sets the activity to appear as resumed.
|
||||
*/
|
||||
public void setResumed() {
|
||||
if (sDebugTracing) Log.d(ACTIVITY_NOT_RESUMED_AFTER_BACK, "Activity setResumed: " + this);
|
||||
addActivityFlags(ACTIVITY_STATE_RESUMED | ACTIVITY_STATE_USER_ACTIVE);
|
||||
removeActivityFlags(ACTIVITY_STATE_USER_WILL_BE_ACTIVE);
|
||||
}
|
||||
|
||||
@@ -1010,7 +1010,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
|
||||
private void setDownloadStateContentDescription(ItemInfoWithIcon info, int progressLevel) {
|
||||
if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK)
|
||||
if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_ARCHIVED) != 0 && progressLevel == 0) {
|
||||
setContentDescription(getContext().getString(R.string.app_archived_title, info.title));
|
||||
} else if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK)
|
||||
!= 0) {
|
||||
String percentageString = NumberFormat.getPercentInstance()
|
||||
.format(progressLevel * 0.01);
|
||||
|
||||
@@ -83,6 +83,7 @@ public class DeviceProfile {
|
||||
|
||||
// Minimum aspect ratio beyond which an extra top padding may be applied to a bottom sheet.
|
||||
private static final float MIN_ASPECT_RATIO_FOR_EXTRA_TOP_PADDING = 1.5f;
|
||||
private static final float MAX_ASPECT_RATIO_FOR_ALTERNATE_EDIT_STATE = 1.5f;
|
||||
|
||||
public static final PointF DEFAULT_SCALE = new PointF(1.0f, 1.0f);
|
||||
public static final ViewScaleProvider DEFAULT_PROVIDER = itemInfo -> DEFAULT_SCALE;
|
||||
@@ -503,8 +504,17 @@ public class DeviceProfile {
|
||||
}
|
||||
|
||||
dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
|
||||
dropTargetBarTopMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_top_margin);
|
||||
dropTargetBarBottomMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_bottom_margin);
|
||||
// Some foldable portrait modes are too wide in terms of aspect ratio so we need to tweak
|
||||
// the dimensions for edit state.
|
||||
final boolean shouldApplyWidePortraitDimens = isTablet
|
||||
&& !isLandscape
|
||||
&& aspectRatio < MAX_ASPECT_RATIO_FOR_ALTERNATE_EDIT_STATE;
|
||||
dropTargetBarTopMarginPx = shouldApplyWidePortraitDimens
|
||||
? 0
|
||||
: res.getDimensionPixelSize(R.dimen.drop_target_top_margin);
|
||||
dropTargetBarBottomMarginPx = shouldApplyWidePortraitDimens
|
||||
? res.getDimensionPixelSize(R.dimen.drop_target_bottom_margin_wide_portrait)
|
||||
: res.getDimensionPixelSize(R.dimen.drop_target_bottom_margin);
|
||||
dropTargetDragPaddingPx = res.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
|
||||
dropTargetTextSizePx = res.getDimensionPixelSize(R.dimen.drop_target_text_size);
|
||||
dropTargetHorizontalPaddingPx = res.getDimensionPixelSize(
|
||||
@@ -595,8 +605,9 @@ public class DeviceProfile {
|
||||
}
|
||||
}
|
||||
|
||||
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
|
||||
R.dimen.spring_loaded_hotseat_top_margin);
|
||||
springLoadedHotseatBarTopMarginPx = shouldApplyWidePortraitDimens
|
||||
? res.getDimensionPixelSize(R.dimen.spring_loaded_hotseat_top_margin_wide_portrait)
|
||||
: res.getDimensionPixelSize(R.dimen.spring_loaded_hotseat_top_margin);
|
||||
|
||||
if (mIsResponsiveGrid) {
|
||||
updateHotseatSizes(mResponsiveWorkspaceCellSpec.getIconSize());
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.launcher3.allapps;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
|
||||
@@ -49,6 +50,7 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.UserProfileManager.UserProfileState;
|
||||
import com.android.launcher3.anim.AnimatedPropertySetter;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.views.RecyclerViewFastScroller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -220,11 +222,15 @@ public class PrivateSpaceHeaderViewController {
|
||||
private ValueAnimator animateCollapseAnimation(ViewGroup lockButton) {
|
||||
float from = 1;
|
||||
float to = 0;
|
||||
RecyclerViewFastScroller scrollBar = mAllApps.getActiveRecyclerView().getScrollbar();
|
||||
ValueAnimator collapseAnim = ValueAnimator.ofFloat(from, to);
|
||||
collapseAnim.setDuration(EXPAND_COLLAPSE_DURATION);
|
||||
collapseAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
if (scrollBar != null) {
|
||||
scrollBar.setVisibility(INVISIBLE);
|
||||
}
|
||||
// scroll up
|
||||
collapse();
|
||||
// Animate the collapsing of the text.
|
||||
@@ -233,6 +239,10 @@ public class PrivateSpaceHeaderViewController {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
if (scrollBar != null) {
|
||||
scrollBar.setThumbOffsetY(-1);
|
||||
scrollBar.setVisibility(VISIBLE);
|
||||
}
|
||||
mPrivateProfileManager.lockPrivateProfile();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UN
|
||||
import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
|
||||
import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
|
||||
import static com.android.launcher3.config.FeatureFlags.enableAppPairs;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -300,6 +301,11 @@ public class TestInformationHandler implements ResourceBasedOverride {
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_FLAG_ENABLE_APP_PAIRS: {
|
||||
response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, enableAppPairs());
|
||||
return response;
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -169,6 +169,15 @@ public final class SplitConfigurationOptions {
|
||||
dividerWidthPercent = visualDividerBounds.width() / totalWidth;
|
||||
dividerHeightPercent = visualDividerBounds.height() / totalHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LeftTop: " + leftTopBounds + ", taskId: " + leftTopTaskId + "\n"
|
||||
+ "RightBottom: " + rightBottomBounds + ", taskId: " + rightBottomTaskId + "\n"
|
||||
+ "Divider: " + visualDividerBounds + "\n"
|
||||
+ "AppsVertical? " + appsStackedVertically + "\n"
|
||||
+ "snapPosition: " + snapPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SplitStageInfo {
|
||||
|
||||
@@ -79,7 +79,7 @@ DeviceProfile:
|
||||
hotseatBarEndOffset: 0.0px (0.0dp)
|
||||
hotseatQsbSpace: 0.0px (0.0dp)
|
||||
hotseatQsbHeight: 0.0px (0.0dp)
|
||||
springLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)
|
||||
springLoadedHotseatBarTopMarginPx: 168.0px (64.0dp)
|
||||
getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
|
||||
getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
|
||||
getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
|
||||
@@ -118,12 +118,12 @@ DeviceProfile:
|
||||
overviewPageSpacing: 0.0px (0.0dp)
|
||||
overviewRowSpacing: 0.0px (0.0dp)
|
||||
overviewGridSideMargin: 0.0px (0.0dp)
|
||||
dropTargetBarTopMarginPx: 168.0px (64.0dp)
|
||||
dropTargetBarTopMarginPx: 0.0px (0.0dp)
|
||||
dropTargetBarSizePx: 147.0px (56.0dp)
|
||||
dropTargetBarBottomMarginPx: 42.0px (16.0dp)
|
||||
getCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)
|
||||
getCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)
|
||||
dropTargetBarBottomMarginPx: 84.0px (32.0dp)
|
||||
getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
|
||||
getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
|
||||
workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
|
||||
getWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)
|
||||
getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
|
||||
getCellLayoutHeight(): 1721.0px (655.619dp)
|
||||
getCellLayoutWidth(): 899.0px (342.4762dp)
|
||||
|
||||
@@ -79,7 +79,7 @@ DeviceProfile:
|
||||
hotseatBarEndOffset: 0.0px (0.0dp)
|
||||
hotseatQsbSpace: 0.0px (0.0dp)
|
||||
hotseatQsbHeight: 0.0px (0.0dp)
|
||||
springLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)
|
||||
springLoadedHotseatBarTopMarginPx: 168.0px (64.0dp)
|
||||
getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
|
||||
getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
|
||||
getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
|
||||
@@ -118,12 +118,12 @@ DeviceProfile:
|
||||
overviewPageSpacing: 0.0px (0.0dp)
|
||||
overviewRowSpacing: 0.0px (0.0dp)
|
||||
overviewGridSideMargin: 0.0px (0.0dp)
|
||||
dropTargetBarTopMarginPx: 168.0px (64.0dp)
|
||||
dropTargetBarTopMarginPx: 0.0px (0.0dp)
|
||||
dropTargetBarSizePx: 147.0px (56.0dp)
|
||||
dropTargetBarBottomMarginPx: 42.0px (16.0dp)
|
||||
getCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)
|
||||
getCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)
|
||||
dropTargetBarBottomMarginPx: 84.0px (32.0dp)
|
||||
getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
|
||||
getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
|
||||
workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
|
||||
getWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)
|
||||
getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
|
||||
getCellLayoutHeight(): 1721.0px (655.619dp)
|
||||
getCellLayoutWidth(): 899.0px (342.4762dp)
|
||||
|
||||
+2
-1
@@ -172,9 +172,9 @@ public final class TestProtocol {
|
||||
public static final String ICON_MISSING = "b/282963545";
|
||||
public static final String OVERVIEW_OVER_HOME = "b/279059025";
|
||||
public static final String UIOBJECT_STALE_ELEMENT = "b/319501259";
|
||||
public static final String ACTIVITY_NOT_RESUMED_AFTER_BACK = "b/322823209";
|
||||
public static final String GET_FROM_RECENTS_FAILURE = "b/321775748";
|
||||
public static final String SUCCESSFUL_GESTURE_MISMATCH_EVENTS = "b/324940434";
|
||||
public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466";
|
||||
public static final String TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE = "b/326073471";
|
||||
|
||||
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
|
||||
@@ -183,6 +183,7 @@ public final class TestProtocol {
|
||||
public static final String REQUEST_EMULATE_PRINT_DEVICE = "emulate-print-device";
|
||||
|
||||
public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview";
|
||||
public static final String REQUEST_FLAG_ENABLE_APP_PAIRS = "enable-app-pairs";
|
||||
|
||||
public static final String REQUEST_UNSTASH_BUBBLE_BAR_IF_STASHED =
|
||||
"unstash-bubble-bar-if-stashed";
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.launcher3.tapl;
|
||||
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
|
||||
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -49,7 +52,7 @@ public abstract class AppIcon extends Launchable {
|
||||
/**
|
||||
* Find an app icon with the given name.
|
||||
*
|
||||
* @param appName app icon to look for
|
||||
* @param appName app icon to look for
|
||||
* @param launcher (optional) - only match ui elements from Launcher's package
|
||||
*/
|
||||
static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
|
||||
@@ -95,6 +98,8 @@ public abstract class AppIcon extends Launchable {
|
||||
|
||||
@Override
|
||||
protected void waitForLongPressConfirmation() {
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"AppIcon.waitForLongPressConfirmation, resName: popupContainer");
|
||||
mLauncher.waitForLauncherObject("popup_container");
|
||||
}
|
||||
|
||||
|
||||
@@ -401,8 +401,11 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) {
|
||||
return false;
|
||||
}
|
||||
// Overview actions aren't visible for split screen tasks.
|
||||
return !task.isTaskSplit();
|
||||
if (!mLauncher.isAppPairsEnabled() && task.isTaskSplit()) {
|
||||
// Overview actions aren't visible for split screen tasks.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package com.android.launcher3.tapl;
|
||||
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.test.uiautomator.UiObject2;
|
||||
@@ -113,11 +115,15 @@ public abstract class Launchable {
|
||||
iconCenter.y - getStartDragThreshold());
|
||||
|
||||
if (runToSpringLoadedState) {
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"Launchable.startDrag: actionName: long-pressing and triggering drag start"
|
||||
+ " iconCenter: " + iconCenter + " dragStartCenter: "
|
||||
+ dragStartCenter);
|
||||
mLauncher.runToState(() -> movePointerForStartDrag(
|
||||
downTime,
|
||||
iconCenter,
|
||||
dragStartCenter,
|
||||
expectLongClickEvents),
|
||||
downTime,
|
||||
iconCenter,
|
||||
dragStartCenter,
|
||||
expectLongClickEvents),
|
||||
SPRING_LOADED_STATE_ORDINAL, "long-pressing and triggering drag start");
|
||||
} else {
|
||||
movePointerForStartDrag(
|
||||
|
||||
+23
-1
@@ -31,6 +31,7 @@ import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORD
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_GET_SPLIT_SELECTION_ACTIVE;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_NUM_ALL_APPS_COLUMNS;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.SUCCESSFUL_GESTURE_MISMATCH_EVENTS;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
|
||||
|
||||
@@ -1165,7 +1166,11 @@ public final class LauncherInstrumentation {
|
||||
log("Hierarchy before clicking home:");
|
||||
dumpViewHierarchy();
|
||||
action = "clicking home button";
|
||||
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.goHome: isThreeFingerTrackpadGesture: "
|
||||
+ isThreeFingerTrackpadGesture
|
||||
+ "getNavigationModel() == NavigationModel.ZERO_BUTTON: " + (
|
||||
getNavigationModel() == NavigationModel.ZERO_BUTTON));
|
||||
runToState(
|
||||
getHomeButton()::click,
|
||||
NORMAL_STATE_ORDINAL,
|
||||
@@ -1512,6 +1517,8 @@ public final class LauncherInstrumentation {
|
||||
|
||||
@NonNull
|
||||
UiObject2 waitForLauncherObject(String resName) {
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.waitForLauncherObject");
|
||||
return waitForObjectBySelector(getLauncherObjectSelector(resName));
|
||||
}
|
||||
|
||||
@@ -1541,12 +1548,16 @@ public final class LauncherInstrumentation {
|
||||
|
||||
@NonNull
|
||||
List<UiObject2> waitForObjectsBySelector(BySelector selector) {
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.waitForObjectsBySelector");
|
||||
final List<UiObject2> objects = mDevice.wait(Until.findObjects(selector), WAIT_TIME_MS);
|
||||
assertNotNull("Can't find any view in Launcher, selector: " + selector, objects);
|
||||
return objects;
|
||||
}
|
||||
|
||||
private UiObject2 waitForObjectBySelector(BySelector selector) {
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.waitForObjectBySelector");
|
||||
final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
|
||||
assertNotNull("Can't find a view in Launcher, selector: " + selector, object);
|
||||
return object;
|
||||
@@ -1589,6 +1600,9 @@ public final class LauncherInstrumentation {
|
||||
|
||||
void runToState(Runnable command, int expectedState, boolean requireEvent, String actionName) {
|
||||
if (requireEvent) {
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.runToState: command: " + command + " expectedState: "
|
||||
+ expectedState + " actionName: " + actionName + "requireEvent: true");
|
||||
runToState(command, expectedState, actionName);
|
||||
} else {
|
||||
command.run();
|
||||
@@ -1938,6 +1952,10 @@ public final class LauncherInstrumentation {
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
|
||||
boolean isAppPairsEnabled() {
|
||||
return getTestInfo(TestProtocol.REQUEST_FLAG_ENABLE_APP_PAIRS).getBoolean(
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
public void sendPointer(long downTime, long currentTime, int action, Point point,
|
||||
GestureScope gestureScope) {
|
||||
sendPointer(downTime, currentTime, action, point, gestureScope,
|
||||
@@ -1966,11 +1984,15 @@ public final class LauncherInstrumentation {
|
||||
mPointerCount = 1;
|
||||
pointerCount = mPointerCount;
|
||||
}
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.sendPointer: ACTION_DOWN");
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (hasTIS && gestureScope == GestureScope.EXPECT_PILFER) {
|
||||
expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
|
||||
}
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"LauncherInstrumentation.sendPointer: ACTION_UP");
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
mPointerCount++;
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.ALL_APPS_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.UIOBJECT_STALE_ELEMENT;
|
||||
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
@@ -626,6 +627,8 @@ public final class Workspace extends Home {
|
||||
try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
|
||||
"want to drag icon to workspace")) {
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"Workspace.dragIconToWorkspace: starting drag | downtime: " + downTime);
|
||||
Point dragStart = launchable.startDrag(
|
||||
downTime,
|
||||
expectLongClickEvents,
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package com.android.launcher3.tapl;
|
||||
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -76,6 +79,9 @@ interface WorkspaceDragSource {
|
||||
LauncherInstrumentation.Closable c = launcher.addContextLayer(
|
||||
String.format("want to drag the icon to cell(%d, %d)", cellX, cellY))) {
|
||||
final Supplier<Point> dest = () -> Workspace.getCellCenter(launcher, cellX, cellY);
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"WorkspaceDragSource.dragToWorkspace: dragging icon to workspace | dest: "
|
||||
+ dest.get());
|
||||
Workspace.dragIconToWorkspace(
|
||||
launcher,
|
||||
launchable,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.dragging;
|
||||
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
|
||||
import static com.android.launcher3.util.TestConstants.AppNames.GMAIL_APP_NAME;
|
||||
import static com.android.launcher3.util.TestConstants.AppNames.MAPS_APP_NAME;
|
||||
import static com.android.launcher3.util.TestConstants.AppNames.PHOTOS_APP_NAME;
|
||||
@@ -233,6 +234,11 @@ public class TaplDragTest extends AbstractLauncherUiTest {
|
||||
final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(TEST_APP_NAME);
|
||||
for (Point target : targets) {
|
||||
startTime = SystemClock.uptimeMillis();
|
||||
Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
|
||||
"TaplDragTest.java.testDragAppIconToMultipleWorkspaceCells: shortcut name: "
|
||||
+ launcherTestAppIcon.getIconName()
|
||||
+ " | target cell coordinates: (" + target.x + ", " + target.y
|
||||
+ ") | start time: " + startTime);
|
||||
launcherTestAppIcon.dragToWorkspace(target.x, target.y);
|
||||
endTime = SystemClock.uptimeMillis();
|
||||
elapsedTime = endTime - startTime;
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.google.common.truth.Truth.assertWithMessage
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@@ -57,6 +58,8 @@ class FolderIconLoadTest {
|
||||
TEST_ACTIVITY14
|
||||
)
|
||||
|
||||
@get:Rule(order = 0) val testStabilityRule = TestStabilityRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
modelHelper = LauncherModelHelper()
|
||||
|
||||
@@ -133,6 +133,7 @@ public class TaplWorkProfileTest extends AbstractLauncherUiTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord // b/325383911
|
||||
public void workTabExists() {
|
||||
assumeTrue(mWorkProfileSetupSuccessful);
|
||||
waitForWorkTabSetup();
|
||||
|
||||
Reference in New Issue
Block a user