Merge "Uninstall an app from workspace via TAPL"
diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java
index 7c66f6e..c252fba 100644
--- a/go/quickstep/src/com/android/launcher3/AppSharing.java
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -22,6 +22,9 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -98,14 +101,19 @@
* The Share App system shortcut, used to initiate p2p sharing of a given app
*/
public final class Share extends SystemShortcut<Launcher> {
- private PopupDataProvider mPopupDataProvider;
+ private final PopupDataProvider mPopupDataProvider;
+ private final boolean mSharingEnabledForUser;
public Share(Launcher target, ItemInfo itemInfo) {
super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo);
mPopupDataProvider = target.getPopupDataProvider();
- if (ENABLE_SHAREABILITY_CHECK) {
- mShareabilityMgr = AppShareabilityManager.INSTANCE.get(target);
+ mSharingEnabledForUser = bluetoothSharingEnabled(target);
+ if (!mSharingEnabledForUser) {
+ setEnabled(false);
+ } else if (ENABLE_SHAREABILITY_CHECK) {
+ mShareabilityMgr =
+ AppShareabilityManager.INSTANCE.get(target.getApplicationContext());
checkShareability(/* requestUpdateIfUnknown */ true);
}
}
@@ -144,7 +152,12 @@
sendIntent.setType(APP_MIME_TYPE);
sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent));
- mTarget.startActivitySafely(view, sendIntent, mItemInfo);
+ UserHandle user = mItemInfo.user;
+ if (user != null && !user.equals(Process.myUserHandle())) {
+ mTarget.startActivityAsUser(sendIntent, user);
+ } else {
+ mTarget.startActivitySafely(view, sendIntent, mItemInfo);
+ }
AbstractFloatingView.closeAllOpenViews(mTarget);
}
@@ -170,8 +183,15 @@
}
}
+ private boolean bluetoothSharingEnabled(Context context) {
+ return !context.getSystemService(UserManager.class)
+ .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH_SHARING, mItemInfo.user);
+ }
+
private void showCannotShareToast(Context context) {
- CharSequence text = context.getText(R.string.toast_p2p_app_not_shareable);
+ CharSequence text = (mSharingEnabledForUser)
+ ? context.getText(R.string.toast_p2p_app_not_shareable)
+ : context.getText(R.string.blocked_by_policy);
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
index cf80c35..0d0f700 100644
--- a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
@@ -47,7 +47,7 @@
* Each app's status is retrieved from the Play Store's API. Statuses are cached in order
* to limit extraneous calls to that API (which can be time-consuming).
*/
-public final class AppShareabilityManager {
+public class AppShareabilityManager {
@Retention(SOURCE)
@IntDef({
ShareabilityStatus.UNKNOWN,
diff --git a/quickstep/res/drawable/ic_sysbar_back_kids.xml b/quickstep/res/drawable/ic_sysbar_back_kids.xml
new file mode 100644
index 0000000..ac6d49b
--- /dev/null
+++ b/quickstep/res/drawable/ic_sysbar_back_kids.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21,11.4v1c0,1 -0.8,1.8 -1.8,1.8l0,0h-8.8l2.7,2.7c0.7,0.7 0.7,1.8 0,2.5c0,0 0,0 0,0l-0.7,0.7c-0.7,0.7 -1.8,0.7 -2.5,0c0,0 0,0 0,0l-5.9,-5.9C2.6,13 2.6,11 3.9,9.7l5.9,-5.9c0.7,-0.7 1.8,-0.7 2.5,0c0,0 0,0 0,0l0.7,0.7c0.7,0.7 0.7,1.8 0,2.5c0,0 0,0 0,0l-2.6,2.6h8.7C20.2,9.6 21,10.5 21,11.4z"/>
+</vector>
diff --git a/quickstep/res/drawable/ic_sysbar_home_kids.xml b/quickstep/res/drawable/ic_sysbar_home_kids.xml
new file mode 100644
index 0000000..2397e70
--- /dev/null
+++ b/quickstep/res/drawable/ic_sysbar_home_kids.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22.7,11l-7.9,-7c-1.6,-1.4 -3.9,-1.4 -5.5,0L7.4,5.7V4.1C7.4,3.5 6.9,3 6.3,3H5.2C4.5,3 4,3.5 4,4.1c0,0 0,0 0,0v4.6L1.4,11c-0.5,0.4 -0.5,1.1 -0.1,1.5c0,0 0,0 0,0c0.2,0.2 0.5,0.4 0.8,0.4H4v5c0,1.3 1,2.3 2.3,2.3c0,0 0,0 0,0h11.4c1.3,0 2.3,-1 2.3,-2.3v-5h2c0.6,0 1.1,-0.5 1.1,-1.1C23,11.5 22.9,11.2 22.7,11L22.7,11zM14.3,15.6c0,0.6 -0.5,1.1 -1.1,1.2h-2.3c-0.6,0 -1.1,-0.5 -1.1,-1.1v-1.3c0,-0.6 0.5,-1.1 1.1,-1.1c0,0 0,0 0,0h2.3c0.6,0 1.1,0.5 1.1,1.1c0,0 0,0 0,0L14.3,15.6z"/>
+</vector>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index c9e33a7..0e5ba2f 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -231,4 +231,10 @@
<dimen name="taskbar_stashed_handle_height">4dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y">25dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y_return_overshoot">4dp</dimen>
+ <dimen name="taskbar_nav_buttons_width_kids">88dp</dimen>
+ <dimen name="taskbar_nav_buttons_height_kids">40dp</dimen>
+ <dimen name="taskbar_nav_buttons_corner_radius_kids">40dp</dimen>
+ <dimen name="taskbar_back_button_left_margin_kids">96dp</dimen>
+ <dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
+ <dimen name="taskbar_icon_size_kids">32dp</dimen>
</resources>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 4269f2d..65b346a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -336,7 +336,8 @@
getSystemService(DeviceStateManager.class),
getSystemService(SensorManager.class),
getMainThreadHandler(),
- getMainExecutor()
+ getMainExecutor(),
+ /* tracingTagPrefix= */ "launcher"
);
mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
@@ -507,7 +508,7 @@
ActivityOptionsCompat.setLauncherSourceInfo(
activityOptions.options, mLastTouchUpTime);
}
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
addLaunchCookie(item, activityOptions.options);
return activityOptions;
}
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index b0fba3d..9c3daea 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -34,7 +34,6 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -60,13 +59,13 @@
Utilities.getDevicePrefs(context).edit()
.putBoolean(LAST_PREDICTION_ENABLED_STATE, !mTargets.isEmpty()).apply();
- FixedContainerItems fci = mPredictorState.items;
- Set<UserHandle> usersForChangedShortcuts = new HashSet<>(fci.items.stream()
- .filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT)
- .map(info -> info.user)
- .collect(Collectors.toSet()));
- fci.items.clear();
+ Set<UserHandle> usersForChangedShortcuts =
+ dataModel.extraItems.get(mPredictorState.containerId).items.stream()
+ .filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT)
+ .map(info -> info.user)
+ .collect(Collectors.toSet());
+ FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId);
for (AppTarget target : mTargets) {
WorkspaceItemInfo itemInfo;
ShortcutInfo si = target.getShortcutInfo();
@@ -109,6 +108,7 @@
fci.items.add(itemInfo);
}
+ dataModel.extraItems.put(fci.containerId, fci);
bindExtraContainerItems(fci);
usersForChangedShortcuts.forEach(
u -> dataModel.updateShortcutPinnedState(app.getContext(), u));
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index da18357..0e534f4 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -119,18 +119,19 @@
WorkspaceItemFactory allAppsFactory = new WorkspaceItemFactory(
mApp, ums, pinnedShortcuts, mIDP.numDatabaseAllAppsColumns);
- mAllAppsState.items.setItems(
+ FixedContainerItems allAppsItems = new FixedContainerItems(mAllAppsState.containerId,
mAllAppsState.storage.read(mApp.getContext(), allAppsFactory, ums.allUsers::get));
- mDataModel.extraItems.put(CONTAINER_PREDICTION, mAllAppsState.items);
+ mDataModel.extraItems.put(mAllAppsState.containerId, allAppsItems);
WorkspaceItemFactory hotseatFactory =
new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, mIDP.numDatabaseHotseatIcons);
- mHotseatState.items.setItems(
+ FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
- mDataModel.extraItems.put(CONTAINER_HOTSEAT_PREDICTION, mHotseatState.items);
+ mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
// Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
- mDataModel.extraItems.put(CONTAINER_WIDGETS_PREDICTION, mWidgetsRecommendationState.items);
+ mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
+ new FixedContainerItems(mWidgetsRecommendationState.containerId));
mActive = true;
}
@@ -371,14 +372,14 @@
static class PredictorState {
- public final FixedContainerItems items;
+ public final int containerId;
public final PersistedItemArray<ItemInfo> storage;
public AppPredictor predictor;
private List<AppTarget> mLastTargets;
- PredictorState(int container, String storageName) {
- items = new FixedContainerItems(container);
+ PredictorState(int containerId, String storageName) {
+ this.containerId = containerId;
storage = new PersistedItemArray<>(storageName);
mLastTargets = Collections.emptyList();
}
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index 4be83dc..9cd9d85 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -59,8 +59,8 @@
Map<PackageUserKey, List<WidgetItem>> allWidgets =
dataModel.widgetsModel.getAllWidgetsWithoutShortcuts();
- FixedContainerItems fixedContainerItems = mPredictorState.items;
- fixedContainerItems.items.clear();
+ FixedContainerItems fixedContainerItems =
+ new FixedContainerItems(mPredictorState.containerId);
if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) {
for (AppTarget app : mTargets) {
@@ -100,6 +100,7 @@
}
}
}
+ dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems);
bindExtraContainerItems(fixedContainerItems);
// Don't store widgets prediction to disk because it is not used frequently.
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index a4ecd8b..002a86c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -45,10 +45,12 @@
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.PaintDrawable;
import android.util.Property;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -58,6 +60,7 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
@@ -128,6 +131,7 @@
private View mA11yButton;
private int mSysuiStateFlags;
private View mBackButton;
+ private View mHomeButton;
private FloatingRotationButton mFloatingRotationButton;
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
@@ -171,6 +175,7 @@
// Force nav buttons (specifically back button) to be visible during setup wizard.
boolean isInSetup = !mContext.isUserSetupComplete();
+ boolean isInKidsMode = mContext.isNavBarKidsModeActive();
boolean alwaysShowButtons = isThreeButtonNav || isInSetup;
// Make sure to remove nav bar buttons translation when notification shade is expanded or
@@ -208,6 +213,64 @@
& Configuration.UI_MODE_NIGHT_MASK;
boolean isDarkTheme = mode == Configuration.UI_MODE_NIGHT_YES;
mTaskbarNavButtonDarkIntensity.updateValue(isDarkTheme ? 0 : 1);
+ } else if (isInKidsMode) {
+ int iconSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_icon_size_kids);
+ int buttonWidth = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_width_kids);
+ int buttonHeight = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_height_kids);
+ int buttonRadius = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_corner_radius_kids);
+ int paddingleft = (buttonWidth - iconSize) / 2;
+ int paddingRight = paddingleft;
+ int paddingTop = (buttonHeight - iconSize) / 2;
+ int paddingBottom = paddingTop;
+
+ // Update icons
+ ((ImageView) mBackButton).setImageDrawable(
+ mBackButton.getContext().getDrawable(R.drawable.ic_sysbar_back_kids));
+ ((ImageView) mBackButton).setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mBackButton.setPadding(paddingleft, paddingTop, paddingRight, paddingBottom);
+ ((ImageView) mHomeButton).setImageDrawable(
+ mHomeButton.getContext().getDrawable(R.drawable.ic_sysbar_home_kids));
+ ((ImageView) mHomeButton).setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mHomeButton.setPadding(paddingleft, paddingTop, paddingRight, paddingBottom);
+
+ // Home button layout
+ LinearLayout.LayoutParams homeLayoutparams = new LinearLayout.LayoutParams(
+ buttonWidth,
+ buttonHeight
+ );
+ int homeButtonLeftMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_home_button_left_margin_kids);
+ homeLayoutparams.setMargins(homeButtonLeftMargin, 0, 0, 0);
+ mHomeButton.setLayoutParams(homeLayoutparams);
+
+ // Back button layout
+ LinearLayout.LayoutParams backLayoutParams = new LinearLayout.LayoutParams(
+ buttonWidth,
+ buttonHeight
+ );
+ int backButtonLeftMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_back_button_left_margin_kids);
+ backLayoutParams.setMargins(backButtonLeftMargin, 0, 0, 0);
+ mBackButton.setLayoutParams(backLayoutParams);
+
+ // Button backgrounds
+ int whiteWith10PctAlpha = Color.argb(0.1f, 1, 1, 1);
+ PaintDrawable buttonBackground = new PaintDrawable(whiteWith10PctAlpha);
+ buttonBackground.setCornerRadius(buttonRadius);
+ mHomeButton.setBackground(buttonBackground);
+ mBackButton.setBackground(buttonBackground);
+
+ // Update alignment within taskbar
+ FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
+ mNavButtonContainer.getLayoutParams();
+ navButtonsLayoutParams.setMarginStart(navButtonsLayoutParams.getMarginEnd() / 2);
+ navButtonsLayoutParams.setMarginEnd(navButtonsLayoutParams.getMarginStart());
+ navButtonsLayoutParams.gravity = Gravity.CENTER;
+ mNavButtonContainer.requestLayout();
}
// Animate taskbar background when any of these flags are enabled
@@ -276,9 +339,9 @@
&& ((flags & FLAG_KEYGUARD_VISIBLE) == 0 || showingOnKeyguard);
}));
boolean isRtl = Utilities.isRtl(mContext.getResources());
- mPropertyHolders.add(new StatePropertyHolder(
- mBackButton, flags -> (flags & FLAG_IME_VISIBLE) != 0, View.ROTATION,
- isRtl ? 90 : -90, 0));
+ mPropertyHolders.add(new StatePropertyHolder(mBackButton,
+ flags -> (flags & FLAG_IME_VISIBLE) != 0 && !mContext.isNavBarKidsModeActive(),
+ View.ROTATION, isRtl ? 90 : -90, 0));
// Translate back button to be at end/start of other buttons for keyguard
int navButtonSize = mContext.getResources().getDimensionPixelSize(
R.dimen.taskbar_nav_buttons_size);
@@ -289,16 +352,16 @@
// home and recents buttons
- View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
+ mHomeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home);
- mPropertyHolders.add(new StatePropertyHolder(homeButton,
+ mPropertyHolders.add(new StatePropertyHolder(mHomeButton,
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
(flags & FLAG_DISABLE_HOME) == 0));
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
navContainer, navButtonController, R.id.recent_apps);
mPropertyHolders.add(new StatePropertyHolder(recentsButton,
- flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
- (flags & FLAG_DISABLE_RECENTS) == 0));
+ flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
+ && !mContext.isNavBarKidsModeActive()));
// A11y button
mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index b1f027a..1198dc5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -112,6 +112,7 @@
private final boolean mIsSafeModeEnabled;
private final boolean mIsUserSetupComplete;
+ private final boolean mIsNavBarKidsMode;
private boolean mIsDestroyed = false;
// The flag to know if the window is excluded from magnification region computation.
private boolean mIsExcludeFromMagnificationRegion = false;
@@ -129,6 +130,8 @@
() -> getPackageManager().isSafeMode());
mIsUserSetupComplete = SettingsCache.INSTANCE.get(this).getValue(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
+ mIsNavBarKidsMode = SettingsCache.INSTANCE.get(this).getValue(
+ Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
final Resources resources = getResources();
float taskbarIconSize = resources.getDimension(R.dimen.taskbar_icon_size);
@@ -385,7 +388,8 @@
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
onNotificationShadeExpandChanged((systemUiStateFlags & shadeExpandedFlags) != 0, fromInit);
mControllers.taskbarViewController.setRecentsButtonDisabled(
- mControllers.navbarButtonsViewController.isRecentsDisabled());
+ mControllers.navbarButtonsViewController.isRecentsDisabled()
+ || isNavBarKidsModeActive());
mControllers.stashedHandleViewController.setIsHomeButtonDisabled(
mControllers.navbarButtonsViewController.isHomeDisabled());
mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags);
@@ -587,6 +591,10 @@
return mIsUserSetupComplete;
}
+ protected boolean isNavBarKidsModeActive() {
+ return mIsNavBarKidsMode && isThreeButtonNav();
+ }
+
/**
* Called when we determine the touchable region.
*
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 7f2e37c..a262674 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -63,11 +63,15 @@
private static final Uri USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(
Settings.Secure.USER_SETUP_COMPLETE);
+ private static final Uri NAV_BAR_KIDS_MODE = Settings.Secure.getUriFor(
+ Settings.Secure.NAV_BAR_KIDS_MODE);
+
private final Context mContext;
private final DisplayController mDisplayController;
private final SysUINavigationMode mSysUINavigationMode;
private final TaskbarNavButtonController mNavButtonController;
private final SettingsCache.OnChangeListener mUserSetupCompleteListener;
+ private final SettingsCache.OnChangeListener mNavBarKidsModeListener;
private final ComponentCallbacks mComponentCallbacks;
private final SimpleBroadcastReceiver mShutdownReceiver;
@@ -97,6 +101,7 @@
mNavButtonController = new TaskbarNavButtonController(service,
SystemUiProxy.INSTANCE.get(mContext), new Handler());
mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar();
+ mNavBarKidsModeListener = isNavBarKidsMode -> recreateTaskbar();
mComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
@@ -126,6 +131,8 @@
mSysUINavigationMode.addModeChangeListener(this);
SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI,
mUserSetupCompleteListener);
+ SettingsCache.INSTANCE.get(mContext).register(NAV_BAR_KIDS_MODE,
+ mNavBarKidsModeListener);
mContext.registerComponentCallbacks(mComponentCallbacks);
mShutdownReceiver.register(mContext, Intent.ACTION_SHUTDOWN);
@@ -289,6 +296,8 @@
mSysUINavigationMode.removeModeChangeListener(this);
SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI,
mUserSetupCompleteListener);
+ SettingsCache.INSTANCE.get(mContext).unregister(NAV_BAR_KIDS_MODE,
+ mNavBarKidsModeListener);
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mContext.unregisterReceiver(mShutdownReceiver);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index c85b256..0eaea83 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -29,12 +29,9 @@
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
-import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION;
-import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.util.FloatProperty;
-import android.util.Pair;
import androidx.annotation.NonNull;
@@ -43,7 +40,6 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.views.RecentsView;
/**
@@ -100,15 +96,6 @@
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
- PagedOrientationHandler orientationHandler =
- ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
- Pair<FloatProperty, FloatProperty> taskViewsFloat =
- orientationHandler.getSplitSelectTaskOffset(
- TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
- mLauncher.getDeviceProfile());
- setter.setFloat(mRecentsView, taskViewsFloat.first,
- toState.getSplitSelectTranslation(mLauncher), LINEAR);
- setter.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 1cf50f7..c058aa7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -71,7 +71,7 @@
}
}
activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+ activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
Object itemInfo = hostView.getTag();
if (itemInfo instanceof ItemInfo) {
mLauncher.addLaunchCookie((ItemInfo) itemInfo, activityOptions.options);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 19897a1..32ce1c4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -23,13 +23,17 @@
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
+import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION;
+import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
+import android.util.Pair;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
@@ -37,6 +41,7 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
@@ -67,11 +72,7 @@
// DepthController to prevent optimizations which might occlude the layers behind
mLauncher.getDepthController().setHasContentBehindLauncher(state.overviewUi);
- if (isSplitSelectionState(state)) {
- mRecentsView.applySplitPrimaryScrollOffset();
- } else {
- mRecentsView.resetSplitPrimaryScrollOffset();
- }
+ handleSplitSelectionState(state, null);
}
@Override
@@ -92,16 +93,7 @@
builder.addListener(AnimatorListeners.forSuccessCallback(() ->
mLauncher.getDepthController().setHasContentBehindLauncher(toState.overviewUi)));
- // Create or dismiss split screen select animations
- LauncherState currentState = mLauncher.getStateManager().getState();
- if (isSplitSelectionState(toState) && !isSplitSelectionState(currentState)) {
- builder.add(mRecentsView.createSplitSelectInitAnimation().buildAnim());
- }
- if (isSplitSelectionState(toState)) {
- mRecentsView.applySplitPrimaryScrollOffset();
- } else {
- mRecentsView.resetSplitPrimaryScrollOffset();
- }
+ handleSplitSelectionState(toState, builder);
setAlphas(builder, config, toState);
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
@@ -109,10 +101,52 @@
}
/**
- * @return true if {@param toState} is {@link LauncherState#OVERVIEW_SPLIT_SELECT}
+ * Create or dismiss split screen select animations.
+ * @param builder if null then this will run the split select animations right away, otherwise
+ * will add animations to builder.
*/
- private boolean isSplitSelectionState(@NonNull LauncherState toState) {
- return toState == OVERVIEW_SPLIT_SELECT;
+ private void handleSplitSelectionState(@NonNull LauncherState toState,
+ @Nullable PendingAnimation builder) {
+ LauncherState currentState = mLauncher.getStateManager().getState();
+ boolean animate = builder != null;
+ PagedOrientationHandler orientationHandler =
+ ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
+ Pair<FloatProperty, FloatProperty> taskViewsFloat =
+ orientationHandler.getSplitSelectTaskOffset(
+ TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
+ mLauncher.getDeviceProfile());
+
+ if (isSplitSelectionState(currentState, toState)) {
+ // Animation to "dismiss" selected taskView
+ PendingAnimation splitSelectInitAnimation =
+ mRecentsView.createSplitSelectInitAnimation();
+ // Add properties to shift remaining taskViews to get out of placeholder view
+ splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.first,
+ toState.getSplitSelectTranslation(mLauncher), LINEAR);
+ splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
+
+ if (!animate && isSplitSelectionState(currentState, toState)) {
+ splitSelectInitAnimation.buildAnim().start();
+ } else if (animate &&
+ isSplitSelectionState(currentState, toState)) {
+ builder.add(splitSelectInitAnimation.buildAnim());
+ }
+ }
+
+ if (isSplitSelectionState(currentState, toState)) {
+ mRecentsView.applySplitPrimaryScrollOffset();
+ } else {
+ mRecentsView.resetSplitPrimaryScrollOffset();
+ }
+ }
+
+ /**
+ * @return true if {@param toState} is {@link LauncherState#OVERVIEW_SPLIT_SELECT}
+ * and {@param fromState} is not {@link LauncherState#OVERVIEW_SPLIT_SELECT}
+ */
+ private boolean isSplitSelectionState(@NonNull LauncherState fromState,
+ @NonNull LauncherState toState) {
+ return fromState != OVERVIEW_SPLIT_SELECT && toState == OVERVIEW_SPLIT_SELECT;
}
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 0e2fbbc..75cf5cb 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -17,6 +17,7 @@
import static android.view.View.VISIBLE;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -44,6 +45,10 @@
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
+import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD;
+import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD;
+import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_OPAQUE_THRESHOLD;
+import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_VISIBLE_THRESHOLD;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import android.animation.ValueAnimator;
@@ -52,6 +57,7 @@
import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.quickstep.SysUINavigationMode;
@@ -171,6 +177,13 @@
mHintToNormalDuration = (int) va.getDuration();
}
config.duration = Math.max(config.duration, mHintToNormalDuration);
+ } else if (fromState == ALL_APPS && toState == NORMAL) {
+ config.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
+ 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
+ 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
+ config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
+ 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
+ 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 3c83d25..59ade49 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -52,22 +52,22 @@
/**
* The progress at which all apps content will be fully visible.
*/
- protected static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f;
+ public static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f;
/**
* Minimum clamping progress for fading in all apps content
*/
- protected static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f;
+ public static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f;
/**
* Minimum clamping progress for fading in all apps scrim
*/
- protected static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = .1f;
+ public static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = .1f;
/**
* Maximum clamping progress for opaque all apps scrim
*/
- protected static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f;
+ public static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f;
private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper;
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index c7f1edd..9f1e47f 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1001,7 +1001,7 @@
}
if (mRecentsAnimationTargets != null) {
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- true /*shown*/, true /*animate*/);
+ true /*shown*/, false /*animate*/);
}
break;
}
@@ -1654,7 +1654,7 @@
if (mRecentsAnimationTargets != null) {
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- true /*shown*/, true /*animate*/);
+ true /*shown*/, false /*animate*/);
}
// Leave the pending invisible flag, as it may be used by wallpaper open animation.
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 103f350..306e864 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -255,7 +255,7 @@
final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
onEndCallback);
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
return activityOptions;
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 0246849..276e1c2 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -23,6 +23,7 @@
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
import android.annotation.SuppressLint;
+import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Matrix;
@@ -54,6 +55,7 @@
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.util.ArrayList;
import java.util.List;
@@ -115,8 +117,9 @@
* Does NOT add split options in the following scenarios:
* * The taskView to add split options is already showing split screen tasks
* * There aren't at least 2 tasks in overview to show split options for
+ * * Device is in "Lock task mode"
* * The taskView to show split options for is the focused task AND we haven't started
- * scrolling in overview (if we haven't scrolled, there's a split overview action so
+ * scrolling in overview (if we haven't scrolled, there's a split overview action button so
* we don't need this menu option)
*/
private static void addSplitOptions(List<SystemShortcut> outShortcuts,
@@ -130,7 +133,11 @@
boolean isFocusedTask = deviceProfile.overviewShowAsGrid && taskView.isFocusedTask();
boolean isTaskInExpectedScrollPosition =
recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
- if (taskViewHasMultipleTasks || notEnoughTasksToSplit ||
+ ActivityManager activityManager =
+ (ActivityManager) taskView.getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ boolean isLockTaskMode = activityManager.isInLockTaskMode();
+
+ if (taskViewHasMultipleTasks || notEnoughTasksToSplit || isLockTaskMode ||
(isFocusedTask && isTaskInExpectedScrollPosition)) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index cbdbdb5..ecb30e5 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -190,7 +190,7 @@
ActivityOptions options = mFactory.makeLaunchOptions(mTarget);
if (options != null) {
- options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
}
if (options != null
&& ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
@@ -242,6 +242,7 @@
}
}
+ /** @Deprecated */
TaskShortcutFactory SPLIT_SCREEN = new MultiWindowFactory(R.drawable.ic_split_screen,
R.string.recent_task_option_split_screen, LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP) {
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 14f3ec4..5d9a537 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -84,6 +84,7 @@
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import java.util.ArrayList;
+import java.util.List;
/**
* Utility class for helpful methods related to {@link TaskView} objects and their tasks.
@@ -606,13 +607,13 @@
}
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- SurfaceControl[] auxiliarySurfaces = new SurfaceControl[nonApps.length];
+ List<SurfaceControl> auxiliarySurfaces = new ArrayList<>(nonApps.length);
boolean hasSurfaceToAnimate = false;
for (int i = 0; i < nonApps.length; ++i) {
final RemoteAnimationTargetCompat targ = nonApps[i];
final SurfaceControl leash = targ.leash.getSurfaceControl();
if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
- auxiliarySurfaces[i] = leash;
+ auxiliarySurfaces.add(leash);
hasSurfaceToAnimate = true;
}
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index d310893..5253e8c 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -64,7 +64,6 @@
private @StagePosition int mStagePosition;
private Task mInitialTask;
private Task mSecondTask;
- private Rect mInitialBounds;
private boolean mRecentsAnimationRunning;
/** If not null, this is the TaskView we want to launch from */
@Nullable
@@ -86,7 +85,6 @@
Rect initialBounds) {
mInitialTask = task;
mStagePosition = stagePosition;
- mInitialBounds = initialBounds;
}
/**
@@ -229,7 +227,6 @@
mInitialTask = null;
mSecondTask = null;
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
- mInitialBounds = null;
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
}
@@ -241,8 +238,4 @@
public boolean isSplitSelectActive() {
return mInitialTask != null && mSecondTask == null;
}
-
- public Rect getInitialBounds() {
- return mInitialBounds;
- }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 10efa3e..f0e57c9 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -3994,7 +3994,7 @@
}
/** TODO(b/181707736) More gracefully handle exiting split selection state */
- private void resetFromSplitSelectionState() {
+ protected void resetFromSplitSelectionState() {
if (mSplitHiddenTaskViewIndex == -1) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 1d8a459..3e0eb91 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -470,7 +470,9 @@
stubInfo.user = componentKey.user;
stubInfo.intent = new Intent().setComponent(componentKey.componentName);
stubInfo.title = task.title;
- stubInfo.screenId = getRecentsView().indexOfChild(this);
+ if (getRecentsView() != null) {
+ stubInfo.screenId = getRecentsView().indexOfChild(this);
+ }
return stubInfo;
}
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 8d489e3..318f04e 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -220,7 +220,7 @@
if (!condition) {
final AssertionError assertionError = new AssertionError(message);
if (description != null) {
- FailureWatcher.onError(launcher.getDevice(), description, assertionError);
+ FailureWatcher.onError(launcher, description, assertionError);
}
throw assertionError;
}
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 08570eb..6db0af3 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -133,6 +133,8 @@
<attr name="numRows" format="integer" />
<attr name="numColumns" format="integer" />
+ <!-- numSearchContainerColumns defaults to numColumns, if not specified -->
+ <attr name="numSearchContainerColumns" format="integer" />
<!-- numFolderRows & numFolderColumns defaults to numRows & numColumns, if not specified -->
<attr name="numFolderRows" format="integer" />
<attr name="numFolderColumns" format="integer" />
@@ -182,76 +184,95 @@
<attr name="minHeightDps" format="float" />
<!-- 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 -->
- <attr name="twoPanelPortraitMinCellHeightDps" format="float" />
- <!-- twoPanelPortraitMinCellHeightDps defaults to minCellWidthDps, if not specified -->
- <attr name="twoPanelPortraitMinCellWidthDps" format="float" />
- <!-- twoPanelLandscapeMinCellHeightDps defaults to minCellHeightDps, if not specified -->
- <attr name="twoPanelLandscapeMinCellHeightDps" format="float" />
- <!-- twoPanelLandscapeMinCellWidthDps defaults to minCellWidthDps, if not specified -->
- <attr name="twoPanelLandscapeMinCellWidthDps" format="float" />
+ <attr name="minCellHeight" format="float" />
+ <attr name="minCellWidth" format="float" />
+ <!-- defaults to minCellHeight, if not specified -->
+ <attr name="minCellHeightTwoPanelPortrait" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="minCellWidthTwoPanelPortrait" format="float" />
+ <!-- defaults to minCellHeight, if not specified -->
+ <attr name="minCellHeightTwoPanelLandscape" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="minCellWidthTwoPanelLandscape" format="float" />
<!-- These border spaces are only used if GridDisplayOption#isScalable is true -->
<!-- space to be used horizontally and vertically -->
- <attr name="borderSpaceDps" format="float" />
- <!-- space to the right of the cell, defaults to borderSpaceDps if not specified -->
- <attr name="borderSpaceHorizontalDps" format="float" />
- <!-- space below the cell, defaults to borderSpaceDps if not specified -->
- <attr name="borderSpaceVerticalDps" format="float" />
+ <attr name="borderSpace" format="float" />
+ <!-- space to the right of the cell, defaults to borderSpace if not specified -->
+ <attr name="borderSpaceHorizontal" format="float" />
+ <!-- space below the cell, defaults to borderSpace if not specified -->
+ <attr name="borderSpaceVertical" format="float" />
<!-- space to be used horizontally and vertically in two panels,
- defaults to borderSpaceDps if not specified -->
- <attr name="twoPanelPortraitBorderSpaceDps" format="float" />
+ defaults to borderSpace if not specified -->
+ <attr name="borderSpaceTwoPanelPortrait" format="float" />
<!-- space to the right of the cell in two panels, defaults to
- twoPanelPortraitBorderSpaceDps if not specified -->
- <attr name="twoPanelPortraitBorderSpaceHorizontalDps" format="float" />
- <!-- space below the cell in two panels, defaults to twoPanelPortraitBorderSpaceDps
+ borderSpaceTwoPanelPortrait if not specified -->
+ <attr name="borderSpaceTwoPanelPortraitHorizontal" format="float" />
+ <!-- space below the cell in two panels, defaults to borderSpaceTwoPanelPortrait
if not specified -->
- <attr name="twoPanelPortraitBorderSpaceVerticalDps" format="float" />
+ <attr name="borderSpaceTwoPanelPortraitVertical" format="float" />
<!-- space to be used horizontally and vertically in two panels,
- defaults to borderSpaceDps if not specified -->
- <attr name="twoPanelLandscapeBorderSpaceDps" format="float" />
+ defaults to borderSpace if not specified -->
+ <attr name="borderSpaceTwoPanelLandscape" format="float" />
<!-- space to the right of the cell in two panels, defaults to
- twoPanelLandscapeBorderSpaceDps if not specified -->
- <attr name="twoPanelLandscapeBorderSpaceHorizontalDps" format="float" />
- <!-- space below the cell in two panels, defaults to twoPanelLandscapeBorderSpaceDps
+ borderSpaceTwoPanelLandscape if not specified -->
+ <attr name="borderSpaceTwoPanelLandscapeHorizontal" format="float" />
+ <!-- space below the cell in two panels, defaults to borderSpaceTwoPanelLandscape
if not specified -->
- <attr name="twoPanelLandscapeBorderSpaceVerticalDps" format="float" />
+ <attr name="borderSpaceTwoPanelLandscapeVertical" format="float" />
- <!-- allAppsCellSpacingDps defaults to borderSpaceDps, if not specified -->
- <attr name="allAppsCellSpacingDps" format="float" />
+ <!-- defaults to borderSpace, if not specified -->
+ <attr name="allAppsBorderSpace" format="float" />
+ <!-- defaults to allAppsBorderSpace, if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsBorderSpace, if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelLandscape" format="float" />
<!-- The following values are only enabled if grid is supported. -->
- <!-- allAppsIconSize defaults to iconSize, if not specified -->
+ <!-- defaults to iconImageSize, if not specified -->
<attr name="allAppsIconSize" format="float" />
- <!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
+ <!-- defaults to allAppsIconSize, if not specified -->
+ <attr name="allAppsIconSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsIconSize, if not specified -->
+ <attr name="allAppsIconSizeTwoPanelLandscape" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
<attr name="allAppsIconTextSize" format="float" />
+ <!-- defaults to allAppsIconTextSize, if not specified -->
+ <attr name="allAppsIconTextSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsIconTextSize, if not specified -->
+ <attr name="allAppsIconTextSizeTwoPanelLandscape" format="float" />
+
+ <!-- defaults to borderSpaceDps, if not specified -->
+ <attr name="hotseatBorderSpace" format="float" />
+ <!-- defaults to hotseatBorderSpace, if not specified -->
+ <attr name="hotseatBorderSpaceTwoPanelLandscape" format="float" />
+ <!-- defaults to hotseatBorderSpace, if not specified -->
+ <attr name="hotseatBorderSpaceTwoPanelPortrait" format="float" />
<attr name="iconImageSize" format="float" />
- <!-- landscapeIconSize defaults to iconImageSize, if not specified -->
- <attr name="landscapeIconSize" format="float" />
- <!-- twoPanelPortraitIconSize defaults to iconImageSize, if not specified -->
- <attr name="twoPanelPortraitIconSize" format="float" />
- <!-- twoPanelLandscapeIconSize defaults to iconImageSize, if not specified -->
- <attr name="twoPanelLandscapeIconSize" format="float" />
+ <!-- defaults to iconImageSize, if not specified -->
+ <attr name="iconSizeLandscape" format="float" />
+ <!-- defaults to iconSize, if not specified -->
+ <attr name="iconSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to iconSize, if not specified -->
+ <attr name="iconSizeTwoPanelLandscape" format="float" />
<attr name="iconTextSize" format="float" />
- <!-- landscapeIconTextSize defaults to iconTextSize, if not specified -->
- <attr name="landscapeIconTextSize" format="float" />
- <!-- twoPanelPortraitIconTextSize defaults to iconTextSize, if not specified -->
- <attr name="twoPanelPortraitIconTextSize" format="float" />
- <!-- twoPanelLandscapeIconTextSize defaults to iconTextSize, if not specified -->
- <attr name="twoPanelLandscapeIconTextSize" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
+ <attr name="iconTextSizeLandscape" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
+ <attr name="iconTextSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
+ <attr name="iconTextSizeTwoPanelLandscape" format="float" />
<!-- If set, this display option is used to determine the default grid -->
<attr name="canBeDefault" format="boolean" />
<!-- 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"/>
+ <!-- defaults to horizontalMargin if not specified -->
+ <attr name="horizontalMarginTwoPanelLandscape" format="float"/>
+ <!-- defaults to horizontalMargin if not specified -->
+ <attr name="horizontalMarginTwoPanelPortrait" format="float"/>
</declare-styleable>
<declare-styleable name="CellLayout">
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 08698e7..dd201e5 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -140,6 +140,7 @@
launcher:name="6_by_5"
launcher:numRows="5"
launcher:numColumns="6"
+ launcher:numSearchContainerColumns="3"
launcher:numFolderRows="3"
launcher:numFolderColumns="3"
launcher:numHotseatIcons="6"
@@ -152,14 +153,14 @@
launcher:name="Tablet"
launcher:minWidthDps="900"
launcher:minHeightDps="820"
- launcher:minCellHeightDps="104"
- launcher:minCellWidthDps="80"
+ launcher:minCellHeight="104"
+ launcher:minCellWidth="80"
launcher:iconImageSize="60"
launcher:iconTextSize="14"
- launcher:borderSpaceDps="16"
+ launcher:borderSpace="16"
launcher:allAppsIconSize="60"
launcher:allAppsIconTextSize="14"
- launcher:allAppsCellSpacingDps="16"
+ launcher:allAppsBorderSpace="16"
launcher:canBeDefault="true" />
</grid-option>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 624afe1..ab8e5e7 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -161,12 +161,13 @@
public final int hotseatBarSidePaddingStartPx;
public final int hotseatBarSidePaddingEndPx;
public final int hotseatQsbHeight;
+ public final int hotseatBorderSpace;
public final float qsbBottomMarginOriginalPx;
public int qsbBottomMarginPx;
// All apps
- public Point allAppsCellSpacePx;
+ public Point allAppsBorderSpacePx;
public int allAppsOpenVerticalTranslate;
public int allAppsCellHeightPx;
public int allAppsCellWidthPx;
@@ -290,9 +291,9 @@
folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv);
- allAppsCellSpacePx = new Point(
- pxFromDp(inv.borderSpaces[InvariantDeviceProfile.INDEX_ALL_APPS].x, mMetrics, 1f),
- pxFromDp(inv.borderSpaces[InvariantDeviceProfile.INDEX_ALL_APPS].y, mMetrics, 1f));
+ allAppsBorderSpacePx = new Point(
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].x, mMetrics),
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].y, mMetrics));
cellLayoutBorderSpaceOriginalPx = new Point(cellLayoutBorderSpacePx);
folderCellLayoutBorderSpaceOriginalPx = pxFromDp(inv.folderBorderSpace, mMetrics, 1f);
folderCellLayoutBorderSpacePx = new Point(folderCellLayoutBorderSpaceOriginalPx,
@@ -349,8 +350,9 @@
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
+ hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
updateHotseatIconSize(
- pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, 1f));
+ pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics));
qsbBottomMarginOriginalPx = isScalableGrid
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
@@ -596,7 +598,7 @@
private void updateAllAppsWidth() {
if (isTwoPanels) {
int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
- + (allAppsCellSpacePx.x * (numShownAllAppsColumns + 1));
+ + (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1));
allAppsLeftRightPadding = Math.max(1, (availableWidthPx - usedWidth) / 2);
} else {
allAppsLeftRightPadding =
@@ -695,9 +697,9 @@
// All apps
if (numShownAllAppsColumns != inv.numColumns) {
allAppsIconSizePx =
- pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_ALL_APPS], mMetrics);
+ pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics);
allAppsIconTextSizePx =
- pxFromSp(inv.iconTextSize[InvariantDeviceProfile.INDEX_ALL_APPS], mMetrics);
+ pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics);
allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
autoResizeAllAppsCells();
} else {
@@ -706,7 +708,7 @@
allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
allAppsCellHeightPx = getCellSize().y;
}
- allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx;
+ allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
updateAllAppsWidth();
if (isVerticalLayout) {
@@ -895,14 +897,10 @@
int hotseatTopDiff = hotseatHeight - taskbarOffset;
int endOffset = ApiWrapper.getHotseatEndOffset(context);
- int requiredWidth = iconSizePx * numShownHotseatIcons;
+ int requiredWidth = iconSizePx * numShownHotseatIcons
+ + hotseatBorderSpace * (numShownHotseatIcons - 1);
- Resources res = context.getResources();
- float taskbarIconSize = res.getDimension(R.dimen.taskbar_icon_size);
- float taskbarIconSpacing = 2 * res.getDimension(R.dimen.taskbar_icon_spacing);
- int maxSize = (int) (requiredWidth
- * (taskbarIconSize + taskbarIconSpacing) / taskbarIconSize);
- int hotseatSize = Math.min(maxSize, availableWidthPx - endOffset);
+ int hotseatSize = Math.min(requiredWidth, availableWidthPx - endOffset);
int sideSpacing = (availableWidthPx - hotseatSize) / 2;
mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset);
@@ -1063,8 +1061,10 @@
writer.println(prefix + "\tisScalableGrid:" + isScalableGrid);
- writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
writer.println(prefix + "\tinv.numRows: " + inv.numRows);
+ writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
+ writer.println(prefix + "\tinv.numSearchContainerColumns: "
+ + inv.numSearchContainerColumns);
writer.println(prefix + "\tminCellSize: " + inv.minCellSize[mTypeIndex] + "dp");
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index ff7a90c..94325d0 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -94,18 +94,18 @@
// Used for arrays to specify different sizes (e.g. border spaces, width/height) in different
// constraints
- static final int COUNT_SIZES = 5;
+ static final int COUNT_SIZES = 4;
static final int INDEX_DEFAULT = 0;
static final int INDEX_LANDSCAPE = 1;
static final int INDEX_TWO_PANEL_PORTRAIT = 2;
static final int INDEX_TWO_PANEL_LANDSCAPE = 3;
- static final int INDEX_ALL_APPS = 4;
/**
* Number of icons per row and column in the workspace.
*/
public int numRows;
public int numColumns;
+ public int numSearchContainerColumns;
/**
* Number of icons per row and column in the folder.
@@ -122,9 +122,14 @@
public PointF[] borderSpaces;
public float folderBorderSpace;
+ public float[] hotseatBorderSpaces;
public float[] horizontalMargin;
+ public float[] allAppsIconSize;
+ public float[] allAppsIconTextSize;
+ public PointF[] allAppsBorderSpaces;
+
private SparseArray<TypedValue> mExtraAttrs;
/**
@@ -300,6 +305,7 @@
GridOption closestProfile = displayOption.grid;
numRows = closestProfile.numRows;
numColumns = closestProfile.numColumns;
+ numSearchContainerColumns = closestProfile.numSearchContainerColumns;
dbFile = closestProfile.dbFile;
defaultLayoutId = closestProfile.defaultLayoutId;
demoModeLayoutId = closestProfile.demoModeLayoutId;
@@ -331,14 +337,18 @@
numShownHotseatIcons = closestProfile.numHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
+ hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
numAllAppsColumns = closestProfile.numAllAppsColumns;
numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns;
+ allAppsBorderSpaces = displayOption.allAppsBorderSpaces;
+ allAppsIconSize = displayOption.allAppsIconSizes;
+ allAppsIconTextSize = displayOption.allAppsIconTextSizes;
if (!Utilities.isGridOptionsEnabled(context)) {
- iconSize[INDEX_ALL_APPS] = iconSize[INDEX_DEFAULT];
- iconTextSize[INDEX_ALL_APPS] = iconTextSize[INDEX_DEFAULT];
+ allAppsIconSize = iconSize;
+ allAppsIconTextSize = iconTextSize;
}
if (devicePaddingId != 0) {
@@ -393,8 +403,8 @@
private Object[] toModelState() {
return new Object[]{
- numColumns, numRows, numDatabaseHotseatIcons, iconBitmapSize, fillResIconDpi,
- numDatabaseAllAppsColumns, dbFile};
+ numColumns, numRows, numSearchContainerColumns, numDatabaseHotseatIcons,
+ iconBitmapSize, fillResIconDpi, numDatabaseAllAppsColumns, dbFile};
}
private void onConfigChanged(Context context) {
@@ -671,6 +681,7 @@
public final String name;
public final int numRows;
public final int numColumns;
+ public final int numSearchContainerColumns;
public final boolean isEnabled;
private final int numFolderRows;
@@ -697,6 +708,8 @@
name = a.getString(R.styleable.GridDisplayOption_name);
numRows = a.getInt(R.styleable.GridDisplayOption_numRows, 0);
numColumns = a.getInt(R.styleable.GridDisplayOption_numColumns, 0);
+ numSearchContainerColumns = a.getInt(
+ R.styleable.GridDisplayOption_numSearchContainerColumns, numColumns);
dbFile = a.getString(R.styleable.GridDisplayOption_dbFile);
defaultLayoutId = a.getResourceId(deviceType == TYPE_MULTI_DISPLAY && a.hasValue(
@@ -756,10 +769,15 @@
private float folderBorderSpace;
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
private final float[] horizontalMargin = new float[COUNT_SIZES];
+ private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
private final float[] iconSizes = new float[COUNT_SIZES];
private final float[] textSizes = new float[COUNT_SIZES];
+ private final float[] allAppsIconSizes = new float[COUNT_SIZES];
+ private final float[] allAppsIconTextSizes = new float[COUNT_SIZES];
+ private final PointF[] allAppsBorderSpaces = new PointF[COUNT_SIZES];
+
DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
this.grid = grid;
@@ -773,97 +791,129 @@
float x;
float y;
- x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
- y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidth, 0);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeight, 0);
minCellSize[INDEX_DEFAULT] = new PointF(x, y);
minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
- minCellSize[INDEX_ALL_APPS] = new PointF(x, y);
- x = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellWidthDps,
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelPortrait,
minCellSize[INDEX_DEFAULT].x);
- y = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellHeightDps,
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightTwoPanelPortrait,
minCellSize[INDEX_DEFAULT].y);
minCellSize[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
- x = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellWidthDps,
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelLandscape,
minCellSize[INDEX_DEFAULT].x);
- y = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellHeightDps,
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightTwoPanelLandscape,
minCellSize[INDEX_DEFAULT].y);
minCellSize[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
- float borderSpace = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceDps, 0);
- float twoPanelPortraitBorderSpaceDps = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceDps, borderSpace);
- float twoPanelLandscapeBorderSpaceDps = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceDps, borderSpace);
+ float borderSpace = a.getFloat(R.styleable.ProfileDisplayOption_borderSpace, 0);
+ float borderSpaceTwoPanelPortrait = a.getFloat(
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelPortrait, borderSpace);
+ float borderSpaceTwoPanelLandscape = a.getFloat(
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelLandscape, borderSpace);
- x = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceHorizontalDps, borderSpace);
- y = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceVerticalDps, borderSpace);
+ x = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceHorizontal, borderSpace);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceVertical, borderSpace);
borderSpaces[INDEX_DEFAULT] = new PointF(x, y);
borderSpaces[INDEX_LANDSCAPE] = new PointF(x, y);
x = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceHorizontalDps,
- twoPanelPortraitBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelPortraitHorizontal,
+ borderSpaceTwoPanelPortrait);
y = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceVerticalDps,
- twoPanelPortraitBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelPortraitVertical,
+ borderSpaceTwoPanelPortrait);
borderSpaces[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
x = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceHorizontalDps,
- twoPanelLandscapeBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelLandscapeHorizontal,
+ borderSpaceTwoPanelLandscape);
y = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceVerticalDps,
- twoPanelLandscapeBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelLandscapeVertical,
+ borderSpaceTwoPanelLandscape);
borderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
- x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellSpacingDps,
- borderSpace);
- borderSpaces[INDEX_ALL_APPS] = new PointF(x, y);
folderBorderSpace = borderSpace;
+ x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpace,
+ borderSpace);
+ allAppsBorderSpaces[INDEX_DEFAULT] = new PointF(x, y);
+ allAppsBorderSpaces[INDEX_LANDSCAPE] = new PointF(x, y);
+ x = y = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelPortrait,
+ allAppsBorderSpaces[INDEX_DEFAULT].x);
+ allAppsBorderSpaces[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
+ x = y = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelLandscape,
+ allAppsBorderSpaces[INDEX_DEFAULT].x);
+ allAppsBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
+
iconSizes[INDEX_DEFAULT] =
a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0);
iconSizes[INDEX_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
- iconSizes[INDEX_DEFAULT]);
- iconSizes[INDEX_ALL_APPS] =
- a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconSizeLandscape,
iconSizes[INDEX_DEFAULT]);
iconSizes[INDEX_TWO_PANEL_PORTRAIT] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitIconSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconSizeTwoPanelPortrait,
iconSizes[INDEX_DEFAULT]);
iconSizes[INDEX_TWO_PANEL_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconSizeTwoPanelLandscape,
iconSizes[INDEX_DEFAULT]);
+ allAppsIconSizes[INDEX_DEFAULT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconSize, iconSizes[INDEX_DEFAULT]);
+ allAppsIconSizes[INDEX_LANDSCAPE] = allAppsIconSizes[INDEX_DEFAULT];
+ allAppsIconSizes[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconSizeTwoPanelPortrait,
+ allAppsIconSizes[INDEX_DEFAULT]);
+ allAppsIconSizes[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconSizeTwoPanelLandscape,
+ allAppsIconSizes[INDEX_DEFAULT]);
+
textSizes[INDEX_DEFAULT] =
a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
textSizes[INDEX_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconTextSize,
- textSizes[INDEX_DEFAULT]);
- textSizes[INDEX_ALL_APPS] =
- a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSizeLandscape,
textSizes[INDEX_DEFAULT]);
textSizes[INDEX_TWO_PANEL_PORTRAIT] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitIconTextSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSizeTwoPanelPortrait,
textSizes[INDEX_DEFAULT]);
textSizes[INDEX_TWO_PANEL_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconTextSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSizeTwoPanelLandscape,
textSizes[INDEX_DEFAULT]);
+ allAppsIconTextSizes[INDEX_DEFAULT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconTextSize, textSizes[INDEX_DEFAULT]);
+ allAppsIconTextSizes[INDEX_LANDSCAPE] = allAppsIconTextSizes[INDEX_DEFAULT];
+ allAppsIconTextSizes[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconTextSizeTwoPanelPortrait,
+ allAppsIconTextSizes[INDEX_DEFAULT]);
+ allAppsIconTextSizes[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconTextSizeTwoPanelLandscape,
+ allAppsIconTextSizes[INDEX_DEFAULT]);
+
horizontalMargin[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMargin, 0);
horizontalMargin[INDEX_LANDSCAPE] = horizontalMargin[INDEX_DEFAULT];
- horizontalMargin[INDEX_ALL_APPS] = horizontalMargin[INDEX_DEFAULT];
horizontalMargin[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeHorizontalMargin,
+ R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelLandscape,
horizontalMargin[INDEX_DEFAULT]);
horizontalMargin[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitHorizontalMargin,
+ R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelPortrait,
horizontalMargin[INDEX_DEFAULT]);
+ hotseatBorderSpaces[INDEX_DEFAULT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpace, borderSpace);
+ hotseatBorderSpaces[INDEX_LANDSCAPE] = hotseatBorderSpaces[INDEX_DEFAULT];
+ hotseatBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelLandscape,
+ hotseatBorderSpaces[INDEX_DEFAULT]);
+ hotseatBorderSpaces[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelPortrait,
+ hotseatBorderSpaces[INDEX_DEFAULT]);
+
a.recycle();
}
@@ -881,6 +931,9 @@
textSizes[i] = 0;
borderSpaces[i] = new PointF();
minCellSize[i] = new PointF();
+ allAppsIconSizes[i] = 0;
+ allAppsIconTextSizes[i] = 0;
+ allAppsBorderSpaces[i] = new PointF();
}
}
@@ -893,6 +946,11 @@
minCellSize[i].x *= w;
minCellSize[i].y *= w;
horizontalMargin[i] *= w;
+ hotseatBorderSpaces[i] *= w;
+ allAppsIconSizes[i] *= w;
+ allAppsIconTextSizes[i] *= w;
+ allAppsBorderSpaces[i].x *= w;
+ allAppsBorderSpaces[i].y *= w;
}
folderBorderSpace *= w;
@@ -909,6 +967,11 @@
minCellSize[i].x += p.minCellSize[i].x;
minCellSize[i].y += p.minCellSize[i].y;
horizontalMargin[i] += p.horizontalMargin[i];
+ hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
+ allAppsIconSizes[i] += p.allAppsIconSizes[i];
+ allAppsIconTextSizes[i] += p.allAppsIconTextSizes[i];
+ allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x;
+ allAppsBorderSpaces[i].y += p.allAppsBorderSpaces[i].y;
}
folderBorderSpace += p.folderBorderSpace;
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 10023b4..9991042 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -98,7 +98,7 @@
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
if (FeatureFlags.IS_STUDIO_BUILD) {
- modelChangeReceiver.register(mContext, ACTION_FORCE_ROLOAD);
+ modelChangeReceiver.register(mContext, Context.RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
}
mOnTerminateCallback.add(() -> mContext.unregisterReceiver(modelChangeReceiver));
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 281dfea..65006ff 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -585,8 +585,8 @@
int cellVSpan = FeatureFlags.EXPANDED_SMARTSPACE.get()
? EXPANDED_SMARTSPACE_HEIGHT : DEFAULT_SMARTSPACE_HEIGHT;
- CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, firstPage.getCountX(),
- cellVSpan);
+ int cellHSpan = mLauncher.getDeviceProfile().inv.numSearchContainerColumns;
+ CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, cellHSpan, cellVSpan);
lp.canReorder = false;
if (!firstPage.addViewToCellLayout(mQsb, 0, R.id.search_container_workspace, lp, true)) {
Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout");
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index abf002f..f4d64df 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -456,10 +456,10 @@
}
IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems,
mDp.numShownHotseatIcons);
- FixedContainerItems hotseatpredictions =
+ FixedContainerItems hotseatPredictions =
dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION);
- List<ItemInfo> predictions = hotseatpredictions == null
- ? Collections.emptyList() : hotseatpredictions.items;
+ List<ItemInfo> predictions = hotseatPredictions == null
+ ? Collections.emptyList() : hotseatPredictions.items;
int count = Math.min(ranks.size(), predictions.size());
for (int i = 0; i < count; i++) {
int rank = ranks.get(i);
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 8b7bebc..a7cfdde 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -372,6 +372,9 @@
@UiEvent(doc = "Notification dismissed by swiping right.")
LAUNCHER_NOTIFICATION_DISMISSED(652),
+ @UiEvent(doc = "Current grid size is changed to 6.")
+ LAUNCHER_GRID_SIZE_6(930),
+
@UiEvent(doc = "Current grid size is changed to 5.")
LAUNCHER_GRID_SIZE_5(662),
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index fa11d4e..08c3149 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_3;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_4;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_5;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_6;
import android.content.Context;
import android.content.SharedPreferences;
@@ -84,6 +85,8 @@
public LauncherEvent getWorkspaceSizeEvent() {
if (!TextUtils.isEmpty(mGridSizeString)) {
switch (mGridSizeString.charAt(0)) {
+ case '6':
+ return LAUNCHER_GRID_SIZE_6;
case '5':
return LAUNCHER_GRID_SIZE_5;
case '4':
diff --git a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
index 465a0e8..4dfa5cc 100644
--- a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
+++ b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
@@ -39,10 +39,17 @@
* Helper method to register multiple actions
*/
public void register(Context context, String... actions) {
+ register(context, 0, actions);
+ }
+
+ /**
+ * Helper method to register multiple actions with one or more {@code flags}.
+ */
+ public void register(Context context, int flags, String... actions) {
IntentFilter filter = new IntentFilter();
for (String action : actions) {
filter.addAction(action);
}
- context.registerReceiver(this, filter);
+ context.registerReceiver(this, filter, flags);
}
}
diff --git a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
index b048cd4..122a130 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -47,20 +48,12 @@
@RunWith(AndroidJUnit4.class)
public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest {
- Workspace mWorkspace;
-
@Before
public void setUp() throws Exception {
super.setUp();
TaplTestsLauncher3.initialize(this);
- mWorkspace = mLauncher.getWorkspace();
- }
- @Test
- public void testDragIconToRightPanel() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ assumeTrue(mLauncher.isTwoPanels());
// Pre verifying the screens
executeOnLauncher(launcher -> {
@@ -68,8 +61,15 @@
assertItemsOnPage(launcher, 0, "Play Store", "Maps");
assertPageEmpty(launcher, 1);
});
+ }
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Chrome"), 1);
+ @Test
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
+ public void testDragIconToRightPanel() {
+ Workspace workspace = mLauncher.getWorkspace();
+
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1);
@@ -79,19 +79,67 @@
}
@Test
- public void testDragIconToPage2() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
+ public void testSinglePageDragIconWhenMultiplePageScrollingIsPossible() {
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 2);
+
+ workspace.flingBackward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3);
+
executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
+ assertPagesExist(launcher, 0, 1, 2, 3);
+ assertItemsOnPage(launcher, 0, "Play Store");
assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Chrome");
+ assertItemsOnPage(launcher, 3, "Maps");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 2, 3, 4, 5);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Chrome");
+ assertPageEmpty(launcher, 3);
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
+ });
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 2, 3);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Chrome");
+ assertItemsOnPage(launcher, 3, "Maps");
+ });
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1);
+
+ workspace.flingForward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), -2);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1);
+ assertItemsOnPage(launcher, 0, "Chrome", "Play Store");
+ assertItemsOnPage(launcher, 1, "Maps");
+ });
+ }
+
+ @Test
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
+ public void testDragIconToPage2() {
+ Workspace workspace = mLauncher.getWorkspace();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -103,19 +151,12 @@
}
@Test
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
public void testDragIconToPage3() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
- executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertPageEmpty(launcher, 1);
- });
-
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Phone"), 3);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Phone"), 3);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -126,22 +167,61 @@
});
}
-
@Test
- public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
+ public void testMultiplePageDragIcon() {
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
+ workspace.dragIcon(workspace.getHotseatAppIcon("Messages"), 2);
+
+ workspace.flingBackward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 5);
+
executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
+ assertPagesExist(launcher, 0, 1, 2, 3, 4, 5);
+ assertItemsOnPage(launcher, 0, "Play Store");
assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Messages");
+ assertPageEmpty(launcher, 3);
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 3);
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Chrome"), 0);
+ workspace.flingBackward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Messages"), 4);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 4, 5, 6, 7);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertPageEmpty(launcher, 1);
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
+ assertItemsOnPage(launcher, 6, "Messages");
+ assertPageEmpty(launcher, 7);
+ });
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Messages"), -3);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 4, 5);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertItemsOnPage(launcher, 1, "Messages");
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
+ });
+ }
+
+ @Test
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
+ public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() {
+ Workspace workspace = mLauncher.getWorkspace();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 0);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -151,7 +231,7 @@
assertItemsOnPage(launcher, 3, "Maps");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), -1);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -163,8 +243,8 @@
// Move Chrome to the right panel as well, to make sure pages are not deleted whichever
// page is the empty one
- mWorkspace.flingForward();
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Chrome"), 1);
+ workspace.flingForward();
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), 1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -175,22 +255,14 @@
});
}
-
@Test
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
public void testEmptyPagesGetRemovedIfBothPagesAreEmpty() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
- executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertPageEmpty(launcher, 1);
- });
-
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Play Store"), 2);
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Camera"), 1);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Play Store"), 2);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Camera"), 1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -200,9 +272,9 @@
assertItemsOnPage(launcher, 3, "Camera");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Camera"), -1);
- mWorkspace.flingForward();
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Play Store"), -2);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Camera"), -1);
+ workspace.flingForward();
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Play Store"), -2);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1);
@@ -212,20 +284,13 @@
}
@Test
+ // TODO(b/197631877) Enable in portrait.
+ // @PortraitLandscape
public void testMiddleEmptyPagesGetRemoved() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
- executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertPageEmpty(launcher, 1);
- });
-
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2);
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Messages"), 3);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Messages"), 3);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3, 4, 5);
@@ -237,8 +302,8 @@
assertItemsOnPage(launcher, 5, "Messages");
});
- mWorkspace.flingBackward();
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2);
+ workspace.flingBackward();
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 4, 5);
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 65aaa24..657f213 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -84,7 +84,7 @@
@Override
protected void failed(Throwable e, Description description) {
- onError(mDevice, description, e);
+ onError(mLauncher, description, e);
}
static File diagFile(Description description, String prefix, String ext) {
@@ -93,7 +93,9 @@
+ description.getMethodName() + "." + ext);
}
- public static void onError(UiDevice device, Description description, Throwable e) {
+ public static void onError(LauncherInstrumentation launcher, Description description,
+ Throwable e) {
+ final UiDevice device = launcher.getDevice();
Log.d("b/196820244", "onError 1");
if (device == null) return;
Log.d("b/196820244", "onError 2");
@@ -128,6 +130,11 @@
}
dumpCommand("logcat -d -s TestRunner", diagFile(description, "FilteredLogcat", "txt"));
+
+ // Dump bugreport
+ if (launcher.getSystemAnomalyMessage(false, false) != null) {
+ dumpCommand("bugreportz -s", diagFile(description, "Bugreport", "zip"));
+ }
}
private static void dumpStringCommand(String cmd, OutputStream out) throws IOException {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index b42f5c1..bc2afaf 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -426,7 +426,7 @@
}
}
- private String getSystemAnomalyMessage(
+ public String getSystemAnomalyMessage(
boolean ignoreNavmodeChangeStates, boolean ignoreOnlySystemUiViews) {
try {
{
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index c71c11f..16987e9 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED;
+
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
@@ -170,15 +172,22 @@
}
/**
- * Drags an icon to the (currentPage + pageDelta) page if the page already exists.
- * If the target page doesn't exist, the icon will be put onto an existing page that is the
- * closest to the target page.
+ * Drags an icon to the (currentPage + pageDelta) page.
+ * If the target page doesn't exist yet, a new page will be created.
+ * In case the target page can't be created (e.g. existing pages are 0, 1, current: 0,
+ * pageDelta: 3, the latest page that can be created is 2) the icon will be dragged onto the
+ * page that can be created and is closest to the target page.
*
* @param appIcon - icon to drag.
* @param pageDelta - how many pages should the icon be dragged from the current page.
- * It can be a negative value.
+ * It can be a negative value. currentPage + pageDelta should be greater
+ * than or equal to 0.
*/
public void dragIcon(AppIcon appIcon, int pageDelta) {
+ if (mHotseat.getVisibleBounds().height() > mHotseat.getVisibleBounds().width()) {
+ throw new UnsupportedOperationException(
+ "dragIcon does NOT support dragging when the hotseat is on the side.");
+ }
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
final UiObject2 workspace = verifyActiveContainer();
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
@@ -385,9 +394,11 @@
while (targetDest.x > displayX || targetDest.x < 0) {
int edgeX = targetDest.x > 0 ? displayX : 0;
Point screenEdge = new Point(edgeX, targetDest.y);
- launcher.movePointer(dragStart, screenEdge, DEFAULT_DRAG_STEPS, isDecelerating,
- downTime, true, LauncherInstrumentation.GestureScope.INSIDE);
- launcher.waitForIdle(); // Wait for the page change to happen
+ Point finalDragStart = dragStart;
+ executeAndWaitForPageScroll(launcher,
+ () -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
+ isDecelerating, downTime, true,
+ LauncherInstrumentation.GestureScope.INSIDE));
targetDest.x += displayX * (targetDest.x > 0 ? -1 : 1);
dragStart = screenEdge;
}
@@ -400,6 +411,13 @@
}
}
+ private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher,
+ Runnable command) {
+ launcher.executeAndWaitForEvent(command,
+ event -> event.getEventType() == TYPE_VIEW_SCROLLED,
+ () -> "Page scroll didn't happen", "Scrolling page");
+ }
+
/**
* Flings to get to screens on the right. Waits for scrolling and a possible overscroll
* recoil to complete.