Merge "Create privateSpaceAnimation Flag" into main
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index be4426d..0ef4541 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.LauncherAnimUtils.ROTATION_DRAWABLE_PERCENT;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneButtonNavMode;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
@@ -734,7 +735,7 @@
// TODO(b/244231596) we're getting the incorrect kidsMode value in small-screen
boolean isInKidsMode = mContext.isNavBarKidsModeActive();
- if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) {
+ if (ENABLE_TASKBAR_NAVBAR_UNIFICATION) {
NavButtonLayoutter navButtonLayoutter =
NavButtonLayoutFactory.Companion.getUiLayoutter(
dp, mNavButtonsView, mImeSwitcherButton,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 6ee151b..db1ea42 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -30,12 +30,12 @@
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.Utilities.calculateTextHeight;
import static com.android.launcher3.Utilities.isRunningInTestHarness;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
-import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW;
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
import static com.android.launcher3.util.VibratorWrapper.EFFECT_CLICK;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
@@ -354,7 +354,7 @@
sharedState.systemBarAttrsBehavior);
onNavButtonsDarkIntensityChanged(sharedState.navButtonsDarkIntensity);
- if (FLAG_HIDE_NAVBAR_WINDOW) {
+ if (ENABLE_TASKBAR_NAVBAR_UNIFICATION) {
// W/ the flag not set this entire class gets re-created, which resets the value of
// mIsDestroyed. We re-use the class for small-screen, so we explicitly have to mark
// this class as non-destroyed
@@ -454,7 +454,7 @@
*/
private WindowManager.LayoutParams createAllWindowParams() {
final int windowType =
- FLAG_HIDE_NAVBAR_WINDOW ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL;
+ ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL;
WindowManager.LayoutParams windowLayoutParams =
createDefaultWindowLayoutParams(windowType, TaskbarActivityContext.WINDOW_TITLE);
boolean isPhoneNavMode = TaskbarManager.isPhoneButtonNavMode(this);
@@ -719,7 +719,7 @@
mIsDestroyed = true;
setUIController(TaskbarUIController.DEFAULT);
mControllers.onDestroy();
- if (!enableTaskbarNoRecreate() && !FLAG_HIDE_NAVBAR_WINDOW) {
+ if (!enableTaskbarNoRecreate() && !ENABLE_TASKBAR_NAVBAR_UNIFICATION) {
mWindowManager.removeViewImmediate(mDragLayer);
mAddedWindow = false;
}
@@ -860,7 +860,7 @@
public int getDefaultTaskbarWindowHeight() {
Resources resources = getResources();
- if (FLAG_HIDE_NAVBAR_WINDOW && mDeviceProfile.isPhone) {
+ if (ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone) {
return isThreeButtonNav() ?
resources.getDimensionPixelSize(R.dimen.taskbar_size) :
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 1eb8d53..a24cf4b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -18,6 +18,8 @@
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_BACK;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
@@ -126,7 +128,7 @@
}
protected void onDestroy() {
- onDestroy(!TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW);
+ onDestroy(!ENABLE_TASKBAR_NAVBAR_UNIFICATION);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 0b52195..1a34b7a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -41,6 +41,7 @@
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.anim.AlphaUpdateListener
+import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
@@ -253,7 +254,7 @@
visInsetsSizeForTappableElement
),
)
- if ((context.isGestureNav || TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ if ((context.isGestureNav || ENABLE_TASKBAR_NAVBAR_UNIFICATION)
&& provider.type == tappableElement()) {
provider.insetsSizeOverrides = insetsSizeOverrideForTappableElement
} else if (provider.type != systemGestures()) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 9bb7e67..c0b07e7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.BaseActivity.EVENT_DESTROYED;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@@ -41,7 +42,6 @@
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Handler;
-import android.os.SystemProperties;
import android.os.Trace;
import android.provider.Settings;
import android.util.Log;
@@ -71,6 +71,7 @@
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+import com.android.wm.shell.Flags;
import java.io.PrintWriter;
import java.util.StringJoiner;
@@ -98,9 +99,6 @@
| ActivityInfo.CONFIG_SCREEN_LAYOUT
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
- public static final boolean FLAG_HIDE_NAVBAR_WINDOW =
- SystemProperties.getBoolean("persist.wm.debug.hide_navbar_window", false);
-
private static final Uri USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(
Settings.Secure.USER_SETUP_COMPLETE);
@@ -198,7 +196,8 @@
Display display =
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
mContext = service.createWindowContext(display,
- FLAG_HIDE_NAVBAR_WINDOW ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL, null);
+ ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL,
+ null);
if (enableTaskbarNoRecreate()) {
mWindowManager = mContext.getSystemService(WindowManager.class);
mTaskbarRootLayout = new FrameLayout(mContext) {
@@ -250,7 +249,7 @@
destroyExistingTaskbar();
} else {
if (dp != null && isTaskbarPresent(dp)) {
- if (FLAG_HIDE_NAVBAR_WINDOW) {
+ if (ENABLE_TASKBAR_NAVBAR_UNIFICATION) {
// Re-initialize for screen size change? Should this be done
// by looking at screen-size change flag in configDiff in the
// block above?
@@ -295,7 +294,7 @@
debugWhyTaskbarNotDestroyed("destroyExistingTaskbar: " + mTaskbarActivityContext);
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.onDestroy();
- if (!FLAG_HIDE_NAVBAR_WINDOW || enableTaskbarNoRecreate()) {
+ if (!ENABLE_TASKBAR_NAVBAR_UNIFICATION || enableTaskbarNoRecreate()) {
mTaskbarActivityContext = null;
}
}
@@ -427,7 +426,7 @@
boolean isTaskbarEnabled = dp != null && isTaskbarPresent(dp);
debugWhyTaskbarNotDestroyed("recreateTaskbar: isTaskbarEnabled=" + isTaskbarEnabled
+ " [dp != null (i.e. mUserUnlocked)]=" + (dp != null)
- + " FLAG_HIDE_NAVBAR_WINDOW=" + FLAG_HIDE_NAVBAR_WINDOW
+ + " FLAG_HIDE_NAVBAR_WINDOW=" + ENABLE_TASKBAR_NAVBAR_UNIFICATION
+ " dp.isTaskbarPresent=" + (dp == null ? "null" : dp.isTaskbarPresent));
if (!isTaskbarEnabled) {
SystemUiProxy.INSTANCE.get(mContext)
@@ -493,7 +492,7 @@
* and we are using a single window for taskbar and navbar.
*/
public static boolean isPhoneMode(DeviceProfile deviceProfile) {
- return TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW && deviceProfile.isPhone;
+ return ENABLE_TASKBAR_NAVBAR_UNIFICATION && deviceProfile.isPhone;
}
/**
@@ -505,7 +504,7 @@
}
private boolean isTaskbarPresent(DeviceProfile deviceProfile) {
- return FLAG_HIDE_NAVBAR_WINDOW || deviceProfile.isTaskbarPresent;
+ return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent;
}
public void onRotationProposal(int rotation, boolean isValid) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 78d5bd3..8f43a2f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.anim.AnimatedFloat.VALUE;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_PERSISTENT;
@@ -214,7 +215,7 @@
mActivity.addOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
- if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) {
+ if (ENABLE_TASKBAR_NAVBAR_UNIFICATION) {
// This gets modified in NavbarButtonsViewController, but the initial value it reads
// may be incorrect since it's state gets destroyed on taskbar recreate, so reset here
mTaskbarIconAlpha.get(ALPHA_INDEX_SMALL_SCREEN)
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index 12cb8c5..6549ad6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -163,6 +163,7 @@
mBubble = overflow;
mBubbleIcon.setImageBitmap(bitmap);
mAppIcon.setVisibility(GONE); // Overflow doesn't show the app badge
+ setContentDescription(getResources().getString(R.string.bubble_bar_overflow_description));
}
/** Returns the bubble being rendered in this view. */
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
index 481e200..630ef39 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.uioverrides.flags;
+import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;
+
import androidx.annotation.NonNull;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
@@ -35,6 +37,21 @@
this.description = description;
}
+ /**
+ * Returns {@code true} if this flag's value has been modified from its default.
+ * <p>
+ * This helps to identify which flags have been toggled in log dumps and bug reports to
+ * further help triaging and debugging.
+ */
+ boolean currentValueModified() {
+ switch (defaultValue) {
+ case ENABLED: return !get();
+ case TEAMFOOD: return TEAMFOOD_FLAG.get() != get();
+ case DISABLED: return get();
+ default: return true;
+ }
+ }
+
@Override
public String toString() {
return key + ": defaultValue=" + defaultValue + ", mCurrentValue=" + get();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
index 035beb4..915f4ae 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
@@ -29,6 +29,11 @@
}
@Override
+ boolean currentValueModified() {
+ return super.currentValueModified() || mDefaultValueInCode != get();
+ }
+
+ @Override
public String toString() {
return super.toString() + ", mDefaultValueInCode=" + mDefaultValueInCode;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
index 28d4bf8..48d313e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -175,7 +175,7 @@
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
if (flag instanceof DeviceFlag) {
- pw.println(" " + flag);
+ pw.println((flag.currentValueModified() ? " ->" : " ") + flag);
}
}
}
@@ -185,11 +185,11 @@
pw.println(" " + flag);
}
}
- pw.println("DebugFlags:");
+ pw.println(" DebugFlags:");
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
if (!(flag instanceof DeviceFlag)) {
- pw.println(" " + flag);
+ pw.println((flag.currentValueModified() ? " ->" : " ") + flag);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index b06a978..9ee9d85 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -20,6 +20,7 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.widget.Toast.LENGTH_SHORT;
+
import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
import static com.android.app.animation.Interpolators.DECELERATE;
import static com.android.app.animation.Interpolators.OVERSHOOT_1_2;
@@ -351,7 +352,7 @@
return ROTATION_0;
}
return mRecentsView.getPagedViewOrientedState().getRecentsActivityRotation();
- }, inputConsumer, /* callback = */ () -> {
+ }, inputConsumer, /* onTouchDownCallback = */ () -> {
endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
endLauncherTransitionController();
}, new InputProxyHandlerFactory(mActivityInterface, mGestureState));
@@ -1943,7 +1944,7 @@
mCurrentShift.cancelAnimation();
// Cleanup when switching handlers
- mInputConsumerProxy.unregisterCallback();
+ mInputConsumerProxy.unregisterOnTouchDownCallback();
mActivityInitListener.unregister();
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
mActivityRestartListener);
@@ -1955,7 +1956,7 @@
mInputConsumerProxy.destroy();
mTaskAnimationManager.setLiveTileCleanUpHandler(null);
}
- mInputConsumerProxy.unregisterCallback();
+ mInputConsumerProxy.unregisterOnTouchDownCallback();
endRunningWindowAnim(false /* cancel */);
if (mGestureEndCallback != null) {
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 49ec85e..575be5f 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -29,13 +29,15 @@
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_HOME;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.SET_END_TARGET_NEW_TASK;
-import android.annotation.Nullable;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
@@ -303,6 +305,7 @@
/**
* @return the running task for this gesture.
*/
+ @Nullable
public CachedTaskInfo getRunningTask() {
return mRunningTask;
}
@@ -336,7 +339,7 @@
/**
* Updates the running task for the gesture to be the given {@param runningTask}.
*/
- public void updateRunningTask(CachedTaskInfo runningTask) {
+ public void updateRunningTask(@NonNull CachedTaskInfo runningTask) {
mRunningTask = runningTask;
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 5784c37..feaa063 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -276,8 +276,11 @@
@Override
public boolean isInLiveTileMode() {
Launcher launcher = getCreatedActivity();
- return launcher != null && launcher.getStateManager().getState() == OVERVIEW &&
- launcher.isStarted();
+
+ return launcher != null
+ && launcher.getStateManager().getState() == OVERVIEW
+ && launcher.isStarted()
+ && TopTaskTracker.INSTANCE.get(launcher).getCachedTopTask(false).isHomeTask();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 00d8008..92aa9fa 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -1222,7 +1222,7 @@
}
try {
mBackAnimation.setBackToLauncherCallback(callback, runner);
- } catch (RemoteException e) {
+ } catch (RemoteException | SecurityException e) {
Log.e(TAG, "Failed call setBackToLauncherCallback", e);
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 3d8191d..ddddc89 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -197,7 +197,11 @@
remoteTargetHandles = gluer.assignTargets(targets);
}
}
+ final int recentsActivityRotation =
+ recentsView.getPagedViewOrientedState().getRecentsActivityRotation();
for (RemoteTargetHandle remoteTargetGluer : remoteTargetHandles) {
+ remoteTargetGluer.getTaskViewSimulator().getOrientationState().setRecentsRotation(
+ recentsActivityRotation);
remoteTargetGluer.getTransformParams().setSyncTransactionApplier(applier);
}
diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java
index f1af2ed..a2a6dde 100644
--- a/quickstep/src/com/android/quickstep/TopTaskTracker.java
+++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java
@@ -29,6 +29,7 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -178,6 +179,7 @@
/**
* Returns the CachedTaskInfo for the top most task
*/
+ @NonNull
@UiThread
public CachedTaskInfo getCachedTopTask(boolean filterOnlyVisibleRecents) {
if (filterOnlyVisibleRecents) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index b4fe5e4..0ad56fb 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -854,7 +854,11 @@
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
gestureState = new GestureState(mOverviewComponentObserver,
ActiveGestureLog.INSTANCE.getLogId());
- taskInfo = previousGestureState.getRunningTask();
+ TopTaskTracker.CachedTaskInfo previousTaskInfo = previousGestureState.getRunningTask();
+ // previousTaskInfo can be null iff previousGestureState == GestureState.DEFAULT_STATE
+ taskInfo = previousTaskInfo != null
+ ? previousTaskInfo
+ : TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false);
gestureState.updateRunningTask(taskInfo);
gestureState.updateLastStartedTaskIds(previousGestureState.getLastStartedTaskIds());
gestureState.updatePreviouslyAppearedTaskIds(
@@ -869,7 +873,7 @@
// Log initial state for the gesture.
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current running task package name=")
- .append(taskInfo == null ? "no running task" : taskInfo.getPackageName()));
+ .append(taskInfo.getPackageName()));
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current SystemUi state flags=")
.append(mDeviceState.getSystemUiStateString()));
return gestureState;
@@ -1078,21 +1082,22 @@
reasonString.append(SUBSTRING_PREFIX).append("keyguard is not showing occluded");
+ TopTaskTracker.CachedTaskInfo runningTask = gestureState.getRunningTask();
// Use overview input consumer for sharesheets on top of home.
boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
- && gestureState.getRunningTask() != null
- && gestureState.getRunningTask().isRootChooseActivity();
+ && runningTask != null
+ && runningTask.isRootChooseActivity();
// In the case where we are in an excluded, translucent overlay, ignore it and treat the
// running activity as the task behind the overlay.
- TopTaskTracker.CachedTaskInfo otherVisibleTask = gestureState.getRunningTask() == null
+ TopTaskTracker.CachedTaskInfo otherVisibleTask = runningTask == null
? null
- : gestureState.getRunningTask().otherVisibleTaskThisIsExcludedOver();
+ : runningTask.otherVisibleTaskThisIsExcludedOver();
if (otherVisibleTask != null) {
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Changing active task to ")
.append(otherVisibleTask.getPackageName())
.append(" because the previous task running on top of this one (")
- .append(gestureState.getRunningTask().getPackageName())
+ .append(runningTask.getPackageName())
.append(") was excluded from recents"));
gestureState.updateRunningTask(otherVisibleTask);
}
@@ -1112,7 +1117,7 @@
forceOverviewInputConsumer,
reasonString.append(SUBSTRING_PREFIX)
.append("is in live tile mode, trying to use overview input consumer"));
- } else if (gestureState.getRunningTask() == null) {
+ } else if (runningTask == null) {
return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
.append("running task == null"));
} else if (previousGestureAnimatedToLauncher
@@ -1130,7 +1135,7 @@
? "launcher resumed through a shell transition"
: "forceOverviewInputConsumer == true"))
.append(", trying to use overview input consumer"));
- } else if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
+ } else if (mDeviceState.isGestureBlockedTask(runningTask)) {
return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
.append("is gesture-blocked task, trying to use default input consumer"));
} else {
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index d102502..a36f501 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -19,6 +19,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Color;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Bundle;
import android.text.TextUtils;
@@ -26,6 +27,7 @@
import android.view.Display;
import android.view.View;
import android.view.Window;
+import android.view.WindowInsets;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -41,6 +43,7 @@
import com.android.quickstep.interaction.TutorialController.TutorialType;
import com.android.quickstep.util.TISBindHelper;
+import java.util.ArrayList;
import java.util.Arrays;
/** Shows the gesture interactive sandbox in full screen mode. */
@@ -101,8 +104,11 @@
correctUserOrientation();
}
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
+
+ initWindowInsets();
}
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -113,6 +119,42 @@
}
}
+ private void initWindowInsets() {
+ View root = findViewById(android.R.id.content);
+ root.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ updateExclusionRects(root);
+ }
+ });
+
+ // Return CONSUMED if you don't want want the window insets to keep being
+ // passed down to descendant views.
+ root.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+ @Override
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ return WindowInsets.CONSUMED;
+ }
+ });
+ }
+
+ private void updateExclusionRects(View rootView) {
+ Insets gestureInsets = rootView.getRootWindowInsets()
+ .getInsets(WindowInsets.Type.systemGestures());
+ ArrayList<Rect> exclusionRects = new ArrayList<>();
+ // Add rect for left
+ exclusionRects.add(new Rect(0, 0, gestureInsets.left, rootView.getHeight()));
+ // Add rect for right
+ exclusionRects.add(new Rect(
+ rootView.getWidth() - gestureInsets.right,
+ 0,
+ rootView.getWidth(),
+ rootView.getHeight()
+ ));
+ rootView.setSystemGestureExclusionRects(exclusionRects);
+ }
+
/**
* Gesture animations are only in landscape for large screens and portrait for mobile. This
* method enforces the following flows:
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index ee72144..4359294 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -147,24 +147,15 @@
break;
case TASK_APPEARED:
errorDetected |= printErrorIfTrue(
- !encounteredEvents.contains(GestureEvent.SET_END_TARGET_NEW_TASK),
- prefix,
- /* errorMessage= */ "onTasksAppeared called "
- + "before/without setting end target to new task",
- writer);
- errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(GestureEvent.EXPECTING_TASK_APPEARED),
prefix,
/* errorMessage= */ "onTasksAppeared was not expected to be called",
writer);
- break;
- case EXPECTING_TASK_APPEARED:
- errorDetected |= printErrorIfTrue(
- !encounteredEvents.contains(GestureEvent.SET_END_TARGET_NEW_TASK),
- prefix,
- /* errorMessage= */ "expecting onTasksAppeared to be called "
- + "before/without setting end target to new task",
- writer);
+ if (encounteredEvents.contains(GestureEvent.EXPECTING_TASK_APPEARED)) {
+ // Remove both events so that we can properly detect following errors.
+ encounteredEvents.remove(GestureEvent.EXPECTING_TASK_APPEARED);
+ encounteredEvents.remove(GestureEvent.TASK_APPEARED);
+ }
break;
case LAUNCHER_DESTROYED:
errorDetected |= printErrorIfTrue(
@@ -282,6 +273,7 @@
case START_RECENTS_ANIMATION:
lastStartRecentAnimationEventEntryTime = eventEntry.getTime();
break;
+ case EXPECTING_TASK_APPEARED:
case MOTION_DOWN:
case SET_END_TARGET:
case SET_END_TARGET_HOME:
diff --git a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
index 91b53c7..cb44a1a 100644
--- a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
@@ -25,6 +25,8 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
+import androidx.annotation.Nullable;
+
import com.android.quickstep.InputConsumer;
import com.android.quickstep.SimpleOrientationTouchTransformer;
import com.android.systemui.shared.system.InputConsumerController;
@@ -42,7 +44,10 @@
private final Context mContext;
private final Supplier<Integer> mRotationSupplier;
private final InputConsumerController mInputConsumerController;
- private Runnable mCallback;
+
+ /** Called if a new InputConsumer is created via touch down event. */
+ private @Nullable Runnable mOnTouchDownCallback;
+
private Supplier<InputConsumer> mConsumerSupplier;
// The consumer is created lazily on demand.
@@ -54,11 +59,11 @@
public InputConsumerProxy(Context context, Supplier<Integer> rotationSupplier,
InputConsumerController inputConsumerController,
- Runnable callback, Supplier<InputConsumer> consumerSupplier) {
+ Runnable onTouchDownCallback, Supplier<InputConsumer> consumerSupplier) {
mContext = context;
mRotationSupplier = rotationSupplier;
mInputConsumerController = inputConsumerController;
- mCallback = callback;
+ mOnTouchDownCallback = onTouchDownCallback;
mConsumerSupplier = consumerSupplier;
}
@@ -82,7 +87,7 @@
onInputConsumerMotionEvent(event);
}
} else if (ev instanceof KeyEvent) {
- initInputConsumerIfNeeded();
+ initInputConsumerIfNeeded(/* isFromTouchDown= */ false);
mInputConsumer.onKeyEvent((KeyEvent) ev);
return true;
}
@@ -105,7 +110,7 @@
if (action == ACTION_DOWN) {
mTouchInProgress = true;
- initInputConsumerIfNeeded();
+ initInputConsumerIfNeeded(/* isFromTouchDown= */ true);
} else if (action == ACTION_CANCEL || action == ACTION_UP) {
// Finish any pending actions
mTouchInProgress = false;
@@ -123,7 +128,7 @@
}
private void onInputConsumerHoverEvent(MotionEvent ev) {
- initInputConsumerIfNeeded();
+ initInputConsumerIfNeeded(/* isFromTouchDown= */ false);
if (mInputConsumer != null) {
SimpleOrientationTouchTransformer.INSTANCE.get(mContext).transform(ev,
mRotationSupplier.get());
@@ -141,14 +146,15 @@
mInputConsumerController.setInputListener(null);
}
- public void unregisterCallback() {
- mCallback = null;
+ /** Sets mOnToudhCownCallback = null. */
+ public void unregisterOnTouchDownCallback() {
+ mOnTouchDownCallback = null;
}
- private void initInputConsumerIfNeeded() {
+ private void initInputConsumerIfNeeded(boolean isFromTouchDown) {
if (mInputConsumer == null) {
- if (mCallback != null) {
- mCallback.run();
+ if (isFromTouchDown && mOnTouchDownCallback != null) {
+ mOnTouchDownCallback.run();
}
mInputConsumer = mConsumerSupplier.get();
mConsumerSupplier = null;
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index fce38e1..fe6ce46 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -159,8 +159,8 @@
// to other classes like PipTaskOrganizer / RecentsAnimationController to complete
// the cleanup.
mPipContentOverlay = new PipContentOverlay.PipAppIconOverlay(view.getContext(),
- mAppBounds, new IconProvider(context).getIcon(mActivityInfo),
- appIconSizePx);
+ mAppBounds, mDestinationBounds,
+ new IconProvider(context).getIcon(mActivityInfo), appIconSizePx);
final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
mPipContentOverlay.attach(tx, mLeash);
} else {
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index ca680db..ebcef30 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -16,13 +16,10 @@
package com.android.quickstep.util;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import android.util.FloatProperty;
import android.view.RemoteAnimationTarget;
-import com.android.app.animation.Interpolators;
-import com.android.launcher3.Utilities;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
@@ -152,19 +149,7 @@
if (activityType == ACTIVITY_TYPE_HOME) {
mHomeBuilderProxy.onBuildTargetParams(builder, app, this);
} else {
- // Fade out translucent overlay.
- // TODO(b/303351074): use app.isNotInRecents directly once it is fixed.
- boolean isNotInRecents = app.taskInfo != null
- && (app.taskInfo.baseIntent.getFlags()
- & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- if (app.isTranslucent && isNotInRecents) {
- float progress = Utilities.boundToRange(getProgress(), 0, 1);
- builder.setAlpha(1 - Interpolators.DECELERATE_QUINT
- .getInterpolation(progress));
- } else {
- builder.setAlpha(getTargetAlpha());
- }
-
+ builder.setAlpha(getTargetAlpha());
proxy.onBuildTargetParams(builder, app, this);
}
} else {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 94183c4..ab51a70 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -35,6 +35,7 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
@@ -106,6 +107,7 @@
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TaskViewUtils;
+import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.BorderAnimator;
import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.RecentsOrientedState;
@@ -859,6 +861,7 @@
getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
if (ActivityManagerWrapper.getInstance()
.startActivityFromRecents(mTask.key, opts.options)) {
+ ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
RecentsView recentsView = getRecentsView();
if (recentsView.getRunningTaskViewId() != -1) {
recentsView.onTaskLaunchedInLiveTileMode();
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
index 37fcf43..9c7f014 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
@@ -12,6 +12,7 @@
import androidx.test.runner.AndroidJUnit4
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
+import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
import com.android.launcher3.taskbar.TaskbarManager
import com.android.systemui.shared.rotation.RotationButton
import java.lang.IllegalStateException
@@ -59,7 +60,7 @@
@Test
fun getKidsLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = true
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -74,7 +75,7 @@
@Test
fun getSetupLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = true
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -89,7 +90,7 @@
@Test
fun getTaskbarNavLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = true
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -104,7 +105,7 @@
@Test(expected = IllegalStateException::class)
fun noValidLayoutForLargeScreenTaskbarNotPresent() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
getLayoutter(
isKidsMode = false,
@@ -117,7 +118,7 @@
@Test
fun getTaskbarPortraitLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -132,7 +133,7 @@
@Test
fun getTaskbarLandscapeLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
setDeviceProfileLandscape()
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
@@ -148,7 +149,7 @@
@Test
fun getTaskbarSeascapeLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
setDeviceProfileLandscape()
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
@@ -164,7 +165,7 @@
@Test(expected = IllegalStateException::class)
fun noValidLayoutForPhoneGestureNav() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
getLayoutter(
isKidsMode = false,
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 12568ea..281516c 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -163,7 +163,7 @@
public void setUp() {
mLauncher.onTestStart();
AbstractLauncherUiTest.waitForSetupWizardDismissal();
- AbstractLauncherUiTest.verifyKeyguardInvisible();
+ AbstractLauncherUiTest.onTestStart();
}
@After
diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
index f51f286..c4c95bc 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
@@ -16,6 +16,8 @@
package com.android.quickstep;
import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -25,6 +27,7 @@
import com.android.launcher3.tapl.OverviewTaskMenu;
import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.rule.TestStabilityRule;
import org.junit.Before;
import org.junit.Test;
@@ -72,6 +75,7 @@
}
@Test
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/288939273
public void testSplitTaskTapBothIconMenus() {
createAndLaunchASplitPair();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 4075c55..0966350 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -16,6 +16,8 @@
package com.android.quickstep;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
@@ -46,6 +48,7 @@
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import com.android.quickstep.views.RecentsView;
@@ -355,7 +358,7 @@
@PortraitLandscape
@TaskbarModeSwitch(mode = PERSISTENT)
@PlatinumTest(focusArea = "launcher")
- @ScreenRecord
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/309820115
public void testOverviewForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index f046eca..1a960f5 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -268,6 +268,10 @@
<attr name="maxAvailableSize" format="dimension" />
</declare-styleable>
+ <declare-styleable name="ResponsiveSpecGroup">
+ <attr name="maxAspectRatio" format="float" />
+ </declare-styleable>
+
<declare-styleable name="WorkspaceSpec">
<attr name="specType" />
<attr name="maxAvailableSize" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 81c2337..c0a1e0a 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -284,7 +284,8 @@
<dimen name="pre_drag_view_scale">6dp</dimen>
<!-- an icon with shortcuts must be dragged this far before the container is removed. -->
<dimen name="deep_shortcuts_start_drag_threshold">16dp</dimen>
- <dimen name="deep_shortcut_icon_size">32dp</dimen>
+ <!-- Possibly related to b/235886078, icon needs to be scaled up to match expected visual size of 32 dp -->
+ <dimen name="deep_shortcut_icon_size">35dp</dimen>
<dimen name="popup_margin">2dp</dimen>
<dimen name="popup_single_item_radius">100dp</dimen>
<dimen name="popup_smaller_radius">4dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4e865d0..f08f8f0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -456,4 +456,8 @@
<!-- Private space label -->
<string name="private_space_label">Private space</string>
+
+ <!-- Strings for bubble bar -->
+ <!-- content description for the overflow bubble [CHAR_LIMIT=none] -->
+ <string name="bubble_bar_overflow_description">Overflow</string>
</resources>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 73cd8c4..a8266ec 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.Flags.enableOverviewIconMenu;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_DEFAULT;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_LANDSCAPE;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
@@ -24,7 +25,6 @@
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
import static com.android.launcher3.config.FeatureFlags.ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH;
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.icons.GraphicsUtils.getShapePath;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
@@ -54,14 +54,12 @@
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.responsive.AllAppsSpecs;
-import com.android.launcher3.responsive.CalculatedAllAppsSpec;
-import com.android.launcher3.responsive.CalculatedFolderSpec;
import com.android.launcher3.responsive.CalculatedHotseatSpec;
-import com.android.launcher3.responsive.CalculatedWorkspaceSpec;
-import com.android.launcher3.responsive.FolderSpecs;
-import com.android.launcher3.responsive.HotseatSpecs;
-import com.android.launcher3.responsive.WorkspaceSpecs;
+import com.android.launcher3.responsive.CalculatedResponsiveSpec;
+import com.android.launcher3.responsive.HotseatSpecsProvider;
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType;
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType;
+import com.android.launcher3.responsive.ResponsiveSpecsProvider;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.CellContentDimensions;
import com.android.launcher3.util.DisplayController;
@@ -84,7 +82,8 @@
public static final PointF DEFAULT_SCALE = new PointF(1.0f, 1.0f);
public static final ViewScaleProvider DEFAULT_PROVIDER = itemInfo -> DEFAULT_SCALE;
- public static final Consumer<DeviceProfile> DEFAULT_DIMENSION_PROVIDER = dp -> {};
+ public static final Consumer<DeviceProfile> DEFAULT_DIMENSION_PROVIDER = dp -> {
+ };
public final InvariantDeviceProfile inv;
private final Info mInfo;
@@ -119,12 +118,12 @@
// Responsive grid
private final boolean mIsResponsiveGrid;
- private CalculatedWorkspaceSpec mResponsiveWidthSpec;
- private CalculatedWorkspaceSpec mResponsiveHeightSpec;
- private CalculatedAllAppsSpec mAllAppsResponsiveWidthSpec;
- private CalculatedAllAppsSpec mAllAppsResponsiveHeightSpec;
- private CalculatedFolderSpec mResponsiveFolderWidthSpec;
- private CalculatedFolderSpec mResponsiveFolderHeightSpec;
+ private CalculatedResponsiveSpec mResponsiveWidthSpec;
+ private CalculatedResponsiveSpec mResponsiveHeightSpec;
+ private CalculatedResponsiveSpec mAllAppsResponsiveWidthSpec;
+ private CalculatedResponsiveSpec mAllAppsResponsiveHeightSpec;
+ private CalculatedResponsiveSpec mResponsiveFolderWidthSpec;
+ private CalculatedResponsiveSpec mResponsiveFolderHeightSpec;
private CalculatedHotseatSpec mResponsiveHotseatSpec;
/**
@@ -376,7 +375,7 @@
res.getDimensionPixelSize(R.dimen.transient_taskbar_bottom_margin);
int transientTaskbarHeight =
Math.round((transientTaskbarIconSize * ICON_VISIBLE_AREA_FACTOR)
- + (2 * res.getDimensionPixelSize(R.dimen.transient_taskbar_padding)));
+ + (2 * res.getDimensionPixelSize(R.dimen.transient_taskbar_padding)));
mTransientTaskbarClaimedSpace = transientTaskbarHeight + 2 * transientTaskbarBottomMargin;
if (!isTaskbarPresent) {
@@ -519,12 +518,15 @@
int minQsbMargin = res.getDimensionPixelSize(R.dimen.min_qsb_margin);
if (mIsResponsiveGrid) {
- HotseatSpecs hotseatSpecs =
- HotseatSpecs.create(new ResourceHelper(context,
+ float responsiveAspectRatio = (float) widthPx / heightPx;
+ HotseatSpecsProvider hotseatSpecsProvider =
+ HotseatSpecsProvider.create(new ResourceHelper(context,
isTwoPanels ? inv.hotseatSpecsTwoPanelId : inv.hotseatSpecsId));
mResponsiveHotseatSpec =
- isVerticalBarLayout() ? hotseatSpecs.getCalculatedWidthSpec(widthPx)
- : hotseatSpecs.getCalculatedHeightSpec(heightPx);
+ isVerticalBarLayout() ? hotseatSpecsProvider.getCalculatedSpec(
+ responsiveAspectRatio, DimensionType.WIDTH, widthPx)
+ : hotseatSpecsProvider.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.HEIGHT, heightPx);
hotseatQsbSpace = mResponsiveHotseatSpec.getHotseatQsbSpace();
hotseatBarBottomSpace =
isVerticalBarLayout() ? 0 : mResponsiveHotseatSpec.getEdgePadding();
@@ -587,35 +589,47 @@
// Needs to be calculated after hotseatBarSizePx is correct,
// for the available height to be correct
if (mIsResponsiveGrid) {
- WorkspaceSpecs workspaceSpecs = WorkspaceSpecs.create(
- new ResourceHelper(context,
- isTwoPanels ? inv.workspaceSpecsTwoPanelId : inv.workspaceSpecsId));
int availableResponsiveWidth =
availableWidthPx - (isVerticalBarLayout() ? hotseatBarSizePx : 0);
- int numColumns = getPanelCount() * inv.numColumns;
+ int numWorkspaceColumns = getPanelCount() * inv.numColumns;
+ int numAllAppsColumns = getPanelCount() * inv.numAllAppsColumns;
// don't use availableHeightPx because it subtracts mInsets.bottom
int availableResponsiveHeight = heightPx - mInsets.top
- - (isVerticalBarLayout() ? 0 : hotseatBarSizePx);
- mResponsiveWidthSpec = workspaceSpecs.getCalculatedWidthSpec(numColumns,
- availableResponsiveWidth);
- mResponsiveHeightSpec = workspaceSpecs.getCalculatedHeightSpec(inv.numRows,
- availableResponsiveHeight);
+ - (isVerticalBarLayout() ? 0 : hotseatBarSizePx);
+ float responsiveAspectRatio = (float) widthPx / heightPx;
- AllAppsSpecs allAppsSpecs = AllAppsSpecs.create(
+ ResponsiveSpecsProvider workspaceSpecs = ResponsiveSpecsProvider.create(
new ResourceHelper(context,
- isTwoPanels ? inv.allAppsSpecsTwoPanelId : inv.allAppsSpecsId));
- mAllAppsResponsiveWidthSpec = allAppsSpecs.getCalculatedWidthSpec(numColumns,
- mResponsiveWidthSpec.getAvailableSpace(), mResponsiveWidthSpec);
- mAllAppsResponsiveHeightSpec = allAppsSpecs.getCalculatedHeightSpec(inv.numRows,
- mResponsiveHeightSpec.getAvailableSpace(), mResponsiveHeightSpec);
+ isTwoPanels ? inv.workspaceSpecsTwoPanelId : inv.workspaceSpecsId),
+ ResponsiveSpecType.Workspace);
+ mResponsiveWidthSpec = workspaceSpecs.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.WIDTH, numWorkspaceColumns, availableResponsiveWidth);
+ mResponsiveHeightSpec = workspaceSpecs.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.HEIGHT, inv.numRows, availableResponsiveHeight);
- FolderSpecs folderSpecs = FolderSpecs.create(
+ ResponsiveSpecsProvider allAppsSpecs = ResponsiveSpecsProvider.create(
new ResourceHelper(context,
- isTwoPanels ? inv.folderSpecsTwoPanelId : inv.folderSpecsId));
- mResponsiveFolderWidthSpec = folderSpecs.getCalculatedWidthSpec(inv.numFolderColumns,
- mResponsiveWidthSpec.getAvailableSpace(), mResponsiveWidthSpec);
- mResponsiveFolderHeightSpec = folderSpecs.getCalculatedHeightSpec(inv.numFolderRows,
- mResponsiveHeightSpec.getAvailableSpace(), mResponsiveHeightSpec);
+ isTwoPanels ? inv.allAppsSpecsTwoPanelId : inv.allAppsSpecsId),
+ ResponsiveSpecType.AllApps);
+ mAllAppsResponsiveWidthSpec = allAppsSpecs.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.WIDTH, numAllAppsColumns, availableWidthPx,
+ mResponsiveWidthSpec);
+ mAllAppsResponsiveHeightSpec = allAppsSpecs.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.HEIGHT, inv.numRows, heightPx - mInsets.top,
+ mResponsiveHeightSpec);
+
+ ResponsiveSpecsProvider folderSpecs = ResponsiveSpecsProvider.create(
+ new ResourceHelper(context,
+ isTwoPanels ? inv.folderSpecsTwoPanelId : inv.folderSpecsId),
+ ResponsiveSpecType.Folder);
+ mResponsiveFolderWidthSpec = folderSpecs.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.WIDTH, inv.numFolderColumns,
+ mResponsiveWidthSpec.getAvailableSpace(),
+ mResponsiveWidthSpec);
+ mResponsiveFolderHeightSpec = folderSpecs.getCalculatedSpec(responsiveAspectRatio,
+ DimensionType.HEIGHT, inv.numFolderRows,
+ mResponsiveHeightSpec.getAvailableSpace(),
+ mResponsiveHeightSpec);
}
desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
@@ -1004,12 +1018,16 @@
+ cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
- private int getNormalizedIconDrawablePadding() {
+ private int getNormalizedIconDrawablePadding(int iconSizePx, int iconDrawablePadding) {
// TODO(b/235886078): workaround needed because of this bug
// Icons are 10% larger on XML than their visual size,
// so remove that extra space to get labels closer to the correct padding
int iconVisibleSizePx = (int) Math.round(ICON_VISIBLE_AREA_FACTOR * iconSizePx);
- return Math.max(0, mIconDrawablePaddingOriginalPx - ((iconSizePx - iconVisibleSizePx) / 2));
+ return Math.max(0, iconDrawablePadding - ((iconSizePx - iconVisibleSizePx) / 2));
+ }
+
+ private int getNormalizedIconDrawablePadding() {
+ return getNormalizedIconDrawablePadding(iconSizePx, mIconDrawablePaddingOriginalPx);
}
private int getNormalizedFolderChildDrawablePaddingPx(int textHeight) {
@@ -1147,7 +1165,7 @@
// All apps
if (mIsResponsiveGrid) {
- updateAllAppsWithResponsiveMeasures();
+ updateAllAppsWithResponsiveMeasures(res);
} else {
updateAllAppsIconSize(scale, res);
}
@@ -1246,11 +1264,7 @@
}
}
- private void updateAllAppsWithResponsiveMeasures() {
- allAppsIconSizePx = iconSizePx;
- allAppsIconTextSizePx = iconTextSizePx;
- allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
-
+ private void updateAllAppsWithResponsiveMeasures(Resources res) {
allAppsBorderSpacePx = new Point(
mAllAppsResponsiveWidthSpec.getGutterPx(),
mAllAppsResponsiveHeightSpec.getGutterPx()
@@ -1258,8 +1272,53 @@
allAppsCellHeightPx = mAllAppsResponsiveHeightSpec.getCellSizePx()
+ mAllAppsResponsiveHeightSpec.getGutterPx();
allAppsCellWidthPx = mAllAppsResponsiveWidthSpec.getCellSizePx();
- allAppsPadding.left = mAllAppsResponsiveWidthSpec.getStartPaddingPx();
- allAppsPadding.right = mAllAppsResponsiveWidthSpec.getEndPaddingPx();
+
+ // This workaround is needed to align AllApps icons with Workspace icons
+ // since AllApps doesn't have borders between cells
+ int halfBorder = allAppsBorderSpacePx.x / 2;
+ allAppsPadding.left = mAllAppsResponsiveWidthSpec.getStartPaddingPx() - halfBorder;
+ allAppsPadding.right = mAllAppsResponsiveWidthSpec.getEndPaddingPx() - halfBorder;
+
+ // TODO(b/287975993): Remove this after icon size is extracted to responsive grid
+ // Copy icon size from the workspace when spec is matchWorkspace or
+ // use the default all apps icon size
+ if (mAllAppsResponsiveHeightSpec.isCellSizeMatchWorkspace()
+ || mAllAppsResponsiveWidthSpec.isCellSizeMatchWorkspace()) {
+ allAppsIconSizePx = iconSizePx;
+ allAppsIconTextSizePx = iconTextSizePx;
+ allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
+ } else {
+ allAppsIconSizePx = pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics);
+ allAppsIconTextSizePx = pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics);
+ allAppsIconDrawablePaddingPx = res.getDimensionPixelSize(
+ R.dimen.all_apps_icon_drawable_padding);
+ allAppsIconDrawablePaddingPx = getNormalizedIconDrawablePadding(allAppsIconSizePx,
+ allAppsIconDrawablePaddingPx);
+ }
+
+ // Reduce the size of the app icon if it doesn't fit
+ if (allAppsCellWidthPx < allAppsIconSizePx) {
+ // get a smaller icon size
+ allAppsIconSizePx = mIconSizeSteps.getIconSmallerThan(allAppsCellWidthPx);
+ }
+
+ CellContentDimensions cellContentDimensions = new CellContentDimensions(
+ allAppsIconSizePx, allAppsIconDrawablePaddingPx, (int) allAppsIconTextSizePx);
+
+ if (allAppsCellHeightPx < cellContentDimensions.getCellContentHeight()) {
+ if (isVerticalBarLayout()) {
+ if (allAppsCellHeightPx < iconSizePx) {
+ cellContentDimensions.setIconSizePx(
+ mIconSizeSteps.getIconSmallerThan(allAppsCellHeightPx));
+ }
+ } else {
+ cellContentDimensions.resizeToFitCellHeight(allAppsCellHeightPx,
+ mIconSizeSteps);
+ }
+ allAppsIconSizePx = cellContentDimensions.getIconSizePx();
+ allAppsIconDrawablePaddingPx = cellContentDimensions.getIconDrawablePaddingPx();
+ allAppsIconTextSizePx = cellContentDimensions.getIconTextSizePx();
+ }
}
/**
@@ -1280,7 +1339,7 @@
+ (allAppsBorderSpacePx.x * (numShownAllAppsColumns - 1))
+ allAppsPadding.left + allAppsPadding.right;
allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
- } else {
+ } else if (!mIsResponsiveGrid) {
allAppsPadding.left = allAppsPadding.right =
Math.max(0, desiredWorkspaceHorizontalMarginPx + cellLayoutHorizontalPadding
- (allAppsBorderSpacePx.x / 2));
@@ -1338,8 +1397,6 @@
if (mIsResponsiveGrid) {
folderCellWidthPx = mResponsiveFolderWidthSpec.getCellSizePx();
-
- // Height
folderCellHeightPx = mResponsiveFolderHeightSpec.getCellSizePx();
folderContentPaddingTop = mResponsiveFolderHeightSpec.getStartPaddingPx();
folderFooterHeightPx = mResponsiveFolderHeightSpec.getEndPaddingPx();
@@ -1356,24 +1413,15 @@
// Recalculating padding and cell height
folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
- int folderCellContentHeight = folderChildIconSizePx + folderChildDrawablePaddingPx
- + textHeight;
- // Reduce the icon in height when it's taller than the expected cell height
- while (folderChildIconSizePx > mIconSizeSteps.minimumIconSize()
- && folderCellContentHeight > folderCellHeightPx) {
- folderChildDrawablePaddingPx -= folderCellContentHeight - folderCellHeightPx;
- if (folderChildDrawablePaddingPx < 0) {
- // get a smaller icon size
- folderChildIconSizePx = mIconSizeSteps.getNextLowerIconSize(
- folderChildIconSizePx);
- folderChildDrawablePaddingPx =
- getNormalizedFolderChildDrawablePaddingPx(textHeight);
- }
- // calculate new cellContentHeight
- folderCellContentHeight = folderChildIconSizePx + folderChildDrawablePaddingPx
- + textHeight;
- }
+ CellContentDimensions cellContentDimensions = new CellContentDimensions(
+ folderChildIconSizePx,
+ folderChildDrawablePaddingPx,
+ folderChildTextSizePx);
+ cellContentDimensions.resizeToFitCellHeight(folderCellHeightPx, mIconSizeSteps);
+ folderChildIconSizePx = cellContentDimensions.getIconSizePx();
+ folderChildDrawablePaddingPx = cellContentDimensions.getIconDrawablePaddingPx();
+ folderChildTextSizePx = cellContentDimensions.getIconTextSizePx();
} else if (mIsScalableGrid) {
if (inv.folderStyle == INVALID_RESOURCE_HANDLE) {
folderCellWidthPx = roundPxValueFromFloat(getCellSize().x * scale);
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index d822fec..5b4d2b8 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -1101,7 +1101,7 @@
mlp.rightMargin = insets.right;
setLayoutParams(mlp);
- if (grid.isVerticalBarLayout()) {
+ if (grid.isVerticalBarLayout() && !FeatureFlags.enableResponsiveWorkspace()) {
setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
} else {
int topPadding = grid.allAppsPadding.top;
@@ -1111,7 +1111,6 @@
}
setPadding(grid.allAppsLeftRightMargin, topPadding, grid.allAppsLeftRightMargin, 0);
}
-
InsettableFrameLayout.dispatchInsets(this, insets);
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 73861c1..1c52a2f 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getDebugFlag;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getIntFlag;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getReleaseFlag;
+import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification;
import android.view.ViewConfiguration;
@@ -217,12 +218,19 @@
public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798,
"ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar.");
+ public static final boolean ENABLE_TASKBAR_NAVBAR_UNIFICATION =
+ enableTaskbarNavbarUnification();
+
// Aconfig migration complete for ENABLE_TASKBAR_NO_RECREATION.
public static final BooleanFlag ENABLE_TASKBAR_NO_RECREATION = getDebugFlag(299193589,
"ENABLE_TASKBAR_NO_RECREATION", DISABLED,
"Enables taskbar with no recreation from lifecycle changes of TaskbarActivityContext.");
public static boolean enableTaskbarNoRecreate() {
- return ENABLE_TASKBAR_NO_RECREATION.get() || Flags.enableTaskbarNoRecreate();
+ return ENABLE_TASKBAR_NO_RECREATION.get() || Flags.enableTaskbarNoRecreate()
+ // Task bar pinning and task bar nav bar unification are both dependent on
+ // ENABLE_TASKBAR_NO_RECREATION. We want to turn ENABLE_TASKBAR_NO_RECREATION on
+ // when either of the dependent features is turned on.
+ || ENABLE_TASKBAR_PINNING.get() || ENABLE_TASKBAR_NAVBAR_UNIFICATION;
}
// TODO(Block 16): Clean up flags
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 2e5f2e5..b39e968e 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -43,6 +43,7 @@
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -434,7 +435,8 @@
drawable.setLevel(item.getProgressLevel());
p.drawable = drawable;
} else {
- p.drawable = item.newIcon(mContext, FLAG_THEMED);
+ p.drawable = item.newIcon(mContext,
+ Themes.isThemedIconEnabled(mContext) ? FLAG_THEMED : 0);
}
p.drawable.setBounds(0, 0, mIconSize, mIconSize);
p.item = item;
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 685e4f1..e3314d4 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -127,6 +127,7 @@
protected final float mElevation;
+ // Tag for Views that have children that will need to be iterated to add styling.
private final String mIterateChildrenTag;
protected final int[] mColorIds;
@@ -244,7 +245,7 @@
for (int i = 0; i < count; i++) {
View view = viewGroup.getChildAt(i);
if (view.getVisibility() == VISIBLE) {
- if (lastView != null) {
+ if (lastView != null && (isShortcutContainer(lastView))) {
MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
mlp.bottomMargin = mChildContainerMargin;
}
diff --git a/src/com/android/launcher3/responsive/AllAppsSpecs.kt b/src/com/android/launcher3/responsive/AllAppsSpecs.kt
deleted file mode 100644
index 8ed3ffc..0000000
--- a/src/com/android/launcher3/responsive/AllAppsSpecs.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2023 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.responsive
-
-import android.content.res.TypedArray
-import com.android.launcher3.R
-import com.android.launcher3.responsive.ResponsiveSpec.SpecType
-import com.android.launcher3.util.ResourceHelper
-
-class AllAppsSpecs(widthSpecs: List<AllAppsSpec>, heightSpecs: List<AllAppsSpec>) :
- ResponsiveSpecs<AllAppsSpec>(widthSpecs, heightSpecs) {
-
- fun getCalculatedWidthSpec(
- columns: Int,
- availableWidth: Int,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
- ): CalculatedAllAppsSpec {
- check(calculatedWorkspaceSpec.spec.specType == SpecType.WIDTH) {
- "Invalid specType for CalculatedWorkspaceSpec. " +
- "Expected: ${SpecType.WIDTH} - " +
- "Found: ${calculatedWorkspaceSpec.spec.specType}}"
- }
-
- val spec = getWidthSpec(availableWidth)
- return CalculatedAllAppsSpec(availableWidth, columns, spec, calculatedWorkspaceSpec)
- }
-
- fun getCalculatedHeightSpec(
- rows: Int,
- availableHeight: Int,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
- ): CalculatedAllAppsSpec {
- check(calculatedWorkspaceSpec.spec.specType == SpecType.HEIGHT) {
- "Invalid specType for CalculatedWorkspaceSpec. " +
- "Expected: ${SpecType.HEIGHT} - " +
- "Found: ${calculatedWorkspaceSpec.spec.specType}}"
- }
-
- val spec = getHeightSpec(availableHeight)
- return CalculatedAllAppsSpec(availableHeight, rows, spec, calculatedWorkspaceSpec)
- }
-
- companion object {
- private const val XML_ALL_APPS_SPEC = "allAppsSpec"
-
- @JvmStatic
- fun create(resourceHelper: ResourceHelper): AllAppsSpecs {
- val parser = ResponsiveSpecsParser(resourceHelper)
- val specs = parser.parseXML(XML_ALL_APPS_SPEC, ::AllAppsSpec)
- val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH }
- return AllAppsSpecs(widthSpecs, heightSpecs)
- }
- }
-}
-
-data class AllAppsSpec(
- override val maxAvailableSize: Int,
- override val specType: SpecType,
- override val startPadding: SizeSpec,
- override val endPadding: SizeSpec,
- override val gutter: SizeSpec,
- override val cellSize: SizeSpec
-) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) {
-
- init {
- check(isValid()) { "Invalid AllAppsSpec found." }
- }
-
- constructor(
- attrs: TypedArray,
- specs: Map<String, SizeSpec>
- ) : this(
- maxAvailableSize =
- attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
- specType =
- SpecType.values()[
- attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)],
- startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
- endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
- gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
- cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
- )
-}
-
-class CalculatedAllAppsSpec(
- availableSpace: Int,
- cells: Int,
- spec: AllAppsSpec,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
-) : CalculatedResponsiveSpec(availableSpace, cells, spec, calculatedWorkspaceSpec)
diff --git a/src/com/android/launcher3/responsive/FolderSpecs.kt b/src/com/android/launcher3/responsive/FolderSpecs.kt
deleted file mode 100644
index bc2db28..0000000
--- a/src/com/android/launcher3/responsive/FolderSpecs.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2023 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.responsive
-
-import android.content.res.TypedArray
-import com.android.launcher3.R
-import com.android.launcher3.responsive.ResponsiveSpec.SpecType
-import com.android.launcher3.util.ResourceHelper
-
-class FolderSpecs(widthSpecs: List<FolderSpec>, heightSpecs: List<FolderSpec>) :
- ResponsiveSpecs<FolderSpec>(widthSpecs, heightSpecs) {
-
- fun getCalculatedWidthSpec(
- columns: Int,
- availableWidth: Int,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
- ): CalculatedFolderSpec {
- check(calculatedWorkspaceSpec.spec.specType == SpecType.WIDTH) {
- "Invalid specType for CalculatedWorkspaceSpec. " +
- "Expected: ${SpecType.WIDTH} - " +
- "Found: ${calculatedWorkspaceSpec.spec.specType}}"
- }
-
- val spec = getWidthSpec(availableWidth)
- return CalculatedFolderSpec(availableWidth, columns, spec, calculatedWorkspaceSpec)
- }
-
- fun getCalculatedHeightSpec(
- rows: Int,
- availableHeight: Int,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
- ): CalculatedFolderSpec {
- check(calculatedWorkspaceSpec.spec.specType == SpecType.HEIGHT) {
- "Invalid specType for CalculatedWorkspaceSpec. " +
- "Expected: ${SpecType.HEIGHT} - " +
- "Found: ${calculatedWorkspaceSpec.spec.specType}}"
- }
-
- val spec = getHeightSpec(availableHeight)
- return CalculatedFolderSpec(availableHeight, rows, spec, calculatedWorkspaceSpec)
- }
-
- companion object {
-
- private const val XML_FOLDER_SPEC = "folderSpec"
-
- @JvmStatic
- fun create(resourceHelper: ResourceHelper): FolderSpecs {
- val parser = ResponsiveSpecsParser(resourceHelper)
- val specs = parser.parseXML(XML_FOLDER_SPEC, ::FolderSpec)
- val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH }
- return FolderSpecs(widthSpecs, heightSpecs)
- }
- }
-}
-
-data class FolderSpec(
- override val maxAvailableSize: Int,
- override val specType: SpecType,
- override val startPadding: SizeSpec,
- override val endPadding: SizeSpec,
- override val gutter: SizeSpec,
- override val cellSize: SizeSpec
-) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) {
-
- init {
- check(isValid()) { "Invalid FolderSpec found." }
- }
-
- constructor(
- attrs: TypedArray,
- specs: Map<String, SizeSpec>
- ) : this(
- maxAvailableSize =
- attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
- specType =
- SpecType.values()[
- attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)],
- startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
- endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
- gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
- cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
- )
-}
-
-class CalculatedFolderSpec(
- availableSpace: Int,
- cells: Int,
- spec: FolderSpec,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
-) : CalculatedResponsiveSpec(availableSpace, cells, spec, calculatedWorkspaceSpec)
diff --git a/src/com/android/launcher3/responsive/HotseatSpecs.kt b/src/com/android/launcher3/responsive/HotseatSpecsProvider.kt
similarity index 70%
rename from src/com/android/launcher3/responsive/HotseatSpecs.kt
rename to src/com/android/launcher3/responsive/HotseatSpecsProvider.kt
index 37a682f..7f7f2f1 100644
--- a/src/com/android/launcher3/responsive/HotseatSpecs.kt
+++ b/src/com/android/launcher3/responsive/HotseatSpecsProvider.kt
@@ -19,67 +19,65 @@
import android.content.res.TypedArray
import android.util.Log
import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
import com.android.launcher3.util.ResourceHelper
-class HotseatSpecs(widthSpecs: List<HotseatSpec>, heightSpecs: List<HotseatSpec>) {
+class HotseatSpecsProvider(private val groupOfSpecs: List<ResponsiveSpecGroup<HotseatSpec>>) {
+ fun getSpecsByAspectRatio(aspectRatio: Float): ResponsiveSpecGroup<HotseatSpec> {
+ check(aspectRatio > 0f) { "Invalid aspect ratio! The value should be bigger than 0." }
- val widthSpecs: List<HotseatSpec>
- val heightSpecs: List<HotseatSpec>
+ val specsGroup = groupOfSpecs.firstOrNull { aspectRatio <= it.aspectRatio }
+ check(specsGroup != null) { "No available spec with aspectRatio within $aspectRatio." }
- init {
- this.widthSpecs = widthSpecs.sortedBy { it.maxAvailableSize }
- this.heightSpecs = heightSpecs.sortedBy { it.maxAvailableSize }
+ return specsGroup
}
- fun getCalculatedHeightSpec(availableHeight: Int): CalculatedHotseatSpec {
- val spec = heightSpecs.firstOrNull { availableHeight <= it.maxAvailableSize }
- check(spec != null) { "No available height spec found within $availableHeight." }
- return CalculatedHotseatSpec(availableHeight, spec)
- }
-
- fun getCalculatedWidthSpec(availableWidth: Int): CalculatedHotseatSpec {
- val spec = widthSpecs.firstOrNull { availableWidth <= it.maxAvailableSize }
- check(spec != null) { "No available width spec found within $availableWidth." }
- return CalculatedHotseatSpec(availableWidth, spec)
+ fun getCalculatedSpec(
+ aspectRatio: Float,
+ dimensionType: DimensionType,
+ availableSpace: Int
+ ): CalculatedHotseatSpec {
+ val specsGroup = getSpecsByAspectRatio(aspectRatio)
+ val spec = specsGroup.getSpec(dimensionType, availableSpace)
+ return CalculatedHotseatSpec(availableSpace, spec)
}
companion object {
- private const val XML_HOTSEAT_SPEC = "hotseatSpec"
-
@JvmStatic
- fun create(resourceHelper: ResourceHelper): HotseatSpecs {
+ fun create(resourceHelper: ResourceHelper): HotseatSpecsProvider {
val parser = ResponsiveSpecsParser(resourceHelper)
- val specs = parser.parseXML(XML_HOTSEAT_SPEC, ::HotseatSpec)
- val (widthSpecs, heightSpecs) =
- specs.partition { it.specType == ResponsiveSpec.SpecType.WIDTH }
- return HotseatSpecs(widthSpecs, heightSpecs)
+ val specs = parser.parseXML(ResponsiveSpecType.Hotseat, ::HotseatSpec)
+ return HotseatSpecsProvider(specs)
}
}
}
data class HotseatSpec(
- val maxAvailableSize: Int,
- val specType: ResponsiveSpec.SpecType,
+ override val maxAvailableSize: Int,
+ override val dimensionType: DimensionType,
+ override val specType: ResponsiveSpecType,
val hotseatQsbSpace: SizeSpec,
val edgePadding: SizeSpec
-) {
-
+) : IResponsiveSpec {
init {
check(isValid()) { "Invalid HotseatSpec found." }
}
constructor(
+ responsiveSpecType: ResponsiveSpecType,
attrs: TypedArray,
specs: Map<String, SizeSpec>
) : this(
maxAvailableSize =
attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
- specType =
- ResponsiveSpec.SpecType.values()[
+ dimensionType =
+ DimensionType.entries[
attrs.getInt(
R.styleable.ResponsiveSpec_specType,
- ResponsiveSpec.SpecType.HEIGHT.ordinal
+ DimensionType.HEIGHT.ordinal
)],
+ specType = responsiveSpecType,
hotseatQsbSpace = specs.getOrError(SizeSpec.XmlTags.HOTSEAT_QSB_SPACE),
edgePadding = specs.getOrError(SizeSpec.XmlTags.EDGE_PADDING)
)
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecs.kt b/src/com/android/launcher3/responsive/ResponsiveSpec.kt
similarity index 63%
rename from src/com/android/launcher3/responsive/ResponsiveSpecs.kt
rename to src/com/android/launcher3/responsive/ResponsiveSpec.kt
index a43c44a..631a905 100644
--- a/src/com/android/launcher3/responsive/ResponsiveSpecs.kt
+++ b/src/com/android/launcher3/responsive/ResponsiveSpec.kt
@@ -16,75 +16,84 @@
package com.android.launcher3.responsive
+import android.content.res.TypedArray
import android.util.Log
+import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
/**
- * Base class for responsive specs that holds a list of width and height specs.
+ * Interface for responsive grid specs
*
- * @param widthSpecs List of width responsive specifications
- * @param heightSpecs List of height responsive specifications
+ * @property maxAvailableSize indicates the breakpoint to use this specification.
+ * @property dimensionType indicates whether the paddings and gutters will be applied vertically or
+ * horizontally.
+ * @property specType a [ResponsiveSpecType] that indicates the type of the spec.
*/
-abstract class ResponsiveSpecs<T : ResponsiveSpec>(widthSpecs: List<T>, heightSpecs: List<T>) {
- val widthSpecs: List<T>
- val heightSpecs: List<T>
-
- init {
- check(widthSpecs.isNotEmpty() && heightSpecs.isNotEmpty()) {
- "${this::class.simpleName} is incomplete - " +
- "width list size = ${widthSpecs.size}; " +
- "height list size = ${heightSpecs.size}."
- }
-
- this.widthSpecs = widthSpecs.sortedBy { it.maxAvailableSize }
- this.heightSpecs = heightSpecs.sortedBy { it.maxAvailableSize }
- }
-
- /**
- * Get a [ResponsiveSpec] for width within the breakpoint.
- *
- * @param availableWidth The width breakpoint for the spec
- * @return A [ResponsiveSpec] for width.
- */
- fun getWidthSpec(availableWidth: Int): T {
- val spec = widthSpecs.firstOrNull { availableWidth <= it.maxAvailableSize }
- check(spec != null) { "No available width spec found within $availableWidth." }
- return spec
- }
-
- /**
- * Get a [ResponsiveSpec] for height within the breakpoint.
- *
- * @param availableHeight The height breakpoint for the spec
- * @return A [ResponsiveSpec] for height.
- */
- fun getHeightSpec(availableHeight: Int): T {
- val spec = heightSpecs.firstOrNull { availableHeight <= it.maxAvailableSize }
- check(spec != null) { "No available height spec found within $availableHeight." }
- return spec
- }
+interface IResponsiveSpec {
+ val maxAvailableSize: Int
+ val dimensionType: ResponsiveSpec.DimensionType
+ val specType: ResponsiveSpecType
}
/**
- * Base class for a responsive specification that is used to calculate the paddings, gutter and cell
+ * Class for a responsive specification that is used to calculate the paddings, gutter and cell
* size.
*
* @param maxAvailableSize indicates the breakpoint to use this specification.
- * @param specType indicates whether the paddings and gutters will be applied vertically or
+ * @param dimensionType indicates whether the paddings and gutters will be applied vertically or
* horizontally.
+ * @param specType a [ResponsiveSpecType] that indicates the type of the spec.
* @param startPadding padding used at the top or left (right in RTL) in the workspace folder.
* @param endPadding padding used at the bottom or right (left in RTL) in the workspace folder.
- * @param gutter the space between the cells vertically or horizontally depending on the [specType].
- * @param cellSize height or width of the cell depending on the [specType].
+ * @param gutter the space between the cells vertically or horizontally depending on the
+ * [dimensionType].
+ * @param cellSize height or width of the cell depending on the [dimensionType].
*/
-abstract class ResponsiveSpec(
- open val maxAvailableSize: Int,
- open val specType: SpecType,
- open val startPadding: SizeSpec,
- open val endPadding: SizeSpec,
- open val gutter: SizeSpec,
- open val cellSize: SizeSpec
-) {
- open fun isValid(): Boolean {
+data class ResponsiveSpec(
+ override val maxAvailableSize: Int,
+ override val dimensionType: DimensionType,
+ override val specType: ResponsiveSpecType,
+ val startPadding: SizeSpec,
+ val endPadding: SizeSpec,
+ val gutter: SizeSpec,
+ val cellSize: SizeSpec,
+) : IResponsiveSpec {
+ init {
+ check(isValid()) { "Invalid ResponsiveSpec found." }
+ }
+
+ constructor(
+ responsiveSpecType: ResponsiveSpecType,
+ attrs: TypedArray,
+ specs: Map<String, SizeSpec>
+ ) : this(
+ maxAvailableSize =
+ attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
+ dimensionType =
+ DimensionType.entries[
+ attrs.getInt(
+ R.styleable.ResponsiveSpec_specType,
+ DimensionType.HEIGHT.ordinal
+ )],
+ specType = responsiveSpecType,
+ startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
+ endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
+ gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
+ cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
+ )
+
+ fun isValid(): Boolean {
+ if (
+ (specType == ResponsiveSpecType.Workspace) &&
+ (startPadding.matchWorkspace ||
+ endPadding.matchWorkspace ||
+ gutter.matchWorkspace ||
+ cellSize.matchWorkspace)
+ ) {
+ Log.e(LOG_TAG, "WorkspaceSpec#isValid - workspace shouldn't contain matchWorkspace!")
+ return false
+ }
+
if (maxAvailableSize <= 0) {
Log.e(LOG_TAG, "${this::class.simpleName}#isValid - maxAvailableSize <= 0")
return false
@@ -106,13 +115,20 @@
cellSize.isValid()
}
- enum class SpecType {
+ enum class DimensionType {
HEIGHT,
WIDTH
}
companion object {
private const val LOG_TAG = "ResponsiveSpec"
+
+ enum class ResponsiveSpecType(val xmlTag: String) {
+ AllApps("allAppsSpec"),
+ Folder("folderSpec"),
+ Workspace("workspaceSpec"),
+ Hotseat("hotseatSpec")
+ }
}
}
@@ -120,7 +136,7 @@
* Calculated responsive specs contains the final paddings, gutter and cell size in pixels after
* they are calculated from the available space, cells and workspace specs.
*/
-sealed class CalculatedResponsiveSpec {
+class CalculatedResponsiveSpec {
var availableSpace: Int = 0
private set
@@ -146,7 +162,7 @@
availableSpace: Int,
cells: Int,
spec: ResponsiveSpec,
- calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+ calculatedWorkspaceSpec: CalculatedResponsiveSpec
) {
this.availableSpace = availableSpace
this.cells = cells
@@ -181,6 +197,11 @@
updateRemainderSpaces(availableSpace, cells, spec)
}
+ fun isResponsiveSpecType(type: ResponsiveSpecType) = spec.specType == type
+
+ // TODO(b/287975993): Remove this after icon size is extracted to responsive grid
+ fun isCellSizeMatchWorkspace(): Boolean = spec.cellSize.matchWorkspace
+
private fun updateRemainderSpaces(availableSpace: Int, cells: Int, spec: ResponsiveSpec) {
val gutters = cells - 1
val usedSpace = startPaddingPx + endPaddingPx + (gutterPx * gutters) + (cellSizePx * cells)
@@ -215,10 +236,10 @@
}
override fun toString(): String {
- return "${this::class.simpleName}(" +
+ return "Calculated${spec.specType}Spec(" +
"availableSpace=$availableSpace, cells=$cells, startPaddingPx=$startPaddingPx, " +
"endPaddingPx=$endPaddingPx, gutterPx=$gutterPx, cellSizePx=$cellSizePx, " +
- "${spec::class.simpleName}.maxAvailableSize=${spec.maxAvailableSize}" +
+ "${spec.specType}Spec.maxAvailableSize=${spec.maxAvailableSize}" +
")"
}
}
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecGroup.kt b/src/com/android/launcher3/responsive/ResponsiveSpecGroup.kt
new file mode 100644
index 0000000..b233d7c
--- /dev/null
+++ b/src/com/android/launcher3/responsive/ResponsiveSpecGroup.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 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.responsive
+
+import android.content.res.TypedArray
+import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
+
+/**
+ * Base class for responsive specs that holds a list of width and height specs.
+ *
+ * @param widthSpecs List of width responsive specifications
+ * @param heightSpecs List of height responsive specifications
+ */
+class ResponsiveSpecGroup<T : IResponsiveSpec>(
+ val aspectRatio: Float,
+ widthSpecs: List<T>,
+ heightSpecs: List<T>
+) {
+ val widthSpecs: List<T>
+ val heightSpecs: List<T>
+
+ init {
+ check(aspectRatio > 0f) { "Invalid aspect ratio! Aspect ratio should be bigger than zero." }
+ this.widthSpecs = widthSpecs.sortedBy { it.maxAvailableSize }
+ this.heightSpecs = heightSpecs.sortedBy { it.maxAvailableSize }
+ }
+
+ /**
+ * Get a [ResponsiveSpec] within the breakpoint.
+ *
+ * @param type Type of the spec to be retrieved (width or height)
+ * @param availableSize The breakpoint for the spec
+ * @return A [ResponsiveSpec].
+ */
+ fun getSpec(type: DimensionType, availableSize: Int): T {
+ val spec =
+ if (type == DimensionType.WIDTH) {
+ widthSpecs.firstOrNull { availableSize <= it.maxAvailableSize }
+ } else {
+ heightSpecs.firstOrNull { availableSize <= it.maxAvailableSize }
+ }
+ check(spec != null) { "No available $type spec found within $availableSize." }
+ return spec
+ }
+
+ companion object {
+ const val XML_GROUP_NAME = "specs"
+
+ fun <T : IResponsiveSpec> create(
+ attrs: TypedArray,
+ specs: List<T>
+ ): ResponsiveSpecGroup<T> {
+ val (widthSpecs, heightSpecs) =
+ specs.partition { it.dimensionType == DimensionType.WIDTH }
+ val aspectRatio = attrs.getFloat(R.styleable.ResponsiveSpecGroup_maxAspectRatio, 0f)
+ return ResponsiveSpecGroup(aspectRatio, widthSpecs, heightSpecs)
+ }
+ }
+}
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt b/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt
index a89b619..d782cd5 100644
--- a/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt
+++ b/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt
@@ -20,6 +20,7 @@
import android.content.res.XmlResourceParser
import android.util.Xml
import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
import com.android.launcher3.util.ResourceHelper
import java.io.IOException
import org.xmlpull.v1.XmlPullParser
@@ -27,6 +28,80 @@
class ResponsiveSpecsParser(private val resourceHelper: ResourceHelper) {
+ fun <T : IResponsiveSpec> parseXML(
+ responsiveSpecType: ResponsiveSpecType,
+ map:
+ (
+ responsiveSpecType: ResponsiveSpecType,
+ attributes: TypedArray,
+ sizeSpecs: Map<String, SizeSpec>
+ ) -> T
+ ): List<ResponsiveSpecGroup<T>> {
+ val parser: XmlResourceParser = resourceHelper.getXml()
+
+ try {
+ val groups = mutableListOf<ResponsiveSpecGroup<T>>()
+ val specs = mutableListOf<T>()
+ var groupAttrs: TypedArray? = null
+
+ var eventType = parser.eventType
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ // Parsing Group
+ when {
+ parser starts ResponsiveSpecGroup.XML_GROUP_NAME -> {
+ groupAttrs =
+ resourceHelper.obtainStyledAttributes(
+ Xml.asAttributeSet(parser),
+ R.styleable.ResponsiveSpecGroup
+ )
+ }
+ parser ends ResponsiveSpecGroup.XML_GROUP_NAME -> {
+ checkNotNull(groupAttrs)
+ groups += ResponsiveSpecGroup.create(groupAttrs, specs)
+ specs.clear()
+ groupAttrs.recycle()
+ groupAttrs = null
+ }
+ // Mapping Spec to WorkspaceSpec, AllAppsSpec, FolderSpecs, HotseatSpec
+ parser starts responsiveSpecType.xmlTag -> {
+ val attrs =
+ resourceHelper.obtainStyledAttributes(
+ Xml.asAttributeSet(parser),
+ R.styleable.ResponsiveSpec
+ )
+
+ val sizeSpecs = parseSizeSpecs(parser)
+ specs += map(responsiveSpecType, attrs, sizeSpecs)
+ attrs.recycle()
+ }
+ }
+
+ eventType = parser.next()
+ }
+
+ parser.close()
+
+ // All the specs should have been linked to a group, otherwise the XML is invalid
+ check(specs.isEmpty()) {
+ throw InvalidResponsiveGridSpec(
+ "Invalid XML. ${specs.size} specs not linked to a group."
+ )
+ }
+
+ return groups
+ } catch (e: Exception) {
+ when (e) {
+ is NoSuchFieldException,
+ is IOException,
+ is XmlPullParserException ->
+ throw RuntimeException("Failure parsing specs file.", e)
+ else -> throw e
+ }
+ } finally {
+ parser.close()
+ }
+ }
+
private fun parseSizeSpecs(parser: XmlResourceParser): Map<String, SizeSpec> {
val parentName = parser.name
parser.next()
@@ -42,49 +117,15 @@
return result
}
- fun <T> parseXML(
- tagName: String,
- map: (attributes: TypedArray, sizeSpecs: Map<String, SizeSpec>) -> T
- ): List<T> {
- val parser: XmlResourceParser = resourceHelper.getXml()
+ private infix fun XmlResourceParser.starts(tag: String): Boolean =
+ name == tag && eventType == XmlPullParser.START_TAG
- try {
- val list = mutableListOf<T>()
-
- var eventType = parser.eventType
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlResourceParser.START_TAG && parser.name == tagName) {
- val attrs =
- resourceHelper.obtainStyledAttributes(
- Xml.asAttributeSet(parser),
- R.styleable.ResponsiveSpec
- )
-
- val sizeSpecs = parseSizeSpecs(parser)
- list += map(attrs, sizeSpecs)
- attrs.recycle()
- }
-
- eventType = parser.next()
- }
-
- parser.close()
-
- return list
- } catch (e: Exception) {
- when (e) {
- is NoSuchFieldException,
- is IOException,
- is XmlPullParserException ->
- throw RuntimeException("Failure parsing specs file.", e)
- else -> throw e
- }
- } finally {
- parser.close()
- }
- }
+ private infix fun XmlResourceParser.ends(tag: String): Boolean =
+ name == tag && eventType == XmlPullParser.END_TAG
}
fun Map<String, SizeSpec>.getOrError(key: String): SizeSpec {
return this.getOrElse(key) { error("Attr '$key' must be defined.") }
}
+
+class InvalidResponsiveGridSpec(message: String) : Exception(message)
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt b/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt
new file mode 100644
index 0000000..bc2f4c5
--- /dev/null
+++ b/src/com/android/launcher3/responsive/ResponsiveSpecsProvider.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 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.responsive
+
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
+import com.android.launcher3.util.ResourceHelper
+
+/**
+ * A class to provide responsive grid specs for workspace, folder and all apps.
+ *
+ * This class is responsible for provide width and height [CalculatedResponsiveSpec] to be used for
+ * the correct placement of the workspace, all apps and folders.
+ *
+ * @param type A [ResponsiveSpecType] to indicates the type of the spec.
+ * @param groupOfSpecs Groups of responsive specifications
+ */
+class ResponsiveSpecsProvider(
+ val type: ResponsiveSpecType,
+ groupOfSpecs: List<ResponsiveSpecGroup<ResponsiveSpec>>
+) {
+ private val groupOfSpecs: List<ResponsiveSpecGroup<ResponsiveSpec>>
+
+ init {
+ this.groupOfSpecs =
+ groupOfSpecs
+ .onEach { group ->
+ check(group.widthSpecs.isNotEmpty() && group.heightSpecs.isNotEmpty()) {
+ "${this::class.simpleName} is incomplete - " +
+ "width list size = ${group.widthSpecs.size}; " +
+ "height list size = ${group.heightSpecs.size}."
+ }
+ }
+ .sortedBy { it.aspectRatio }
+ }
+
+ fun getSpecsByAspectRatio(aspectRatio: Float): ResponsiveSpecGroup<ResponsiveSpec> {
+ check(aspectRatio > 0f) { "Invalid aspect ratio! The value should be bigger than 0." }
+
+ val specsGroup = groupOfSpecs.firstOrNull { aspectRatio <= it.aspectRatio }
+ checkNotNull(specsGroup) { "No available spec with aspectRatio within $aspectRatio." }
+
+ return specsGroup
+ }
+
+ /**
+ * Retrieves a responsive grid specification that matches the number of [numCells],
+ * * [availableSpace] and [aspectRatio].
+ *
+ * @param aspectRatio the device width divided by device height (aspect ratio) to filter the
+ * specifications
+ * @param dimensionType the grid axis of the spec width is x axis, height is y axis.
+ * @param numCells number of rows/columns in the grid
+ * @param availableSpace available width to filter the specifications
+ * @return A [CalculatedResponsiveSpec] that matches the parameters provided.
+ */
+ fun getCalculatedSpec(
+ aspectRatio: Float,
+ dimensionType: DimensionType,
+ numCells: Int,
+ availableSpace: Int,
+ ): CalculatedResponsiveSpec {
+ val specsGroup = getSpecsByAspectRatio(aspectRatio)
+ val spec = specsGroup.getSpec(dimensionType, availableSpace)
+ return CalculatedResponsiveSpec(availableSpace, numCells, spec)
+ }
+
+ /**
+ * Retrieves a responsive grid specification that matches the number of [numCells],
+ * * [availableSpace] and [aspectRatio]. This function uses a [CalculatedResponsiveSpec] to
+ * match workspace when its true.
+ *
+ * @param aspectRatio the device width divided by device height (aspect ratio) to filter the
+ * specifications
+ * @param dimensionType the grid axis of the spec width is x axis, height is y axis.
+ * @param numCells number of rows/columns in the grid
+ * @param availableSpace available width to filter the specifications
+ * @param calculatedWorkspaceSpec the calculated workspace specification to use its values as
+ * base when matchWorkspace is true.
+ * @return A [CalculatedResponsiveSpec] that matches the parameters provided.
+ */
+ fun getCalculatedSpec(
+ aspectRatio: Float,
+ dimensionType: DimensionType,
+ numCells: Int,
+ availableSpace: Int,
+ calculatedWorkspaceSpec: CalculatedResponsiveSpec
+ ): CalculatedResponsiveSpec {
+ check(calculatedWorkspaceSpec.spec.dimensionType == dimensionType) {
+ "Invalid specType for CalculatedWorkspaceSpec. " +
+ "Expected: $dimensionType - " +
+ "Found: ${calculatedWorkspaceSpec.spec.dimensionType}}"
+ }
+
+ check(calculatedWorkspaceSpec.isResponsiveSpecType(ResponsiveSpecType.Workspace)) {
+ "Invalid specType for CalculatedWorkspaceSpec. " +
+ "Expected: ${ResponsiveSpecType.Workspace} - " +
+ "Found: ${calculatedWorkspaceSpec.spec.specType}}"
+ }
+
+ val specsGroup = getSpecsByAspectRatio(aspectRatio)
+ val spec = specsGroup.getSpec(dimensionType, availableSpace)
+ return CalculatedResponsiveSpec(availableSpace, numCells, spec, calculatedWorkspaceSpec)
+ }
+
+ companion object {
+ @JvmStatic
+ fun create(
+ resourceHelper: ResourceHelper,
+ type: ResponsiveSpecType
+ ): ResponsiveSpecsProvider {
+ val parser = ResponsiveSpecsParser(resourceHelper)
+ val specs = parser.parseXML(type, ::ResponsiveSpec)
+ return ResponsiveSpecsProvider(type, specs)
+ }
+ }
+}
diff --git a/src/com/android/launcher3/responsive/WorkspaceSpecs.kt b/src/com/android/launcher3/responsive/WorkspaceSpecs.kt
deleted file mode 100644
index 0da7026..0000000
--- a/src/com/android/launcher3/responsive/WorkspaceSpecs.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2023 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.responsive
-
-import android.content.res.TypedArray
-import android.util.Log
-import com.android.launcher3.R
-import com.android.launcher3.responsive.ResponsiveSpec.SpecType
-import com.android.launcher3.util.ResourceHelper
-
-private const val TAG = "WorkspaceSpecs"
-
-class WorkspaceSpecs(widthSpecs: List<WorkspaceSpec>, heightSpecs: List<WorkspaceSpec>) :
- ResponsiveSpecs<WorkspaceSpec>(widthSpecs, heightSpecs) {
-
- fun getCalculatedWidthSpec(columns: Int, availableWidth: Int): CalculatedWorkspaceSpec {
- val spec = getWidthSpec(availableWidth)
- return CalculatedWorkspaceSpec(availableWidth, columns, spec)
- }
-
- fun getCalculatedHeightSpec(rows: Int, availableHeight: Int): CalculatedWorkspaceSpec {
- val spec = getHeightSpec(availableHeight)
- return CalculatedWorkspaceSpec(availableHeight, rows, spec)
- }
-
- companion object {
- private const val XML_WORKSPACE_SPEC = "workspaceSpec"
-
- @JvmStatic
- fun create(resourceHelper: ResourceHelper): WorkspaceSpecs {
- val parser = ResponsiveSpecsParser(resourceHelper)
- val specs = parser.parseXML(XML_WORKSPACE_SPEC, ::WorkspaceSpec)
- val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH }
- return WorkspaceSpecs(widthSpecs, heightSpecs)
- }
- }
-}
-
-data class WorkspaceSpec(
- override val maxAvailableSize: Int,
- override val specType: SpecType,
- override val startPadding: SizeSpec,
- override val endPadding: SizeSpec,
- override val gutter: SizeSpec,
- override val cellSize: SizeSpec
-) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) {
-
- init {
- check(isValid()) { "Invalid WorkspaceSpec found." }
- }
-
- constructor(
- attrs: TypedArray,
- specs: Map<String, SizeSpec>
- ) : this(
- maxAvailableSize =
- attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
- specType =
- SpecType.values()[
- attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)],
- startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
- endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
- gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
- cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
- )
-
- override fun isValid(): Boolean {
- // Workspace spec should not match workspace
- if (
- startPadding.matchWorkspace ||
- endPadding.matchWorkspace ||
- gutter.matchWorkspace ||
- cellSize.matchWorkspace
- ) {
- Log.e(TAG, "WorkspaceSpec#isValid - workspace shouldn't contain matchWorkspace!")
- return false
- }
-
- return super.isValid()
- }
-}
-
-class CalculatedWorkspaceSpec(availableSpace: Int, cells: Int, spec: WorkspaceSpec) :
- CalculatedResponsiveSpec(availableSpace, cells, spec)
diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java
index 70691f8..60d0e95 100644
--- a/src/com/android/launcher3/testing/TestLogging.java
+++ b/src/com/android/launcher3/testing/TestLogging.java
@@ -76,7 +76,7 @@
// be more useful.
// That's why we pass false as the value for the 'reportToTapl' parameter.
recordEventSlow(sequence, message + ": " + event, false);
- registerEventNotFromTest(event);
+ if (action != MotionEvent.ACTION_CANCEL) registerEventNotFromTest(event);
}
}
diff --git a/src/com/android/launcher3/util/IconSizeSteps.kt b/src/com/android/launcher3/util/IconSizeSteps.kt
index aa644b0..6128eb4 100644
--- a/src/com/android/launcher3/util/IconSizeSteps.kt
+++ b/src/com/android/launcher3/util/IconSizeSteps.kt
@@ -39,8 +39,8 @@
return steps[max(0, getIndexForIconSize(iconSizePx) - 1)]
}
- fun getIconSmallerThan(cellWidth: Int): Int {
- return steps.lastOrNull { it <= cellWidth } ?: steps[0]
+ fun getIconSmallerThan(cellSize: Int): Int {
+ return steps.lastOrNull { it <= cellSize } ?: steps[0]
}
private fun getIndexForIconSize(iconSizePx: Int): Int {
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index cf59085..cbc85b6 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -149,6 +149,13 @@
public void assignMarginsAndBackgrounds(ViewGroup viewGroup) {
assignMarginsAndBackgrounds(viewGroup,
getColorStateList(getContext(), mColorIds[0]).getDefaultColor());
+ // last shortcut doesn't need bottom margin
+ final int count = viewGroup.getChildCount() - 1;
+ for (int i = 0; i < count; i++) {
+ // These are shortcuts and not shortcut containers, but they still need bottom margin
+ MarginLayoutParams mlp = (MarginLayoutParams) viewGroup.getChildAt(i).getLayoutParams();
+ mlp.bottomMargin = mChildContainerMargin;
+ }
}
public static <T extends Context & ActivityContext> OptionsPopupView<T> show(
diff --git a/tests/Launcher3Tests.xml b/tests/Launcher3Tests.xml
index 3fff622..0aed1e1 100644
--- a/tests/Launcher3Tests.xml
+++ b/tests/Launcher3Tests.xml
@@ -46,5 +46,6 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.launcher3.tests" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="instrumentation-arg" key="waitForActivitiesToComplete" value="false" />
</test>
</configuration>
diff --git a/tests/res/values/attrs.xml b/tests/res/values/attrs.xml
index e5ee064..4ba4fc7 100644
--- a/tests/res/values/attrs.xml
+++ b/tests/res/values/attrs.xml
@@ -26,6 +26,10 @@
<attr name="maxAvailableSize" format="dimension" />
</declare-styleable>
+ <declare-styleable name="ResponsiveSpecGroup">
+ <attr name="maxAspectRatio" format="float" />
+ </declare-styleable>
+
<declare-styleable name="WorkspaceSpec">
<attr name="specType" />
<attr name="maxAvailableSize" />
diff --git a/tests/res/xml/invalid_all_apps_file_case_1.xml b/tests/res/xml/invalid_all_apps_file_case_1.xml
index 6fd35b1..f09ecd8 100644
--- a/tests/res/xml/invalid_all_apps_file_case_1.xml
+++ b/tests/res/xml/invalid_all_apps_file_case_1.xml
@@ -14,23 +14,24 @@
~ limitations under the License.
-->
<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <allAppsSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <!-- missing startPadding -->
- <endPadding launcher:fixedSize="0dp" />
- <gutter launcher:matchWorkspace="true" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
+ <specs launcher:maxAspectRatio="10">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <!-- missing startPadding -->
+ <endPadding launcher:fixedSize="0dp" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
- <allAppsSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:matchWorkspace="true" />
- <endPadding launcher:matchWorkspace="true" />
- <gutter launcher:matchWorkspace="true" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
-
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+ </specs>
</allAppsSpecs>
diff --git a/tests/res/xml/invalid_all_apps_file_case_2.xml b/tests/res/xml/invalid_all_apps_file_case_2.xml
index de9c1ac..7644def 100644
--- a/tests/res/xml/invalid_all_apps_file_case_2.xml
+++ b/tests/res/xml/invalid_all_apps_file_case_2.xml
@@ -14,25 +14,26 @@
~ limitations under the License.
-->
<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <allAppsSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:fixedSize="0dp" />
- <!-- more than 1 value in one tag -->
- <gutter
- launcher:matchWorkspace="true"
- launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
+ <specs launcher:maxAspectRatio="10">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="0dp" />
+ <!-- more than 1 value in one tag -->
+ <gutter
+ launcher:matchWorkspace="true"
+ launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
- <allAppsSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:matchWorkspace="true" />
- <endPadding launcher:matchWorkspace="true" />
- <gutter launcher:matchWorkspace="true" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
-
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+ </specs>
</allAppsSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/invalid_all_apps_file_case_3.xml b/tests/res/xml/invalid_all_apps_file_case_3.xml
index 7af0af4..5a3bc64 100644
--- a/tests/res/xml/invalid_all_apps_file_case_3.xml
+++ b/tests/res/xml/invalid_all_apps_file_case_3.xml
@@ -14,24 +14,25 @@
~ limitations under the License.
-->
<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <allAppsSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:fixedSize="0dp" />
- <gutter launcher:matchWorkspace="true" />
- <!-- value bigger than 1 -->
- <cellSize launcher:ofRemainderSpace="1.001" />
- </allAppsSpec>
+ <specs launcher:maxAspectRatio="10">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="0dp" />
+ <gutter launcher:matchWorkspace="true" />
+ <!-- value bigger than 1 -->
+ <cellSize launcher:ofRemainderSpace="1.001" />
+ </allAppsSpec>
- <allAppsSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:matchWorkspace="true" />
- <endPadding launcher:matchWorkspace="true" />
- <gutter launcher:matchWorkspace="true" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
-
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+ </specs>
</allAppsSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_1.xml b/tests/res/xml/invalid_folders_specs_1.xml
index 0864249..1715ffd 100644
--- a/tests/res/xml/invalid_folders_specs_1.xml
+++ b/tests/res/xml/invalid_folders_specs_1.xml
@@ -16,25 +16,27 @@
<!-- Tablet - 6x5 portrait -->
<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
- <!-- missing startPadding -->
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </folderSpec>
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="102dp" />
- </folderSpec>
+ <specs launcher:maxAspectRatio="10">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <!-- missing startPadding -->
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
- <!-- Height spec is fixed -->
- <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="24dp" />
- <!-- mapped to footer height size -->
- <endPadding launcher:fixedSize="64dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </folderSpec>
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+ </specs>
</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_2.xml b/tests/res/xml/invalid_folders_specs_2.xml
index 0b7dd62..bb26e2e 100644
--- a/tests/res/xml/invalid_folders_specs_2.xml
+++ b/tests/res/xml/invalid_folders_specs_2.xml
@@ -16,28 +16,30 @@
<!-- Tablet - 6x5 portrait -->
<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <!-- more than 1 value in one tag -->
- <gutter
- launcher:ofAvailableSpace="0.0125"
- launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </folderSpec>
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="102dp" />
- </folderSpec>
+ <specs launcher:maxAspectRatio="10">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <!-- more than 1 value in one tag -->
+ <gutter
+ launcher:ofAvailableSpace="0.0125"
+ launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
- <!-- Height spec is fixed -->
- <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="24dp" />
- <!-- mapped to footer height size -->
- <endPadding launcher:fixedSize="64dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </folderSpec>
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+ </specs>
</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_3.xml b/tests/res/xml/invalid_folders_specs_3.xml
index 83fd3e1..cdd8056 100644
--- a/tests/res/xml/invalid_folders_specs_3.xml
+++ b/tests/res/xml/invalid_folders_specs_3.xml
@@ -16,26 +16,28 @@
<!-- Tablet - 6x5 portrait - More the one value first gutter -->
<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <!-- value bigger than 1 -->
- <cellSize launcher:ofRemainderSpace="1.001" />
- </folderSpec>
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="102dp" />
- </folderSpec>
+ <specs launcher:maxAspectRatio="10">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <!-- value bigger than 1 -->
+ <cellSize launcher:ofRemainderSpace="1.001" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
- <!-- Height spec is fixed -->
- <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="24dp" />
- <!-- mapped to footer height size -->
- <endPadding launcher:fixedSize="64dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </folderSpec>
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+ </specs>
</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_4.xml b/tests/res/xml/invalid_folders_specs_4.xml
index 2d8c730..cd5f334 100644
--- a/tests/res/xml/invalid_folders_specs_4.xml
+++ b/tests/res/xml/invalid_folders_specs_4.xml
@@ -15,10 +15,12 @@
-->
<!-- missing height spec -->
<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </folderSpec>
+ <specs launcher:maxAspectRatio="10">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ </specs>
</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_5.xml b/tests/res/xml/invalid_folders_specs_5.xml
index b4f1f4d..f554521 100644
--- a/tests/res/xml/invalid_folders_specs_5.xml
+++ b/tests/res/xml/invalid_folders_specs_5.xml
@@ -15,19 +15,21 @@
-->
<!-- missing breakpoints > 800dp -->
<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </folderSpec>
+ <specs launcher:maxAspectRatio="10">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
- <!-- Height spec is fixed -->
- <folderSpec launcher:specType="height" launcher:maxAvailableSize="800dp">
- <startPadding launcher:fixedSize="24dp" />
- <!-- mapped to footer height size -->
- <endPadding launcher:fixedSize="64dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </folderSpec>
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+ </specs>
</folderSpecs>
diff --git a/tests/res/xml/invalid_hotseat_file_case_1.xml b/tests/res/xml/invalid_hotseat_file_case_1.xml
index aaaf8bb..bd40690 100644
--- a/tests/res/xml/invalid_hotseat_file_case_1.xml
+++ b/tests/res/xml/invalid_hotseat_file_case_1.xml
@@ -14,19 +14,19 @@
~ limitations under the License.
-->
<hotseatSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="10">
+ <hotseatSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="847dp">
+ <hotseatQsbSpace launcher:ofAvailableSpace="1" />
+ <edgePadding launcher:fixedSize="36dp" />
+ </hotseatSpec>
- <hotseatSpec
- launcher:specType="height"
- launcher:maxAvailableSize="847dp">
- <hotseatQsbSpace launcher:ofAvailableSpace="1" />
- <edgePadding launcher:fixedSize="36dp" />
- </hotseatSpec>
-
- <hotseatSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <hotseatQsbSpace launcher:fixedSize="36dp" />
- <edgePadding launcher:fixedSize="36dp" />
- </hotseatSpec>
-
+ <hotseatSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <hotseatQsbSpace launcher:fixedSize="36dp" />
+ <edgePadding launcher:fixedSize="36dp" />
+ </hotseatSpec>
+ </specs>
</hotseatSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/invalid_responsive_spec_1.xml b/tests/res/xml/invalid_responsive_spec_1.xml
new file mode 100644
index 0000000..7a474bf
--- /dev/null
+++ b/tests/res/xml/invalid_responsive_spec_1.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 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.
+ -->
+<!-- invalid file - missing groups (specs) with aspect ratio -->
+<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <cellSize launcher:fixedSize="104dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="8dp" />
+ </workspaceSpec>
+
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="22dp" />
+ </workspaceSpec>
+</workspaceSpecs>
diff --git a/tests/res/xml/invalid_responsive_spec_2.xml b/tests/res/xml/invalid_responsive_spec_2.xml
new file mode 100644
index 0000000..6735300
--- /dev/null
+++ b/tests/res/xml/invalid_responsive_spec_2.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 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.
+ -->
+<!-- invalid file - groups (specs) applied only for half of the specs -->
+<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <cellSize launcher:fixedSize="104dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="8dp" />
+ </workspaceSpec>
+
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="22dp" />
+ </workspaceSpec>
+ </specs>
+
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="22dp" />
+ </workspaceSpec>
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <cellSize launcher:fixedSize="104dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="8dp" />
+ </workspaceSpec>
+</workspaceSpecs>
diff --git a/tests/res/xml/invalid_responsive_spec_3.xml b/tests/res/xml/invalid_responsive_spec_3.xml
new file mode 100644
index 0000000..72d0c20
--- /dev/null
+++ b/tests/res/xml/invalid_responsive_spec_3.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 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.
+ -->
+<!-- invalid file - aspect ratio = 0 (it must be bigger than zero) -->
+<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <cellSize launcher:fixedSize="104dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="8dp" />
+ </workspaceSpec>
+
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="22dp" />
+ </workspaceSpec>
+ </specs>
+
+ <specs launcher:maxAspectRatio="0">
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <cellSize launcher:fixedSize="104dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="8dp" />
+ </workspaceSpec>
+
+ <workspaceSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <startPadding launcher:fixedSize="22dp" />
+ </workspaceSpec>
+ </specs>
+
+</workspaceSpecs>
diff --git a/tests/res/xml/invalid_workspace_file_case_1.xml b/tests/res/xml/invalid_workspace_file_case_1.xml
index 0be704b..fc6ff59 100644
--- a/tests/res/xml/invalid_workspace_file_case_1.xml
+++ b/tests/res/xml/invalid_workspace_file_case_1.xml
@@ -15,42 +15,44 @@
-->
<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="648dp">
- <!-- missing startPadding -->
- <endPadding
- launcher:ofAvailableSpace="0.05" />
- <gutter
- launcher:fixedSize="16dp" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="648dp">
+ <!-- missing startPadding -->
+ <endPadding
+ launcher:ofAvailableSpace="0.05" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofAvailableSpace="0.0306" />
- <endPadding
- launcher:ofAvailableSpace="0.068" />
- <gutter
- launcher:fixedSize="16dp" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0306" />
+ <endPadding
+ launcher:ofAvailableSpace="0.068" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <!-- Width spec is always the same -->
- <workspaceSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofRemainderSpace="0.21436227" />
- <endPadding
- launcher:ofRemainderSpace="0.21436227" />
- <gutter
- launcher:ofRemainderSpace="0.11425509" />
- <cellSize
- launcher:fixedSize="120dp" />
- </workspaceSpec>
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <endPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <gutter
+ launcher:ofRemainderSpace="0.11425509" />
+ <cellSize
+ launcher:fixedSize="120dp" />
+ </workspaceSpec>
+ </specs>
</workspaceSpecs>
diff --git a/tests/res/xml/invalid_workspace_file_case_2.xml b/tests/res/xml/invalid_workspace_file_case_2.xml
index 5a37d97..2feeb54 100644
--- a/tests/res/xml/invalid_workspace_file_case_2.xml
+++ b/tests/res/xml/invalid_workspace_file_case_2.xml
@@ -15,45 +15,47 @@
-->
<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="648dp">
- <startPadding
- launcher:ofAvailableSpace="0.0125" />
- <endPadding
- launcher:ofAvailableSpace="0.05" />
- <!-- more than 1 value in one tag -->
- <gutter
- launcher:ofAvailableSpace="0.0125"
- launcher:fixedSize="16dp" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="648dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0125" />
+ <endPadding
+ launcher:ofAvailableSpace="0.05" />
+ <!-- more than 1 value in one tag -->
+ <gutter
+ launcher:ofAvailableSpace="0.0125"
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofAvailableSpace="0.0306" />
- <endPadding
- launcher:ofAvailableSpace="0.068" />
- <gutter
- launcher:fixedSize="16dp" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0306" />
+ <endPadding
+ launcher:ofAvailableSpace="0.068" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <!-- Width spec is always the same -->
- <workspaceSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofRemainderSpace="0.21436227" />
- <endPadding
- launcher:ofRemainderSpace="0.21436227" />
- <gutter
- launcher:ofRemainderSpace="0.11425509" />
- <cellSize
- launcher:fixedSize="120dp" />
- </workspaceSpec>
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <endPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <gutter
+ launcher:ofRemainderSpace="0.11425509" />
+ <cellSize
+ launcher:fixedSize="120dp" />
+ </workspaceSpec>
+ </specs>
</workspaceSpecs>
diff --git a/tests/res/xml/invalid_workspace_file_case_3.xml b/tests/res/xml/invalid_workspace_file_case_3.xml
index 3e68edb..79e6fbd 100644
--- a/tests/res/xml/invalid_workspace_file_case_3.xml
+++ b/tests/res/xml/invalid_workspace_file_case_3.xml
@@ -15,44 +15,46 @@
-->
<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="648dp">
- <startPadding
- launcher:ofAvailableSpace="0.0125" />
- <endPadding
- launcher:ofAvailableSpace="0.05" />
- <gutter
- launcher:fixedSize="16dp" />
- <!-- value bigger than 1 -->
- <cellSize
- launcher:ofRemainderSpace="1.001" />
- </workspaceSpec>
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="648dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0125" />
+ <endPadding
+ launcher:ofAvailableSpace="0.05" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <!-- value bigger than 1 -->
+ <cellSize
+ launcher:ofRemainderSpace="1.001" />
+ </workspaceSpec>
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofAvailableSpace="0.0306" />
- <endPadding
- launcher:ofAvailableSpace="0.068" />
- <gutter
- launcher:fixedSize="16dp" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0306" />
+ <endPadding
+ launcher:ofAvailableSpace="0.068" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <!-- Width spec is always the same -->
- <workspaceSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofRemainderSpace="0.21436227" />
- <endPadding
- launcher:ofRemainderSpace="0.21436227" />
- <gutter
- launcher:ofRemainderSpace="0.11425509" />
- <cellSize
- launcher:fixedSize="120dp" />
- </workspaceSpec>
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <endPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <gutter
+ launcher:ofRemainderSpace="0.11425509" />
+ <cellSize
+ launcher:fixedSize="120dp" />
+ </workspaceSpec>
+ </specs>
</workspaceSpecs>
diff --git a/tests/res/xml/invalid_workspace_file_case_4.xml b/tests/res/xml/invalid_workspace_file_case_4.xml
index 9e74c85..66a2618 100644
--- a/tests/res/xml/invalid_workspace_file_case_4.xml
+++ b/tests/res/xml/invalid_workspace_file_case_4.xml
@@ -15,44 +15,46 @@
-->
<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="648dp">
- <startPadding
- launcher:ofAvailableSpace="0.0125" />
- <endPadding
- launcher:ofAvailableSpace="0.05" />
- <!-- value in workspace spec using matchWorkspace -->
- <gutter
- launcher:matchWorkspace="true" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="648dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0125" />
+ <endPadding
+ launcher:ofAvailableSpace="0.05" />
+ <!-- value in workspace spec using matchWorkspace -->
+ <gutter
+ launcher:matchWorkspace="true" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofAvailableSpace="0.0306" />
- <endPadding
- launcher:ofAvailableSpace="0.068" />
- <gutter
- launcher:fixedSize="16dp" />
- <cellSize
- launcher:ofRemainderSpace="0.2" />
- </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0306" />
+ <endPadding
+ launcher:ofAvailableSpace="0.068" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
- <!-- Width spec is always the same -->
- <workspaceSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding
- launcher:ofRemainderSpace="0.21436227" />
- <endPadding
- launcher:ofRemainderSpace="0.21436227" />
- <gutter
- launcher:ofRemainderSpace="0.11425509" />
- <cellSize
- launcher:fixedSize="120dp" />
- </workspaceSpec>
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <endPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <gutter
+ launcher:ofRemainderSpace="0.11425509" />
+ <cellSize
+ launcher:fixedSize="120dp" />
+ </workspaceSpec>
+ </specs>
</workspaceSpecs>
diff --git a/tests/res/xml/valid_all_apps_file.xml b/tests/res/xml/valid_all_apps_file.xml
index 0be55d1..f0967c4 100644
--- a/tests/res/xml/valid_all_apps_file.xml
+++ b/tests/res/xml/valid_all_apps_file.xml
@@ -15,22 +15,23 @@
-->
<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <allAppsSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:fixedSize="0dp" />
- <gutter launcher:matchWorkspace="true" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
+ <specs launcher:maxAspectRatio="10">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="0dp" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
- <allAppsSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:matchWorkspace="true" />
- <endPadding launcher:matchWorkspace="true" />
- <gutter launcher:matchWorkspace="true" />
- <cellSize launcher:matchWorkspace="true" />
- </allAppsSpec>
-
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+ </specs>
</allAppsSpecs>
diff --git a/tests/res/xml/valid_folders_specs.xml b/tests/res/xml/valid_folders_specs.xml
index 0c45544..2ef59a9 100644
--- a/tests/res/xml/valid_folders_specs.xml
+++ b/tests/res/xml/valid_folders_specs.xml
@@ -14,25 +14,27 @@
~ limitations under the License.
-->
<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </folderSpec>
- <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="16dp" />
- <endPadding launcher:fixedSize="16dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="102dp" />
- </folderSpec>
+ <specs launcher:maxAspectRatio="10">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
- <!-- Height spec is fixed -->
- <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="24dp" />
- <!-- mapped to footer height size -->
- <endPadding launcher:fixedSize="64dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:matchWorkspace="true" />
- </folderSpec>
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ </specs>
</folderSpecs>
diff --git a/tests/res/xml/valid_hotseat_file.xml b/tests/res/xml/valid_hotseat_file.xml
index f698bd1..d1c9e49 100644
--- a/tests/res/xml/valid_hotseat_file.xml
+++ b/tests/res/xml/valid_hotseat_file.xml
@@ -14,19 +14,19 @@
~ limitations under the License.
-->
<hotseatSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="10">
+ <hotseatSpec
+ launcher:maxAvailableSize="847dp"
+ launcher:specType="height">
+ <hotseatQsbSpace launcher:fixedSize="24dp" />
+ <edgePadding launcher:fixedSize="48dp" />
+ </hotseatSpec>
- <hotseatSpec
- launcher:maxAvailableSize="847dp"
- launcher:specType="height">
- <hotseatQsbSpace launcher:fixedSize="24dp" />
- <edgePadding launcher:fixedSize="48dp" />
- </hotseatSpec>
-
- <hotseatSpec
- launcher:maxAvailableSize="9999dp"
- launcher:specType="height">
- <hotseatQsbSpace launcher:fixedSize="36dp" />
- <edgePadding launcher:fixedSize="48dp" />
- </hotseatSpec>
-
+ <hotseatSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <hotseatQsbSpace launcher:fixedSize="36dp" />
+ <edgePadding launcher:fixedSize="48dp" />
+ </hotseatSpec>
+ </specs>
</hotseatSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/valid_hotseat_land_file.xml b/tests/res/xml/valid_hotseat_land_file.xml
index fc4a836..a72fd18 100644
--- a/tests/res/xml/valid_hotseat_land_file.xml
+++ b/tests/res/xml/valid_hotseat_land_file.xml
@@ -14,19 +14,19 @@
~ limitations under the License.
-->
<hotseatSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="10">
+ <hotseatSpec
+ launcher:maxAvailableSize="743dp"
+ launcher:specType="width">
+ <hotseatQsbSpace launcher:fixedSize="0dp" />
+ <edgePadding launcher:fixedSize="48dp" />
+ </hotseatSpec>
- <hotseatSpec
- launcher:maxAvailableSize="743dp"
- launcher:specType="width">
- <hotseatQsbSpace launcher:fixedSize="0dp" />
- <edgePadding launcher:fixedSize="48dp" />
- </hotseatSpec>
-
- <hotseatSpec
- launcher:maxAvailableSize="9999dp"
- launcher:specType="width">
- <hotseatQsbSpace launcher:fixedSize="0dp" />
- <edgePadding launcher:fixedSize="64dp" />
- </hotseatSpec>
-
+ <hotseatSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <hotseatQsbSpace launcher:fixedSize="0dp" />
+ <edgePadding launcher:fixedSize="64dp" />
+ </hotseatSpec>
+ </specs>
</hotseatSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/valid_responsive_spec_unsorted.xml b/tests/res/xml/valid_responsive_spec_unsorted.xml
new file mode 100644
index 0000000..7cefc8e
--- /dev/null
+++ b/tests/res/xml/valid_responsive_spec_unsorted.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="10">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="34dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+
+ <!-- Height spec -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="371dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="24dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+
+ <!-- Width spec -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="716dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="36dp" />
+ <endPadding launcher:fixedSize="80dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="602dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="36dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ </specs>
+
+ <!-- specs from land/handheld_workspace_spec_4x4.xml -->
+ <specs launcher:maxAspectRatio="12">
+ <!-- Height spec -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="2dp" />
+ <endPadding launcher:fixedSize="2dp" />
+ <gutter launcher:fixedSize="8dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+
+ <!-- Width spec -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="1dp" />
+ <endPadding launcher:fixedSize="1dp" />
+ <gutter launcher:fixedSize="8dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ </specs>
+
+ <specs launcher:maxAspectRatio="1.05">
+ <!-- 584 grid height + 28 remainder space -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="612dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
+
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="8dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
+
+ <!-- 584 grid height -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="584dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="32dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofAvailableSpace="0.15808" />
+ </workspaceSpec>
+
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="22dp" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ </specs>
+</workspaceSpecs>
diff --git a/tests/res/xml/valid_workspace_file.xml b/tests/res/xml/valid_workspace_file.xml
index 1f97314..da5ca11 100644
--- a/tests/res/xml/valid_workspace_file.xml
+++ b/tests/res/xml/valid_workspace_file.xml
@@ -15,45 +15,93 @@
-->
<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
- <!-- 584 grid height -->
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="584dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:fixedSize="32dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:ofAvailableSpace="0.15808" />
- </workspaceSpec>
+ <specs launcher:maxAspectRatio="1.05">
+ <!-- 584 grid height -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="584dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="32dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofAvailableSpace="0.15808" />
+ </workspaceSpec>
- <!-- 584 grid height + 28 remainder space -->
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="612dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:ofRemainderSpace="1" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </workspaceSpec>
+ <!-- 584 grid height + 28 remainder space -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="612dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="8dp" />
- <endPadding launcher:ofRemainderSpace="1" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="8dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
- <!-- TODO(b/241386436): other specs here for height ... -->
+ <!-- TODO(b/241386436): other specs here for height ... -->
- <!-- Width spec is always the same -->
- <workspaceSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="22dp" />
- <endPadding launcher:fixedSize="22dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:ofRemainderSpace="0.25" />
- </workspaceSpec>
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="22dp" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ </specs>
+ <!-- specs from land/handheld_workspace_spec_4x4.xml -->
+ <specs launcher:maxAspectRatio="99999">
+ <!-- Height spec -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="371dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="24dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="34dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+
+ <!-- Width spec -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="602dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="36dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="716dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="36dp" />
+ <endPadding launcher:fixedSize="80dp" />
+ <gutter launcher:fixedSize="12dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ </specs>
</workspaceSpecs>
diff --git a/tests/res/xml/valid_workspace_unsorted_file.xml b/tests/res/xml/valid_workspace_unsorted_file.xml
index 1216c81..9f2bdc3 100644
--- a/tests/res/xml/valid_workspace_unsorted_file.xml
+++ b/tests/res/xml/valid_workspace_unsorted_file.xml
@@ -15,44 +15,44 @@
-->
<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <specs launcher:maxAspectRatio="1.05">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="8dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="8dp" />
- <endPadding launcher:ofRemainderSpace="1" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </workspaceSpec>
+ <!-- 584 grid height -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="584dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="32dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofAvailableSpace="0.15808" />
+ </workspaceSpec>
- <!-- 584 grid height -->
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="584dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:fixedSize="32dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:ofAvailableSpace="0.15808" />
- </workspaceSpec>
+ <!-- 584 grid height + 28 remainder space -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="612dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
- <!-- 584 grid height + 28 remainder space -->
- <workspaceSpec
- launcher:specType="height"
- launcher:maxAvailableSize="612dp">
- <startPadding launcher:fixedSize="0dp" />
- <endPadding launcher:ofRemainderSpace="1" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:fixedSize="104dp" />
- </workspaceSpec>
-
- <!-- Width spec is always the same -->
- <workspaceSpec
- launcher:specType="width"
- launcher:maxAvailableSize="9999dp">
- <startPadding launcher:fixedSize="22dp" />
- <endPadding launcher:fixedSize="22dp" />
- <gutter launcher:fixedSize="16dp" />
- <cellSize launcher:ofRemainderSpace="0.25" />
- </workspaceSpec>
-
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="22dp" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+ </specs>
</workspaceSpecs>
diff --git a/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt b/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt
index cd95e99..c99da96 100644
--- a/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt
+++ b/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt
@@ -21,6 +21,7 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
import com.android.launcher3.tests.R as TestR
import com.android.launcher3.util.TestResourceHelper
import com.google.common.truth.Truth.assertThat
@@ -32,22 +33,30 @@
@RunWith(AndroidJUnit4::class)
class AllAppsSpecsTest : AbstractDeviceProfileTest() {
override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
@Before
fun setup() {
- initializeVarsForPhone(deviceSpecs["phone"]!!)
+ initializeVarsForPhone(deviceSpec)
}
@Test
fun parseValidFile() {
val allAppsSpecs =
- AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_all_apps_file))
- assertThat(allAppsSpecs.heightSpecs.size).isEqualTo(1)
- assertThat(allAppsSpecs.heightSpecs[0].toString())
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_all_apps_file),
+ ResponsiveSpecType.AllApps
+ )
+
+ val specs = allAppsSpecs.getSpecsByAspectRatio(aspectRatio)
+ assertThat(specs.heightSpecs.size).isEqualTo(1)
+ assertThat(specs.heightSpecs[0].toString())
.isEqualTo(
- "AllAppsSpec(" +
+ "ResponsiveSpec(" +
"maxAvailableSize=26247, " +
- "specType=HEIGHT, " +
+ "dimensionType=HEIGHT, " +
+ "specType=AllApps, " +
"startPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
@@ -71,12 +80,13 @@
")"
)
- assertThat(allAppsSpecs.widthSpecs.size).isEqualTo(1)
- assertThat(allAppsSpecs.widthSpecs[0].toString())
+ assertThat(specs.widthSpecs.size).isEqualTo(1)
+ assertThat(specs.widthSpecs[0].toString())
.isEqualTo(
- "AllAppsSpec(" +
+ "ResponsiveSpec(" +
"maxAvailableSize=26247, " +
- "specType=WIDTH, " +
+ "dimensionType=WIDTH, " +
+ "specType=AllApps, " +
"startPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
@@ -103,16 +113,25 @@
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_missingTag_throwsError() {
- AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_all_apps_file_case_1))
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_all_apps_file_case_1),
+ ResponsiveSpecType.AllApps
+ )
}
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
- AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_all_apps_file_case_2))
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_all_apps_file_case_2),
+ ResponsiveSpecType.AllApps
+ )
}
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_valueBiggerThan1_throwsError() {
- AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_all_apps_file_case_3))
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_all_apps_file_case_3),
+ ResponsiveSpecType.AllApps
+ )
}
}
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt
index 0f12e58..1cc5ed2 100644
--- a/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt
+++ b/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt
@@ -21,6 +21,8 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
import com.android.launcher3.tests.R as TestR
import com.android.launcher3.util.TestResourceHelper
import com.google.common.truth.Truth.assertThat
@@ -40,6 +42,7 @@
@Test
fun normalPhone_copiesFromWorkspace() {
val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
initializeVarsForPhone(deviceSpec)
val availableWidth = deviceSpec.naturalSize.first
@@ -48,14 +51,30 @@
val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 495
val workspaceSpecs =
- WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
- val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
- val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_workspace_file),
+ ResponsiveSpecType.Workspace
+ )
+ val widthSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.WIDTH, 4, availableWidth)
+ val heightSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.HEIGHT, 5, availableHeight)
val allAppsSpecs =
- AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_all_apps_file))
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_all_apps_file),
+ ResponsiveSpecType.AllApps
+ )
- with(allAppsSpecs.getCalculatedWidthSpec(4, availableWidth, widthSpec)) {
+ with(
+ allAppsSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ 4,
+ availableWidth,
+ widthSpec
+ )
+ ) {
assertThat(availableSpace).isEqualTo(availableWidth)
assertThat(cells).isEqualTo(4)
assertThat(startPaddingPx).isEqualTo(widthSpec.startPaddingPx)
@@ -64,7 +83,15 @@
assertThat(cellSizePx).isEqualTo(widthSpec.cellSizePx)
}
- with(allAppsSpecs.getCalculatedHeightSpec(5, availableHeight, heightSpec)) {
+ with(
+ allAppsSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ 5,
+ availableHeight,
+ heightSpec
+ )
+ ) {
assertThat(availableSpace).isEqualTo(availableHeight)
assertThat(cells).isEqualTo(5)
assertThat(startPaddingPx).isEqualTo(0)
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt
new file mode 100644
index 0000000..c4e2d2a
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 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.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
+import com.android.launcher3.tests.R
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CalculatedFolderSpecTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ private val deviceSpec = deviceSpecs["phone"]!!
+ private val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpec)
+ }
+
+ @Test
+ fun validate_matchWidthWorkspace() {
+ val columns = 6
+
+ // Loading workspace specs
+ val resourceHelperWorkspace = TestResourceHelper(context, R.xml.valid_workspace_file)
+ val workspaceSpecs =
+ ResponsiveSpecsProvider.create(resourceHelperWorkspace, ResponsiveSpecType.Workspace)
+
+ // Loading folders specs
+ val resourceHelperFolder = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs =
+ ResponsiveSpecsProvider.create(resourceHelperFolder, ResponsiveSpecType.Folder)
+ val specs = folderSpecs.getSpecsByAspectRatio(aspectRatio)
+
+ assertThat(specs.widthSpecs.size).isEqualTo(2)
+ assertThat(specs.widthSpecs[0].cellSize.matchWorkspace).isEqualTo(true)
+ assertThat(specs.widthSpecs[1].cellSize.matchWorkspace).isEqualTo(false)
+
+ // Validate width spec <= 800
+ var availableWidth = deviceSpec.naturalSize.first
+ var calculatedWorkspace =
+ workspaceSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ columns,
+ availableWidth
+ )
+ var calculatedWidthFolderSpec =
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ columns,
+ availableWidth,
+ calculatedWorkspace
+ )
+ with(calculatedWidthFolderSpec) {
+ assertThat(availableSpace).isEqualTo(availableWidth)
+ assertThat(cells).isEqualTo(columns)
+ assertThat(startPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(endPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(gutterPx).isEqualTo(16.dpToPx())
+ assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx)
+ }
+
+ // Validate width spec > 800
+ availableWidth = 2000.dpToPx()
+ calculatedWorkspace =
+ workspaceSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ columns,
+ availableWidth
+ )
+ calculatedWidthFolderSpec =
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ columns,
+ availableWidth,
+ calculatedWorkspace
+ )
+ with(calculatedWidthFolderSpec) {
+ assertThat(availableSpace).isEqualTo(availableWidth)
+ assertThat(cells).isEqualTo(columns)
+ assertThat(startPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(endPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(gutterPx).isEqualTo(16.dpToPx())
+ assertThat(cellSizePx).isEqualTo(102.dpToPx())
+ }
+ }
+
+ @Test
+ fun validate_matchHeightWorkspace() {
+ // Hotseat is roughly 495px on a real device, it doesn't need to be precise on unit tests
+ val hotseatSize = 495
+ val statusBarHeight = deviceSpec.statusBarNaturalPx
+ val availableHeight = deviceSpec.naturalSize.second - statusBarHeight - hotseatSize
+ val rows = 5
+
+ // Loading workspace specs
+ val resourceHelperWorkspace = TestResourceHelper(context, R.xml.valid_workspace_file)
+ val workspaceSpecs =
+ ResponsiveSpecsProvider.create(resourceHelperWorkspace, ResponsiveSpecType.Workspace)
+
+ // Loading folders specs
+ val resourceHelperFolder = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs =
+ ResponsiveSpecsProvider.create(resourceHelperFolder, ResponsiveSpecType.Folder)
+ val specs = folderSpecs.getSpecsByAspectRatio(aspectRatio)
+
+ assertThat(specs.heightSpecs.size).isEqualTo(1)
+ assertThat(specs.heightSpecs[0].cellSize.matchWorkspace).isEqualTo(true)
+
+ // Validate height spec
+ val calculatedWorkspace =
+ workspaceSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ rows,
+ availableHeight
+ )
+ val calculatedFolderSpec =
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ rows,
+ availableHeight,
+ calculatedWorkspace
+ )
+ with(calculatedFolderSpec) {
+ assertThat(availableSpace).isEqualTo(availableHeight)
+ assertThat(cells).isEqualTo(rows)
+ assertThat(startPaddingPx).isEqualTo(24.dpToPx())
+ assertThat(endPaddingPx).isEqualTo(64.dpToPx())
+ assertThat(gutterPx).isEqualTo(16.dpToPx())
+ assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx)
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt
deleted file mode 100644
index f2a269a..0000000
--- a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2023 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.responsive
-
-import android.content.Context
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.launcher3.AbstractDeviceProfileTest
-import com.android.launcher3.tests.R
-import com.android.launcher3.util.TestResourceHelper
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class CalculatedFolderSpecsTest : AbstractDeviceProfileTest() {
- override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
-
- private val deviceSpec = deviceSpecs["phone"]!!
-
- @Before
- fun setup() {
- initializeVarsForPhone(deviceSpec)
- }
-
- @Test
- fun validate_matchWidthWorkspace() {
- val columns = 6
-
- // Loading workspace specs
- val resourceHelperWorkspace = TestResourceHelper(context!!, R.xml.valid_workspace_file)
- val workspaceSpecs = WorkspaceSpecs.create(resourceHelperWorkspace)
-
- // Loading folders specs
- val resourceHelperFolder = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelperFolder)
-
- assertThat(folderSpecs.widthSpecs.size).isEqualTo(2)
- assertThat(folderSpecs.widthSpecs[0].cellSize.matchWorkspace).isEqualTo(true)
- assertThat(folderSpecs.widthSpecs[1].cellSize.matchWorkspace).isEqualTo(false)
-
- // Validate width spec <= 800
- var availableWidth = deviceSpec.naturalSize.first
- var calculatedWorkspace = workspaceSpecs.getCalculatedWidthSpec(columns, availableWidth)
- var calculatedWidthFolderSpec =
- folderSpecs.getCalculatedWidthSpec(columns, availableWidth, calculatedWorkspace)
- with(calculatedWidthFolderSpec) {
- assertThat(availableSpace).isEqualTo(availableWidth)
- assertThat(cells).isEqualTo(columns)
- assertThat(startPaddingPx).isEqualTo(16.dpToPx())
- assertThat(endPaddingPx).isEqualTo(16.dpToPx())
- assertThat(gutterPx).isEqualTo(16.dpToPx())
- assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx)
- }
-
- // Validate width spec > 800
- availableWidth = 2000.dpToPx()
- calculatedWorkspace = workspaceSpecs.getCalculatedWidthSpec(columns, availableWidth)
- calculatedWidthFolderSpec =
- folderSpecs.getCalculatedWidthSpec(columns, availableWidth, calculatedWorkspace)
- with(calculatedWidthFolderSpec) {
- assertThat(availableSpace).isEqualTo(availableWidth)
- assertThat(cells).isEqualTo(columns)
- assertThat(startPaddingPx).isEqualTo(16.dpToPx())
- assertThat(endPaddingPx).isEqualTo(16.dpToPx())
- assertThat(gutterPx).isEqualTo(16.dpToPx())
- assertThat(cellSizePx).isEqualTo(102.dpToPx())
- }
- }
-
- @Test
- fun validate_matchHeightWorkspace() {
- // Hotseat is roughly 495px on a real device, it doesn't need to be precise on unit tests
- val hotseatSize = 495
- val statusBarHeight = deviceSpec.statusBarNaturalPx
- val availableHeight = deviceSpec.naturalSize.second - statusBarHeight - hotseatSize
- val rows = 5
-
- // Loading workspace specs
- val resourceHelperWorkspace = TestResourceHelper(context!!, R.xml.valid_workspace_file)
- val workspaceSpecs = WorkspaceSpecs.create(resourceHelperWorkspace)
-
- // Loading folders specs
- val resourceHelperFolder = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelperFolder)
-
- assertThat(folderSpecs.heightSpecs.size).isEqualTo(1)
- assertThat(folderSpecs.heightSpecs[0].cellSize.matchWorkspace).isEqualTo(true)
-
- // Validate height spec
- val calculatedWorkspace = workspaceSpecs.getCalculatedHeightSpec(rows, availableHeight)
- val calculatedFolderSpec =
- folderSpecs.getCalculatedHeightSpec(rows, availableHeight, calculatedWorkspace)
- with(calculatedFolderSpec) {
- assertThat(availableSpace).isEqualTo(availableHeight)
- assertThat(cells).isEqualTo(rows)
- assertThat(startPaddingPx).isEqualTo(24.dpToPx())
- assertThat(endPaddingPx).isEqualTo(64.dpToPx())
- assertThat(gutterPx).isEqualTo(16.dpToPx())
- assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx)
- }
- }
-}
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt
index 5865036..1a564ac 100644
--- a/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt
+++ b/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt
@@ -21,6 +21,7 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
import com.android.launcher3.tests.R as TestR
import com.android.launcher3.util.TestResourceHelper
import com.google.common.truth.Truth.assertThat
@@ -31,6 +32,8 @@
@RunWith(AndroidJUnit4::class)
class CalculatedHotseatSpecTest : AbstractDeviceProfileTest() {
override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
/**
* This test tests:
@@ -38,15 +41,19 @@
*/
@Test
fun normalPhone_returnsSecondBreakpointSpec() {
- val deviceSpec = deviceSpecs["phone"]!!
initializeVarsForPhone(deviceSpec)
// Hotseat uses the whole device height
val availableHeight = deviceSpec.naturalSize.second
- val hotseatSpecs =
- HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file))
- val heightSpec = hotseatSpecs.getCalculatedHeightSpec(availableHeight)
+ val hotseatSpecsProvider =
+ HotseatSpecsProvider.create(TestResourceHelper(context, TestR.xml.valid_hotseat_file))
+ val heightSpec =
+ hotseatSpecsProvider.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ availableHeight
+ )
assertThat(heightSpec.availableSpace).isEqualTo(availableHeight)
assertThat(heightSpec.hotseatQsbSpace).isEqualTo(95)
@@ -59,16 +66,20 @@
*/
@Test
fun smallPhone_returnsFirstBreakpointSpec() {
- val deviceSpec = deviceSpecs["phone"]!!
deviceSpec.densityDpi = 540 // larger display size
initializeVarsForPhone(deviceSpec)
// Hotseat uses the whole device height
val availableHeight = deviceSpec.naturalSize.second
- val hotseatSpecs =
- HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file))
- val heightSpec = hotseatSpecs.getCalculatedHeightSpec(availableHeight)
+ val hotseatSpecsProvider =
+ HotseatSpecsProvider.create(TestResourceHelper(context, TestR.xml.valid_hotseat_file))
+ val heightSpec =
+ hotseatSpecsProvider.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ availableHeight
+ )
assertThat(heightSpec.availableSpace).isEqualTo(availableHeight)
assertThat(heightSpec.hotseatQsbSpace).isEqualTo(81)
@@ -81,15 +92,17 @@
*/
@Test
fun normalPhoneLandscape_returnsSecondBreakpointSpec() {
- val deviceSpec = deviceSpecs["phone"]!!
initializeVarsForPhone(deviceSpec, isVerticalBar = true)
// Hotseat uses the whole device width
val availableWidth = deviceSpec.naturalSize.second
- val hotseatSpecs =
- HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_land_file))
- val widthSpec = hotseatSpecs.getCalculatedWidthSpec(availableWidth)
+ val hotseatSpecsProvider =
+ HotseatSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_hotseat_land_file)
+ )
+ val widthSpec =
+ hotseatSpecsProvider.getCalculatedSpec(aspectRatio, DimensionType.WIDTH, availableWidth)
assertThat(widthSpec.availableSpace).isEqualTo(availableWidth)
assertThat(widthSpec.hotseatQsbSpace).isEqualTo(0)
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt
index 8f56c5f..0c5d347 100644
--- a/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt
+++ b/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt
@@ -21,6 +21,8 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
import com.android.launcher3.tests.R as TestR
import com.android.launcher3.util.TestResourceHelper
import com.google.common.truth.Truth.assertThat
@@ -41,6 +43,7 @@
@Test
fun normalPhone_returnsThirdBreakpointSpec() {
val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
initializeVarsForPhone(deviceSpec)
val availableWidth = deviceSpec.naturalSize.first
@@ -49,9 +52,14 @@
val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 495
val workspaceSpecs =
- WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
- val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
- val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_workspace_file),
+ ResponsiveSpecType.Workspace
+ )
+ val widthSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.WIDTH, 4, availableWidth)
+ val heightSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.HEIGHT, 5, availableHeight)
assertThat(widthSpec.availableSpace).isEqualTo(availableWidth)
assertThat(widthSpec.cells).isEqualTo(4)
@@ -77,6 +85,7 @@
@Test
fun smallPhone_returnsFirstBreakpointSpec() {
val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
deviceSpec.densityDpi = 540 // larger display size
initializeVarsForPhone(deviceSpec)
@@ -86,9 +95,14 @@
val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 640
val workspaceSpecs =
- WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
- val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
- val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_workspace_file),
+ ResponsiveSpecType.Workspace
+ )
+ val widthSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.WIDTH, 4, availableWidth)
+ val heightSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.HEIGHT, 5, availableHeight)
assertThat(widthSpec.availableSpace).isEqualTo(availableWidth)
assertThat(widthSpec.cells).isEqualTo(4)
@@ -114,6 +128,7 @@
@Test
fun smallPhone_returnsFirstBreakpointSpec_unsortedFile() {
val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
deviceSpec.densityDpi = 540 // larger display size
initializeVarsForPhone(deviceSpec)
@@ -121,13 +136,15 @@
// Hotseat size is roughly 640px on a real device,
// it doesn't need to be precise on unit tests
val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 640
-
val workspaceSpecs =
- WorkspaceSpecs.create(
- TestResourceHelper(context!!, TestR.xml.valid_workspace_unsorted_file)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_workspace_unsorted_file),
+ ResponsiveSpecType.Workspace
)
- val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
- val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
+ val widthSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.WIDTH, 4, availableWidth)
+ val heightSpec =
+ workspaceSpecs.getCalculatedSpec(aspectRatio, DimensionType.HEIGHT, 5, availableHeight)
assertThat(widthSpec.availableSpace).isEqualTo(availableWidth)
assertThat(widthSpec.cells).isEqualTo(4)
diff --git a/tests/src/com/android/launcher3/responsive/FolderSpecTest.kt b/tests/src/com/android/launcher3/responsive/FolderSpecTest.kt
new file mode 100644
index 0000000..1756c9a
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/FolderSpecTest.kt
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2023 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.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
+import com.android.launcher3.tests.R
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class FolderSpecTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ val deviceSpec = deviceSpecs["tablet"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpec)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ val specs = folderSpecs.getSpecsByAspectRatio(aspectRatio)
+
+ val sizeSpec16 = SizeSpec(16f.dpToPx())
+ val widthSpecsExpected =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 800.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = sizeSpec16,
+ endPadding = sizeSpec16,
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(matchWorkspace = true)
+ ),
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = sizeSpec16,
+ endPadding = sizeSpec16,
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(102f.dpToPx())
+ )
+ )
+
+ val heightSpecsExpected =
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = SizeSpec(24f.dpToPx()),
+ endPadding = SizeSpec(64f.dpToPx()),
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(matchWorkspace = true)
+ )
+
+ assertThat(specs.widthSpecs.size).isEqualTo(widthSpecsExpected.size)
+ assertThat(specs.widthSpecs[0]).isEqualTo(widthSpecsExpected[0])
+ assertThat(specs.widthSpecs[1]).isEqualTo(widthSpecsExpected[1])
+
+ assertThat(specs.heightSpecs.size).isEqualTo(1)
+ assertThat(specs.heightSpecs[0]).isEqualTo(heightSpecsExpected)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingTag_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_1)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_2)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_valueBiggerThan1_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_3)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingSpecs_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_4)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingWidthBreakpoint_throwsError() {
+ val availableSpace = 900.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ ResponsiveSpec(
+ maxAvailableSize = availableSpace,
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedResponsiveSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_5)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ cells,
+ availableSpace,
+ calculatedWorkspaceSpec
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingHeightBreakpoint_throwsError() {
+ val availableSpace = 900.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ ResponsiveSpec(
+ maxAvailableSize = availableSpace,
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedResponsiveSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_5)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ cells,
+ availableSpace,
+ calculatedWorkspaceSpec
+ )
+ }
+
+ @Test
+ fun retrievesCalculatedWidthSpec() {
+ val availableSpace = 800.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ ResponsiveSpec(
+ maxAvailableSize = availableSpace,
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedResponsiveSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ val calculatedWidthSpec =
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ cells,
+ availableSpace,
+ calculatedWorkspaceSpec
+ )
+
+ assertThat(calculatedWidthSpec.cells).isEqualTo(cells)
+ assertThat(calculatedWidthSpec.availableSpace).isEqualTo(availableSpace)
+ assertThat(calculatedWidthSpec.startPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedWidthSpec.endPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedWidthSpec.gutterPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedWidthSpec.cellSizePx).isEqualTo(calculatedWorkspaceSpec.cellSizePx)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun retrievesCalculatedWidthSpec_invalidCalculatedResponsiveSpecType_throwsError() {
+ val availableSpace = 10.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ ResponsiveSpec(
+ maxAvailableSize = availableSpace,
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedResponsiveSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.WIDTH,
+ cells,
+ availableSpace,
+ calculatedWorkspaceSpec
+ )
+ }
+
+ @Test
+ fun retrievesCalculatedHeightSpec() {
+ val availableSpace = 700.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ ResponsiveSpec(
+ maxAvailableSize = availableSpace,
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedResponsiveSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ val calculatedHeightSpec =
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ cells,
+ availableSpace,
+ calculatedWorkspaceSpec
+ )
+
+ assertThat(calculatedHeightSpec.cells).isEqualTo(cells)
+ assertThat(calculatedHeightSpec.availableSpace).isEqualTo(availableSpace)
+ assertThat(calculatedHeightSpec.startPaddingPx).isEqualTo(24.dpToPx())
+ assertThat(calculatedHeightSpec.endPaddingPx).isEqualTo(64.dpToPx())
+ assertThat(calculatedHeightSpec.gutterPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedHeightSpec.cellSizePx).isEqualTo(calculatedWorkspaceSpec.cellSizePx)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun retrievesCalculatedHeightSpec_invalidCalculatedResponsiveSpecType_throwsError() {
+ val availableSpace = 10.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ ResponsiveSpec(
+ maxAvailableSize = availableSpace,
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Folder,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedResponsiveSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs)
+ val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder)
+ folderSpecs.getCalculatedSpec(
+ aspectRatio,
+ DimensionType.HEIGHT,
+ cells,
+ availableSpace,
+ calculatedWorkspaceSpec
+ )
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt b/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt
deleted file mode 100644
index 4b05949..0000000
--- a/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2023 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.responsive
-
-import android.content.Context
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.launcher3.AbstractDeviceProfileTest
-import com.android.launcher3.responsive.ResponsiveSpec.SpecType
-import com.android.launcher3.tests.R
-import com.android.launcher3.util.TestResourceHelper
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class FolderSpecsTest : AbstractDeviceProfileTest() {
- override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
-
- @Before
- fun setup() {
- initializeVarsForPhone(deviceSpecs["tablet"]!!)
- }
-
- @Test
- fun parseValidFile() {
- val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelper)
-
- val sizeSpec16 = SizeSpec(16f.dpToPx())
- val widthSpecsExpected =
- listOf(
- FolderSpec(
- maxAvailableSize = 800.dpToPx(),
- specType = SpecType.WIDTH,
- startPadding = sizeSpec16,
- endPadding = sizeSpec16,
- gutter = sizeSpec16,
- cellSize = SizeSpec(matchWorkspace = true)
- ),
- FolderSpec(
- maxAvailableSize = 9999.dpToPx(),
- specType = SpecType.WIDTH,
- startPadding = sizeSpec16,
- endPadding = sizeSpec16,
- gutter = sizeSpec16,
- cellSize = SizeSpec(102f.dpToPx())
- )
- )
-
- val heightSpecsExpected =
- FolderSpec(
- maxAvailableSize = 9999.dpToPx(),
- specType = SpecType.HEIGHT,
- startPadding = SizeSpec(24f.dpToPx()),
- endPadding = SizeSpec(64f.dpToPx()),
- gutter = sizeSpec16,
- cellSize = SizeSpec(matchWorkspace = true)
- )
-
- assertThat(folderSpecs.widthSpecs.size).isEqualTo(widthSpecsExpected.size)
- assertThat(folderSpecs.widthSpecs[0]).isEqualTo(widthSpecsExpected[0])
- assertThat(folderSpecs.widthSpecs[1]).isEqualTo(widthSpecsExpected[1])
-
- assertThat(folderSpecs.heightSpecs.size).isEqualTo(1)
- assertThat(folderSpecs.heightSpecs[0]).isEqualTo(heightSpecsExpected)
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_missingTag_throwsError() {
- val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_1)
- FolderSpecs.create(resourceHelper)
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
- val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_2)
- FolderSpecs.create(resourceHelper)
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_valueBiggerThan1_throwsError() {
- val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_3)
- FolderSpecs.create(resourceHelper)
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_missingSpecs_throwsError() {
- val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_4)
- FolderSpecs.create(resourceHelper)
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_missingWidthBreakpoint_throwsError() {
- val availableSpace = 900.dpToPx()
- val cells = 3
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize = availableSpace,
- specType = SpecType.WIDTH,
- startPadding = SizeSpec(fixedSize = 10f),
- endPadding = SizeSpec(fixedSize = 10f),
- gutter = SizeSpec(fixedSize = 10f),
- cellSize = SizeSpec(fixedSize = 10f)
- )
- val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
-
- val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_5)
- val folderSpecs = FolderSpecs.create(resourceHelper)
- folderSpecs.getCalculatedWidthSpec(cells, availableSpace, calculatedWorkspaceSpec)
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_missingHeightBreakpoint_throwsError() {
- val availableSpace = 900.dpToPx()
- val cells = 3
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize = availableSpace,
- specType = SpecType.HEIGHT,
- startPadding = SizeSpec(fixedSize = 10f),
- endPadding = SizeSpec(fixedSize = 10f),
- gutter = SizeSpec(fixedSize = 10f),
- cellSize = SizeSpec(fixedSize = 10f)
- )
- val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
-
- val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_5)
- val folderSpecs = FolderSpecs.create(resourceHelper)
- folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec)
- }
-
- @Test
- fun retrievesCalculatedWidthSpec() {
- val availableSpace = 800.dpToPx()
- val cells = 3
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize = availableSpace,
- specType = SpecType.WIDTH,
- startPadding = SizeSpec(fixedSize = 10f),
- endPadding = SizeSpec(fixedSize = 10f),
- gutter = SizeSpec(fixedSize = 10f),
- cellSize = SizeSpec(fixedSize = 10f)
- )
- val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
-
- val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelper)
- val calculatedWidthSpec =
- folderSpecs.getCalculatedWidthSpec(cells, availableSpace, calculatedWorkspaceSpec)
-
- assertThat(calculatedWidthSpec.cells).isEqualTo(cells)
- assertThat(calculatedWidthSpec.availableSpace).isEqualTo(availableSpace)
- assertThat(calculatedWidthSpec.startPaddingPx).isEqualTo(16.dpToPx())
- assertThat(calculatedWidthSpec.endPaddingPx).isEqualTo(16.dpToPx())
- assertThat(calculatedWidthSpec.gutterPx).isEqualTo(16.dpToPx())
- assertThat(calculatedWidthSpec.cellSizePx).isEqualTo(calculatedWorkspaceSpec.cellSizePx)
- }
-
- @Test(expected = IllegalStateException::class)
- fun retrievesCalculatedWidthSpec_invalidCalculatedWorkspaceSpecType_throwsError() {
- val availableSpace = 10.dpToPx()
- val cells = 3
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize = availableSpace,
- specType = SpecType.HEIGHT,
- startPadding = SizeSpec(fixedSize = 10f),
- endPadding = SizeSpec(fixedSize = 10f),
- gutter = SizeSpec(fixedSize = 10f),
- cellSize = SizeSpec(fixedSize = 10f)
- )
- val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
-
- val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelper)
- folderSpecs.getCalculatedWidthSpec(cells, availableSpace, calculatedWorkspaceSpec)
- }
-
- @Test
- fun retrievesCalculatedHeightSpec() {
- val availableSpace = 700.dpToPx()
- val cells = 3
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize = availableSpace,
- specType = SpecType.HEIGHT,
- startPadding = SizeSpec(fixedSize = 10f),
- endPadding = SizeSpec(fixedSize = 10f),
- gutter = SizeSpec(fixedSize = 10f),
- cellSize = SizeSpec(fixedSize = 10f)
- )
- val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
-
- val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelper)
- val calculatedHeightSpec =
- folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec)
-
- assertThat(calculatedHeightSpec.cells).isEqualTo(cells)
- assertThat(calculatedHeightSpec.availableSpace).isEqualTo(availableSpace)
- assertThat(calculatedHeightSpec.startPaddingPx).isEqualTo(24.dpToPx())
- assertThat(calculatedHeightSpec.endPaddingPx).isEqualTo(64.dpToPx())
- assertThat(calculatedHeightSpec.gutterPx).isEqualTo(16.dpToPx())
- assertThat(calculatedHeightSpec.cellSizePx).isEqualTo(calculatedWorkspaceSpec.cellSizePx)
- }
-
- @Test(expected = IllegalStateException::class)
- fun retrievesCalculatedHeightSpec_invalidCalculatedWorkspaceSpecType_throwsError() {
- val availableSpace = 10.dpToPx()
- val cells = 3
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize = availableSpace,
- specType = SpecType.WIDTH,
- startPadding = SizeSpec(fixedSize = 10f),
- endPadding = SizeSpec(fixedSize = 10f),
- gutter = SizeSpec(fixedSize = 10f),
- cellSize = SizeSpec(fixedSize = 10f)
- )
- val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
-
- val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
- val folderSpecs = FolderSpecs.create(resourceHelper)
- folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec)
- }
-}
diff --git a/tests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt b/tests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt
new file mode 100644
index 0000000..32249e0
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023 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.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.tests.R as TestR
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HotseatSpecsProviderTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpec)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val hotseatSpecsProvider =
+ HotseatSpecsProvider.create(TestResourceHelper(context, TestR.xml.valid_hotseat_file))
+ val specs = hotseatSpecsProvider.getSpecsByAspectRatio(aspectRatio)
+
+ val expectedHeightSpecs =
+ listOf(
+ HotseatSpec(
+ maxAvailableSize = 847.dpToPx(),
+ dimensionType = ResponsiveSpec.DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Hotseat,
+ hotseatQsbSpace = SizeSpec(24f.dpToPx()),
+ edgePadding = SizeSpec(48f.dpToPx())
+ ),
+ HotseatSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = ResponsiveSpec.DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Hotseat,
+ hotseatQsbSpace = SizeSpec(36f.dpToPx()),
+ edgePadding = SizeSpec(48f.dpToPx())
+ ),
+ )
+
+ assertThat(specs.heightSpecs.size).isEqualTo(expectedHeightSpecs.size)
+ assertThat(specs.heightSpecs[0]).isEqualTo(expectedHeightSpecs[0])
+ assertThat(specs.heightSpecs[1]).isEqualTo(expectedHeightSpecs[1])
+
+ assertThat(specs.widthSpecs.size).isEqualTo(0)
+ }
+
+ @Test
+ fun parseValidLandscapeFile() {
+ val hotseatSpecsProvider =
+ HotseatSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_hotseat_land_file)
+ )
+ val specs = hotseatSpecsProvider.getSpecsByAspectRatio(aspectRatio)
+ assertThat(specs.heightSpecs.size).isEqualTo(0)
+
+ val expectedWidthSpecs =
+ listOf(
+ HotseatSpec(
+ maxAvailableSize = 743.dpToPx(),
+ dimensionType = ResponsiveSpec.DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Hotseat,
+ hotseatQsbSpace = SizeSpec(0f),
+ edgePadding = SizeSpec(48f.dpToPx())
+ ),
+ HotseatSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = ResponsiveSpec.DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Hotseat,
+ hotseatQsbSpace = SizeSpec(0f),
+ edgePadding = SizeSpec(64f.dpToPx())
+ ),
+ )
+
+ assertThat(specs.widthSpecs.size).isEqualTo(expectedWidthSpecs.size)
+ assertThat(specs.widthSpecs[0]).isEqualTo(expectedWidthSpecs[0])
+ assertThat(specs.widthSpecs[1]).isEqualTo(expectedWidthSpecs[1])
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_spaceIsNotFixedSize_throwsError() {
+ HotseatSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_hotseat_file_case_1)
+ )
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt b/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt
deleted file mode 100644
index f650e91..0000000
--- a/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2023 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.responsive
-
-import android.content.Context
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.launcher3.AbstractDeviceProfileTest
-import com.android.launcher3.tests.R as TestR
-import com.android.launcher3.util.TestResourceHelper
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class HotseatSpecsTest : AbstractDeviceProfileTest() {
- override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
-
- @Before
- fun setup() {
- initializeVarsForPhone(deviceSpecs["phone"]!!)
- }
-
- @Test
- fun parseValidFile() {
- val hotseatSpecs =
- HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file))
-
- val expectedHeightSpecs =
- listOf(
- HotseatSpec(
- maxAvailableSize = 847.dpToPx(),
- specType = ResponsiveSpec.SpecType.HEIGHT,
- hotseatQsbSpace = SizeSpec(24f.dpToPx()),
- edgePadding = SizeSpec(48f.dpToPx())
- ),
- HotseatSpec(
- maxAvailableSize = 9999.dpToPx(),
- specType = ResponsiveSpec.SpecType.HEIGHT,
- hotseatQsbSpace = SizeSpec(36f.dpToPx()),
- edgePadding = SizeSpec(48f.dpToPx())
- ),
- )
-
- assertThat(hotseatSpecs.heightSpecs.size).isEqualTo(expectedHeightSpecs.size)
- assertThat(hotseatSpecs.heightSpecs[0]).isEqualTo(expectedHeightSpecs[0])
- assertThat(hotseatSpecs.heightSpecs[1]).isEqualTo(expectedHeightSpecs[1])
-
- assertThat(hotseatSpecs.widthSpecs.size).isEqualTo(0)
- }
-
- @Test
- fun parseValidLandscapeFile() {
- val hotseatSpecs =
- HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_land_file))
- assertThat(hotseatSpecs.heightSpecs.size).isEqualTo(0)
-
- val expectedWidthSpecs =
- listOf(
- HotseatSpec(
- maxAvailableSize = 743.dpToPx(),
- specType = ResponsiveSpec.SpecType.WIDTH,
- hotseatQsbSpace = SizeSpec(0f),
- edgePadding = SizeSpec(48f.dpToPx())
- ),
- HotseatSpec(
- maxAvailableSize = 9999.dpToPx(),
- specType = ResponsiveSpec.SpecType.WIDTH,
- hotseatQsbSpace = SizeSpec(0f),
- edgePadding = SizeSpec(64f.dpToPx())
- ),
- )
-
- assertThat(hotseatSpecs.widthSpecs.size).isEqualTo(expectedWidthSpecs.size)
- assertThat(hotseatSpecs.widthSpecs[0]).isEqualTo(expectedWidthSpecs[0])
- assertThat(hotseatSpecs.widthSpecs[1]).isEqualTo(expectedWidthSpecs[1])
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_spaceIsNotFixedSize_throwsError() {
- HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_hotseat_file_case_1))
- }
-}
diff --git a/tests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt b/tests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt
new file mode 100644
index 0000000..7af0823
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2023 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.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
+import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
+import com.android.launcher3.tests.R
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ResponsiveSpecsProviderTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ val deviceSpec = deviceSpecs["tablet"]!!
+ var aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpec)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_responsive_spec_unsorted)
+ val provider = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace)
+
+ // Validate Portrait
+ val aspectRatioPortrait = 1.0f
+ val portraitSpecs = provider.getSpecsByAspectRatio(aspectRatioPortrait)
+
+ val (expectedPortWidthSpecs, expectedPortHeightSpecs) = expectedPortraitSpecs()
+ validateSpecs(
+ portraitSpecs,
+ aspectRatioPortrait,
+ expectedPortWidthSpecs,
+ expectedPortHeightSpecs
+ )
+
+ // Validate Landscape
+ val aspectRatioLandscape = 1.051f
+ val landscapeSpecs = provider.getSpecsByAspectRatio(aspectRatioLandscape)
+
+ val (expectedLandWidthSpecs, expectedLandHeightSpecs) = expectedLandscapeSpecs()
+ validateSpecs(
+ landscapeSpecs,
+ aspectRatioLandscape,
+ expectedLandWidthSpecs,
+ expectedLandHeightSpecs
+ )
+
+ // Validate Extra Spec
+ val aspectRatioExtra = 10.1f
+ val extraSpecs = provider.getSpecsByAspectRatio(aspectRatioExtra)
+
+ val expectedOtherWidthSpecs =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(1f.dpToPx()),
+ endPadding = SizeSpec(1f.dpToPx()),
+ gutter = SizeSpec(8f.dpToPx()),
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ )
+ )
+
+ val expectedOtherHeightSpecs =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(2f.dpToPx()),
+ endPadding = SizeSpec(2f.dpToPx()),
+ gutter = SizeSpec(8f.dpToPx()),
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ ),
+ )
+
+ validateSpecs(
+ extraSpecs,
+ aspectRatioExtra,
+ expectedOtherWidthSpecs,
+ expectedOtherHeightSpecs
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseValidFile_invalidAspectRatio_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.valid_responsive_spec_unsorted)
+ val provider = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace)
+ provider.getSpecsByAspectRatio(0f)
+ }
+
+ @Test(expected = InvalidResponsiveGridSpec::class)
+ fun parseInvalidFile_missingGroups_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_1)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace)
+ }
+
+ @Test(expected = InvalidResponsiveGridSpec::class)
+ fun parseInvalidFile_partialGroups_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_2)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_invalidAspectRatio_throwsError() {
+ val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_3)
+ ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace)
+ }
+
+ private fun validateSpecs(
+ specs: ResponsiveSpecGroup<ResponsiveSpec>,
+ expectedAspectRatio: Float,
+ expectedWidthSpecs: List<ResponsiveSpec>,
+ expectedHeightSpecs: List<ResponsiveSpec>
+ ) {
+ assertThat(specs.aspectRatio).isAtLeast(expectedAspectRatio)
+
+ assertThat(specs.widthSpecs.size).isEqualTo(expectedWidthSpecs.size)
+ specs.widthSpecs.forEachIndexed { index, responsiveSpec ->
+ assertThat(responsiveSpec).isEqualTo(expectedWidthSpecs[index])
+ }
+
+ assertThat(specs.heightSpecs.size).isEqualTo(expectedHeightSpecs.size)
+ specs.heightSpecs.forEachIndexed { index, responsiveSpec ->
+ assertThat(responsiveSpec).isEqualTo(expectedHeightSpecs[index])
+ }
+ }
+
+ private fun expectedPortraitSpecs(): Pair<List<ResponsiveSpec>, List<ResponsiveSpec>> {
+ val sizeSpec16 = SizeSpec(16f.dpToPx())
+ val expectedWidthSpecs =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(22f.dpToPx()),
+ endPadding = SizeSpec(22f.dpToPx()),
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ )
+ )
+
+ val expectedHeightSpecs =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 584.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(0f),
+ endPadding = SizeSpec(32f.dpToPx()),
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(ofAvailableSpace = .15808f)
+ ),
+ ResponsiveSpec(
+ maxAvailableSize = 612.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(0f),
+ endPadding = SizeSpec(ofRemainderSpace = 1f),
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(104f.dpToPx())
+ ),
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(8f.dpToPx()),
+ endPadding = SizeSpec(ofRemainderSpace = 1f),
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(104f.dpToPx())
+ ),
+ )
+
+ return Pair(expectedWidthSpecs, expectedHeightSpecs)
+ }
+
+ private fun expectedLandscapeSpecs(): Pair<List<ResponsiveSpec>, List<ResponsiveSpec>> {
+ val sizeSpec12 = SizeSpec(12f.dpToPx())
+ val expectedWidthSpecs =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 602.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(0f.dpToPx()),
+ endPadding = SizeSpec(36f.dpToPx()),
+ gutter = sizeSpec12,
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ ),
+ ResponsiveSpec(
+ maxAvailableSize = 716.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(16f.dpToPx()),
+ endPadding = SizeSpec(64f.dpToPx()),
+ gutter = sizeSpec12,
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ ),
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.WIDTH,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(36f.dpToPx()),
+ endPadding = SizeSpec(80f.dpToPx()),
+ gutter = sizeSpec12,
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ )
+ )
+
+ val expectedHeightSpecs =
+ listOf(
+ ResponsiveSpec(
+ maxAvailableSize = 371.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(0f),
+ endPadding = SizeSpec(24f.dpToPx()),
+ gutter = sizeSpec12,
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ ),
+ ResponsiveSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ dimensionType = DimensionType.HEIGHT,
+ specType = ResponsiveSpecType.Workspace,
+ startPadding = SizeSpec(0f),
+ endPadding = SizeSpec(34f.dpToPx()),
+ gutter = sizeSpec12,
+ cellSize = SizeSpec(ofRemainderSpace = .25f)
+ ),
+ )
+
+ return Pair(expectedWidthSpecs, expectedHeightSpecs)
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt b/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt
index 0364069..9781645 100644
--- a/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt
+++ b/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt
@@ -21,6 +21,7 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
import com.android.launcher3.tests.R as TestR
import com.android.launcher3.util.TestResourceHelper
import com.google.common.truth.Truth.assertThat
@@ -32,22 +33,30 @@
@RunWith(AndroidJUnit4::class)
class WorkspaceSpecsTest : AbstractDeviceProfileTest() {
override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+ val deviceSpec = deviceSpecs["phone"]!!
+ val aspectRatio = deviceSpec.naturalSize.first.toFloat() / deviceSpec.naturalSize.second
@Before
fun setup() {
- initializeVarsForPhone(deviceSpecs["phone"]!!)
+ initializeVarsForPhone(deviceSpec)
}
@Test
fun parseValidFile() {
val workspaceSpecs =
- WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
- assertThat(workspaceSpecs.heightSpecs.size).isEqualTo(3)
- assertThat(workspaceSpecs.heightSpecs[0].toString())
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.valid_workspace_file),
+ ResponsiveSpecType.Workspace
+ )
+
+ val specs = workspaceSpecs.getSpecsByAspectRatio(aspectRatio)
+ assertThat(specs.heightSpecs.size).isEqualTo(3)
+ assertThat(specs.heightSpecs[0].toString())
.isEqualTo(
- "WorkspaceSpec(" +
+ "ResponsiveSpec(" +
"maxAvailableSize=1533, " +
- "specType=HEIGHT, " +
+ "dimensionType=HEIGHT, " +
+ "specType=Workspace, " +
"startPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
@@ -70,11 +79,12 @@
"maxSize=2147483647)" +
")"
)
- assertThat(workspaceSpecs.heightSpecs[1].toString())
+ assertThat(specs.heightSpecs[1].toString())
.isEqualTo(
- "WorkspaceSpec(" +
+ "ResponsiveSpec(" +
"maxAvailableSize=1607, " +
- "specType=HEIGHT, " +
+ "dimensionType=HEIGHT, " +
+ "specType=Workspace, " +
"startPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
@@ -97,11 +107,12 @@
"maxSize=2147483647)" +
")"
)
- assertThat(workspaceSpecs.heightSpecs[2].toString())
+ assertThat(specs.heightSpecs[2].toString())
.isEqualTo(
- "WorkspaceSpec(" +
+ "ResponsiveSpec(" +
"maxAvailableSize=26247, " +
- "specType=HEIGHT, " +
+ "dimensionType=HEIGHT, " +
+ "specType=Workspace, " +
"startPadding=SizeSpec(fixedSize=21.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
@@ -124,12 +135,13 @@
"maxSize=2147483647)" +
")"
)
- assertThat(workspaceSpecs.widthSpecs.size).isEqualTo(1)
- assertThat(workspaceSpecs.widthSpecs[0].toString())
+ assertThat(specs.widthSpecs.size).isEqualTo(1)
+ assertThat(specs.widthSpecs[0].toString())
.isEqualTo(
- "WorkspaceSpec(" +
+ "ResponsiveSpec(" +
"maxAvailableSize=26247, " +
- "specType=WIDTH, " +
+ "dimensionType=WIDTH, " +
+ "specType=Workspace, " +
"startPadding=SizeSpec(fixedSize=58.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
@@ -156,29 +168,33 @@
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_missingTag_throwsError() {
- WorkspaceSpecs.create(
- TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_1)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_1),
+ ResponsiveSpecType.Workspace
)
}
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
- WorkspaceSpecs.create(
- TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_2)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_2),
+ ResponsiveSpecType.Workspace
)
}
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_valueBiggerThan1_throwsError() {
- WorkspaceSpecs.create(
- TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_3)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_3),
+ ResponsiveSpecType.Workspace
)
}
@Test(expected = IllegalStateException::class)
fun parseInvalidFile_matchWorkspace_true_throwsError() {
- WorkspaceSpecs.create(
- TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_4)
+ ResponsiveSpecsProvider.create(
+ TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_4),
+ ResponsiveSpecType.Workspace
)
}
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 9bfafcf..8847b8b 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -45,6 +45,7 @@
import android.system.OsConstants;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
@@ -108,7 +109,7 @@
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
protected LooperExecutor mMainThreadExecutor = MAIN_EXECUTOR;
- protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+ protected final UiDevice mDevice = getUiDevice();
protected final LauncherInstrumentation mLauncher = new LauncherInstrumentation();
protected Context mTargetContext;
protected String mTargetPackage;
@@ -160,7 +161,7 @@
if (TestHelpers.isInLauncherProcess()) {
Debug.dumpHprofData(fileName);
} else {
- final UiDevice device = UiDevice.getInstance(getInstrumentation());
+ final UiDevice device = getUiDevice();
device.executeShellCommand(
"am dumpheap " + device.getLauncherPackageName() + " " + fileName);
}
@@ -249,11 +250,6 @@
mLauncher.onTestStart();
waitForSetupWizardDismissal();
- if (TestStabilityRule.isPresubmit()) {
- aggressivelyUnlockSysUi();
- } else {
- verifyKeyguardInvisible();
- }
final String launcherPackageName = mDevice.getLauncherPackageName();
try {
@@ -285,23 +281,38 @@
}
}
- verifyKeyguardInvisible();
+ onTestStart();
}
- private boolean hasSystemUiObject(String resId) {
- return mDevice.hasObject(By.res(SYSTEMUI_PACKAGE, resId));
+ /** Method that should be called when a test starts. */
+ public static void onTestStart() {
+ if (TestStabilityRule.isPresubmit()) {
+ aggressivelyUnlockSysUi();
+ } else {
+ verifyKeyguardInvisible();
+ }
}
- // Seeing if this will decrease: b/303755862
- void aggressivelyUnlockSysUi() {
+ private static boolean hasSystemUiObject(String resId) {
+ return getUiDevice().hasObject(
+ By.res(SYSTEMUI_PACKAGE, resId));
+ }
+
+ @NonNull
+ private static UiDevice getUiDevice() {
+ return UiDevice.getInstance(getInstrumentation());
+ }
+
+ private static void aggressivelyUnlockSysUi() {
+ final UiDevice device = getUiDevice();
for (int i = 0; i < 10 && hasSystemUiObject("keyguard_status_view"); ++i) {
Log.d(TAG, "Before attempting to unlock the phone");
try {
- mDevice.executeShellCommand("input keyevent 82");
+ device.executeShellCommand("input keyevent 82");
} catch (IOException e) {
throw new RuntimeException(e);
}
- mDevice.waitForIdle();
+ device.waitForIdle();
}
Assert.assertTrue("Keyguard still visible",
TestHelpers.wait(
@@ -321,9 +332,11 @@
// TODO(309471958) Productize killing/dismissal of setup wizard.
/** Waits for setup wizard to go away. */
public static void waitForSetupWizardDismissal() {
- if (sFirstTimeWaitingForWizard && TestStabilityRule.isPresubmit()) {
+ if (!TestStabilityRule.isPresubmit()) return;
+
+ if (sFirstTimeWaitingForWizard) {
try {
- UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+ getUiDevice().executeShellCommand(
"am force-stop com.google.android.setupwizard");
} catch (IOException e) {
throw new RuntimeException(e);
@@ -334,12 +347,10 @@
Until.gone(By.pkg("com.google.android.setupwizard").depth(0)),
sFirstTimeWaitingForWizard ? 120000 : 0);
sFirstTimeWaitingForWizard = false;
- // b/309496273
-// Assert.assertTrue("Setup wizard is still visible",
-// wizardDismissed);
+ Assert.assertTrue("Setup wizard is still visible", wizardDismissed);
}
- public static void verifyKeyguardInvisible() {
+ private static void verifyKeyguardInvisible() {
final boolean keyguardAlreadyVisible = sSeenKeyguard;
sSeenKeyguard = sSeenKeyguard
diff --git a/tests/src/com/android/launcher3/util/TestResourceHelper.kt b/tests/src/com/android/launcher3/util/TestResourceHelper.kt
index cf80ece..b4d3ba8 100644
--- a/tests/src/com/android/launcher3/util/TestResourceHelper.kt
+++ b/tests/src/com/android/launcher3/util/TestResourceHelper.kt
@@ -32,6 +32,8 @@
styleId.contentEquals(R.styleable.WorkspaceSpec) -> TestR.styleable.WorkspaceSpec
styleId.contentEquals(R.styleable.FolderSpec) -> TestR.styleable.FolderSpec
styleId.contentEquals(R.styleable.AllAppsSpec) -> TestR.styleable.AllAppsSpec
+ styleId.contentEquals(R.styleable.ResponsiveSpecGroup) ->
+ TestR.styleable.ResponsiveSpecGroup
else -> styleId.clone()
}
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 62d70ad..10b428a 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -59,8 +59,9 @@
throw new AssertionError(
"Launcher received events not sent by the test. This may mean "
+ "that the touch screen of the lab device has sent false"
- + " events. See the logcat for TaplEvents tag and look "
- + "for events with deviceId != -1");
+ + " events. See the logcat for "
+ + "TaplEvents|LauncherEvents|TaplTarget tag and look for "
+ + "events with deviceId != -1");
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 17169b3..e30885b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -564,6 +564,9 @@
if (hasSystemLauncherObject(OVERVIEW_RES_ID)) return "Overview";
if (hasLauncherObject(WORKSPACE_RES_ID)) return "Workspace";
if (hasLauncherObject(APPS_RES_ID)) return "AllApps";
+ if (mDevice.hasObject(By.pkg(getLauncherPackageName()).depth(0))) {
+ return "<Launcher in invalid state>";
+ }
return "LaunchedApp (" + getVisiblePackages() + ")";
}
@@ -2063,6 +2066,7 @@
}
// TODO(b/270393900): Remove with ENABLE_ALL_APPS_SEARCH_IN_TASKBAR flag cleanup.
+
/** Refreshes the known overview target in TIS. */
public void refreshOverviewTarget() {
getTestInfo(TestProtocol.REQUEST_REFRESH_OVERVIEW_TARGET);