Merge "Ignoring display size change when display is off" into sc-v2-dev
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index 710e2e0..196541f 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -120,16 +120,6 @@
android:layout_height="1dp"
android:layout_weight="1"
android:visibility="gone" />
-
- <Button
- android:id="@+id/action_share"
- style="@style/GoOverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableStart="@drawable/ic_share"
- android:text="@string/action_share"
- android:theme="@style/ThemeControlHighlightWorkspaceColor"
- android:visibility="gone" />
</LinearLayout>
</com.android.quickstep.views.GoOverviewActionsView>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
index 97ba590..492611f 100644
--- a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
@@ -117,7 +117,7 @@
*/
public void updateOrientationState(RecentsOrientedState orientedState) {
// dismiss tooltip
- boolean canLauncherRotate = orientedState.canRecentsActivityRotate();
+ boolean canLauncherRotate = orientedState.isRecentsActivityRotationAllowed();
if (mArrowTipView != null && !canLauncherRotate) {
mArrowTipView.close(/* animate= */ false);
}
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index f8448da..1aa5d03 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -79,12 +79,13 @@
}
public WidgetItem getWidgetProviderInfoByProviderName(
- ComponentName providerName) {
+ ComponentName providerName, UserHandle user) {
return null;
}
/** Returns {@link PackageItemInfo} of a pending widget. */
- public static PackageItemInfo newPendingItemInfo(ComponentName provider) {
- return new PackageItemInfo(provider.getPackageName());
+ public static PackageItemInfo newPendingItemInfo(
+ Context context, ComponentName provider, UserHandle userHandle) {
+ return new PackageItemInfo(provider.getPackageName(), userHandle);
}
}
\ No newline at end of file
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index bc8bd3a..124cd57 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -100,7 +100,6 @@
<activity android:name="com.android.quickstep.interaction.GestureSandboxActivity"
android:autoRemoveFromRecents="true"
android:excludeFromRecents="true"
- android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="com.android.quickstep.action.GESTURE_SANDBOX"/>
diff --git a/quickstep/res/drawable/default_sandbox_app_previous_task_thumbnail.xml b/quickstep/res/drawable/default_sandbox_app_previous_task_thumbnail.xml
deleted file mode 100644
index 9c95497..0000000
--- a/quickstep/res/drawable/default_sandbox_app_previous_task_thumbnail.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/gesture_tutorial_fake_previous_task_view_color" />
-</shape>
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index cfb3eb0..0f01190 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -41,13 +41,54 @@
android:layout_height="20dp"
android:visibility="invisible" />
- <View
+ <com.android.quickstep.interaction.AnimatedTaskView
android:id="@+id/gesture_tutorial_fake_previous_task_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleX="0.98"
android:scaleY="0.98"
- android:visibility="invisible" />
+ android:visibility="invisible">
+
+ <View
+ android:id="@+id/full_task_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/top_task_view"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:visibility="invisible"
+ android:layout_marginBottom="@dimen/gesture_tutorial_multi_row_task_view_spacing"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_small_task_view_corner_radius"
+ app:layout_constraintVertical_chainStyle="spread"
+ app:layout_constraintTop_toTopOf="@id/full_task_view"
+ app:layout_constraintBottom_toTopOf="@id/bottom_task_view"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/bottom_task_view"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:visibility="invisible"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_small_task_view_corner_radius"
+ app:layout_constraintTop_toBottomOf="@id/top_task_view"
+ app:layout_constraintBottom_toBottomOf="@id/full_task_view"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </com.android.quickstep.interaction.AnimatedTaskView>
<FrameLayout
android:id="@+id/gesture_tutorial_fake_task_view"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
index 89973d3..9951663 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
@@ -118,19 +118,17 @@
<androidx.cardview.widget.CardView
android:id="@+id/reply_icon_1"
- android:layout_width="0dp"
- android:layout_height="0dp"
+ android:layout_width="44dp"
+ android:layout_height="44dp"
android:layout_marginBottom="32dp"
android:layout_marginStart="26dp"
- android:layout_marginEnd="342dp"
app:cardElevation="0dp"
app:cardCornerRadius="100dp"
app:cardBackgroundColor="@color/mock_conversation_profile_icon"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBottom_toTopOf="@id/message_2"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
+ app:layout_constraintStart_toStartOf="parent"/>
<androidx.cardview.widget.CardView
android:layout_width="0dp"
@@ -178,19 +176,17 @@
<androidx.cardview.widget.CardView
android:id="@+id/reply_icon_2"
- android:layout_width="0dp"
- android:layout_height="0dp"
+ android:layout_width="44dp"
+ android:layout_height="44dp"
android:layout_marginBottom="32dp"
android:layout_marginStart="26dp"
- android:layout_marginEnd="342dp"
app:cardElevation="0dp"
app:cardCornerRadius="100dp"
app:cardBackgroundColor="@color/mock_conversation_profile_icon"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBottom_toTopOf="@id/message_4"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
+ app:layout_constraintStart_toStartOf="parent"/>
<androidx.cardview.widget.CardView
android:layout_width="0dp"
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index acbb5b9..dd8afc2 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -63,16 +63,6 @@
android:layout_weight="1"
android:visibility="gone" />
- <Button
- android:id="@+id/action_share"
- style="@style/OverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableStart="@drawable/ic_share"
- android:text="@string/action_share"
- android:theme="@style/ThemeControlHighlightWorkspaceColor"
- android:visibility="gone" />
-
<Space
android:id="@+id/oav_three_button_space"
android:layout_width="0dp"
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 38c202b..e903377 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -121,6 +121,8 @@
<dimen name="gesture_tutorial_subtitle_margin_start_end">16dp</dimen>
<dimen name="gesture_tutorial_feedback_margin_start_end">24dp</dimen>
<dimen name="gesture_tutorial_button_margin_start_end">18dp</dimen>
+ <dimen name="gesture_tutorial_multi_row_task_view_spacing">72dp</dimen>
+ <dimen name="gesture_tutorial_small_task_view_corner_radius">18dp</dimen>
<!-- All Set page -->
<dimen name="allset_page_margin_horizontal">40dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 7158287..52bd48b 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -193,6 +193,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 toast with instructions for split screen selection mode. [CHAR_LIMIT=50] -->
+ <string name="toast_split_select_app">Tap another app to use splitscreen</string>
<!-- Message shown when an action is blocked by a policy enforced by the app or the organization managing the device. [CHAR_LIMIT=NONE] -->
<string name="blocked_by_policy">This action isn\'t allowed by the app or your organization</string>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index a68322d..088009a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -631,11 +631,10 @@
@Override
public void onDisplayInfoChanged(Context context, DisplayController.Info info, int flags) {
super.onDisplayInfoChanged(context, info, flags);
- // When changing screens with live tile active, finish the recents animation to close
- // overview as it should be an interim state
- if ((flags & CHANGE_ACTIVE_SCREEN) != 0 && ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- RecentsView recentsView = getOverviewPanel();
- recentsView.finishRecentsAnimation(/* toRecents= */ true, null);
+ // When changing screens, force moving to rest state similar to StatefulActivity.onStop, as
+ // StatefulActivity isn't called consistently.
+ if ((flags & CHANGE_ACTIVE_SCREEN) != 0) {
+ getStateManager().moveToRestState();
}
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index f210e3a..ddb20a1 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1555,11 +1555,13 @@
if (anim == null) {
anim = new AnimatorSet();
- boolean playFallBackAnimation = mLauncher.isInState(LauncherState.ALL_APPS)
+ View workspaceView = findWorkspaceView(appTargets);
+ boolean isWorkspaceViewVisible = workspaceView != null
+ && !mLauncher.isInState(LauncherState.ALL_APPS);
+ boolean playFallBackAnimation = !isWorkspaceViewVisible
&& (launcherIsATargetWithMode(appTargets, MODE_OPENING)
|| mLauncher.isForceInvisible());
- View workspaceView = findWorkspaceView(appTargets);
boolean playWorkspaceReveal = true;
if (mFromUnlock) {
anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 63a569a..1b0f967 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -282,8 +282,7 @@
@Override
public void setInsets(Rect insets, DeviceProfile grid) {
- int leftRightPadding = grid.desiredWorkspaceLeftRightMarginPx
- + grid.cellLayoutPaddingLeftRightPx;
+ int leftRightPadding = grid.allAppsLeftRightPadding;
setPadding(leftRightPadding, getPaddingTop(), leftRightPadding, getPaddingBottom());
}
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 5242b3c..9ad8bb2 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -249,8 +249,7 @@
@Override
public void setInsets(Rect insets, DeviceProfile grid) {
- int leftRightPadding = grid.desiredWorkspaceLeftRightMarginPx
- + grid.cellLayoutPaddingLeftRightPx;
+ int leftRightPadding = grid.allAppsLeftRightPadding;
setPadding(leftRightPadding, getPaddingTop(), leftRightPadding, getPaddingBottom());
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
index 0224bc4..6db5839 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
@@ -15,6 +15,10 @@
*/
package com.android.launcher3.taskbar;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -23,15 +27,20 @@
import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
public class StashedHandleView extends View {
+ private static final long COLOR_CHANGE_DURATION = 120;
+
private final @ColorInt int mStashedHandleLightColor;
private final @ColorInt int mStashedHandleDarkColor;
private final Rect mSampledRegion = new Rect();
private final int[] mTmpArr = new int[2];
+ private @Nullable ObjectAnimator mColorChangeAnim;
+
public StashedHandleView(Context context) {
this(context, null);
}
@@ -54,17 +63,44 @@
R.color.taskbar_stashed_handle_dark_color);
}
- public void updateSampledRegion() {
+ /**
+ * Updates mSampledRegion to be the location of the stashedHandleBounds relative to the screen.
+ * @see #getSampledRegion()
+ */
+ public void updateSampledRegion(Rect stashedHandleBounds) {
getLocationOnScreen(mTmpArr);
- mSampledRegion.set(mTmpArr[0], mTmpArr[1], mTmpArr[0] + getWidth(),
- mTmpArr[1] + getHeight());
+ mSampledRegion.set(stashedHandleBounds);
+ mSampledRegion.offset(mTmpArr[0], mTmpArr[1]);
}
public Rect getSampledRegion() {
return mSampledRegion;
}
- public void updateHandleColor(boolean isRegionDark) {
- setBackgroundColor(isRegionDark ? mStashedHandleLightColor : mStashedHandleDarkColor);
+ /**
+ * Updates the handle color.
+ * @param isRegionDark Whether the background behind the handle is dark, and thus the handle
+ * should be light (and vice versa).
+ * @param animate Whether to animate the change, or apply it immediately.
+ */
+ public void updateHandleColor(boolean isRegionDark, boolean animate) {
+ int newColor = isRegionDark ? mStashedHandleLightColor : mStashedHandleDarkColor;
+ if (mColorChangeAnim != null) {
+ mColorChangeAnim.cancel();
+ }
+ if (animate) {
+ mColorChangeAnim = ObjectAnimator.ofArgb(this,
+ LauncherAnimUtils.VIEW_BACKGROUND_COLOR, newColor);
+ mColorChangeAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mColorChangeAnim = null;
+ }
+ });
+ mColorChangeAnim.setDuration(COLOR_CHANGE_DURATION);
+ mColorChangeAnim.start();
+ } else {
+ setBackgroundColor(newColor);
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 2858d7c..10da826 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -70,7 +70,8 @@
mPrefs = Utilities.getPrefs(mActivity);
mStashedHandleView = stashedHandleView;
mStashedHandleView.updateHandleColor(
- mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false));
+ mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false),
+ false /* animate */);
final Resources resources = mActivity.getResources();
mStashedHandleWidth = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
mStashedHandleHeight = resources.getDimensionPixelSize(
@@ -79,7 +80,7 @@
new RegionSamplingHelper.SamplingCallback() {
@Override
public void onRegionDarknessChanged(boolean isRegionDark) {
- mStashedHandleView.updateHandleColor(isRegionDark);
+ mStashedHandleView.updateHandleColor(isRegionDark, true /* animate */);
mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY,
isRegionDark).apply();
}
@@ -109,6 +110,7 @@
stashedCenterY - mStashedHandleHeight / 2,
stashedCenterX + mStashedHandleWidth / 2,
stashedCenterY + mStashedHandleHeight / 2);
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
mStashedHandleRadius = view.getHeight() / 2f;
outline.setRoundRect(mStashedHandleBounds, mStashedHandleRadius);
}
@@ -154,7 +156,7 @@
public void onIsStashed(boolean isStashed) {
mRegionSamplingHelper.setWindowVisible(isStashed);
if (isStashed) {
- mStashedHandleView.updateSampledRegion();
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
mRegionSamplingHelper.start(mStashedHandleView.getSampledRegion());
} else {
mRegionSamplingHelper.stop();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 010f463..37a1674 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -84,6 +84,8 @@
private TaskView mTaskBeingDragged;
+ private boolean mIsDismissHapticRunning = false;
+
public TaskViewTouchController(T activity) {
mActivity = activity;
mRecentsView = activity.getOverviewPanel();
@@ -365,9 +367,10 @@
mCurrentAnimation.startWithVelocity(mActivity, goingToEnd,
velocity * orientationHandler.getSecondaryTranslationDirectionFactor(),
mEndDisplacement, animationDuration);
- if (goingUp && goingToEnd) {
+ if (goingUp && goingToEnd && !mIsDismissHapticRunning) {
VibratorWrapper.INSTANCE.get(mActivity).vibrate(TASK_DISMISS_VIBRATION_PRIMITIVE,
TASK_DISMISS_VIBRATION_PRIMITIVE_SCALE, TASK_DISMISS_VIBRATION_FALLBACK);
+ mIsDismissHapticRunning = true;
}
}
@@ -376,5 +379,6 @@
mDetector.setDetectableScrollConditions(0, false);
mTaskBeingDragged = null;
mCurrentAnimation = null;
+ mIsDismissHapticRunning = false;
}
}
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 9fa0f1a..8a1b391 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -221,7 +221,7 @@
int taskMargin = dp.overviewTaskMarginPx;
calculateTaskSizeInternal(context, dp,
dp.overviewTaskThumbnailTopMarginPx,
- getProactiveRowAndMargin(context, dp) + getOverviewActionsHeight(context, dp),
+ getOverviewActionsHeight(context, dp),
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
outRect);
}
@@ -301,8 +301,7 @@
Resources res = context.getResources();
Rect insets = dp.getInsets();
int topMargin = dp.overviewTaskThumbnailTopMarginPx;
- int bottomMargin =
- getProactiveRowAndMargin(context, dp) + getOverviewActionsHeight(context, dp);
+ int bottomMargin = getOverviewActionsHeight(context, dp);
int sideMargin = res.getDimensionPixelSize(R.dimen.overview_grid_side_margin);
outRect.set(0, 0, dp.widthPx, dp.heightPx);
@@ -345,21 +344,6 @@
outRect);
}
- private int getProactiveRowAndMargin(Context context, DeviceProfile dp) {
- Resources res = context.getResources();
- int proactiveRowAndMargin;
- if (!TaskView.SHOW_PROACTIVE_ACTIONS || dp.isVerticalBarLayout()) {
- // In Vertical Bar Layout the proactive row doesn't have its own space, it's inside
- // the actions row.
- proactiveRowAndMargin = 0;
- } else {
- proactiveRowAndMargin = res.getDimensionPixelSize(
- R.dimen.overview_proactive_row_height)
- + res.getDimensionPixelSize(R.dimen.overview_proactive_row_bottom_margin);
- }
- return proactiveRowAndMargin;
- }
-
/** Gets the space that the overview actions will take, including bottom margin. */
private int getOverviewActionsHeight(Context context, DeviceProfile dp) {
Resources res = context.getResources();
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index d531339..12fba0d 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -2,10 +2,10 @@
import android.app.Activity;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Bundle;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
@@ -53,15 +53,14 @@
Bundle::putInt, PortraitStatesTouchController::getHotseatTop);
}
- case TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED: {
- response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- FeatureFlags.ENABLE_OVERVIEW_SHARE.get());
- return response;
- }
-
- case TestProtocol.REQUEST_OVERVIEW_CONTENT_PUSH_ENABLED: {
- response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- FeatureFlags.ENABLE_OVERVIEW_CONTENT_PUSH.get());
+ case TestProtocol.REQUEST_GET_FOCUSED_TASK_WIDTH_FOR_TABLET: {
+ if (!mDeviceProfile.isTablet) {
+ return null;
+ }
+ Rect focusedTaskRect = new Rect();
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(mContext, mDeviceProfile,
+ focusedTaskRect);
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.width());
return response;
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 085bfbb..9ac00e8 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -86,7 +86,7 @@
}
}
RecentsOrientedState orientedState = taskView.getRecentsView().getPagedViewOrientedState();
- boolean canLauncherRotate = orientedState.canRecentsActivityRotate();
+ boolean canLauncherRotate = orientedState.isRecentsActivityRotationAllowed();
boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0;
// Add overview actions to the menu when in in-place rotate landscape mode.
@@ -331,14 +331,6 @@
mTask = task;
}
- public void onShare() {
- if (mIsAllowedByPolicy) {
- endLiveTileMode(() -> mImageApi.startShareActivity(null));
- } else {
- showBlockedByPolicyMessage();
- }
- }
-
@SuppressLint("NewApi")
public void onScreenshot() {
endLiveTileMode(() -> saveScreenshot(mTask));
@@ -355,9 +347,6 @@
* controller.
*/
public interface OverlayUICallbacks {
- /** User has indicated they want to share the current task. */
- void onShare();
-
/** User has indicated they want to screenshot the current task. */
void onScreenshot();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
index fb420a2..e984b4f 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
@@ -230,9 +230,6 @@
// Make sure there isn't an app to quick switch to on our right
int maxIndex = 0;
- if (mRecentsView != null && mRecentsView.hasRecentsExtraCard()) {
- maxIndex = 1;
- }
boolean atRightMostApp = mRecentsView == null
|| (mRecentsView.getRunningTaskIndex() <= maxIndex);
diff --git a/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java
new file mode 100644
index 0000000..53ad138
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2021 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.quickstep.interaction;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.cardview.widget.CardView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.launcher3.R;
+
+import java.util.ArrayList;
+
+/**
+ * Helper View for the gesture tutorial mock previous app task view.
+ *
+ * This helper class allows animating from a single-row layout to a two-row layout as seen in
+ * large screen devices.
+ */
+public class AnimatedTaskView extends ConstraintLayout {
+
+ private View mFullTaskView;
+ private CardView mTopTaskView;
+ private CardView mBottomTaskView;
+
+ private ViewOutlineProvider mTaskViewOutlineProvider = null;
+ private final Rect mTaskViewAnimatedRect = new Rect();
+ private float mTaskViewAnimatedRadius;
+
+ public AnimatedTaskView(@NonNull Context context) {
+ super(context);
+ }
+
+ public AnimatedTaskView(@NonNull Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AnimatedTaskView(
+ @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public AnimatedTaskView(
+ @NonNull Context context,
+ @Nullable AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mFullTaskView = findViewById(R.id.full_task_view);
+ mTopTaskView = findViewById(R.id.top_task_view);
+ mBottomTaskView = findViewById(R.id.bottom_task_view);
+
+ setToSingleRowLayout(false);
+ }
+
+ AnimatorSet createAnimationToMultiRowLayout() {
+ if (mTaskViewOutlineProvider == null) {
+ // This is an illegal state.
+ return null;
+ }
+ Outline startOutline = new Outline();
+ mTaskViewOutlineProvider.getOutline(this, startOutline);
+ Rect outlineStartRect = new Rect();
+ startOutline.getRect(outlineStartRect);
+ int endRectBottom = mTopTaskView.getHeight();
+ float outlineStartRadius = startOutline.getRadius();
+ float outlineEndRadius = getContext().getResources().getDimensionPixelSize(
+ R.dimen.gesture_tutorial_small_task_view_corner_radius);
+
+ ValueAnimator outlineAnimator = ValueAnimator.ofFloat(0f, 1f);
+ outlineAnimator.addUpdateListener(valueAnimator -> {
+ float progress = (float) valueAnimator.getAnimatedValue();
+ mTaskViewAnimatedRect.bottom = (int) (outlineStartRect.bottom
+ + progress * (endRectBottom - outlineStartRect.bottom));
+ mTaskViewAnimatedRadius = outlineStartRadius
+ + progress * (outlineEndRadius - outlineStartRadius);
+ mFullTaskView.invalidateOutline();
+ });
+ outlineAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+
+ mTaskViewAnimatedRect.set(outlineStartRect);
+ mTaskViewAnimatedRadius = outlineStartRadius;
+
+ mFullTaskView.setClipToOutline(true);
+ mFullTaskView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(mTaskViewAnimatedRect, mTaskViewAnimatedRadius);
+ }
+ });
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mFullTaskView.setOutlineProvider(mTaskViewOutlineProvider);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ mFullTaskView.setOutlineProvider(mTaskViewOutlineProvider);
+ }
+ });
+
+ ArrayList<Animator> animations = new ArrayList<>();
+ animations.add(ObjectAnimator.ofFloat(
+ mBottomTaskView, View.TRANSLATION_X, -mBottomTaskView.getWidth(), 0));
+ animations.add(outlineAnimator);
+
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(animations);
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ setToSingleRowLayout(true);
+
+ setPadding(0, outlineStartRect.top, 0, getHeight() - outlineStartRect.bottom);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ setToMultiRowLayout();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ setToMultiRowLayout();
+ }
+ });
+
+ return animatorSet;
+ }
+
+ void setToSingleRowLayout(boolean forAnimation) {
+ mFullTaskView.setVisibility(VISIBLE);
+ mTopTaskView.setVisibility(INVISIBLE);
+ mBottomTaskView.setVisibility(forAnimation ? VISIBLE : INVISIBLE);
+ }
+
+ void setToMultiRowLayout() {
+ mFullTaskView.setVisibility(INVISIBLE);
+ mTopTaskView.setVisibility(VISIBLE);
+ mBottomTaskView.setVisibility(VISIBLE);
+ }
+
+ void setFakeTaskViewFillColor(@ColorInt int colorResId) {
+ mFullTaskView.setBackgroundColor(colorResId);
+ mTopTaskView.setCardBackgroundColor(colorResId);
+ mBottomTaskView.setCardBackgroundColor(colorResId);
+ }
+
+ @Override
+ public void setClipToOutline(boolean clipToOutline) {
+ mFullTaskView.setClipToOutline(clipToOutline);
+ }
+
+ @Override
+ public void setOutlineProvider(ViewOutlineProvider provider) {
+ mTaskViewOutlineProvider = provider;
+ mFullTaskView.setOutlineProvider(mTaskViewOutlineProvider);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index ff1743f..9d60e1b 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.anim.Interpolators.ACCEL;
+import android.animation.Animator;
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.graphics.PointF;
@@ -29,6 +30,8 @@
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
+import java.util.ArrayList;
+
/** A {@link TutorialController} for the Overview tutorial. */
@TargetApi(Build.VERSION_CODES.R)
final class OverviewGestureTutorialController extends SwipeUpGestureTutorialController {
@@ -123,10 +126,24 @@
}
public void animateTaskViewToOverview() {
- PendingAnimation anim = new PendingAnimation(300);
+ PendingAnimation anim = new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
anim.setFloat(mTaskViewSwipeUpAnimation
.getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
- AnimatorSet animset = anim.buildAnim();
+
+ ArrayList<Animator> animators = new ArrayList<>();
+
+ if (mTutorialFragment.isLargeScreen()) {
+ Animator multiRowAnimation = mFakePreviousTaskView.createAnimationToMultiRowLayout();
+
+ if (multiRowAnimation != null) {
+ multiRowAnimation.setDuration(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
+ animators.add(multiRowAnimation);
+ }
+ }
+ animators.add(anim.buildAnim());
+
+ AnimatorSet animset = new AnimatorSet();
+ animset.playTogether(animators);
animset.start();
mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 30430ff..0c7b35b 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -63,6 +63,7 @@
private static final int FAKE_PREVIOUS_TASK_MARGIN = Utilities.dpToPx(12);
+ protected static final long TASK_VIEW_END_ANIMATION_DURATION_MILLIS = 300;
private static final long HOME_SWIPE_ANIMATION_DURATION_MILLIS = 625;
private static final long OVERVIEW_SWIPE_ANIMATION_DURATION_MILLIS = 1000;
@@ -89,6 +90,7 @@
mFakeTaskView.setAlpha(1);
mFakePreviousTaskView.setVisibility(View.INVISIBLE);
mFakePreviousTaskView.setAlpha(1);
+ mFakePreviousTaskView.setToSingleRowLayout(false);
mShowTasks = false;
mShowPreviousTasks = false;
mRunningWindowAnim = null;
@@ -146,7 +148,8 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation, boolean isReverse) {
- PendingAnimation fadeAnim = new PendingAnimation(300);
+ PendingAnimation fadeAnim =
+ new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
if (reset) {
fadeAnim.setFloat(mTaskViewSwipeUpAnimation
.getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
@@ -159,6 +162,23 @@
fadeAnim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
}
AnimatorSet animset = fadeAnim.buildAnim();
+
+ if (reset && mTutorialFragment.isLargeScreen()) {
+ animset.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ Animator multiRowAnimation =
+ mFakePreviousTaskView.createAnimationToMultiRowLayout();
+
+ if (multiRowAnimation != null) {
+ multiRowAnimation.setDuration(
+ TASK_VIEW_END_ANIMATION_DURATION_MILLIS).start();
+ }
+ }
+ });
+ }
+
animset.setStartDelay(100);
animset.start();
mRunningWindowAnim = RunningWindowAnim.wrap(animset);
@@ -301,7 +321,7 @@
public RectF getWindowTargetRect() {
int fakeHomeIconSizePx = Utilities.dpToPx(60);
int fakeHomeIconLeft = mFakeHotseatView.getLeft();
- int fakeHomeIconTop = mDp.heightPx - Utilities.dpToPx(216);
+ int fakeHomeIconTop = mFakeHotseatView.getTop();
return new RectF(fakeHomeIconLeft, fakeHomeIconTop,
fakeHomeIconLeft + fakeHomeIconSizePx,
fakeHomeIconTop + fakeHomeIconSizePx);
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index ef62fd6..94fb556 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -24,6 +24,7 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.ColorRes;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimatedVectorDrawable;
@@ -87,7 +88,7 @@
final ImageView mFakeHotseatView;
final ClipIconView mFakeIconView;
final FrameLayout mFakeTaskView;
- final View mFakePreviousTaskView;
+ final AnimatedTaskView mFakePreviousTaskView;
final View mRippleView;
final RippleDrawable mRippleDrawable;
final Button mActionButton;
@@ -177,9 +178,9 @@
return View.NO_ID;
}
- @DrawableRes
- protected int getMockPreviousAppTaskThumbnailResId() {
- return R.drawable.default_sandbox_app_previous_task_thumbnail;
+ @ColorRes
+ protected int getMockPreviousAppTaskThumbnailColorResId() {
+ return R.color.gesture_tutorial_fake_previous_task_view_color;
}
@DrawableRes
@@ -442,8 +443,8 @@
updateFakeAppTaskViewLayout(getMockAppTaskLayoutResId());
mFakeTaskView.animate().alpha(1).setListener(
AnimatorListeners.forSuccessCallback(() -> mFakeTaskView.animate().cancel()));
- mFakePreviousTaskView.setBackground(AppCompatResources.getDrawable(
- mContext, getMockPreviousAppTaskThumbnailResId()));
+ mFakePreviousTaskView.setFakeTaskViewFillColor(mContext.getResources().getColor(
+ getMockPreviousAppTaskThumbnailColorResId()));
mFakeIconView.setBackground(AppCompatResources.getDrawable(
mContext, getMockAppIconResId()));
}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 1d78c6b..89be1a6 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -20,6 +20,7 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.graphics.Insets;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
@@ -40,6 +41,7 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.quickstep.interaction.TutorialController.TutorialType;
@@ -63,6 +65,8 @@
private boolean mFragmentStopped = false;
+ private boolean mIsLargeScreen;
+
public static TutorialFragment newInstance(TutorialType tutorialType) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
if (fragment == null) {
@@ -130,6 +134,21 @@
mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE);
mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
mNavBarGestureHandler = new NavBarGestureHandler(getContext());
+
+ mIsLargeScreen = InvariantDeviceProfile.INSTANCE.get(getContext())
+ .getDeviceProfile(getContext()).isTablet;
+
+ if (mIsLargeScreen) {
+ ((Activity) getContext()).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
+ } else {
+ // Temporary until UI mocks for landscape mode for phones are created.
+ ((Activity) getContext()).setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+ }
+
+ public boolean isLargeScreen() {
+ return mIsLargeScreen;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index a4db596..9c6fd3d 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -218,8 +218,8 @@
private boolean updateHandler() {
mRecentsActivityRotation = inferRecentsActivityRotation(mDisplayRotation);
- if (mRecentsActivityRotation == mTouchRotation
- || (canRecentsActivityRotate() && (mFlags & FLAG_SWIPE_UP_NOT_RUNNING) != 0)) {
+ if (mRecentsActivityRotation == mTouchRotation || (isRecentsActivityRotationAllowed()
+ && (mFlags & FLAG_SWIPE_UP_NOT_RUNNING) != 0)) {
mOrientationHandler = PagedOrientationHandler.PORTRAIT;
} else if (mTouchRotation == ROTATION_90) {
mOrientationHandler = PagedOrientationHandler.LANDSCAPE;
@@ -253,7 +253,7 @@
private boolean setFlag(int mask, boolean enabled) {
boolean wasRotationEnabled = !TestProtocol.sDisableSensorRotation
&& (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED
- && !canRecentsActivityRotate();
+ && !isRecentsActivityRotationAllowed();
if (enabled) {
mFlags |= mask;
} else {
@@ -262,7 +262,7 @@
boolean isRotationEnabled = !TestProtocol.sDisableSensorRotation
&& (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED
- && !canRecentsActivityRotate();
+ && !isRecentsActivityRotationAllowed();
if (wasRotationEnabled != isRotationEnabled) {
UI_HELPER_EXECUTOR.execute(() -> {
if (isRotationEnabled) {
@@ -376,13 +376,6 @@
}
/**
- * Returns true if the activity can rotate, if allowed by system rotation settings
- */
- public boolean canRecentsActivityRotate() {
- return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isRecentsActivityRotationAllowed();
- }
-
- /**
* Enables or disables the rotation watcher for listening to rotation callbacks
*/
public void setRotationWatcherEnabled(boolean isEnabled) {
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index ddb1fca..5ca5c94 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -29,18 +29,14 @@
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.Surface;
-import android.widget.FrameLayout;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateListener;
-import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.util.SplitSelectStateController;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.RecentsExtraCard;
/**
* {@link RecentsView} used in Launcher activity
@@ -49,25 +45,6 @@
public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher, LauncherState>
implements StateListener<LauncherState> {
- private RecentsExtraCard mRecentsExtraCardPlugin;
- private RecentsExtraViewContainer mRecentsExtraViewContainer;
- private PluginListener<RecentsExtraCard> mRecentsExtraCardPluginListener =
- new PluginListener<RecentsExtraCard>() {
- @Override
- public void onPluginConnected(RecentsExtraCard recentsExtraCard, Context context) {
- createRecentsExtraCard();
- mRecentsExtraCardPlugin = recentsExtraCard;
- mRecentsExtraCardPlugin.setupView(context, mRecentsExtraViewContainer, mActivity);
- }
-
- @Override
- public void onPluginDisconnected(RecentsExtraCard plugin) {
- removeView(mRecentsExtraViewContainer);
- mRecentsExtraCardPlugin = null;
- mRecentsExtraViewContainer = null;
- }
- };
-
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -148,73 +125,6 @@
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- PluginManagerWrapper.INSTANCE.get(getContext()).addPluginListener(
- mRecentsExtraCardPluginListener, RecentsExtraCard.class);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(
- mRecentsExtraCardPluginListener);
- }
-
- @Override
- protected int computeMinScroll() {
- if (canComputeScrollX() && !mIsRtl) {
- return computeScrollX();
- }
- return super.computeMinScroll();
- }
-
- @Override
- protected int computeMaxScroll() {
- if (canComputeScrollX() && mIsRtl) {
- return computeScrollX();
- }
- return super.computeMaxScroll();
- }
-
- private boolean canComputeScrollX() {
- return mRecentsExtraCardPlugin != null && getTaskViewCount() > 0
- && !mDisallowScrollToClearAll;
- }
-
- private int computeScrollX() {
- int scrollIndex = getTaskViewStartIndex() - 1;
- while (scrollIndex >= 0 && getChildAt(scrollIndex) instanceof RecentsExtraViewContainer
- && ((RecentsExtraViewContainer) getChildAt(scrollIndex)).isScrollable()) {
- scrollIndex--;
- }
- return getScrollForPage(scrollIndex + 1);
- }
-
- private void createRecentsExtraCard() {
- mRecentsExtraViewContainer = new RecentsExtraViewContainer(getContext());
- FrameLayout.LayoutParams helpCardParams =
- new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.MATCH_PARENT);
- mRecentsExtraViewContainer.setLayoutParams(helpCardParams);
- mRecentsExtraViewContainer.setScrollable(true);
- addView(mRecentsExtraViewContainer, 0);
- }
-
- @Override
- public boolean hasRecentsExtraCard() {
- return mRecentsExtraViewContainer != null;
- }
-
- @Override
- public void setContentAlpha(float alpha) {
- super.setContentAlpha(alpha);
- if (mRecentsExtraViewContainer != null) {
- mRecentsExtraViewContainer.setAlpha(alpha);
- }
- }
-
- @Override
protected DepthController getDepthController() {
return mActivity.getDepthController();
}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index da3fa2a..76d3591 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -16,8 +16,6 @@
package com.android.quickstep.views;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SHARE;
-
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -111,15 +109,9 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- View share = findViewById(R.id.action_share);
- share.setOnClickListener(this);
findViewById(R.id.action_screenshot).setOnClickListener(this);
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
- if (ENABLE_OVERVIEW_SHARE.get()) {
- share.setVisibility(VISIBLE);
- findViewById(R.id.oav_three_button_space).setVisibility(VISIBLE);
- }
}
/**
@@ -137,9 +129,7 @@
return;
}
int id = view.getId();
- if (id == R.id.action_share) {
- mCallbacks.onShare();
- } else if (id == R.id.action_screenshot) {
+ if (id == R.id.action_screenshot) {
mCallbacks.onScreenshot();
} else if (id == R.id.action_split) {
mCallbacks.onSplit();
diff --git a/quickstep/src/com/android/quickstep/views/RecentsExtraViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsExtraViewContainer.java
deleted file mode 100644
index 16bc3bc..0000000
--- a/quickstep/src/com/android/quickstep/views/RecentsExtraViewContainer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep.views;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-/**
- * Empty view to house recents overview extra card
- */
-public class RecentsExtraViewContainer extends FrameLayout {
-
- private boolean mScrollable = false;
-
- public RecentsExtraViewContainer(Context context) {
- super(context);
- }
-
- public RecentsExtraViewContainer(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public RecentsExtraViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- /**
- * Determine whether the view should be scrolled to in the recents overview, similar to the
- * taskviews.
- * @return true if viewed should be scrolled to, false if not
- */
- public boolean isScrollable() {
- return mScrollable;
- }
-
- public void setScrollable(boolean scrollable) {
- this.mScrollable = scrollable;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 88f82a4..e1a3895 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -103,6 +103,7 @@
import android.view.animation.Interpolator;
import android.widget.ListView;
import android.widget.OverScroller;
+import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -116,7 +117,6 @@
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
@@ -591,6 +591,8 @@
private TaskView mSplitHiddenTaskView;
private TaskView mSecondSplitHiddenTaskView;
private SplitConfigurationOptions.StagedSplitBounds mSplitBoundsConfig;
+ private final Toast mSplitToast = Toast.makeText(getContext(),
+ R.string.toast_split_select_app, Toast.LENGTH_SHORT);
/**
* Keeps track of the index of the TaskView that split screen was initialized with so we know
@@ -609,8 +611,6 @@
*/
private TaskView mMovingTaskView;
- // Keeps track of the index where the first TaskView should be
- private int mTaskViewStartIndex = 0;
private OverviewActionsView mActionsView;
private MultiWindowModeChangedListener mMultiWindowModeChangedListener =
@@ -895,7 +895,6 @@
taskView.setTaskViewId(-1);
mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0);
}
- updateTaskStartIndex(child);
}
@Override
@@ -905,7 +904,6 @@
// RecentsView is set to RTL in the constructor when system is using LTR. Here we set the
// child direction back to match system settings.
child.setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_LTR : View.LAYOUT_DIRECTION_RTL);
- updateTaskStartIndex(child);
mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, false);
updateEmptyMessage();
}
@@ -998,18 +996,6 @@
anim.start();
}
- private void updateTaskStartIndex(View affectingView) {
- if (!(affectingView instanceof TaskView) && !(affectingView instanceof ClearAllButton)) {
- int childCount = getChildCount();
-
- mTaskViewStartIndex = 0;
- while (mTaskViewStartIndex < childCount
- && !(getChildAt(mTaskViewStartIndex) instanceof TaskView)) {
- mTaskViewStartIndex++;
- }
- }
- }
-
public boolean isTaskViewVisible(TaskView tv) {
if (showAsGrid()) {
int screenStart = mOrientationHandler.getPrimaryScroll(this);
@@ -1074,8 +1060,7 @@
* @param taskIndex the index of the task
*/
public boolean isTaskSnapped(int taskIndex) {
- return getScrollForPage(taskIndex + mTaskViewStartIndex)
- == getPagedOrientationHandler().getPrimaryScroll(this);
+ return getScrollForPage(taskIndex) == getPagedOrientationHandler().getPrimaryScroll(this);
}
public TaskView getTaskViewByTaskId(int taskId) {
@@ -1289,7 +1274,7 @@
return;
}
- if (mCurrentPage == mTaskViewStartIndex) {
+ if (mCurrentPage == 0) {
return;
}
@@ -1301,8 +1286,8 @@
removeView(focusedTaskView);
mMovingTaskView = null;
focusedTaskView.resetPersistentViewTransforms();
- addView(focusedTaskView, mTaskViewStartIndex);
- setCurrentPage(mTaskViewStartIndex);
+ addView(focusedTaskView, 0);
+ setCurrentPage(0);
updateGridProperties();
}
@@ -1320,7 +1305,7 @@
}
int currentTaskId = -1;
- TaskView currentTaskView = getTaskViewAtByAbsoluteIndex(mCurrentPage);
+ TaskView currentTaskView = getTaskViewAt(mCurrentPage);
if (currentTaskView != null) {
currentTaskId = currentTaskView.getTask().key.id;
}
@@ -1374,7 +1359,7 @@
for (int taskViewIndex = requiredTaskViewCount - 1, taskDataIndex = tasks.size() - 1;
taskViewIndex >= 0;
taskViewIndex--, taskDataIndex--) {
- final int pageIndex = requiredTaskViewCount - taskViewIndex - 1 + mTaskViewStartIndex;
+ final int pageIndex = requiredTaskViewCount - taskViewIndex - 1;
final Task task = tasks.get(taskDataIndex);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
if (taskView instanceof GroupedTaskView) {
@@ -1415,7 +1400,7 @@
if (newRunningTaskView == null) {
StringBuilder sb = new StringBuilder();
for (int i = requiredTaskViewCount - 1; i >= 0; i--) {
- final int pageIndex = requiredTaskViewCount - i - 1 + mTaskViewStartIndex;
+ final int pageIndex = requiredTaskViewCount - i - 1;
final TaskView taskView = (TaskView) getChildAt(pageIndex);
int taskViewId = taskView.getTaskViewId();
sb.append(" taskViewId: " + taskViewId
@@ -1478,7 +1463,7 @@
}
public int getTaskViewCount() {
- int taskViewCount = getChildCount() - mTaskViewStartIndex;
+ int taskViewCount = getChildCount();
if (indexOfChild(mClearAllButton) != -1) {
taskViewCount--;
}
@@ -1612,7 +1597,7 @@
boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0
|| mOrientationState.getRecentsActivityRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
- !mOrientationState.canRecentsActivityRotate() && isInLandscape);
+ !mOrientationState.isRecentsActivityRotationAllowed() && isInLandscape);
// Update TaskView's DeviceProfile dependent layout.
updateChildTaskOrientations();
@@ -1893,11 +1878,6 @@
public abstract void startHome();
- /** `true` if there is a +1 space available in overview. */
- public boolean hasRecentsExtraCard() {
- return false;
- }
-
public void reset() {
setCurrentTask(-1);
mIgnoreResetTaskId = -1;
@@ -2004,10 +1984,6 @@
return tv == null ? -1 : indexOfChild(tv);
}
- public int getTaskViewStartIndex() {
- return mTaskViewStartIndex;
- }
-
/**
* Reloads the view if anything in recents changed.
*/
@@ -2044,7 +2020,7 @@
}
private void animateRecentsRotationInPlace(int newRotation) {
- if (mOrientationState.canRecentsActivityRotate()) {
+ if (mOrientationState.isRecentsActivityRotationAllowed()) {
// Let system take care of the rotation
return;
}
@@ -2182,7 +2158,7 @@
Task.from(new TaskKey(taskInfo), taskInfo, false),
Task.from(new TaskKey(secondaryTaskInfo), secondaryTaskInfo, false)
};
- addView(taskView, mTaskViewStartIndex);
+ addView(taskView, 0);
// When we create a placeholder task view mSplitBoundsConfig will be null, but with
// the actual app running we won't need to show the thumbnail until all the tasks
// load later anyways
@@ -2190,7 +2166,7 @@
mOrientationState, mSplitBoundsConfig);
} else {
taskView = getTaskViewFromPool(false);
- addView(taskView, mTaskViewStartIndex);
+ addView(taskView, 0);
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
mTmpRunningTasks = new Task[]{Task.from(new TaskKey(taskInfo), taskInfo, false)};
@@ -2358,7 +2334,7 @@
int focusedTaskWidthAndSpacing = 0;
int snappedTaskRowWidth = 0;
int snappedPage = getNextPage();
- TaskView snappedTaskView = getTaskViewAtByAbsoluteIndex(snappedPage);
+ TaskView snappedTaskView = getTaskViewAt(snappedPage);
TaskView homeTaskView = getHomeTaskView();
TaskView nextFocusedTaskView = null;
@@ -2471,7 +2447,7 @@
if (snappedTaskView != null) {
snappedTaskNonGridScrollAdjustment = snappedTaskView.getScrollAdjustment(
/*fullscreenEnabled=*/true, /*gridEnabled=*/false);
- snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex];
+ snappedTaskGridTranslationX = gridTranslations[snappedPage];
}
// Use the accumulated translation of the row containing the last task.
@@ -2679,6 +2655,11 @@
mFirstFloatingTaskView.setAlpha(1);
mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
mTempRect, mSplitHiddenTaskView, true /*fadeWithThumbnail*/);
+ anim.addEndListener(success -> {
+ if (success) {
+ mSplitToast.show();
+ }
+ });
}
/**
@@ -3022,7 +3003,7 @@
// Get the id of the task view we will snap to based on the current
// page's relative position as the order of indices change over time due
// to dismissals.
- TaskView snappedTaskView = getTaskViewAtByAbsoluteIndex(mCurrentPage);
+ TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
if (snappedTaskView != null) {
if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
if (finalNextFocusedTaskView != null) {
@@ -3221,10 +3202,7 @@
if (isTaskViewVisible(topTask)) {
TaskView bottomTask = getTaskViewFromTaskViewId(bottomRowIdArray.get(i));
- lastVisibleIndex = Math.max(
- indexOfChild(topTask) - mTaskViewStartIndex,
- indexOfChild(bottomTask) - mTaskViewStartIndex
- );
+ lastVisibleIndex = Math.max(indexOfChild(topTask), indexOfChild(bottomTask));
} else if (lastVisibleIndex < Integer.MAX_VALUE) {
break;
}
@@ -3497,22 +3475,22 @@
@Nullable
public TaskView getNextTaskView() {
- return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() + 1);
+ return getTaskViewAt(getRunningTaskIndex() + 1);
}
@Nullable
public TaskView getCurrentPageTaskView() {
- return getTaskViewAtByAbsoluteIndex(getCurrentPage());
+ return getTaskViewAt(getCurrentPage());
}
@Nullable
public TaskView getNextPageTaskView() {
- return getTaskViewAtByAbsoluteIndex(getNextPage());
+ return getTaskViewAt(getNextPage());
}
@Nullable
public TaskView getTaskViewNearestToCenterOfScreen() {
- return getTaskViewAtByAbsoluteIndex(getPageNearestToCenterOfScreen());
+ return getTaskViewAt(getPageNearestToCenterOfScreen());
}
/**
@@ -3520,16 +3498,8 @@
*/
@Nullable
public TaskView getTaskViewAt(int index) {
- return getTaskViewAtByAbsoluteIndex(index + mTaskViewStartIndex);
- }
-
- @Nullable
- private TaskView getTaskViewAtByAbsoluteIndex(int index) {
- if (index < getChildCount() && index >= 0) {
- View child = getChildAt(index);
- return child instanceof TaskView ? (TaskView) child : null;
- }
- return null;
+ View child = getChildAt(index);
+ return child instanceof TaskView ? (TaskView) child : null;
}
public void setOnEmptyMessageUpdatedListener(OnEmptyMessageUpdatedListener listener) {
@@ -3810,6 +3780,7 @@
}
public void confirmSplitSelect(TaskView taskView) {
+ mSplitToast.cancel();
RectF secondTaskStartingBounds = new RectF();
Rect secondTaskEndingBounds = new Rect();
// TODO(194414938) starting bounds seem slightly off, investigate
@@ -3851,6 +3822,7 @@
splitController.resetState();
int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext());
PendingAnimation pendingAnim = new PendingAnimation(duration);
+ mSplitToast.cancel();
if (!animate) {
resetFromSplitSelectionState();
return pendingAnim;
@@ -4385,7 +4357,7 @@
} else {
TaskView focusedTaskView = mShowAsGridLastOnLayout ? getFocusedTaskView() : null;
return getScrollForPage(focusedTaskView != null ? indexOfChild(focusedTaskView)
- : mTaskViewStartIndex);
+ : 0);
}
}
return super.computeMinScroll();
@@ -4397,7 +4369,7 @@
if (mIsRtl) {
TaskView focusedTaskView = mShowAsGridLastOnLayout ? getFocusedTaskView() : null;
return getScrollForPage(focusedTaskView != null ? indexOfChild(focusedTaskView)
- : mTaskViewStartIndex);
+ : 0);
} else {
// If we aren't showing the clear all button, use the leftmost task as the min
// scroll.
@@ -4449,7 +4421,7 @@
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
float scrollDiff = taskView.getScrollAdjustment(showAsFullscreen, showAsGrid);
- int pageScroll = newPageScrolls[i + mTaskViewStartIndex] + (int) scrollDiff;
+ int pageScroll = newPageScrolls[i] + (int) scrollDiff;
if ((mIsRtl && pageScroll < clearAllScroll + clearAllWidth)
|| (!mIsRtl && pageScroll > clearAllScroll - clearAllWidth)) {
pageScroll = clearAllScroll + (mIsRtl ? clearAllWidth : -clearAllWidth);
@@ -4478,7 +4450,7 @@
@Override
protected int getChildVisibleSize(int index) {
- final TaskView taskView = getTaskViewAtByAbsoluteIndex(index);
+ final TaskView taskView = getTaskViewAt(index);
if (taskView == null) {
return super.getChildVisibleSize(index);
}
@@ -4521,7 +4493,7 @@
* according to {@link #mGridProgress}.
*/
public float getGridTranslationSecondary(int pageIndex) {
- TaskView taskView = getTaskViewAtByAbsoluteIndex(pageIndex);
+ TaskView taskView = getTaskViewAt(pageIndex);
if (taskView == null) {
return 0;
}
@@ -4562,8 +4534,8 @@
private void updateEnabledOverlays() {
int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1;
int taskCount = getTaskViewCount();
- for (int i = mTaskViewStartIndex; i < mTaskViewStartIndex + taskCount; i++) {
- getTaskViewAtByAbsoluteIndex(i).setOverlayEnabled(i == overlayEnabledPage);
+ for (int i = 0; i < taskCount; i++) {
+ getTaskViewAt(i).setOverlayEnabled(i == overlayEnabledPage);
}
}
@@ -4666,7 +4638,7 @@
getCurrentPageTaskView().setModalness(modalness);
}
// Only show actions view when it's modal for in-place landscape mode.
- boolean inPlaceLandscape = !mOrientationState.canRecentsActivityRotate()
+ boolean inPlaceLandscape = !mOrientationState.isRecentsActivityRotationAllowed()
&& mOrientationState.getTouchRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape);
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 6a8d66d..7b4bf62 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -16,8 +16,6 @@
package com.android.quickstep.views;
-import static android.view.Gravity.BOTTOM;
-import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
@@ -131,12 +129,6 @@
@IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL})
public @interface TaskDataChanges {}
- /**
- * Should the layout account for space for a proactive action (or chip) to be added under
- * the task.
- */
- public static final boolean SHOW_PROACTIVE_ACTIONS = false;
-
/** The maximum amount that a task view can be scrimmed, dimmed or tinted. */
public static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
@@ -190,7 +182,6 @@
* delegated bounds only to be updated.
*/
private TransformingTouchDelegate mIconTouchDelegate;
- private TransformingTouchDelegate mChipTouchDelegate;
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
@@ -421,9 +412,7 @@
private boolean mEndQuickswitchCuj;
- private View mContextualChipWrapper;
private final float[] mIconCenterCoords = new float[2];
- private final float[] mChipCenterCoords = new float[2];
private boolean mIsClickableAsLiveTile = true;
@@ -490,14 +479,10 @@
public boolean offerTouchToChildren(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
- computeAndSetChipTouchDelegate();
}
if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
return true;
}
- if (mChipTouchDelegate != null && mChipTouchDelegate.onTouchEvent(event)) {
- return true;
- }
return false;
}
@@ -514,23 +499,6 @@
(int) (tempCenterCoords[1] + iconHalfSize));
}
- private void computeAndSetChipTouchDelegate() {
- if (mContextualChipWrapper != null) {
- float chipHalfWidth = mContextualChipWrapper.getWidth() / 2f;
- float chipHalfHeight = mContextualChipWrapper.getHeight() / 2f;
- mChipCenterCoords[0] = chipHalfWidth;
- mChipCenterCoords[1] = chipHalfHeight;
- getDescendantCoordRelativeToAncestor(mContextualChipWrapper, mActivity.getDragLayer(),
- mChipCenterCoords,
- false);
- mChipTouchDelegate.setBounds(
- (int) (mChipCenterCoords[0] - chipHalfWidth),
- (int) (mChipCenterCoords[1] - chipHalfHeight),
- (int) (mChipCenterCoords[0] + chipHalfWidth),
- (int) (mChipCenterCoords[1] + chipHalfHeight));
- }
- }
-
/**
* The modalness of this view is how it should be displayed when it is shown on its own in the
* modal state of overview.
@@ -543,10 +511,6 @@
}
mModalness = modalness;
mIconView.setAlpha(comp(modalness));
- if (mContextualChipWrapper != null) {
- mContextualChipWrapper.setScaleX(comp(modalness));
- mContextualChipWrapper.setScaleY(comp(modalness));
- }
mDigitalWellBeingToast.updateBannerOffset(modalness,
mCurrentFullscreenParams.mCurrentDrawnInsets.top
+ mCurrentFullscreenParams.mCurrentDrawnInsets.bottom);
@@ -910,11 +874,6 @@
float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
.getInterpolation(progress);
mIconView.setAlpha(scale);
- if (mContextualChipWrapper != null && mContextualChipWrapper != null) {
- mContextualChipWrapper.setAlpha(scale);
- mContextualChipWrapper.setScaleX(Math.min(scale, comp(mModalness)));
- mContextualChipWrapper.setScaleY(Math.min(scale, comp(mModalness)));
- }
mDigitalWellBeingToast.updateBannerOffset(1f - scale,
mCurrentFullscreenParams.mCurrentDrawnInsets.top
+ mCurrentFullscreenParams.mCurrentDrawnInsets.bottom);
@@ -988,53 +947,10 @@
onTaskListVisibilityChanged(false);
}
- /**
- * Sets the contextual chip.
- *
- * @param view Wrapper view containing contextual chip.
- */
- public void setContextualChip(View view) {
- if (mContextualChipWrapper != null) {
- removeView(mContextualChipWrapper);
- }
- if (view != null) {
- mContextualChipWrapper = view;
- LayoutParams layoutParams = new LayoutParams(((View) getParent()).getMeasuredWidth(),
- LayoutParams.WRAP_CONTENT);
- layoutParams.gravity = BOTTOM | CENTER_HORIZONTAL;
- int expectedChipHeight = getExpectedViewHeight(view);
- float chipOffset = getResources().getDimension(R.dimen.chip_hint_vertical_offset);
- layoutParams.bottomMargin = -expectedChipHeight - (int) chipOffset;
- mContextualChipWrapper.setScaleX(0f);
- mContextualChipWrapper.setScaleY(0f);
- addView(view, getChildCount(), layoutParams);
- if (mContextualChipWrapper != null) {
- float scale = comp(mModalness);
- mContextualChipWrapper.animate().scaleX(scale).scaleY(scale).setDuration(50);
- mChipTouchDelegate = new TransformingTouchDelegate(mContextualChipWrapper);
- }
- }
- }
-
public float getTaskCornerRadius() {
return TaskCornerRadius.get(mActivity);
}
- /**
- * Clears the contextual chip from TaskView.
- *
- * @return The contextual chip wrapper view to be recycled.
- */
- public View clearContextualChip() {
- if (mContextualChipWrapper != null) {
- removeView(mContextualChipWrapper);
- }
- View oldContextualChipWrapper = mContextualChipWrapper;
- mContextualChipWrapper = null;
- mChipTouchDelegate = null;
- return oldContextualChipWrapper;
- }
-
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 17a88e5..3b7370f 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -170,7 +170,6 @@
OverviewActions actionsView =
mLauncher.pressHome().switchToOverview().getOverviewActions();
actionsView.clickAndDismissScreenshot();
- actionsView.clickAndDismissShare();
}
private int getCurrentOverviewPage(Launcher launcher) {
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 95ff0ca..af5c5e5 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -96,7 +96,7 @@
<string name="folder_name_format_exact" msgid="8626242716117004803">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SIZE">%2$d</xliff:g> elementos)"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SIZE">%2$d</xliff:g> o más elementos)"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Estilo y fondo de pantalla"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fondo de pantalla y estilo"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ajustes de la pantalla de inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitado por el administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotación de la pantalla de inicio"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 705eaf4..956bc8e 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -41,7 +41,7 @@
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"విడ్జెట్లు"</string>
<string name="widgets_full_sheet_search_bar_hint" msgid="8484659090860596457">"సెర్చ్ చేయండి"</string>
- <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"సెర్చ్ బాక్స్ నుండి టెక్స్ట్ను క్లియర్ చేయి"</string>
+ <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"సెర్చ్ బాక్స్ నుండి టెక్స్ట్ను క్లియర్ చేయండి"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"విడ్జెట్లు, షార్ట్కట్లు అందుబాటులో లేవు"</string>
<string name="no_search_results" msgid="3787956167293097509">"విడ్జెట్లు లేదా షార్ట్కట్లు కనుగొనబడలేదు"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"వ్యక్తిగత గ్యాడ్జెట్స్"</string>
@@ -52,10 +52,10 @@
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"విడ్జెట్ సెట్టింగ్లను మార్చడానికి ట్యాప్ చేయండి"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"అర్థమైంది"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"విడ్జెట్ సెట్టింగ్లను మార్చండి"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"అప్లికేషన్లను వెతకండి"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"యాప్ల కోసం సెర్చ్ చేయండి"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"అప్లికేషన్లను లోడ్ చేస్తోంది…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"కి సరిపోలే అప్లికేషన్లేవీ కనుగొనబడలేదు"</string>
- <string name="all_apps_search_market_message" msgid="1366263386197059176">"మరిన్ని యాప్ల కోసం వెతుకు"</string>
+ <string name="all_apps_search_market_message" msgid="1366263386197059176">"మరిన్ని యాప్ల కోసం సెర్చ్ చేయండి"</string>
<string name="label_application" msgid="8531721983832654978">"యాప్"</string>
<string name="notifications_header" msgid="1404149926117359025">"నోటిఫికేషన్లు"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"షార్ట్కట్ను తరలించడానికి తాకి & నొక్కి ఉంచు."</string>
@@ -114,7 +114,7 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
<string name="abandoned_search" msgid="891119232568284442">"సెర్చ్"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ఈ యాప్ ఇన్స్టాల్ చేయబడలేదు"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ఈ చిహ్నం యొక్క యాప్ ఇన్స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ యాప్ కోసం శోధించి దాన్ని మాన్యువల్గా ఇన్స్టాల్ చేయవచ్చు."</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ఈ ఐకాన్కు చెందిన యాప్ ఇన్స్టాల్ చేయలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ యాప్ కోసం సెర్చ్ చేసి, దాన్ని మాన్యువల్గా ఇన్స్టాల్ చేయవచ్చు."</string>
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g>ను ఇన్స్టాల్ చేయడం, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> డౌన్లోడ్ అవుతోంది, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ఇన్స్టాల్ కావడానికి వేచి ఉంది"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 720d736..ca3ce78 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -177,7 +177,7 @@
<attr name="minWidthDps" format="float" />
<attr name="minHeightDps" format="float" />
- <!-- These min cell values are only used if GridDisplayOption#isScalable is true-->
+ <!-- These min cell values are only used if GridDisplayOption#isScalable is true -->
<attr name="minCellHeightDps" format="float" />
<attr name="minCellWidthDps" format="float" />
<!-- twoPanelPortraitMinCellWidthDps defaults to minCellHeightDps, if not specified -->
@@ -193,6 +193,8 @@
<attr name="borderSpacingDps" format="float" />
+ <attr name="allAppsCellSpacingDps" format="float" />
+
<attr name="iconImageSize" format="float" />
<!-- landscapeIconSize defaults to iconImageSize, if not specified -->
<attr name="landscapeIconSize" format="float" />
@@ -221,6 +223,12 @@
<!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
<attr name="allAppsIconTextSize" format="float" />
+ <!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
+ <attr name="horizontalMargin" format="float"/>
+ <!-- twoPanelLandscapeHorizontalMargin defaults to horizontalMargin if not specified -->
+ <attr name="twoPanelLandscapeHorizontalMargin" format="float"/>
+ <!-- twoPanelPortraitHorizontalMargin defaults to horizontalMargin if not specified -->
+ <attr name="twoPanelPortraitHorizontalMargin" format="float"/>
</declare-styleable>
<declare-styleable name="CellLayout">
@@ -258,4 +266,18 @@
<declare-styleable name="WidgetsListRowHeader">
<attr name="appIconSize" format="dimension" />
</declare-styleable>
+
+ <declare-styleable name="WidgetSections">
+ <!-- Component name of an app widget provider. -->
+ <attr name="provider" format="string" />
+ <!-- If true, keep the app widget under its app listing in addition to the widget category
+ in the widget picker. Defaults to false if not specified. -->
+ <attr name="alsoKeepInApp" format="boolean" />
+ <!-- The category of an app widget provider. Defaults to -1 if not specified. -->
+ <attr name="category" format="integer" />
+ <!-- The title name of a widget category. -->
+ <attr name="sectionTitle" format="reference" />
+ <!-- The icon drawable of a widget category. -->
+ <attr name="sectionDrawable" format="reference" />
+ </declare-styleable>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1cf49fc..b1294b4 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -29,9 +29,6 @@
<dimen name="dynamic_grid_cell_layout_padding">5.5dp</dimen>
<dimen name="dynamic_grid_cell_padding_x">8dp</dimen>
- <dimen name="two_panels_home_side_padding_landscape">36dp</dimen>
- <dimen name="two_panels_home_side_padding_portrait">9dp</dimen>
-
<!-- Hotseat -->
<dimen name="dynamic_grid_hotseat_top_padding">8dp</dimen>
<dimen name="dynamic_grid_hotseat_bottom_padding">2dp</dimen>
@@ -41,7 +38,6 @@
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
<!-- Scalable Grid -->
- <dimen name="scalable_grid_left_right_margin">22dp</dimen>
<dimen name="scalable_grid_qsb_bottom_margin">42dp</dimen>
<!-- Workspace page indicator -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 323c5ca..f315725 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -198,8 +198,11 @@
<!-- Error text that lets a user know that the widget can't load. -->
<string name="gadget_error_text">Can\'t load widget</string>
+ <!-- Button text. This button lets a user change a widget's settings. -->
+ <string name="gadget_setup_text">Widget settings</string>
+
<!-- Instructional text to encourage a user to finish setting up the widget. -->
- <string name="gadget_setup_text">Tap to finish setup</string>
+ <string name="gadget_complete_setup_text">Tap to finish setup</string>
<!-- Text to inform the user that they can't uninstall a system application -->
<string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
diff --git a/res/xml/widget_sections.xml b/res/xml/widget_sections.xml
new file mode 100644
index 0000000..d755de6
--- /dev/null
+++ b/res/xml/widget_sections.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+
+<widget-sections xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <section
+ launcher:category="0"
+ launcher:sectionDrawable="@drawable/ic_conversations_widget_category"
+ launcher:sectionTitle="@string/widget_category_conversations">
+ <widget launcher:provider="com.android.systemui/.people.widget.PeopleSpaceWidgetProvider" />
+ </section>
+</widget-sections>
\ No newline at end of file
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index c7ae373..07221fc 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -97,8 +97,8 @@
private static final int PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER = 4;
// Workspace
- public final int desiredWorkspaceLeftRightOriginalPx;
- public int desiredWorkspaceLeftRightMarginPx;
+ public final int desiredWorkspaceHorizontalMarginOriginalPx;
+ public int desiredWorkspaceHorizontalMarginPx;
public final int cellLayoutBorderSpacingOriginalPx;
public int cellLayoutBorderSpacingPx;
public final int cellLayoutPaddingLeftRightPx;
@@ -168,11 +168,13 @@
public int qsbBottomMarginPx;
// All apps
+ public int allAppsCellSpacingPx;
public int allAppsOpenVerticalTranslate;
public int allAppsCellHeightPx;
public int allAppsCellWidthPx;
public int allAppsIconSizePx;
public int allAppsIconDrawablePaddingPx;
+ public int allAppsLeftRightPadding;
public final int numShownAllAppsColumns;
public float allAppsIconTextSizePx;
@@ -268,11 +270,8 @@
edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
- desiredWorkspaceLeftRightMarginPx = isVerticalBarLayout() ? 0 : isScalableGrid
- ? res.getDimensionPixelSize(R.dimen.scalable_grid_left_right_margin)
- : res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
- desiredWorkspaceLeftRightOriginalPx = desiredWorkspaceLeftRightMarginPx;
-
+ desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
+ desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
allAppsOpenVerticalTranslate = res.getDimensionPixelSize(
R.dimen.all_apps_open_vertical_translate);
@@ -283,6 +282,7 @@
folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
setCellLayoutBorderSpacing(pxFromDp(inv.borderSpacing, mMetrics, 1f));
+ allAppsCellSpacingPx = pxFromDp(inv.allAppsCellSpacing, mMetrics, 1f);
cellLayoutBorderSpacingOriginalPx = cellLayoutBorderSpacingPx;
folderCellLayoutBorderSpacingPx = cellLayoutBorderSpacingPx;
@@ -293,10 +293,7 @@
: res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
if (isTwoPanels) {
- cellLayoutPaddingLeftRightPx = res.getDimensionPixelSize(
- isLandscape
- ? R.dimen.two_panels_home_side_padding_landscape
- : R.dimen.two_panels_home_side_padding_portrait);
+ cellLayoutPaddingLeftRightPx = 0;
cellLayoutBottomPaddingPx = 0;
} else if (isLandscape) {
cellLayoutPaddingLeftRightPx = 0;
@@ -446,6 +443,29 @@
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
+ private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
+ if (isVerticalBarLayout()) {
+ return 0;
+ }
+
+ int horizontalMarginPx;
+
+ if (isScalableGrid) {
+ if (isTwoPanels) {
+ if (isLandscape) {
+ horizontalMarginPx = pxFromDp(idp.twoPanelLandscapeHorizontalMargin, mMetrics);
+ } else {
+ horizontalMarginPx = pxFromDp(idp.twoPanelPortraitHorizontalMargin, mMetrics);
+ }
+ } else {
+ horizontalMarginPx = pxFromDp(idp.horizontalMargin, mMetrics);
+ }
+ } else {
+ horizontalMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
+ }
+ return horizontalMarginPx;
+ }
+
private void updateHotseatIconSize(int hotseatIconSizePx) {
// Ensure there is enough space for folder icons, which have a slightly larger radius.
hotseatCellHeightPx = (int) Math.ceil(hotseatIconSizePx * ICON_OVERLAP_FACTOR);
@@ -547,6 +567,17 @@
+ textHeight + (topBottomPadding * 2);
}
+ private void updateAllAppsWidth() {
+ if (isTwoPanels) {
+ int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
+ + (allAppsCellSpacingPx * (numShownAllAppsColumns + 1));
+ allAppsLeftRightPadding = Math.max(1, (availableWidthPx - usedWidth) / 2);
+ } else {
+ allAppsLeftRightPadding =
+ desiredWorkspaceHorizontalMarginPx + cellLayoutPaddingLeftRightPx;
+ }
+ }
+
/**
* Returns the amount of extra (or unused) vertical space.
*/
@@ -570,7 +601,7 @@
int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
float usedWidth = (cellWidthPx * numColumns)
+ (cellLayoutBorderSpacingPx * (numColumns - 1))
- + (desiredWorkspaceLeftRightMarginPx * 2);
+ + (desiredWorkspaceHorizontalMarginPx * 2);
// We do not subtract padding here, as we also scale the workspace padding if needed.
scaleX = availableWidthPx / usedWidth;
shouldScale = true;
@@ -636,7 +667,8 @@
int cellContentHeight = iconSizePx + iconDrawablePaddingPx
+ Utilities.calculateTextHeight(iconTextSizePx);
cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
- desiredWorkspaceLeftRightMarginPx = (int) (desiredWorkspaceLeftRightOriginalPx * scale);
+ desiredWorkspaceHorizontalMarginPx =
+ (int) (desiredWorkspaceHorizontalMarginOriginalPx * scale);
} else {
cellWidthPx = iconSizePx + iconDrawablePaddingPx;
cellHeightPx = (int) Math.ceil(iconSizePx * ICON_OVERLAP_FACTOR)
@@ -666,6 +698,7 @@
allAppsCellHeightPx = getCellSize().y;
}
allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx;
+ updateAllAppsWidth();
if (isVerticalLayout) {
hideWorkspaceLabelsIfNotEnoughSpace();
@@ -802,7 +835,9 @@
Point padding = getTotalWorkspacePadding();
int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
- int screenWidthPx = availableWidthPx - padding.x - 2 * cellLayoutPaddingLeftRightPx;
+ int cellLayoutTotalPadding =
+ isTwoPanels ? 4 * cellLayoutPaddingLeftRightPx : 2 * cellLayoutPaddingLeftRightPx;
+ int screenWidthPx = availableWidthPx - padding.x - cellLayoutTotalPadding;
result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacingPx, numColumns);
result.y = calculateCellHeight(availableHeightPx - padding.y
- cellLayoutBottomPaddingPx, cellLayoutBorderSpacingPx, inv.numRows);
@@ -832,33 +867,15 @@
padding.right = hotseatBarSizePx;
}
} else {
+ // Pad the bottom of the workspace with search/hotseat bar sizes
int hotseatTop = hotseatBarSizePx;
int paddingBottom = hotseatTop + workspacePageIndicatorHeight
+ workspaceBottomPadding - mWorkspacePageIndicatorOverlapWorkspace;
- if (isTablet) {
- // Pad the left and right of the workspace to ensure consistent spacing
- // between all icons
- // The amount of screen space available for left/right padding.
- int availablePaddingX = Math.max(0, widthPx - ((inv.numColumns * cellWidthPx) +
- ((inv.numColumns - 1) * cellWidthPx)));
- availablePaddingX = (int) Math.min(availablePaddingX,
- widthPx * MAX_HORIZONTAL_PADDING_PERCENT);
- int hotseatVerticalPadding = hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
- int availablePaddingY = Math.max(0, heightPx - edgeMarginPx - paddingBottom
- - (2 * inv.numRows * cellHeightPx) - hotseatVerticalPadding);
- padding.set(availablePaddingX / 2, edgeMarginPx + availablePaddingY / 2,
- availablePaddingX / 2, paddingBottom + availablePaddingY / 2);
- if (isTwoPanels) {
- padding.set(0, padding.top, 0, padding.bottom);
- }
- } else {
- // Pad the top and bottom of the workspace with search/hotseat bar sizes
- padding.set(desiredWorkspaceLeftRightMarginPx,
- workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx),
- desiredWorkspaceLeftRightMarginPx,
- paddingBottom);
- }
+ padding.set(desiredWorkspaceHorizontalMarginPx,
+ (isScalableGrid ? workspaceTopPadding : edgeMarginPx),
+ desiredWorkspaceHorizontalMarginPx,
+ paddingBottom);
}
}
@@ -1085,8 +1102,8 @@
writer.println(prefix + pxToDpStr("cellLayoutBorderSpacingPx",
cellLayoutBorderSpacingPx));
- writer.println(prefix + pxToDpStr("desiredWorkspaceLeftRightMarginPx",
- desiredWorkspaceLeftRightMarginPx));
+ writer.println(prefix + pxToDpStr("desiredWorkspaceHorizontalMarginPx",
+ desiredWorkspaceHorizontalMarginPx));
writer.println(prefix + pxToDpStr("allAppsIconSizePx", allAppsIconSizePx));
writer.println(prefix + pxToDpStr("allAppsIconTextSizePx", allAppsIconTextSizePx));
@@ -1117,6 +1134,7 @@
writer.println(prefix + pxToDpStr("iconScale", iconScale));
writer.println(prefix + pxToDpStr("cellScaleToFit ", cellScaleToFit));
writer.println(prefix + pxToDpStr("extraSpace", extraSpace));
+ writer.println(prefix + pxToDpStr("unscaled extraSpace", extraSpace / iconScale));
if (inv.devicePaddings != null) {
int unscaledExtraSpace = (int) (extraSpace / iconScale);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index b3ae15e..e86c02c 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -151,7 +151,8 @@
}
return mWorkspace.onTouchEvent(event);
}
- return event.getY() > getCellHeight();
+ // Always let touch follow through to Workspace.
+ return false;
}
@Override
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 5f441d1..92cc9e8 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -108,6 +108,7 @@
public float iconTextSize;
public float allAppsIconSize;
public float allAppsIconTextSize;
+ public float allAppsCellSpacing;
public boolean isSplitDisplay;
public float minCellHeight;
@@ -117,6 +118,9 @@
public float twoPanelLandscapeMinCellHeightDps;
public float twoPanelLandscapeMinCellWidthDps;
public float borderSpacing;
+ public float horizontalMargin;
+ public float twoPanelLandscapeHorizontalMargin;
+ public float twoPanelPortraitHorizontalMargin;
private SparseArray<TypedValue> mExtraAttrs;
@@ -153,7 +157,8 @@
*/
public List<DeviceProfile> supportedProfiles = Collections.EMPTY_LIST;
- @Nullable public DevicePaddings devicePaddings;
+ @Nullable
+ public DevicePaddings devicePaddings;
public Point defaultWallpaperSize;
public Rect defaultWidgetPadding;
@@ -161,7 +166,8 @@
private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
@VisibleForTesting
- public InvariantDeviceProfile() {}
+ public InvariantDeviceProfile() {
+ }
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
@@ -219,6 +225,7 @@
result.minCellHeight = defaultDisplayOption.minCellHeight;
result.minCellWidth = defaultDisplayOption.minCellWidth;
result.borderSpacing = defaultDisplayOption.borderSpacing;
+ result.allAppsCellSpacing = defaultDisplayOption.allAppsCellSpacing;
initGrid(context, myInfo, result, false);
}
@@ -283,6 +290,11 @@
twoPanelLandscapeMinCellHeightDps = displayOption.twoPanelLandscapeMinCellHeightDps;
twoPanelLandscapeMinCellWidthDps = displayOption.twoPanelLandscapeMinCellWidthDps;
borderSpacing = displayOption.borderSpacing;
+ allAppsCellSpacing = displayOption.allAppsCellSpacing;
+
+ horizontalMargin = displayOption.horizontalMargin;
+ twoPanelLandscapeHorizontalMargin = displayOption.twoPanelLandscapeHorizontalMargin;
+ twoPanelPortraitHorizontalMargin = displayOption.twoPanelPortraitHorizontalMargin;
numShownHotseatIcons = closestProfile.numHotseatIcons;
numDatabaseHotseatIcons = isSplitDisplay
@@ -356,7 +368,7 @@
}
private Object[] toModelState() {
- return new Object[] {
+ return new Object[]{
numColumns, numRows, numDatabaseHotseatIcons, iconBitmapSize, fillResIconDpi,
numDatabaseAllAppsColumns, dbFile};
}
@@ -402,7 +414,7 @@
}
}
}
- } catch (IOException|XmlPullParserException e) {
+ } catch (IOException | XmlPullParserException e) {
throw new RuntimeException(e);
}
@@ -456,7 +468,7 @@
private int getLauncherIconDensity(int requiredSize) {
// Densities typically defined by an app.
- int[] densityBuckets = new int[] {
+ int[] densityBuckets = new int[]{
DisplayMetrics.DENSITY_LOW,
DisplayMetrics.DENSITY_MEDIUM,
DisplayMetrics.DENSITY_TV,
@@ -596,8 +608,8 @@
// We will use these two data points to extrapolate how much the wallpaper parallax effect
// to span (ie travel) at any aspect ratio:
- final float ASPECT_RATIO_LANDSCAPE = 16/10f;
- final float ASPECT_RATIO_PORTRAIT = 10/16f;
+ final float ASPECT_RATIO_LANDSCAPE = 16 / 10f;
+ final float ASPECT_RATIO_PORTRAIT = 10 / 16f;
final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
@@ -607,7 +619,8 @@
// (10/16)x + y = 1.2
// We solve for x and y and end up with a final formula:
final float x =
- (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
+ (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE
+ - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
(ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
return x * aspectRatio + y;
@@ -719,8 +732,13 @@
private float twoPanelPortraitMinCellWidthDps;
private float twoPanelLandscapeMinCellHeightDps;
private float twoPanelLandscapeMinCellWidthDps;
+ private float allAppsCellSpacing;
private float borderSpacing;
+ private float horizontalMargin;
+ private float twoPanelLandscapeHorizontalMargin;
+ private float twoPanelPortraitHorizontalMargin;
+
private final float[] iconSizes = new float[COUNT_TOTAL];
private final float[] textSizes = new float[COUNT_TOTAL];
@@ -750,6 +768,8 @@
R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellWidthDps,
twoPanelPortraitMinCellWidthDps);
borderSpacing = a.getFloat(R.styleable.ProfileDisplayOption_borderSpacingDps, 0);
+ allAppsCellSpacing = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellSpacingDps,
+ borderSpacing);
iconSizes[INDEX_DEFAULT] =
a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0);
@@ -781,6 +801,14 @@
a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconTextSize,
textSizes[INDEX_LANDSCAPE]);
+ horizontalMargin = a.getFloat(R.styleable.ProfileDisplayOption_horizontalMargin, 0);
+ twoPanelLandscapeHorizontalMargin = a.getFloat(
+ R.styleable.ProfileDisplayOption_twoPanelLandscapeHorizontalMargin,
+ horizontalMargin);
+ twoPanelPortraitHorizontalMargin = a.getFloat(
+ R.styleable.ProfileDisplayOption_twoPanelPortraitHorizontalMargin,
+ horizontalMargin);
+
a.recycle();
}
@@ -810,6 +838,10 @@
twoPanelLandscapeMinCellHeightDps *= w;
twoPanelLandscapeMinCellWidthDps *= w;
borderSpacing *= w;
+ allAppsCellSpacing *= w;
+ horizontalMargin *= w;
+ twoPanelLandscapeHorizontalMargin *= w;
+ twoPanelPortraitHorizontalMargin *= w;
return this;
}
@@ -825,6 +857,10 @@
twoPanelLandscapeMinCellHeightDps += p.twoPanelLandscapeMinCellHeightDps;
twoPanelLandscapeMinCellWidthDps += p.twoPanelLandscapeMinCellWidthDps;
borderSpacing += p.borderSpacing;
+ allAppsCellSpacing += p.allAppsCellSpacing;
+ horizontalMargin += p.horizontalMargin;
+ twoPanelLandscapeHorizontalMargin += p.twoPanelLandscapeHorizontalMargin;
+ twoPanelPortraitHorizontalMargin += p.twoPanelPortraitHorizontalMargin;
return this;
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 409ee83..f429d76 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2118,12 +2118,24 @@
@Override
public IntSet getPagesToBindSynchronously(IntArray orderedScreenIds) {
- IntSet visibleIds = mPagesToBindSynchronously.isEmpty()
- ? mWorkspace.getCurrentPageScreenIds() : mPagesToBindSynchronously;
+ IntSet visibleIds;
+ if (!mPagesToBindSynchronously.isEmpty()) {
+ visibleIds = mPagesToBindSynchronously;
+ } else if (!mWorkspaceLoading) {
+ visibleIds = mWorkspace.getCurrentPageScreenIds();
+ } else {
+ // If workspace binding is still in progress, getCurrentPageScreenIds won't be accurate,
+ // and we should use mSynchronouslyBoundPages that's set during initial binding.
+ visibleIds = mSynchronouslyBoundPages;
+ }
IntArray actualIds = new IntArray();
IntSet result = new IntSet();
if (visibleIds.isEmpty()) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NULL_INT_SET, "getPagesToBindSynchronously (1): "
+ + result);
+ }
return result;
}
for (int id : orderedScreenIds.toArray()) {
@@ -2144,6 +2156,10 @@
// pages being hidden in single panel.
result.add(pairId);
}
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NULL_INT_SET, "getPagesToBindSynchronously (2): "
+ + result);
+ }
return result;
}
@@ -2289,7 +2305,7 @@
final boolean focusFirstItemForAccessibility) {
// Get the list of added items and intersect them with the set of items here
final Collection<Animator> bounceAnims = new ArrayList<>();
- final boolean animateIcons = forceAnimateIcons && canRunNewAppsAnimation();
+ boolean canAnimatePageChange = canAnimatePageChange();
Workspace workspace = mWorkspace;
int newItemsScreenId = -1;
int end = items.size();
@@ -2350,7 +2366,7 @@
}
}
workspace.addInScreenFromBind(view, item);
- if (animateIcons) {
+ if (forceAnimateIcons) {
// Animate all the applications up now
view.setAlpha(0f);
view.setScaleX(0f);
@@ -2366,7 +2382,7 @@
View viewToFocus = newView;
// Animate to the correct pager
- if (animateIcons && newItemsScreenId > -1) {
+ if (forceAnimateIcons && newItemsScreenId > -1) {
AnimatorSet anim = new AnimatorSet();
anim.playTogether(bounceAnims);
if (focusFirstItemForAccessibility && viewToFocus != null) {
@@ -2382,7 +2398,7 @@
final int newScreenIndex = mWorkspace.getPageIndexForScreenId(newItemsScreenId);
final Runnable startBounceAnimRunnable = anim::start;
- if (newItemsScreenId != currentScreenId) {
+ if (canAnimatePageChange && newItemsScreenId != currentScreenId) {
// We post the animation slightly delayed to prevent slowdowns
// when we are loading right after we return to launcher.
mWorkspace.postDelayed(new Runnable() {
@@ -2663,7 +2679,7 @@
TraceHelper.INSTANCE.endSection(traceToken);
}
- private boolean canRunNewAppsAnimation() {
+ private boolean canAnimatePageChange() {
if (mDragController.isDragging()) {
return false;
} else {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index d534c5d..523ac72 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -638,7 +638,10 @@
}
private int getPageWidthSize(int widthSize) {
- return (widthSize - mInsets.left - mInsets.right) / getPanelCount();
+ // It's necessary to add the padding back because it is remove when measuring children,
+ // like when MeasureSpec.getSize in CellLayout.
+ return (widthSize - mInsets.left - mInsets.right - getPaddingLeft() - getPaddingRight())
+ / getPanelCount() + getPaddingLeft() + getPaddingRight();
}
@Override
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index c5e9dd2..6ce2930 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -342,16 +342,15 @@
for (int i = 0; i < numberOfScreens; i++) {
int paddingLeft = paddingLeftRight;
int paddingRight = paddingLeftRight;
+ // Add missing cellLayout border in-between panels.
if (panelCount > 1) {
if (i % panelCount == leftPanelModulus) {
- paddingLeft = paddingLeftRight;
- paddingRight = grid.cellLayoutBorderSpacingPx / 2;
+ paddingRight += grid.cellLayoutBorderSpacingPx / 2;
} else if (i % panelCount == rightPanelModulus) { // right side panel
- paddingLeft = grid.cellLayoutBorderSpacingPx / 2;
- paddingRight = paddingLeftRight;
+ paddingLeft += grid.cellLayoutBorderSpacingPx / 2;
} else { // middle panel
- paddingLeft = grid.cellLayoutBorderSpacingPx / 2;
- paddingRight = grid.cellLayoutBorderSpacingPx / 2;
+ paddingLeft += grid.cellLayoutBorderSpacingPx / 2;
+ paddingRight += grid.cellLayoutBorderSpacingPx / 2;
}
}
// SparseArrayMap doesn't keep the order
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 9a5fd05..3f1f915 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -382,12 +382,10 @@
public void setInsets(Rect insets) {
mInsets.set(insets);
DeviceProfile grid = mLauncher.getDeviceProfile();
- int leftRightPadding = grid.desiredWorkspaceLeftRightMarginPx
- + grid.cellLayoutPaddingLeftRightPx;
for (int i = 0; i < mAH.length; i++) {
mAH[i].padding.bottom = insets.bottom;
- mAH[i].padding.left = mAH[i].padding.right = leftRightPadding;
+ mAH[i].padding.left = mAH[i].padding.right = grid.allAppsLeftRightPadding;
mAH[i].applyPadding();
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 49e0171..0acafc0 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -94,11 +94,6 @@
"ENABLE_QUICKSTEP_WIDGET_APP_START", true,
"Enable Quickstep animation when launching activities from an app widget");
- // Keep as DeviceFlag to allow remote disable in emergency.
- public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag(
- "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", false, "Show chip hints on the overview screen");
-
-
public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag(
"ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
@@ -152,6 +147,11 @@
false,
"Enable loading workspace icons in bulk.");
+ public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(
+ "ENABLE_BULK_ALL_APPS_ICON_LOADING",
+ false,
+ "Enable loading all apps icons in bulk.");
+
// Keep as DeviceFlag for remote disable in emergency.
public static final BooleanFlag ENABLE_OVERVIEW_SELECTIONS = new DeviceFlag(
"ENABLE_OVERVIEW_SELECTIONS", true, "Show Select Mode button in Overview Actions");
@@ -159,16 +159,10 @@
public static final BooleanFlag ENABLE_WIDGETS_PICKER_AIAI_SEARCH = new DeviceFlag(
"ENABLE_WIDGETS_PICKER_AIAI_SEARCH", false, "Enable AiAi search in the widgets picker");
- public static final BooleanFlag ENABLE_OVERVIEW_SHARE = getDebugFlag(
- "ENABLE_OVERVIEW_SHARE", false, "Show Share button in Overview Actions");
-
public static final BooleanFlag ENABLE_OVERVIEW_SHARING_TO_PEOPLE = getDebugFlag(
"ENABLE_OVERVIEW_SHARING_TO_PEOPLE", true,
"Show indicators for content on Overview to share with top people. ");
- public static final BooleanFlag ENABLE_OVERVIEW_CONTENT_PUSH = getDebugFlag(
- "ENABLE_OVERVIEW_CONTENT_PUSH", false, "Show Content Push button in Overview Actions");
-
public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
"ENABLE_DATABASE_RESTORE", false,
"Enable database restore when new restore session is created");
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index b4907e8..468cb55 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -230,16 +230,19 @@
CellLayout firstScreen = mRootView.findViewById(R.id.workspace);
firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingLeftRightPx,
mDp.workspacePadding.top,
- mDp.workspacePadding.right + mDp.cellLayoutBorderSpacingPx / 2,
+ (mDp.isTwoPanels ? mDp.cellLayoutBorderSpacingPx / 2 : mDp.workspacePadding.right)
+ + mDp.cellLayoutPaddingLeftRightPx,
mDp.workspacePadding.bottom);
mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
if (mDp.isTwoPanels) {
CellLayout rightPanel = mRootView.findViewById(R.id.workspace_right);
- rightPanel.setPadding(mDp.workspacePadding.left + mDp.cellLayoutBorderSpacingPx / 2,
+ rightPanel.setPadding(
+ mDp.cellLayoutBorderSpacingPx / 2 + mDp.cellLayoutPaddingLeftRightPx,
mDp.workspacePadding.top,
mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.bottom);
+ mDp.workspacePadding.bottom
+ );
mWorkspaceScreens.put(Workspace.SECOND_SCREEN_ID, rightPanel);
}
@@ -349,7 +352,7 @@
private void inflateAndAddWidgets(LauncherAppWidgetInfo info, WidgetsModel widgetsModel) {
WidgetItem widgetItem = widgetsModel.getWidgetProviderInfoByProviderName(
- info.providerName);
+ info.providerName, info.user);
if (widgetItem == null) {
return;
}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 60d6e83..936eeb9 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
import static java.util.stream.Collectors.groupingBy;
@@ -46,7 +47,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherFiles;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
@@ -63,6 +63,8 @@
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.widget.WidgetSections;
+import com.android.launcher3.widget.WidgetSections.WidgetSection;
import java.util.Collections;
import java.util.List;
@@ -275,7 +277,8 @@
getTitleAndIcon(appInfo, false);
return appInfo.bitmap;
} else {
- PackageItemInfo pkgInfo = new PackageItemInfo(shortcutInfo.getPackage());
+ PackageItemInfo pkgInfo = new PackageItemInfo(shortcutInfo.getPackage(),
+ shortcutInfo.getUserHandle());
getTitleAndIconForApp(pkgInfo, false);
return pkgInfo.bitmap;
}
@@ -409,8 +412,10 @@
CacheEntry entry = getEntryForPackageLocked(
infoInOut.packageName, infoInOut.user, useLowResIcon);
applyCacheEntry(entry, infoInOut);
- if (infoInOut.category == PackageItemInfo.CONVERSATIONS) {
- infoInOut.title = mContext.getString(R.string.widget_category_conversations);
+ if (infoInOut.widgetCategory != NO_CATEGORY) {
+ WidgetSection widgetSection = WidgetSections.getWidgetSections(mContext)
+ .get(infoInOut.widgetCategory);
+ infoInOut.title = mContext.getString(widgetSection.mSectionTitle);
infoInOut.contentDescription = mPackageManager.getUserBadgedLabel(
infoInOut.title, infoInOut.user);
}
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index 92b5885..dbed9a9 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -130,30 +130,54 @@
* If the app is already in the list, doesn't add it.
*/
public void add(AppInfo info, LauncherActivityInfo activityInfo) {
+ add(info, activityInfo, true);
+ }
+
+ public void add(AppInfo info, LauncherActivityInfo activityInfo, boolean loadIcon) {
if (!mAppFilter.shouldShowApp(info.componentName)) {
return;
}
if (findAppInfo(info.componentName, info.user) != null) {
return;
}
- mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */);
- info.sectionName = mIndex.computeSectionName(info.title);
+ if (loadIcon) {
+ mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */);
+ info.sectionName = mIndex.computeSectionName(info.title);
+ }
data.add(info);
mDataChanged = true;
}
- public void addPromiseApp(Context context, PackageInstallInfo installInfo) {
- // only if not yet installed
- if (!new PackageManagerHelper(context)
- .isAppInstalled(installInfo.packageName, installInfo.user)) {
- AppInfo info = new AppInfo(installInfo);
- mIconCache.getTitleAndIcon(info, info.usingLowResIcon());
- info.sectionName = mIndex.computeSectionName(info.title);
+ @Nullable
+ public AppInfo addPromiseApp(Context context, PackageInstallInfo installInfo) {
+ return addPromiseApp(context, installInfo, true);
+ }
- data.add(info);
- mDataChanged = true;
+ @Nullable
+ public AppInfo addPromiseApp(
+ Context context, PackageInstallInfo installInfo, boolean loadIcon) {
+ // only if not yet installed
+ if (new PackageManagerHelper(context)
+ .isAppInstalled(installInfo.packageName, installInfo.user)) {
+ return null;
}
+ AppInfo promiseAppInfo = new AppInfo(installInfo);
+
+ if (loadIcon) {
+ mIconCache.getTitleAndIcon(promiseAppInfo, promiseAppInfo.usingLowResIcon());
+ promiseAppInfo.sectionName = mIndex.computeSectionName(promiseAppInfo.title);
+ }
+
+ data.add(promiseAppInfo);
+ mDataChanged = true;
+
+ return promiseAppInfo;
+ }
+
+ public void updateSectionName(AppInfo appInfo) {
+ appInfo.sectionName = mIndex.computeSectionName(appInfo.title);
+
}
/** Updates the given PackageInstallInfo's associated AppInfo's installation info. */
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index 0e132c2..e9feb1c 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -32,6 +32,7 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperExecutor;
@@ -173,8 +174,18 @@
ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>();
ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>();
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NULL_INT_SET, "bind (1) currentScreenIds: "
+ + currentScreenIds
+ + ", mCallBacks: "
+ + mCallbacks.getClass().getSimpleName());
+ }
filterCurrentWorkspaceItems(currentScreenIds, mWorkspaceItems, currentWorkspaceItems,
otherWorkspaceItems);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NULL_INT_SET, "bind (2) currentScreenIds: "
+ + currentScreenIds);
+ }
filterCurrentWorkspaceItems(currentScreenIds, mAppWidgets, currentAppWidgets,
otherAppWidgets);
final InvariantDeviceProfile idp = mApp.getInvariantDeviceProfile();
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 1249606..8a494ba 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -804,8 +804,9 @@
if (appWidgetInfo.restoreStatus !=
LauncherAppWidgetInfo.RESTORE_COMPLETED) {
appWidgetInfo.pendingItemInfo = WidgetsModel.newPendingItemInfo(
- appWidgetInfo.providerName);
- appWidgetInfo.pendingItemInfo.user = appWidgetInfo.user;
+ mApp.getContext(),
+ appWidgetInfo.providerName,
+ appWidgetInfo.user);
mIconCache.getTitleAndIconForApp(
appWidgetInfo.pendingItemInfo, false);
}
@@ -936,6 +937,8 @@
List<LauncherActivityInfo> allActivityList = new ArrayList<>();
// Clear the list of apps
mBgAllAppsList.clear();
+
+ List<IconRequestInfo<AppInfo>> iconRequestInfos = new ArrayList<>();
for (UserHandle user : profiles) {
// Query for the set of apps
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
@@ -948,18 +951,43 @@
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfo app = apps.get(i);
- // This builds the icon bitmaps.
- mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
+ AppInfo appInfo = new AppInfo(app, user, quietMode);
+
+ iconRequestInfos.add(new IconRequestInfo<>(
+ appInfo, app, /* useLowResIcon= */ false));
+ mBgAllAppsList.add(
+ appInfo, app, !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
}
allActivityList.addAll(apps);
}
+
if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
// get all active sessions and add them to the all apps list
for (PackageInstaller.SessionInfo info :
mSessionHelper.getAllVerifiedSessions()) {
- mBgAllAppsList.addPromiseApp(mApp.getContext(),
- PackageInstallInfo.fromInstallingState(info));
+ AppInfo promiseAppInfo = mBgAllAppsList.addPromiseApp(
+ mApp.getContext(),
+ PackageInstallInfo.fromInstallingState(info),
+ !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
+
+ if (promiseAppInfo != null) {
+ iconRequestInfos.add(new IconRequestInfo<>(
+ promiseAppInfo,
+ /* launcherActivityInfo= */ null,
+ promiseAppInfo.usingLowResIcon()));
+ }
+ }
+ }
+
+ if (FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()) {
+ Trace.beginSection("LoadAllAppsIconsInBulk");
+ try {
+ mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
+ iconRequestInfos.forEach(iconRequestInfo ->
+ mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo));
+ } finally {
+ Trace.endSection();
}
}
diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java
index 58aa9e5..ef5eef1 100644
--- a/src/com/android/launcher3/model/ModelUtils.java
+++ b/src/com/android/launcher3/model/ModelUtils.java
@@ -31,6 +31,7 @@
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
@@ -66,6 +67,10 @@
(lhs, rhs) -> Integer.compare(lhs.container, rhs.container));
for (T info : allWorkspaceItems) {
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NULL_INT_SET, "filterCurrentWorkspaceItems: "
+ + currentScreenIds);
+ }
if (currentScreenIds.contains(info.screenId)) {
currentScreenItems.add(info);
itemsOnScreen.add(info.id);
diff --git a/src/com/android/launcher3/model/data/IconRequestInfo.java b/src/com/android/launcher3/model/data/IconRequestInfo.java
index 2f566f6..5dc6a3b 100644
--- a/src/com/android/launcher3/model/data/IconRequestInfo.java
+++ b/src/com/android/launcher3/model/data/IconRequestInfo.java
@@ -50,6 +50,19 @@
public IconRequestInfo(
@NonNull T itemInfo,
@Nullable LauncherActivityInfo launcherActivityInfo,
+ boolean useLowResIcon) {
+ this(
+ itemInfo,
+ launcherActivityInfo,
+ /* packageName= */ null,
+ /* resourceName= */ null,
+ /* iconBlob= */ null,
+ useLowResIcon);
+ }
+
+ public IconRequestInfo(
+ @NonNull T itemInfo,
+ @Nullable LauncherActivityInfo launcherActivityInfo,
@Nullable String packageName,
@Nullable String resourceName,
@Nullable byte[] iconBlob,
diff --git a/src/com/android/launcher3/model/data/PackageItemInfo.java b/src/com/android/launcher3/model/data/PackageItemInfo.java
index a81fe6a..0055763 100644
--- a/src/com/android/launcher3/model/data/PackageItemInfo.java
+++ b/src/com/android/launcher3/model/data/PackageItemInfo.java
@@ -16,47 +16,41 @@
package com.android.launcher3.model.data;
-import androidx.annotation.IntDef;
+import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
+
+import android.os.UserHandle;
import com.android.launcher3.LauncherSettings;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* Represents a {@link Package} in the widget tray section.
*/
public class PackageItemInfo extends ItemInfoWithIcon {
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({NO_CATEGORY, CONVERSATIONS})
- public @interface Category{}
- /** The package is not categorized in the widget tray. */
- public static final int NO_CATEGORY = 0;
- /** The package is categorized to conversations widget in the widget tray. */
- public static final int CONVERSATIONS = 1;
-
/**
* Package name of the {@link PackageItemInfo}.
*/
public final String packageName;
/** Represents a widget category shown in the widget tray section. */
- @Category public final int category;
+ public final int widgetCategory;
- public PackageItemInfo(String packageName) {
- this(packageName, NO_CATEGORY);
+ public PackageItemInfo(String packageName, UserHandle user) {
+ this(packageName, NO_CATEGORY, user);
}
- public PackageItemInfo(String packageName, @Category int category) {
+ public PackageItemInfo(String packageName, int widgetCategory, UserHandle user) {
this.packageName = packageName;
- this.category = category;
+ this.widgetCategory = widgetCategory;
+ this.user = user;
this.itemType = LauncherSettings.Favorites.ITEM_TYPE_NON_ACTIONABLE;
}
public PackageItemInfo(PackageItemInfo copy) {
this.packageName = copy.packageName;
- this.category = copy.category;
+ this.widgetCategory = copy.widgetCategory;
+ this.user = copy.user;
this.itemType = LauncherSettings.Favorites.ITEM_TYPE_NON_ACTIONABLE;
}
@@ -75,11 +69,13 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PackageItemInfo that = (PackageItemInfo) o;
- return Objects.equals(packageName, that.packageName);
+ return Objects.equals(packageName, that.packageName)
+ && Objects.equals(user, that.user)
+ && widgetCategory == that.widgetCategory;
}
@Override
public int hashCode() {
- return Objects.hash(packageName, user);
+ return Objects.hash(packageName, user, widgetCategory);
}
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 117ae42..2230914 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -270,6 +270,15 @@
backgroundColor = colors[numVisibleChild % colors.length];
}
+ if (!ENABLE_LOCAL_COLOR_POPUPS.get()) {
+ // Arrow color matches the first child or the last child.
+ if (!mIsAboveIcon && numVisibleChild == 0 && viewGroup == this) {
+ mArrowColor = backgroundColor;
+ } else if (mIsAboveIcon) {
+ mArrowColor = backgroundColor;
+ }
+ }
+
if (view instanceof ViewGroup && mIterateChildrenTag.equals(view.getTag())) {
assignMarginsAndBackgrounds((ViewGroup) view, backgroundColor);
numVisibleChild++;
@@ -293,12 +302,6 @@
if (!ENABLE_LOCAL_COLOR_POPUPS.get()) {
setChildColor(view, backgroundColor, colorAnimator);
- // Arrow color matches the first child or the last child.
- if (!mIsAboveIcon && numVisibleChild == 0) {
- mArrowColor = backgroundColor;
- } else if (mIsAboveIcon) {
- mArrowColor = backgroundColor;
- }
}
numVisibleChild++;
@@ -495,7 +498,7 @@
mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
}
- private void updateArrowColor() {
+ protected void updateArrowColor() {
if (!Gravity.isVertical(mGravity)) {
mArrow.setBackground(new RoundedArrowDrawable(
mArrowWidth, mArrowHeight, mArrowPointRadius,
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index e340b21..65dd8ea 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -593,6 +593,7 @@
mNotificationContainer.setVisibility(GONE);
updateHiddenShortcuts();
assignMarginsAndBackgrounds(PopupContainerWithArrow.this);
+ updateArrowColor();
} else {
mNotificationContainer.trimNotifications(
NotificationKeyData.extractKeysOnly(dotInfo.getNotificationKeys()));
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index f78f6dd..1820933 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -112,7 +112,7 @@
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child == mAppsView) {
- int padding = 2 * (grid.desiredWorkspaceLeftRightMarginPx
+ int padding = 2 * (grid.desiredWorkspaceHorizontalMarginPx
+ grid.cellLayoutPaddingLeftRightPx);
int maxWidth = grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + padding;
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 9e52dac..ce01d4e 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -102,6 +102,8 @@
public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT =
"get-activities-created-count";
public static final String REQUEST_GET_ACTIVITIES = "get-activities";
+ public static final String REQUEST_GET_FOCUSED_TASK_WIDTH_FOR_TABLET =
+ "get-focused-task-width-for-tablet";
public static Long sForcePauseTimeout;
public static final String REQUEST_SET_FORCE_PAUSE_TIMEOUT = "set-force-pause-timeout";
@@ -110,9 +112,6 @@
public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing";
public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
- public static final String REQUEST_OVERVIEW_SHARE_ENABLED = "overview-share-enabled";
- public static final String REQUEST_OVERVIEW_CONTENT_PUSH_ENABLED =
- "overview-content-push-enabled";
public static boolean sDisableSensorRotation;
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
@@ -121,4 +120,5 @@
public static final String WORK_PROFILE_REMOVED = "b/159671700";
public static final String TASK_VIEW_ID_CRASH = "b/195430732";
public static final String NO_DROP_TARGET = "b/195031154";
+ public static final String NULL_INT_SET = "b/200572078";
}
diff --git a/src/com/android/launcher3/util/PackageUserKey.java b/src/com/android/launcher3/util/PackageUserKey.java
index 3a3b5a2..92d9737 100644
--- a/src/com/android/launcher3/util/PackageUserKey.java
+++ b/src/com/android/launcher3/util/PackageUserKey.java
@@ -1,19 +1,24 @@
package com.android.launcher3.util;
+import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
+
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.PackageItemInfo;
-import java.util.Arrays;
+import java.util.Objects;
-/** Creates a hash key based on package name and user. */
+/** Creates a hash key based on package name, widget category, and user. */
public class PackageUserKey {
public String mPackageName;
+ public int mWidgetCategory;
public UserHandle mUser;
private int mHashCode;
@@ -27,14 +32,31 @@
return new PackageUserKey(notification.getPackageName(), notification.getUser());
}
+ /** Creates a {@link PackageUserKey} from {@link PackageItemInfo}. */
+ public static PackageUserKey fromPackageItemInfo(PackageItemInfo info) {
+ if (TextUtils.isEmpty(info.packageName) && info.widgetCategory != NO_CATEGORY) {
+ return new PackageUserKey(info.widgetCategory, info.user);
+ }
+ return new PackageUserKey(info.packageName, info.user);
+ }
+
public PackageUserKey(String packageName, UserHandle user) {
update(packageName, user);
}
+ public PackageUserKey(int widgetCategory, UserHandle user) {
+ update(/* packageName= */ "", widgetCategory, user);
+ }
+
public void update(String packageName, UserHandle user) {
+ update(packageName, NO_CATEGORY, user);
+ }
+
+ private void update(String packageName, int widgetCategory, UserHandle user) {
mPackageName = packageName;
+ mWidgetCategory = widgetCategory;
mUser = user;
- mHashCode = Arrays.hashCode(new Object[] {packageName, user});
+ mHashCode = Objects.hash(packageName, widgetCategory, user);
}
/**
@@ -59,12 +81,14 @@
public boolean equals(Object obj) {
if (!(obj instanceof PackageUserKey)) return false;
PackageUserKey otherKey = (PackageUserKey) obj;
- return mPackageName.equals(otherKey.mPackageName) && mUser.equals(otherKey.mUser);
+ return Objects.equals(mPackageName, otherKey.mPackageName)
+ && mWidgetCategory == otherKey.mWidgetCategory
+ && Objects.equals(mUser, otherKey.mUser);
}
@NonNull
@Override
public String toString() {
- return mPackageName + "#" + mUser;
+ return mPackageName + "#" + mUser + ",category=" + mWidgetCategory;
}
}
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 57a6d3f..553ba13 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -17,7 +17,7 @@
package com.android.launcher3.widget;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
-import static com.android.launcher3.model.data.PackageItemInfo.CONVERSATIONS;
+import static com.android.launcher3.widget.WidgetSections.getWidgetSections;
import android.content.Context;
import android.graphics.Canvas;
@@ -89,8 +89,8 @@
setOnClickListener(ItemClickHandler.INSTANCE);
if (info.pendingItemInfo == null) {
- info.pendingItemInfo = new PackageItemInfo(info.providerName.getPackageName());
- info.pendingItemInfo.user = info.user;
+ info.pendingItemInfo = new PackageItemInfo(info.providerName.getPackageName(),
+ info.user);
cache.updateIconInBackground(this, info.pendingItemInfo);
} else {
reapplyItemInfo(info.pendingItemInfo);
@@ -268,8 +268,8 @@
if (availableWidth > 0) {
// Recreate the setup text.
mSetupTextLayout = new StaticLayout(
- getResources().getText(R.string.gadget_setup_text), mPaint, availableWidth,
- Layout.Alignment.ALIGN_CENTER, 1, 0, true);
+ getResources().getText(R.string.gadget_complete_setup_text), mPaint,
+ availableWidth, Layout.Alignment.ALIGN_CENTER, 1, 0, true);
int textHeight = mSetupTextLayout.getHeight();
// Extra icon size due to the setting icon
@@ -338,10 +338,11 @@
*/
@Nullable
private Drawable getWidgetCategoryIcon() {
- switch (mInfo.pendingItemInfo.category) {
- case CONVERSATIONS:
- return getContext().getDrawable(R.drawable.ic_conversations_widget_category);
+ if (mInfo.pendingItemInfo.widgetCategory == WidgetSections.NO_CATEGORY) {
+ return null;
}
- return null;
+ Context context = getContext();
+ return context.getDrawable(getWidgetSections(context).get(
+ mInfo.pendingItemInfo.widgetCategory).mSectionDrawable);
}
}
diff --git a/src/com/android/launcher3/widget/WidgetSections.java b/src/com/android/launcher3/widget/WidgetSections.java
new file mode 100644
index 0000000..c45b095
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetSections.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 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.widget;
+
+import static android.content.res.Resources.ID_NULL;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.StringRes;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.IntSet;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Map;
+
+/** A helper class to parse widget sections (categories) resource overlay. */
+public final class WidgetSections {
+ /** The package is not categorized in the widget tray. */
+ public static final int NO_CATEGORY = -1;
+
+ private static final String TAG_SECTION_NAME = "section";
+ private static final String TAG_WIDGET_NAME = "widget";
+
+ private static SparseArray<WidgetSection> sWidgetSections;
+ private static Map<ComponentName, IntSet> sWidgetsToCategories;
+
+ /** Returns a list of widget sections that are shown in the widget picker. */
+ public static synchronized SparseArray<WidgetSection> getWidgetSections(Context context) {
+ if (sWidgetSections != null) {
+ return sWidgetSections;
+ }
+ parseWidgetSectionsXml(context);
+ return sWidgetSections;
+ }
+
+ /** Returns a map which maps app widget providers to app widget categories. */
+ public static synchronized Map<ComponentName, IntSet> getWidgetsToCategory(
+ Context context) {
+ if (sWidgetsToCategories != null) {
+ return sWidgetsToCategories;
+ }
+ parseWidgetSectionsXml(context);
+ return sWidgetsToCategories;
+ }
+
+ private static synchronized void parseWidgetSectionsXml(Context context) {
+ SparseArray<WidgetSection> widgetSections = new SparseArray();
+ Map<ComponentName, IntSet> widgetsToCategories = new ArrayMap<>();
+ try (XmlResourceParser parser = context.getResources().getXml(R.xml.widget_sections)) {
+ final int depth = parser.getDepth();
+ int type;
+ while (((type = parser.next()) != XmlPullParser.END_TAG
+ || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG)
+ && TAG_SECTION_NAME.equals(parser.getName())) {
+ AttributeSet sectionAttributes = Xml.asAttributeSet(parser);
+ WidgetSection section = new WidgetSection(context, sectionAttributes);
+ final int sectionDepth = parser.getDepth();
+ while (((type = parser.next()) != XmlPullParser.END_TAG
+ || parser.getDepth() > sectionDepth)
+ && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG)
+ && TAG_WIDGET_NAME.equals(parser.getName())) {
+ TypedArray a = context.obtainStyledAttributes(
+ Xml.asAttributeSet(parser), R.styleable.WidgetSections);
+ ComponentName provider = ComponentName.unflattenFromString(
+ a.getString(R.styleable.WidgetSections_provider));
+ boolean alsoKeepInApp = a.getBoolean(
+ R.styleable.WidgetSections_alsoKeepInApp,
+ /* defValue= */ false);
+ final IntSet categories;
+ if (widgetsToCategories.containsKey(provider)) {
+ categories = widgetsToCategories.get(provider);
+ } else {
+ categories = new IntSet();
+ widgetsToCategories.put(provider, categories);
+ }
+ if (alsoKeepInApp) {
+ categories.add(NO_CATEGORY);
+ }
+ categories.add(section.mCategory);
+ }
+ }
+ widgetSections.put(section.mCategory, section);
+ }
+ }
+ sWidgetSections = widgetSections;
+ sWidgetsToCategories = widgetsToCategories;
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** A data class which contains a widget section's information. */
+ public static final class WidgetSection {
+ public final int mCategory;
+ @StringRes
+ public final int mSectionTitle;
+ @DrawableRes
+ public final int mSectionDrawable;
+
+ public WidgetSection(Context context, AttributeSet attrs) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WidgetSections);
+ mCategory = a.getInt(R.styleable.WidgetSections_category, NO_CATEGORY);
+ mSectionTitle = a.getResourceId(R.styleable.WidgetSections_sectionTitle, ID_NULL);
+ mSectionDrawable = a.getResourceId(R.styleable.WidgetSections_sectionDrawable, ID_NULL);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 68532ca..b152ddc 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -183,15 +183,16 @@
TableLayout widgetsTable = findViewById(R.id.widgets_table);
widgetsTable.removeAllViews();
- WidgetsTableUtils.groupWidgetItemsIntoTable(widgets, mMaxHorizontalSpan).forEach(row -> {
- TableRow tableRow = new TableRow(getContext());
- tableRow.setGravity(Gravity.TOP);
- row.forEach(widgetItem -> {
- WidgetCell widget = addItemCell(tableRow);
- widget.applyFromCellItem(widgetItem);
- });
- widgetsTable.addView(tableRow);
- });
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(widgets, mMaxHorizontalSpan)
+ .forEach(row -> {
+ TableRow tableRow = new TableRow(getContext());
+ tableRow.setGravity(Gravity.TOP);
+ row.forEach(widgetItem -> {
+ WidgetCell widget = addItemCell(tableRow);
+ widget.applyFromCellItem(widgetItem);
+ });
+ widgetsTable.addView(tableRow);
+ });
}
@Override
diff --git a/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java b/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java
index e62425f..7f24905 100644
--- a/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetListSpaceEntry.java
@@ -16,6 +16,8 @@
package com.android.launcher3.widget.model;
+import android.os.Process;
+
import com.android.launcher3.model.data.PackageItemInfo;
import java.util.Collections;
@@ -26,7 +28,9 @@
public class WidgetListSpaceEntry extends WidgetsListBaseEntry {
public WidgetListSpaceEntry() {
- super(new PackageItemInfo(""), "", Collections.EMPTY_LIST);
+ super(new PackageItemInfo(/* packageName= */ "", Process.myUserHandle()),
+ /* titleSectionName= */ "",
+ Collections.EMPTY_LIST);
mPkgItem.title = "";
}
diff --git a/src/com/android/launcher3/widget/picker/OnHeaderClickListener.java b/src/com/android/launcher3/widget/picker/OnHeaderClickListener.java
index 7372751..35f11bd 100644
--- a/src/com/android/launcher3/widget/picker/OnHeaderClickListener.java
+++ b/src/com/android/launcher3/widget/picker/OnHeaderClickListener.java
@@ -24,5 +24,5 @@
/**
* Calls when a header is clicked to show / hide widgets for a package.
*/
- void onHeaderClicked(boolean showWidgets, PackageUserKey packageUserKey);
+ void onHeaderClicked(boolean showWidgets, PackageUserKey key);
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 9e12f6f..894c4c9 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -535,8 +535,8 @@
- noWidgetsViewHeight) * RECOMMENDATION_TABLE_HEIGHT_RATIO;
List<ArrayList<WidgetItem>> recommendedWidgetsInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTable(recommendedWidgets,
- mMaxSpansPerRow);
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithoutReordering(
+ recommendedWidgets, mMaxSpansPerRow);
table.setRecommendedWidgets(recommendedWidgetsInTable, maxTableHeight);
} else {
table.setVisibility(GONE);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index d52134c..0e5a7d7 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -98,7 +98,7 @@
private Predicate<WidgetsListBaseEntry> mHeaderAndSelectedContentFilter = entry ->
entry instanceof WidgetsListHeaderEntry
|| entry instanceof WidgetsListSearchHeaderEntry
- || new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
+ || PackageUserKey.fromPackageItemInfo(entry.mPkgItem)
.equals(mWidgetsContentVisiblePackageUserKey);
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
@Nullable private RecyclerView mRecyclerView;
@@ -252,10 +252,11 @@
return entry instanceof WidgetsListBaseEntry.Header && matchesKey(entry, key);
}
- private static boolean matchesKey(
- @NonNull WidgetsListBaseEntry entry, @Nullable PackageUserKey key) {
+ private static boolean matchesKey(@NonNull WidgetsListBaseEntry entry,
+ @Nullable PackageUserKey key) {
if (key == null) return false;
return entry.mPkgItem.packageName.equals(key.mPackageName)
+ && entry.mPkgItem.widgetCategory == key.mWidgetCategory
&& entry.mPkgItem.user.equals(key.mUser);
}
@@ -434,11 +435,10 @@
.filter(entry -> entry instanceof WidgetsListHeaderEntry)
.map(entry -> entry.mPkgItem)
.collect(Collectors.toMap(
- entry -> new PackageUserKey(entry.packageName, entry.user),
+ entry -> PackageUserKey.fromPackageItemInfo(entry),
entry -> entry));
for (WidgetsListBaseEntry visibleEntry: mVisibleEntries) {
- PackageUserKey key = new PackageUserKey(visibleEntry.mPkgItem.packageName,
- visibleEntry.mPkgItem.user);
+ PackageUserKey key = PackageUserKey.fromPackageItemInfo(visibleEntry.mPkgItem);
PackageItemInfo packageItemInfo = packagesInfo.get(key);
if (packageItemInfo != null
&& !visibleEntry.mPkgItem.title.equals(packageItemInfo.title)) {
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index ebd2d10..932e06d 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget.picker;
+import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
+
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -41,6 +43,8 @@
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.util.PluralMessageFormat;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.widget.WidgetSections;
+import com.android.launcher3.widget.WidgetSections.WidgetSection;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
@@ -173,12 +177,12 @@
private void setIcon(PackageItemInfo info) {
Drawable icon;
- switch (info.category) {
- case PackageItemInfo.CONVERSATIONS:
- icon = getContext().getDrawable(R.drawable.ic_conversations_widget_category);
- break;
- default:
- icon = info.newIcon(getContext());
+ if (info.widgetCategory == NO_CATEGORY) {
+ icon = info.newIcon(getContext());
+ } else {
+ WidgetSection widgetSection = WidgetSections.getWidgetSections(getContext())
+ .get(info.widgetCategory);
+ icon = getContext().getDrawable(widgetSection.mSectionDrawable);
}
applyDrawables(icon);
mIconDrawable = icon;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java
index fadb637..c6a7285 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinder.java
@@ -62,9 +62,7 @@
(position & POSITION_LAST) != 0,
/* isExpanded= */ data.isWidgetListShown()));
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
- mOnHeaderClickListener.onHeaderClicked(
- isExpanded,
- new PackageUserKey(data.mPkgItem.packageName, data.mPkgItem.user)
- ));
+ mOnHeaderClickListener.onHeaderClicked(isExpanded,
+ PackageUserKey.fromPackageItemInfo(data.mPkgItem)));
}
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java
index bff43c1..2b27fc2 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinder.java
@@ -64,6 +64,6 @@
/* isExpanded= */ data.isWidgetListShown()));
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
mOnHeaderClickListener.onHeaderClicked(isExpanded,
- new PackageUserKey(data.mPkgItem.packageName, data.mPkgItem.user)));
+ PackageUserKey.fromPackageItemInfo(data.mPkgItem)));
}
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
index 8c9ff09..05e26ad 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
@@ -93,7 +93,7 @@
}
table.setListDrawableState(((position & POSITION_LAST) != 0) ? LAST : MIDDLE);
List<ArrayList<WidgetItem>> widgetItemsTable =
- WidgetsTableUtils.groupWidgetItemsIntoTable(
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
entry.mWidgets, entry.getMaxSpanSizeInCells());
recycleTableBeforeBinding(table, widgetItemsTable);
diff --git a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
index 54aaf93..72e27bf 100644
--- a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
+++ b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
@@ -45,9 +45,20 @@
return item.spanX > otherItem.spanX ? 1 : -1;
};
+ /**
+ * Groups {@code widgetItems} items into a 2D array which matches their appearance in a UI
+ * table. This takes liberty to rearrange widgets to make the table visually appealing.
+ */
+ public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithReordering(
+ List<WidgetItem> widgetItems, final int maxSpansPerRow) {
+ List<WidgetItem> sortedWidgetItems = widgetItems.stream().sorted(WIDGET_SHORTCUT_COMPARATOR)
+ .collect(Collectors.toList());
+ return groupWidgetItemsIntoTableWithoutReordering(sortedWidgetItems, maxSpansPerRow);
+ }
/**
- * Groups widgets items into a 2D array which matches their appearance in a UI table.
+ * Groups {@code widgetItems} into a 2D array which matches their appearance in a UI table while
+ * maintaining their order.
*
* <p>Grouping:
* 1. Widgets and shortcuts never group together in the same row.
@@ -64,13 +75,12 @@
* should be moved to a new row.
* Example 3: Row 1: 6x4. This is okay because this is the only item in the row.
*/
- public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTable(
+ public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithoutReordering(
List<WidgetItem> widgetItems, final int maxSpansPerRow) {
- List<WidgetItem> sortedWidgetItems = widgetItems.stream().sorted(WIDGET_SHORTCUT_COMPARATOR)
- .collect(Collectors.toList());
+
List<ArrayList<WidgetItem>> widgetItemsTable = new ArrayList<>();
ArrayList<WidgetItem> widgetItemsAtRow = null;
- for (WidgetItem widgetItem : sortedWidgetItems) {
+ for (WidgetItem widgetItem : widgetItems) {
if (widgetItemsAtRow == null) {
widgetItemsAtRow = new ArrayList<>();
widgetItemsTable.add(widgetItemsAtRow);
diff --git a/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java b/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java
deleted file mode 100644
index cd9f33d..0000000
--- a/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins;
-
-import android.app.Activity;
-import android.content.Context;
-import android.widget.FrameLayout;
-
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-/**
- * Implement this interface to allow extra card on recents overview.
- */
-@ProvidesInterface(action = RecentsExtraCard.ACTION, version = RecentsExtraCard.VERSION)
-public interface RecentsExtraCard extends Plugin {
-
- String ACTION = "com.android.systemui.action.PLUGIN_RECENTS_EXTRA_CARD";
- int VERSION = 1;
-
- /**
- * Sets up the recents overview extra card and fills in data.
- *
- * @param context Plugin context
- * @param frameLayout PlaceholderView
- * @param activity Recents activity to hold extra view
- */
- void setupView(Context context, FrameLayout frameLayout, Activity activity);
-}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 12e9e1e..702f343 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -4,7 +4,10 @@
import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;
import static com.android.launcher3.pm.ShortcutConfigActivityInfo.queryList;
+import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
import android.appwidget.AppWidgetProviderInfo;
@@ -13,6 +16,7 @@
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.Log;
+import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.collection.ArrayMap;
@@ -27,10 +31,12 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
+import com.android.launcher3.widget.WidgetSections;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
@@ -40,12 +46,12 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
/**
* Widgets data model that is used by the adapters of the widget views and controllers.
@@ -61,9 +67,6 @@
private static final String TAG = "WidgetsModel";
private static final boolean DEBUG = false;
- private static final ComponentName CONVERSATION_WIDGET = ComponentName.createRelative(
- "com.android.systemui", ".people.widget.PeopleSpaceWidgetProvider");
-
/* Map of widgets and shortcuts that are tracked per package. */
private final Map<PackageItemInfo, List<WidgetItem>> mWidgetsList = new HashMap<>();
@@ -168,16 +171,15 @@
mWidgetsList.clear();
} else {
// Otherwise, only clear the widgets and shortcuts for the changed package.
- mWidgetsList.remove(
- packageItemInfoCache.getOrCreate(new WidgetPackageOrCategoryKey(packageUser)));
+ mWidgetsList.remove(packageItemInfoCache.getOrCreate(packageUser));
}
// add and update.
mWidgetsList.putAll(rawWidgetsShortcuts.stream()
.filter(new WidgetValidityCheck(app))
- .collect(Collectors.groupingBy(item ->
- packageItemInfoCache.getOrCreate(getWidgetPackageOrCategoryKey(item))
- )));
+ .flatMap(widgetItem -> getPackageUserKeys(app.getContext(), widgetItem).stream()
+ .map(key -> new Pair<>(packageItemInfoCache.getOrCreate(key), widgetItem)))
+ .collect(groupingBy(pair -> pair.first, mapping(pair -> pair.second, toList()))));
// Update each package entry
IconCache iconCache = app.getIconCache();
@@ -209,9 +211,9 @@
}
public WidgetItem getWidgetProviderInfoByProviderName(
- ComponentName providerName) {
+ ComponentName providerName, UserHandle user) {
List<WidgetItem> widgetsList = mWidgetsList.get(
- new PackageItemInfo(providerName.getPackageName()));
+ new PackageItemInfo(providerName.getPackageName(), user));
if (widgetsList == null) {
return null;
}
@@ -225,18 +227,40 @@
}
/** Returns {@link PackageItemInfo} of a pending widget. */
- public static PackageItemInfo newPendingItemInfo(ComponentName provider) {
- if (CONVERSATION_WIDGET.equals(provider)) {
- return new PackageItemInfo(provider.getPackageName(), PackageItemInfo.CONVERSATIONS);
+ public static PackageItemInfo newPendingItemInfo(Context context, ComponentName provider,
+ UserHandle user) {
+ Map<ComponentName, IntSet> widgetsToCategories =
+ WidgetSections.getWidgetsToCategory(context);
+ if (widgetsToCategories.containsKey(provider)) {
+ Iterator<Integer> categoriesIterator = widgetsToCategories.get(provider).iterator();
+ int firstCategory = NO_CATEGORY;
+ while (categoriesIterator.hasNext() && firstCategory == NO_CATEGORY) {
+ firstCategory = categoriesIterator.next();
+ }
+ return new PackageItemInfo(provider.getPackageName(), firstCategory, user);
}
- return new PackageItemInfo(provider.getPackageName());
+ return new PackageItemInfo(provider.getPackageName(), user);
}
- private WidgetPackageOrCategoryKey getWidgetPackageOrCategoryKey(WidgetItem item) {
- if (CONVERSATION_WIDGET.equals(item.componentName)) {
- return new WidgetPackageOrCategoryKey(PackageItemInfo.CONVERSATIONS, item.user);
+ private List<PackageUserKey> getPackageUserKeys(Context context, WidgetItem item) {
+ Map<ComponentName, IntSet> widgetsToCategories =
+ WidgetSections.getWidgetsToCategory(context);
+ IntSet categories = widgetsToCategories.get(item.componentName);
+ if (categories == null || categories.isEmpty()) {
+ return Arrays.asList(
+ new PackageUserKey(item.componentName.getPackageName(), item.user));
}
- return new WidgetPackageOrCategoryKey(item.componentName.getPackageName(), item.user);
+ List<PackageUserKey> packageUserKeys = new ArrayList<>();
+ categories.forEach(category -> {
+ if (category == NO_CATEGORY) {
+ packageUserKeys.add(
+ new PackageUserKey(item.componentName.getPackageName(),
+ item.user));
+ } else {
+ packageUserKeys.add(new PackageUserKey(category, item.user));
+ }
+ });
+ return packageUserKeys;
}
private static class WidgetValidityCheck implements Predicate<WidgetItem> {
@@ -279,53 +303,13 @@
}
}
- /** A hash key for grouping widgets by package name or category. */
- private static class WidgetPackageOrCategoryKey {
- /**
- * The package name of the widget provider.
- *
- * <p>This shouldn't be empty if {@link #mCategory} has a value,
- * {@link PackageItemInfo#NO_CATEGORY}.
- */
- public final String mPackage;
- /** A widget category. */
- @PackageItemInfo.Category public final int mCategory;
- public final UserHandle mUser;
- private final int mHashCode;
-
- WidgetPackageOrCategoryKey(PackageUserKey key) {
- this(key.mPackageName, key.mUser);
- }
-
- WidgetPackageOrCategoryKey(String packageName, UserHandle user) {
- this(packageName, PackageItemInfo.NO_CATEGORY, user);
- }
-
- WidgetPackageOrCategoryKey(@PackageItemInfo.Category int category, UserHandle user) {
- this("", category, user);
- }
-
- private WidgetPackageOrCategoryKey(String packageName,
- @PackageItemInfo.Category int category, UserHandle user) {
- mPackage = packageName;
- mCategory = category;
- mUser = user;
- mHashCode = Arrays.hashCode(new Object[]{mPackage, mCategory, mUser});
- }
-
- @Override
- public int hashCode() {
- return mHashCode;
- }
- }
-
private static final class PackageItemInfoCache {
- private final Map<WidgetPackageOrCategoryKey, PackageItemInfo> mMap = new ArrayMap<>();
+ private final Map<PackageUserKey, PackageItemInfo> mMap = new ArrayMap<>();
- PackageItemInfo getOrCreate(WidgetPackageOrCategoryKey key) {
+ PackageItemInfo getOrCreate(PackageUserKey key) {
PackageItemInfo pInfo = mMap.get(key);
if (pInfo == null) {
- pInfo = new PackageItemInfo(key.mPackage, key.mCategory);
+ pInfo = new PackageItemInfo(key.mPackageName, key.mWidgetCategory, key.mUser);
pInfo.user = key.mUser;
mMap.put(key, pInfo);
}
diff --git a/tests/src/com/android/launcher3/util/PackageUserKeyTest.java b/tests/src/com/android/launcher3/util/PackageUserKeyTest.java
new file mode 100644
index 0000000..99490eb
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/PackageUserKeyTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 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.widget.WidgetSections.NO_CATEGORY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.UserHandle;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.model.data.PackageItemInfo;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class PackageUserKeyTest {
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ private static final String TEST_PACKAGE = "com.android.test.package";
+ private static final int CONVERSATIONS = 0;
+ private static final int WEATHER = 1;
+
+ @Test
+ public void fromPackageItemInfo_shouldCreateExpectedObject() {
+ PackageUserKey packageUserKey = PackageUserKey.fromPackageItemInfo(
+ new PackageItemInfo(TEST_PACKAGE, UserHandle.CURRENT));
+
+ assertThat(packageUserKey.mPackageName).isEqualTo(TEST_PACKAGE);
+ assertThat(packageUserKey.mWidgetCategory).isEqualTo(NO_CATEGORY);
+ assertThat(packageUserKey.mUser).isEqualTo(UserHandle.CURRENT);
+ }
+
+ @Test
+ public void constructor_packageNameAndUserHandle_shouldCreateExpectedObject() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+
+ assertThat(packageUserKey.mPackageName).isEqualTo(TEST_PACKAGE);
+ assertThat(packageUserKey.mWidgetCategory).isEqualTo(NO_CATEGORY);
+ assertThat(packageUserKey.mUser).isEqualTo(UserHandle.CURRENT);
+ }
+
+ @Test
+ public void constructor_widgetCategoryAndUserHandle_shouldCreateExpectedObject() {
+ PackageUserKey packageUserKey = new PackageUserKey(CONVERSATIONS, UserHandle.CURRENT);
+
+ assertThat(packageUserKey.mPackageName).isEqualTo("");
+ assertThat(packageUserKey.mWidgetCategory).isEqualTo(CONVERSATIONS);
+ assertThat(packageUserKey.mUser).isEqualTo(UserHandle.CURRENT);
+ }
+
+ @Test
+ public void equals_sameObject_shouldReturnTrue() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = packageUserKey;
+
+ assertThat(packageUserKey).isEqualTo(otherPackageUserKey);
+ }
+
+ @Test
+ public void equals_differentObjectSameContent_shouldReturnTrue() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+
+ assertThat(packageUserKey).isEqualTo(otherPackageUserKey);
+ }
+
+ @Test
+ public void equals_compareAgainstNull_shouldReturnFalse() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+
+ assertThat(packageUserKey).isNotEqualTo(null);
+ }
+
+ @Test
+ public void equals_differentPackage_shouldReturnFalse() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = new PackageUserKey(TEST_PACKAGE + "1",
+ UserHandle.CURRENT);
+
+ assertThat(packageUserKey).isNotEqualTo(otherPackageUserKey);
+ }
+
+
+ @Test
+ public void equals_differentCategory_shouldReturnFalse() {
+ PackageUserKey packageUserKey = new PackageUserKey(WEATHER, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = new PackageUserKey(CONVERSATIONS, UserHandle.CURRENT);
+
+ assertThat(packageUserKey).isNotEqualTo(otherPackageUserKey);
+ }
+
+ @Test
+ public void equals_differentUser_shouldReturnFalse() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.of(1));
+ PackageUserKey otherPackageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.of(2));
+
+ assertThat(packageUserKey).isNotEqualTo(otherPackageUserKey);
+ }
+
+ @Test
+ public void hashCode_sameObject_shouldBeTheSame() {
+ PackageUserKey packageUserKey = new PackageUserKey(WEATHER, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = packageUserKey;
+
+ assertThat(packageUserKey.hashCode()).isEqualTo(otherPackageUserKey.hashCode());
+ }
+
+ @Test
+ public void hashCode_differentObjectSameContent_shouldBeTheSame() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+
+ assertThat(packageUserKey.hashCode()).isEqualTo(otherPackageUserKey.hashCode());
+ }
+
+ @Test
+ public void hashCode_differentPackage_shouldBeDifferent() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = new PackageUserKey(TEST_PACKAGE + "1",
+ UserHandle.CURRENT);
+
+ assertThat(packageUserKey.hashCode()).isNotEqualTo(otherPackageUserKey.hashCode());
+ }
+
+
+ @Test
+ public void hashCode_differentCategory_shouldBeDifferent() {
+ PackageUserKey packageUserKey = new PackageUserKey(WEATHER, UserHandle.CURRENT);
+ PackageUserKey otherPackageUserKey = new PackageUserKey(CONVERSATIONS, UserHandle.CURRENT);
+
+ assertThat(packageUserKey.hashCode()).isNotEqualTo(otherPackageUserKey.hashCode());
+ }
+
+ @Test
+ public void hashCode_differentUser_shouldBeDifferent() {
+ PackageUserKey packageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.of(1));
+ PackageUserKey otherPackageUserKey = new PackageUserKey(TEST_PACKAGE, UserHandle.of(2));
+
+ assertThat(packageUserKey.hashCode()).isNotEqualTo(otherPackageUserKey.hashCode());
+ }
+}
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
index 6232938..b480a4c 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
@@ -288,9 +288,8 @@
private PackageItemInfo createPackageItemInfo(String packageName, String appName,
UserHandle userHandle) {
- PackageItemInfo pInfo = new PackageItemInfo(packageName);
+ PackageItemInfo pInfo = new PackageItemInfo(packageName, userHandle);
pInfo.title = appName;
- pInfo.user = userHandle;
pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
return pInfo;
}
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
index 44d6964..4e0bdda 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
@@ -215,14 +215,23 @@
@Test
public void setWidgetsOnSearch_expandedApp_shouldResetExpandedApp() {
// GIVEN a list of widgets entries:
- // [com.google.test0, com.google.test0 content,
- // com.google.test1, com.google.test1 content,
- // com.google.test2, com.google.test2 content]
- // The visible widgets entries: [com.google.test0, com.google.test1, com.google.test2].
- ArrayList<WidgetsListBaseEntry> allEntries = generateSampleMap(2);
+ // [Empty item
+ // com.google.test0,
+ // com.google.test0 content,
+ // com.google.test1,
+ // com.google.test1 content,
+ // com.google.test2,
+ // com.google.test2 content]
+ // The visible widgets entries:
+ // [Empty item,
+ // com.google.test0,
+ // com.google.test1,
+ // com.google.test2].
+ ArrayList<WidgetsListBaseEntry> allEntries = generateSampleMap(3);
mAdapter.setWidgetsOnSearch(allEntries);
// GIVEN com.google.test.1 header is expanded. The visible entries list becomes:
- // [com.google.test0, com.google.test1, com.google.test1 content, com.google.test2]
+ // [Empty item, com.google.test0, com.google.test1, com.google.test1 content,
+ // com.google.test2]
mAdapter.onHeaderClicked(/* showWidgets= */ true,
new PackageUserKey(TEST_PACKAGE_PLACEHOLDER + 1, mUserHandle));
Mockito.reset(mListener);
@@ -231,7 +240,7 @@
mAdapter.setWidgetsOnSearch(allEntries);
// THEN expanded app is reset and the visible entries list becomes:
- // [com.google.test0, com.google.test1, com.google.test2]
+ // [Empty item, com.google.test0, com.google.test1, com.google.test2]
verify(mListener).onItemRangeChanged(eq(2), eq(1), isNull());
verify(mListener).onItemRangeRemoved(/* positionStart= */ 3, /* itemCount= */ 1);
}
@@ -257,9 +266,8 @@
List<WidgetItem> widgetItems = generateWidgetItems(packageName, /* numOfWidgets= */ 1);
- PackageItemInfo pInfo = new PackageItemInfo(packageName);
+ PackageItemInfo pInfo = new PackageItemInfo(packageName, widgetItems.get(0).user);
pInfo.title = pInfo.packageName;
- pInfo.user = widgetItems.get(0).user;
pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
result.add(new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems));
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
index 969c12a..211318c 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
@@ -30,6 +30,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
+import android.os.UserHandle;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -124,12 +125,12 @@
widgetsListHeader.callOnClick();
verify(mOnHeaderClickListener).onHeaderClicked(eq(true),
- eq(new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)));
+ eq(PackageUserKey.fromPackageItemInfo(entry.mPkgItem)));
}
private WidgetsListHeaderEntry generateSampleAppHeader(String appName, String packageName,
int numOfWidgets) {
- PackageItemInfo appInfo = new PackageItemInfo(packageName);
+ PackageItemInfo appInfo = new PackageItemInfo(packageName, UserHandle.CURRENT);
appInfo.title = appName;
appInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
index 453f4fb..66c2f36 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java
@@ -30,6 +30,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
+import android.os.UserHandle;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -124,12 +125,12 @@
widgetsListHeader.callOnClick();
verify(mOnHeaderClickListener).onHeaderClicked(eq(true),
- eq(new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)));
+ eq(PackageUserKey.fromPackageItemInfo(entry.mPkgItem)));
}
private WidgetsListSearchHeaderEntry generateSampleSearchHeader(String appName,
String packageName, int numOfWidgets) {
- PackageItemInfo appInfo = new PackageItemInfo(packageName);
+ PackageItemInfo appInfo = new PackageItemInfo(packageName, UserHandle.CURRENT);
appInfo.title = appName;
appInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 5816b77..7ec4d20 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -28,6 +28,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
+import android.os.UserHandle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -125,7 +126,7 @@
private WidgetsListContentEntry generateSampleAppWithWidgets(String appName, String packageName,
int numOfWidgets) {
- PackageItemInfo appInfo = new PackageItemInfo(packageName);
+ PackageItemInfo appInfo = new PackageItemInfo(packageName, UserHandle.CURRENT);
appInfo.title = appName;
appInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
diff --git a/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java b/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
index 4b61b2c..d8f1f14 100644
--- a/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
@@ -26,6 +26,7 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
+import android.os.UserHandle;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -53,8 +54,10 @@
public final class WidgetsListContentEntryTest {
private static final String PACKAGE_NAME = "com.android.test";
private static final String PACKAGE_NAME_2 = "com.android.test2";
- private final PackageItemInfo mPackageItemInfo1 = new PackageItemInfo(PACKAGE_NAME);
- private final PackageItemInfo mPackageItemInfo2 = new PackageItemInfo(PACKAGE_NAME_2);
+ private final PackageItemInfo mPackageItemInfo1 = new PackageItemInfo(PACKAGE_NAME,
+ UserHandle.CURRENT);
+ private final PackageItemInfo mPackageItemInfo2 = new PackageItemInfo(PACKAGE_NAME_2,
+ UserHandle.CURRENT);
private final ComponentName mWidget1 = ComponentName.createRelative(PACKAGE_NAME, ".mWidget1");
private final ComponentName mWidget2 = ComponentName.createRelative(PACKAGE_NAME, ".mWidget2");
private final ComponentName mWidget3 = ComponentName.createRelative(PACKAGE_NAME, ".mWidget3");
diff --git a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java b/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
index c862d6b..d812ab0 100644
--- a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
@@ -189,9 +189,8 @@
private PackageItemInfo createPackageItemInfo(String packageName, String appName,
UserHandle userHandle) {
- PackageItemInfo pInfo = new PackageItemInfo(packageName);
+ PackageItemInfo pInfo = new PackageItemInfo(packageName, userHandle);
pInfo.title = appName;
- pInfo.user = userHandle;
pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
return pInfo;
}
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index d6da776..715dcca 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -92,12 +92,13 @@
@Test
- public void groupWidgetItemsIntoTable_widgetsOnly_maxSpansPerRow5_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpansPerRow5_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
mWidget2x2);
- List<ArrayList<WidgetItem>> widgetItemInTable = WidgetsTableUtils.groupWidgetItemsIntoTable(
- widgetItems, /* maxSpansPerRow= */ 5);
+ List<ArrayList<WidgetItem>> widgetItemInTable =
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
+ widgetItems, /* maxSpansPerRow= */ 5);
// Row 0: 1x1, 2x2
// Row 1: 2x3, 2x4
@@ -109,12 +110,13 @@
}
@Test
- public void groupWidgetItemsIntoTable_widgetsOnly_maxSpansPerRow4_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpansPerRow4_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
mWidget2x2);
- List<ArrayList<WidgetItem>> widgetItemInTable = WidgetsTableUtils.groupWidgetItemsIntoTable(
- widgetItems, /* maxSpansPerRow= */ 4);
+ List<ArrayList<WidgetItem>> widgetItemInTable =
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
+ widgetItems, /* maxSpansPerRow= */ 4);
// Row 0: 1x1, 2x2
// Row 1: 2x3,
@@ -128,12 +130,13 @@
}
@Test
- public void groupWidgetItemsIntoTable_mixItems_maxSpansPerRow4_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_mixItems_maxSpansPerRow4_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mShortcut3, mWidget2x3, mShortcut1,
mWidget1x1, mShortcut2, mWidget2x4, mWidget2x2);
- List<ArrayList<WidgetItem>> widgetItemInTable = WidgetsTableUtils.groupWidgetItemsIntoTable(
- widgetItems, /* maxSpansPerRow= */ 4);
+ List<ArrayList<WidgetItem>> widgetItemInTable =
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
+ widgetItems, /* maxSpansPerRow= */ 4);
// Row 0: 1x1, 2x2
// Row 1: 2x3,
@@ -148,6 +151,24 @@
assertThat(widgetItemInTable.get(4)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
}
+ @Test
+ public void groupWidgetItemsIntoTableWithoutReordering_shouldMaintainTheOrder() {
+ List<WidgetItem> widgetItems =
+ List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4, mWidget2x2);
+
+ List<ArrayList<WidgetItem>> widgetItemInTable =
+ WidgetsTableUtils.groupWidgetItemsIntoTableWithoutReordering(
+ widgetItems, /* maxSpansPerRow= */ 5);
+
+ // Row 0: 4x4
+ // Row 1: 2x3, 1x1
+ // Row 2: 2x4, 2x2
+ assertThat(widgetItemInTable).hasSize(3);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget4x4);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget1x1);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4, mWidget2x2);
+ }
+
private void initTestWidgets() {
List<Point> widgetSizes = List.of(new Point(1, 1), new Point(2, 2), new Point(2, 3),
new Point(2, 4), new Point(4, 4));
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 588b6b8..7137c00 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -35,6 +35,7 @@
BaseOverview(LauncherInstrumentation launcher) {
super(launcher);
verifyActiveContainer();
+ verifyActionsViewVisibility();
}
@Override
@@ -59,7 +60,11 @@
final int leftMargin = mLauncher.getTargetInsets().left;
mLauncher.scroll(
overview, Direction.LEFT, new Rect(leftMargin + 1, 0, 0, 0), 20, false);
- verifyActiveContainer();
+ try (LauncherInstrumentation.Closable c2 =
+ mLauncher.addContextLayer("flung forwards")) {
+ verifyActiveContainer();
+ verifyActionsViewVisibility();
+ }
}
}
@@ -95,7 +100,11 @@
final int rightMargin = mLauncher.getTargetInsets().right;
mLauncher.scroll(
overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false);
- verifyActiveContainer();
+ try (LauncherInstrumentation.Closable c2 =
+ mLauncher.addContextLayer("flung backwards")) {
+ verifyActiveContainer();
+ verifyActionsViewVisibility();
+ }
}
}
@@ -150,4 +159,55 @@
return new OverviewActions(overviewActions, mLauncher);
}
}
+
+ /* TODO(b/197630182): Once b/188790554 is fixed, remove instanceof check. Currently, when
+ swiping from app to overview in Fallback Recents, taskbar remains and no action buttons
+ are visible, so we are only testing Overview for now, not BaseOverview. */
+ private void verifyActionsViewVisibility() {
+ if (!(this instanceof Overview)) {
+ return;
+ }
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to assert overview actions view visibility")) {
+ if (mLauncher.isTablet() && !isOverviewSnappedToFocusedTask()) {
+ mLauncher.waitUntilLauncherObjectGone("action_buttons");
+ } else {
+ mLauncher.waitForLauncherObject("action_buttons");
+ }
+ }
+ }
+
+ /**
+ * Returns if focused task is currently snapped task in overview.
+ */
+ private boolean isOverviewSnappedToFocusedTask() {
+ if (!mLauncher.isTablet()) {
+ // Focused task only exists in tablet's grid-overview
+ return false;
+ }
+ UiObject2 focusedTask = getFocusedTask();
+ if (focusedTask == null) {
+ return false;
+ }
+ return Math.abs(
+ focusedTask.getVisibleBounds().exactCenterX() - mLauncher.getExactScreenCenterX())
+ < 1;
+ }
+
+ /**
+ * Returns Overview focused task if it exists.
+ */
+ private UiObject2 getFocusedTask() {
+ final List<UiObject2> taskViews = getTasks();
+ if (taskViews.size() == 0) {
+ return null;
+ }
+ int focusedTaskWidth = mLauncher.getFocusedTaskWidth();
+ for (UiObject2 task : taskViews) {
+ if (task.getVisibleBounds().width() == focusedTaskWidth) {
+ return task;
+ }
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 0360a7d..f83c031 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -321,6 +321,15 @@
.getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+ int getFocusedTaskWidth() {
+ return getTestInfo(TestProtocol.REQUEST_GET_FOCUSED_TASK_WIDTH_FOR_TABLET).getInt(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
+ float getExactScreenCenterX() {
+ return getRealDisplaySize().x / 2f;
+ }
+
private void setForcePauseTimeout(long timeout) {
getTestInfo(TestProtocol.REQUEST_SET_FORCE_PAUSE_TIMEOUT, Long.toString(timeout));
}
@@ -1455,16 +1464,6 @@
getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
}
- boolean overviewShareEnabled() {
- return getTestInfo(TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED).getBoolean(
- TestProtocol.TEST_INFO_RESPONSE_FIELD);
- }
-
- boolean overviewContentPushEnabled() {
- return getTestInfo(TestProtocol.REQUEST_OVERVIEW_CONTENT_PUSH_ENABLED).getBoolean(
- TestProtocol.TEST_INFO_RESPONSE_FIELD);
- }
-
private void disableSensorRotation() {
getTestInfo(TestProtocol.REQUEST_MOCK_SENSOR_ROTATION);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 4d673a8..0d06be3 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -30,7 +30,6 @@
Overview(LauncherInstrumentation launcher) {
super(launcher);
- verifyActiveContainer();
}
@Override
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index 950c052..c8c06e4 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -34,27 +34,6 @@
}
/**
- * Clicks content push button.
- */
- @NonNull
- public Overview clickAndDismissContentPush() {
- if (mLauncher.overviewContentPushEnabled()) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to click content push button and exit screenshot ui")) {
- UiObject2 exo = mLauncher.waitForObjectInContainer(mOverviewActions,
- "action_content_push");
- mLauncher.clickLauncherObject(exo);
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "clicked content push button")) {
- return new Overview(mLauncher);
- }
- }
- }
- return new Overview(mLauncher);
- }
-
- /**
* Clicks screenshot button and closes screenshot ui.
*/
@NonNull
@@ -87,35 +66,6 @@
}
/**
- * Click share button, then drags sharesheet down to remove it.
- *
- * Share is currently hidden behind flag, test is kept in case share becomes a default feature.
- * If share is completely removed then remove this test as well.
- */
- @NonNull
- public Overview clickAndDismissShare() {
- if (mLauncher.overviewShareEnabled()) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to click share button and dismiss sharesheet")) {
- UiObject2 share = mLauncher.waitForObjectInContainer(mOverviewActions,
- "action_share");
- mLauncher.clickLauncherObject(share);
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "clicked share button")) {
- mLauncher.waitForAndroidObject("contentPanel");
- mLauncher.getDevice().pressBack();
- try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
- "dismissed sharesheet")) {
- return new Overview(mLauncher);
- }
- }
- }
- }
- return new Overview(mLauncher);
- }
-
- /**
* Click select button
*
* @return The select mode buttons that are now shown instead of action buttons.