Check kotlin format before uploading
This uses ktfmt on the PREUPLOAD hook to check file formatting. Bug: 264851618 Test: manual Change-Id: I8bdeabd9c1ed571a464707e6912419ad3190a169
This commit is contained in:
@@ -1,2 +1,4 @@
|
||||
[Hook Scripts]
|
||||
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --config_xml tools/checkstyle.xml --sha ${PREUPLOAD_COMMIT}
|
||||
|
||||
ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check ${PREUPLOAD_FILES}
|
||||
@@ -16,20 +16,17 @@
|
||||
|
||||
package com.android.launcher3.taskbar
|
||||
|
||||
import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
|
||||
import com.android.launcher3.Utilities.mapToRange
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Path
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities.mapToRange
|
||||
import com.android.launcher3.anim.Interpolators
|
||||
import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
|
||||
import com.android.launcher3.util.DisplayController
|
||||
|
||||
/**
|
||||
* Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners.
|
||||
*/
|
||||
/** Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners. */
|
||||
class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
|
||||
|
||||
val paint: Paint = Paint()
|
||||
@@ -39,7 +36,7 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
|
||||
private var maxBackgroundHeight = context.deviceProfile.taskbarSize.toFloat()
|
||||
private val transientBackgroundBounds = context.transientTaskbarBounds
|
||||
|
||||
private val isTransientTaskbar = DisplayController.isTransientTaskbar(context);
|
||||
private val isTransientTaskbar = DisplayController.isTransientTaskbar(context)
|
||||
|
||||
private var shadowBlur = 0f
|
||||
private var keyShadowDistance = 0f
|
||||
@@ -98,9 +95,7 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
|
||||
invertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE)
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the background with the given paint and height, on the provided canvas.
|
||||
*/
|
||||
/** Draws the background with the given paint and height, on the provided canvas. */
|
||||
fun draw(canvas: Canvas) {
|
||||
canvas.save()
|
||||
canvas.translate(0f, canvas.height - backgroundHeight - bottomMargin)
|
||||
@@ -124,21 +119,26 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
|
||||
canvas.translate(0f, bottomMargin * ((1f - scaleFactor) / 2f))
|
||||
|
||||
// Draw shadow.
|
||||
val shadowAlpha = mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, 25f,
|
||||
Interpolators.LINEAR)
|
||||
paint.setShadowLayer(shadowBlur, 0f, keyShadowDistance,
|
||||
val shadowAlpha =
|
||||
mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, 25f, Interpolators.LINEAR)
|
||||
paint.setShadowLayer(
|
||||
shadowBlur,
|
||||
0f,
|
||||
keyShadowDistance,
|
||||
setColorAlphaBound(Color.BLACK, Math.round(shadowAlpha))
|
||||
)
|
||||
|
||||
// Draw background.
|
||||
val radius = backgroundHeight / 2f;
|
||||
val radius = backgroundHeight / 2f
|
||||
|
||||
canvas.drawRoundRect(
|
||||
transientBackgroundBounds.left + (delta / 2f),
|
||||
translationYForSwipe,
|
||||
transientBackgroundBounds.right - (delta / 2f),
|
||||
backgroundHeight + translationYForSwipe,
|
||||
radius, radius, paint
|
||||
radius,
|
||||
radius,
|
||||
paint
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,10 +36,8 @@ import com.android.launcher3.anim.AlphaUpdateListener
|
||||
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
|
||||
import java.io.PrintWriter
|
||||
|
||||
/**
|
||||
* Handles the insets that Taskbar provides to underlying apps and the IME.
|
||||
*/
|
||||
class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTaskbarController {
|
||||
/** Handles the insets that Taskbar provides to underlying apps and the IME. */
|
||||
class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTaskbarController {
|
||||
|
||||
/** The bottom insets taskbar provides to the IME when IME is visible. */
|
||||
val taskbarHeightForIme: Int = context.resources.getDimensionPixelSize(R.dimen.taskbar_ime_size)
|
||||
@@ -77,13 +75,19 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
|
||||
fun onTaskbarWindowHeightOrInsetsChanged() {
|
||||
val touchableHeight = controllers.taskbarStashController.touchableHeight
|
||||
touchableRegion.set(0, windowLayoutParams.height - touchableHeight,
|
||||
context.deviceProfile.widthPx, windowLayoutParams.height)
|
||||
touchableRegion.set(
|
||||
0,
|
||||
windowLayoutParams.height - touchableHeight,
|
||||
context.deviceProfile.widthPx,
|
||||
windowLayoutParams.height
|
||||
)
|
||||
val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
|
||||
val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
|
||||
for (provider in windowLayoutParams.providedInsets) {
|
||||
if (provider.type == ITYPE_EXTRA_NAVIGATION_BAR
|
||||
|| provider.type == ITYPE_BOTTOM_MANDATORY_GESTURES) {
|
||||
if (
|
||||
provider.type == ITYPE_EXTRA_NAVIGATION_BAR ||
|
||||
provider.type == ITYPE_BOTTOM_MANDATORY_GESTURES
|
||||
) {
|
||||
provider.insetsSize = getInsetsByNavMode(contentHeight)
|
||||
} else if (provider.type == ITYPE_BOTTOM_TAPPABLE_ELEMENT) {
|
||||
provider.insetsSize = getInsetsByNavMode(tappableHeight)
|
||||
@@ -91,24 +95,20 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
}
|
||||
|
||||
val imeInsetsSize = getInsetsByNavMode(taskbarHeightForIme)
|
||||
val insetsSizeOverride = arrayOf(
|
||||
InsetsFrameProvider.InsetsSizeOverride(
|
||||
TYPE_INPUT_METHOD,
|
||||
imeInsetsSize
|
||||
),
|
||||
)
|
||||
val insetsSizeOverride =
|
||||
arrayOf(
|
||||
InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
|
||||
)
|
||||
// Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled.
|
||||
val visInsetsSizeForGestureNavTappableElement = getInsetsByNavMode(0)
|
||||
val insetsSizeOverrideForGestureNavTappableElement = arrayOf(
|
||||
InsetsFrameProvider.InsetsSizeOverride(
|
||||
TYPE_INPUT_METHOD,
|
||||
imeInsetsSize
|
||||
),
|
||||
InsetsFrameProvider.InsetsSizeOverride(
|
||||
TYPE_VOICE_INTERACTION,
|
||||
visInsetsSizeForGestureNavTappableElement
|
||||
),
|
||||
)
|
||||
val insetsSizeOverrideForGestureNavTappableElement =
|
||||
arrayOf(
|
||||
InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
|
||||
InsetsFrameProvider.InsetsSizeOverride(
|
||||
TYPE_VOICE_INTERACTION,
|
||||
visInsetsSizeForGestureNavTappableElement
|
||||
),
|
||||
)
|
||||
for (provider in windowLayoutParams.providedInsets) {
|
||||
if (context.isGestureNav && provider.type == ITYPE_BOTTOM_TAPPABLE_ELEMENT) {
|
||||
provider.insetsSizeOverrides = insetsSizeOverrideForGestureNavTappableElement
|
||||
@@ -120,9 +120,11 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
|
||||
/**
|
||||
* @return [Insets] where the [bottomInset] is either used as a bottom inset or
|
||||
* ```
|
||||
* right/left inset if using 3 button nav
|
||||
* ```
|
||||
*/
|
||||
private fun getInsetsByNavMode(bottomInset: Int) : Insets {
|
||||
private fun getInsetsByNavMode(bottomInset: Int): Insets {
|
||||
val devicePortrait = !context.deviceProfile.isLandscape
|
||||
if (!TaskbarManager.isPhoneButtonNavMode(context) || devicePortrait) {
|
||||
// Taskbar or portrait phone mode
|
||||
@@ -139,9 +141,9 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
* @param providesInsetsTypes The inset types we would like this layout params to provide.
|
||||
*/
|
||||
fun setProvidesInsetsTypes(params: WindowManager.LayoutParams, providesInsetsTypes: IntArray) {
|
||||
params.providedInsets = arrayOfNulls<InsetsFrameProvider>(providesInsetsTypes.size);
|
||||
params.providedInsets = arrayOfNulls<InsetsFrameProvider>(providesInsetsTypes.size)
|
||||
for (i in providesInsetsTypes.indices) {
|
||||
params.providedInsets[i] = InsetsFrameProvider(providesInsetsTypes[i]);
|
||||
params.providedInsets[i] = InsetsFrameProvider(providesInsetsTypes[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,14 +155,17 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
insetsInfo.touchableRegion.setEmpty()
|
||||
// Always have nav buttons be touchable
|
||||
controllers.navbarButtonsViewController.addVisibleButtonsRegion(
|
||||
context.dragLayer, insetsInfo.touchableRegion
|
||||
context.dragLayer,
|
||||
insetsInfo.touchableRegion
|
||||
)
|
||||
var insetsIsTouchableRegion = true
|
||||
if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
|
||||
// Let touches pass through us.
|
||||
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
|
||||
} else if (controllers.navbarButtonsViewController.isImeVisible
|
||||
&& controllers.taskbarStashController.isStashed()) {
|
||||
} else if (
|
||||
controllers.navbarButtonsViewController.isImeVisible &&
|
||||
controllers.taskbarStashController.isStashed()
|
||||
) {
|
||||
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
|
||||
} else if (!controllers.uiController.isTaskbarTouchable) {
|
||||
// Let touches pass through us.
|
||||
@@ -174,9 +179,10 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
insetsInfo.touchableRegion.set(touchableRegion)
|
||||
}
|
||||
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
|
||||
} else if (controllers.taskbarViewController.areIconsVisible()
|
||||
|| AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL)
|
||||
|| context.isNavBarKidsModeActive
|
||||
} else if (
|
||||
controllers.taskbarViewController.areIconsVisible() ||
|
||||
AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL) ||
|
||||
context.isNavBarKidsModeActive
|
||||
) {
|
||||
// Taskbar has some touchable elements, take over the full taskbar area
|
||||
insetsInfo.setTouchableInsets(
|
||||
@@ -198,8 +204,12 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask
|
||||
pw.println(prefix + "TaskbarInsetsController:")
|
||||
pw.println("$prefix\twindowHeight=${windowLayoutParams.height}")
|
||||
for (provider in windowLayoutParams.providedInsets) {
|
||||
pw.print("$prefix\tprovidedInsets: (type=" + InsetsState.typeToString(provider.type)
|
||||
+ " insetsSize=" + provider.insetsSize)
|
||||
pw.print(
|
||||
"$prefix\tprovidedInsets: (type=" +
|
||||
InsetsState.typeToString(provider.type) +
|
||||
" insetsSize=" +
|
||||
provider.insetsSize
|
||||
)
|
||||
if (provider.insetsSizeOverrides != null) {
|
||||
pw.print(" insetsSizeOverrides={")
|
||||
for ((i, overrideSize) in provider.insetsSizeOverrides.withIndex()) {
|
||||
|
||||
@@ -10,12 +10,9 @@ import java.io.PrintWriter
|
||||
private const val TASKBAR_ICONS_FADE_DURATION = 300L
|
||||
private const val STASHED_HANDLE_FADE_DURATION = 180L
|
||||
|
||||
/**
|
||||
* Controls Taskbar behavior while Voice Interaction Window (assistant) is showing.
|
||||
*/
|
||||
class VoiceInteractionWindowController(val context: TaskbarActivityContext)
|
||||
: TaskbarControllers.LoggableTaskbarController,
|
||||
TaskbarControllers.BackgroundRendererController {
|
||||
/** Controls Taskbar behavior while Voice Interaction Window (assistant) is showing. */
|
||||
class VoiceInteractionWindowController(val context: TaskbarActivityContext) :
|
||||
TaskbarControllers.LoggableTaskbarController, TaskbarControllers.BackgroundRendererController {
|
||||
|
||||
private val taskbarBackgroundRenderer = TaskbarBackgroundRenderer(context)
|
||||
|
||||
@@ -37,8 +34,10 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext)
|
||||
|
||||
override fun draw(canvas: Canvas) {
|
||||
super.draw(canvas)
|
||||
if (this@VoiceInteractionWindowController.context.isGestureNav
|
||||
&& controllers.taskbarStashController.isInAppAndNotStashed) {
|
||||
if (
|
||||
this@VoiceInteractionWindowController.context.isGestureNav &&
|
||||
controllers.taskbarStashController.isInAppAndNotStashed
|
||||
) {
|
||||
taskbarBackgroundRenderer.draw(canvas)
|
||||
}
|
||||
}
|
||||
@@ -46,8 +45,8 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext)
|
||||
separateWindowForTaskbarBackground.recreateControllers()
|
||||
separateWindowForTaskbarBackground.setWillNotDraw(false)
|
||||
|
||||
separateWindowLayoutParams = context.createDefaultWindowLayoutParams(
|
||||
TYPE_APPLICATION_OVERLAY)
|
||||
separateWindowLayoutParams =
|
||||
context.createDefaultWindowLayoutParams(TYPE_APPLICATION_OVERLAY)
|
||||
separateWindowLayoutParams.isSystemApplicationOverlay = true
|
||||
}
|
||||
|
||||
@@ -63,14 +62,16 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext)
|
||||
|
||||
// Fade out taskbar icons and stashed handle.
|
||||
val taskbarIconAlpha = if (isVoiceInteractionWindowVisible) 0f else 1f
|
||||
val fadeTaskbarIcons = controllers.taskbarViewController.taskbarIconAlpha
|
||||
.get(TaskbarViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
|
||||
.animateToValue(taskbarIconAlpha)
|
||||
.setDuration(TASKBAR_ICONS_FADE_DURATION)
|
||||
val fadeStashedHandle = controllers.stashedHandleViewController.stashedHandleAlpha
|
||||
.get(StashedHandleViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
|
||||
.animateToValue(taskbarIconAlpha)
|
||||
.setDuration(STASHED_HANDLE_FADE_DURATION)
|
||||
val fadeTaskbarIcons =
|
||||
controllers.taskbarViewController.taskbarIconAlpha
|
||||
.get(TaskbarViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
|
||||
.animateToValue(taskbarIconAlpha)
|
||||
.setDuration(TASKBAR_ICONS_FADE_DURATION)
|
||||
val fadeStashedHandle =
|
||||
controllers.stashedHandleViewController.stashedHandleAlpha
|
||||
.get(StashedHandleViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
|
||||
.animateToValue(taskbarIconAlpha)
|
||||
.setDuration(STASHED_HANDLE_FADE_DURATION)
|
||||
fadeTaskbarIcons.start()
|
||||
fadeStashedHandle.start()
|
||||
if (skipAnim) {
|
||||
@@ -83,23 +84,30 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext)
|
||||
|
||||
/**
|
||||
* Either:
|
||||
*
|
||||
* Hides the TaskbarDragLayer background and creates a new window to draw just that background.
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* Removes the temporary window and show the TaskbarDragLayer background again.
|
||||
*/
|
||||
private fun moveTaskbarBackgroundToAppropriateLayer(skipAnim: Boolean) {
|
||||
val taskbarBackgroundOverride = controllers.taskbarDragLayerController
|
||||
.overrideBackgroundAlpha
|
||||
val taskbarBackgroundOverride =
|
||||
controllers.taskbarDragLayerController.overrideBackgroundAlpha
|
||||
val moveToLowerLayer = isVoiceInteractionWindowVisible
|
||||
val onWindowsSynchronized = if (moveToLowerLayer) {
|
||||
// First add the temporary window, then hide the overlapping taskbar background.
|
||||
context.addWindowView(separateWindowForTaskbarBackground, separateWindowLayoutParams);
|
||||
{ taskbarBackgroundOverride.updateValue(0f) }
|
||||
} else {
|
||||
// First reapply the original taskbar background, then remove the temporary window.
|
||||
taskbarBackgroundOverride.updateValue(1f);
|
||||
{ context.removeWindowView(separateWindowForTaskbarBackground) }
|
||||
}
|
||||
val onWindowsSynchronized =
|
||||
if (moveToLowerLayer) {
|
||||
// First add the temporary window, then hide the overlapping taskbar background.
|
||||
context.addWindowView(
|
||||
separateWindowForTaskbarBackground,
|
||||
separateWindowLayoutParams
|
||||
);
|
||||
{ taskbarBackgroundOverride.updateValue(0f) }
|
||||
} else {
|
||||
// First reapply the original taskbar background, then remove the temporary window.
|
||||
taskbarBackgroundOverride.updateValue(1f);
|
||||
{ context.removeWindowView(separateWindowForTaskbarBackground) }
|
||||
}
|
||||
|
||||
if (skipAnim) {
|
||||
onWindowsSynchronized()
|
||||
@@ -121,4 +129,4 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext)
|
||||
pw.println(prefix + "VoiceInteractionWindowController:")
|
||||
pw.println("$prefix\tisVoiceInteractionWindowVisible=$isVoiceInteractionWindowVisible")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-12
@@ -30,20 +30,17 @@ import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonL
|
||||
* [navButtonContainer]
|
||||
*
|
||||
* @property navButtonContainer ViewGroup that holds the 3 navigation buttons.
|
||||
* @property endContextualContainer ViewGroup that holds the end contextual button (ex, IME dismiss).
|
||||
* @property endContextualContainer ViewGroup that holds the end contextual button (ex, IME
|
||||
* dismiss).
|
||||
* @property startContextualContainer ViewGroup that holds the start contextual button (ex, A11y).
|
||||
*/
|
||||
abstract class AbstractNavButtonLayoutter(
|
||||
val resources: Resources,
|
||||
val navButtonContainer: LinearLayout,
|
||||
protected val endContextualContainer: ViewGroup,
|
||||
protected val startContextualContainer: ViewGroup
|
||||
val resources: Resources,
|
||||
val navButtonContainer: LinearLayout,
|
||||
protected val endContextualContainer: ViewGroup,
|
||||
protected val startContextualContainer: ViewGroup
|
||||
) : NavButtonLayoutter {
|
||||
protected val homeButton: ImageView = navButtonContainer
|
||||
.findViewById(R.id.home)
|
||||
protected val recentsButton: ImageView = navButtonContainer
|
||||
.findViewById(R.id.recent_apps)
|
||||
protected val backButton: ImageView = navButtonContainer
|
||||
.findViewById(R.id.back)
|
||||
protected val homeButton: ImageView = navButtonContainer.findViewById(R.id.home)
|
||||
protected val recentsButton: ImageView = navButtonContainer.findViewById(R.id.recent_apps)
|
||||
protected val backButton: ImageView = navButtonContainer.findViewById(R.id.back)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,56 +28,47 @@ import com.android.launcher3.DeviceProfile
|
||||
import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.*
|
||||
|
||||
class KidsNavLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) : AbstractNavButtonLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) :
|
||||
AbstractNavButtonLayoutter(
|
||||
resources,
|
||||
navBarContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
) {
|
||||
) {
|
||||
|
||||
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
|
||||
val iconSize: Int = resources.getDimensionPixelSize(
|
||||
DIMEN_TASKBAR_ICON_SIZE_KIDS)
|
||||
val buttonWidth: Int = resources.getDimensionPixelSize(
|
||||
DIMEN_TASKBAR_NAV_BUTTONS_WIDTH_KIDS)
|
||||
val buttonHeight: Int = resources.getDimensionPixelSize(
|
||||
DIMEN_TASKBAR_NAV_BUTTONS_HEIGHT_KIDS)
|
||||
val buttonRadius: Int = resources.getDimensionPixelSize(
|
||||
DIMEN_TASKBAR_NAV_BUTTONS_CORNER_RADIUS_KIDS)
|
||||
val iconSize: Int = resources.getDimensionPixelSize(DIMEN_TASKBAR_ICON_SIZE_KIDS)
|
||||
val buttonWidth: Int = resources.getDimensionPixelSize(DIMEN_TASKBAR_NAV_BUTTONS_WIDTH_KIDS)
|
||||
val buttonHeight: Int =
|
||||
resources.getDimensionPixelSize(DIMEN_TASKBAR_NAV_BUTTONS_HEIGHT_KIDS)
|
||||
val buttonRadius: Int =
|
||||
resources.getDimensionPixelSize(DIMEN_TASKBAR_NAV_BUTTONS_CORNER_RADIUS_KIDS)
|
||||
val paddingLeft = (buttonWidth - iconSize) / 2
|
||||
val paddingTop = (buttonHeight - iconSize) / 2
|
||||
|
||||
// Update icons
|
||||
backButton.setImageDrawable(
|
||||
backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS))
|
||||
backButton.setImageDrawable(backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS))
|
||||
backButton.scaleType = ImageView.ScaleType.FIT_CENTER
|
||||
backButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop)
|
||||
homeButton.setImageDrawable(
|
||||
homeButton.getContext().getDrawable(DRAWABLE_SYSBAR_HOME_KIDS))
|
||||
homeButton.setImageDrawable(homeButton.getContext().getDrawable(DRAWABLE_SYSBAR_HOME_KIDS))
|
||||
homeButton.scaleType = ImageView.ScaleType.FIT_CENTER
|
||||
homeButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop)
|
||||
|
||||
// Home button layout
|
||||
val homeLayoutparams = LinearLayout.LayoutParams(
|
||||
buttonWidth,
|
||||
buttonHeight
|
||||
)
|
||||
val homeButtonLeftMargin: Int = resources.getDimensionPixelSize(
|
||||
DIMEN_TASKBAR_HOME_BUTTON_LEFT_MARGIN_KIDS)
|
||||
val homeLayoutparams = LinearLayout.LayoutParams(buttonWidth, buttonHeight)
|
||||
val homeButtonLeftMargin: Int =
|
||||
resources.getDimensionPixelSize(DIMEN_TASKBAR_HOME_BUTTON_LEFT_MARGIN_KIDS)
|
||||
homeLayoutparams.setMargins(homeButtonLeftMargin, 0, 0, 0)
|
||||
homeButton.layoutParams = homeLayoutparams
|
||||
|
||||
// Back button layout
|
||||
val backLayoutParams = LinearLayout.LayoutParams(
|
||||
buttonWidth,
|
||||
buttonHeight
|
||||
)
|
||||
val backButtonLeftMargin: Int = resources.getDimensionPixelSize(
|
||||
DIMEN_TASKBAR_BACK_BUTTON_LEFT_MARGIN_KIDS)
|
||||
val backLayoutParams = LinearLayout.LayoutParams(buttonWidth, buttonHeight)
|
||||
val backButtonLeftMargin: Int =
|
||||
resources.getDimensionPixelSize(DIMEN_TASKBAR_BACK_BUTTON_LEFT_MARGIN_KIDS)
|
||||
backLayoutParams.setMargins(backButtonLeftMargin, 0, 0, 0)
|
||||
backButton.layoutParams = backLayoutParams
|
||||
|
||||
@@ -99,4 +90,4 @@ class KidsNavLayoutter(
|
||||
|
||||
homeButton.onLongClickListener = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,9 @@ import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonL
|
||||
/**
|
||||
* Select the correct layout for nav buttons
|
||||
*
|
||||
* Since layouts are done dynamically for the nav buttons on Taskbar, this
|
||||
* class returns a corresponding [NavButtonLayoutter] via
|
||||
* [Companion.getUiLayoutter]
|
||||
* that can help position the buttons based on the current [DeviceProfile]
|
||||
* Since layouts are done dynamically for the nav buttons on Taskbar, this class returns a
|
||||
* corresponding [NavButtonLayoutter] via [Companion.getUiLayoutter] that can help position the
|
||||
* buttons based on the current [DeviceProfile]
|
||||
*/
|
||||
class NavButtonLayoutFactory {
|
||||
companion object {
|
||||
@@ -39,11 +38,10 @@ class NavButtonLayoutFactory {
|
||||
* Get the correct instance of [NavButtonLayoutter]
|
||||
*
|
||||
* No layouts supported for configurations where:
|
||||
* * taskbar isn't showing AND
|
||||
* * the device is not in [phoneMode]
|
||||
* OR
|
||||
* * phone is showing
|
||||
* * device is using gesture navigation
|
||||
* * taskbar isn't showing AND
|
||||
* * the device is not in [phoneMode] OR
|
||||
* * phone is showing
|
||||
* * device is using gesture navigation
|
||||
*
|
||||
* @param navButtonsView ViewGroup that contains start, end, nav button ViewGroups
|
||||
* @param isKidsMode no-op when taskbar is hidden/not showing
|
||||
@@ -51,44 +49,64 @@ class NavButtonLayoutFactory {
|
||||
* @param phoneMode refers to the device using the taskbar window on phones
|
||||
* @param isThreeButtonNav are no-ops when taskbar is present/showing
|
||||
*/
|
||||
fun getUiLayoutter(deviceProfile: DeviceProfile,
|
||||
navButtonsView: FrameLayout,
|
||||
resources: Resources,
|
||||
isKidsMode: Boolean,
|
||||
isInSetup: Boolean,
|
||||
isThreeButtonNav: Boolean,
|
||||
phoneMode: Boolean):
|
||||
NavButtonLayoutter {
|
||||
val navButtonContainer =
|
||||
navButtonsView.findViewById<LinearLayout>(ID_END_NAV_BUTTONS)
|
||||
fun getUiLayoutter(
|
||||
deviceProfile: DeviceProfile,
|
||||
navButtonsView: FrameLayout,
|
||||
resources: Resources,
|
||||
isKidsMode: Boolean,
|
||||
isInSetup: Boolean,
|
||||
isThreeButtonNav: Boolean,
|
||||
phoneMode: Boolean
|
||||
): NavButtonLayoutter {
|
||||
val navButtonContainer = navButtonsView.findViewById<LinearLayout>(ID_END_NAV_BUTTONS)
|
||||
val endContextualContainer =
|
||||
navButtonsView.findViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
|
||||
navButtonsView.findViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
|
||||
val startContextualContainer =
|
||||
navButtonsView.findViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
|
||||
navButtonsView.findViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
|
||||
val isPhoneNavMode = phoneMode && isThreeButtonNav
|
||||
return when {
|
||||
isPhoneNavMode -> {
|
||||
if (!deviceProfile.isLandscape) {
|
||||
PhonePortraitNavLayoutter(resources, navButtonContainer,
|
||||
endContextualContainer, startContextualContainer)
|
||||
PhonePortraitNavLayoutter(
|
||||
resources,
|
||||
navButtonContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
)
|
||||
} else {
|
||||
PhoneLandscapeNavLayoutter(resources, navButtonContainer,
|
||||
endContextualContainer, startContextualContainer)
|
||||
PhoneLandscapeNavLayoutter(
|
||||
resources,
|
||||
navButtonContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
)
|
||||
}
|
||||
}
|
||||
deviceProfile.isTaskbarPresent -> {
|
||||
return when {
|
||||
isInSetup -> {
|
||||
SetupNavLayoutter(resources, navButtonContainer, endContextualContainer,
|
||||
startContextualContainer)
|
||||
SetupNavLayoutter(
|
||||
resources,
|
||||
navButtonContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
)
|
||||
}
|
||||
isKidsMode -> {
|
||||
KidsNavLayoutter(resources, navButtonContainer, endContextualContainer,
|
||||
startContextualContainer)
|
||||
KidsNavLayoutter(
|
||||
resources,
|
||||
navButtonContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
)
|
||||
}
|
||||
else ->
|
||||
TaskbarNavLayoutter(resources, navButtonContainer, endContextualContainer,
|
||||
startContextualContainer)
|
||||
TaskbarNavLayoutter(
|
||||
resources,
|
||||
navButtonContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> error("No layoutter found")
|
||||
@@ -96,8 +114,8 @@ class NavButtonLayoutFactory {
|
||||
}
|
||||
}
|
||||
|
||||
/** Lays out and provides access to the home, recents, and back buttons for various mischief */
|
||||
/** Lays out and provides access to the home, recents, and back buttons for various mischief */
|
||||
interface NavButtonLayoutter {
|
||||
fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -28,24 +28,24 @@ import com.android.launcher3.taskbar.TaskbarManager
|
||||
import com.android.launcher3.util.DimensionUtils
|
||||
|
||||
class PhoneLandscapeNavLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) : AbstractNavButtonLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) :
|
||||
AbstractNavButtonLayoutter(
|
||||
resources,
|
||||
navBarContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
) {
|
||||
) {
|
||||
|
||||
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
|
||||
// TODO(b/230395757): Polish pending, this is just to make it usable
|
||||
val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
|
||||
val endStartMargins =
|
||||
resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
|
||||
val taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(dp, resources,
|
||||
TaskbarManager.isPhoneMode(dp))
|
||||
val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
|
||||
val taskbarDimensions =
|
||||
DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp))
|
||||
navButtonContainer.removeAllViews()
|
||||
navButtonContainer.orientation = LinearLayout.VERTICAL
|
||||
|
||||
@@ -68,7 +68,7 @@ class PhoneLandscapeNavLayoutter(
|
||||
|
||||
// Add the spaces in between the nav buttons
|
||||
val spaceInBetween: Int =
|
||||
resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
|
||||
resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
|
||||
navButtonContainer.children.forEachIndexed { i, navButton ->
|
||||
val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
|
||||
buttonLayoutParams.weight = 1f
|
||||
@@ -86,4 +86,4 @@ class PhoneLandscapeNavLayoutter(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,17 +26,24 @@ import com.android.launcher3.R
|
||||
import com.android.launcher3.taskbar.TaskbarManager
|
||||
import com.android.launcher3.util.DimensionUtils
|
||||
|
||||
class PhonePortraitNavLayoutter(resources: Resources, navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup) :
|
||||
AbstractNavButtonLayoutter(resources, navBarContainer, endContextualContainer,
|
||||
startContextualContainer) {
|
||||
class PhonePortraitNavLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) :
|
||||
AbstractNavButtonLayoutter(
|
||||
resources,
|
||||
navBarContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
) {
|
||||
|
||||
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
|
||||
// TODO(b/230395757): Polish pending, this is just to make it usable
|
||||
val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
|
||||
val taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(dp, resources,
|
||||
TaskbarManager.isPhoneMode(dp))
|
||||
val taskbarDimensions =
|
||||
DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp))
|
||||
val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
|
||||
navContainerParams.width = taskbarDimensions.x
|
||||
navContainerParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
@@ -58,7 +65,7 @@ class PhonePortraitNavLayoutter(resources: Resources, navBarContainer: LinearLay
|
||||
|
||||
// Add the spaces in between the nav buttons
|
||||
val spaceInBetween =
|
||||
resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
|
||||
resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone)
|
||||
for (i in 0 until navButtonContainer.childCount) {
|
||||
val navButton = navButtonContainer.getChildAt(i)
|
||||
val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
|
||||
@@ -80,4 +87,4 @@ class PhonePortraitNavLayoutter(resources: Resources, navBarContainer: LinearLay
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,17 @@ import android.widget.LinearLayout
|
||||
import com.android.launcher3.DeviceProfile
|
||||
|
||||
class SetupNavLayoutter(
|
||||
resources: Resources,
|
||||
navButtonContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) : AbstractNavButtonLayoutter(
|
||||
resources: Resources,
|
||||
navButtonContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) :
|
||||
AbstractNavButtonLayoutter(
|
||||
resources,
|
||||
navButtonContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
) {
|
||||
) {
|
||||
|
||||
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
|
||||
// Since setup wizard only has back button enabled, it looks strange to be
|
||||
@@ -46,4 +47,4 @@ class SetupNavLayoutter(
|
||||
}
|
||||
navButtonContainer.requestLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,20 +24,19 @@ import android.widget.LinearLayout
|
||||
import com.android.launcher3.DeviceProfile
|
||||
import com.android.launcher3.R
|
||||
|
||||
/**
|
||||
* Layoutter for showing 3 button navigation on large screen
|
||||
*/
|
||||
/** Layoutter for showing 3 button navigation on large screen */
|
||||
class TaskbarNavLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) : AbstractNavButtonLayoutter(
|
||||
resources: Resources,
|
||||
navBarContainer: LinearLayout,
|
||||
endContextualContainer: ViewGroup,
|
||||
startContextualContainer: ViewGroup
|
||||
) :
|
||||
AbstractNavButtonLayoutter(
|
||||
resources,
|
||||
navBarContainer,
|
||||
endContextualContainer,
|
||||
startContextualContainer
|
||||
) {
|
||||
) {
|
||||
|
||||
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
|
||||
// Add spacing after the end of the last nav button
|
||||
@@ -80,4 +79,4 @@ class TaskbarNavLayoutter(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,14 @@ import com.android.internal.logging.InstanceIdSequence
|
||||
import com.android.launcher3.logging.InstanceId
|
||||
|
||||
object LogUtils {
|
||||
/**
|
||||
* @return a [Pair] of two InstanceIds but with different types, one that can be used by framework
|
||||
* (if needing to pass through an intent or such) and one used in Launcher
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getShellShareableInstanceId():
|
||||
Pair<com.android.internal.logging.InstanceId, InstanceId> {
|
||||
val internalInstanceId = InstanceIdSequence(InstanceId.INSTANCE_ID_MAX).newInstanceId()
|
||||
val launcherInstanceId = InstanceId(internalInstanceId.id)
|
||||
return Pair(internalInstanceId, launcherInstanceId)
|
||||
}
|
||||
/**
|
||||
* @return a [Pair] of two InstanceIds but with different types, one that can be used by
|
||||
* framework (if needing to pass through an intent or such) and one used in Launcher
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getShellShareableInstanceId(): Pair<com.android.internal.logging.InstanceId, InstanceId> {
|
||||
val internalInstanceId = InstanceIdSequence(InstanceId.INSTANCE_ID_MAX).newInstanceId()
|
||||
val launcherInstanceId = InstanceId(internalInstanceId.id)
|
||||
return Pair(internalInstanceId, launcherInstanceId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,13 +48,15 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
taskContainer: TaskIdAttributeContainer,
|
||||
alignSecondRow: Boolean = false
|
||||
): Boolean {
|
||||
val activity = BaseDraggingActivity
|
||||
.fromContext<BaseDraggingActivity>(taskContainer.taskView.context)
|
||||
val taskMenuViewWithArrow = activity.layoutInflater
|
||||
.inflate(
|
||||
R.layout.task_menu_with_arrow,
|
||||
activity.dragLayer,
|
||||
false
|
||||
val activity =
|
||||
BaseDraggingActivity.fromContext<BaseDraggingActivity>(
|
||||
taskContainer.taskView.context
|
||||
)
|
||||
val taskMenuViewWithArrow =
|
||||
activity.layoutInflater.inflate(
|
||||
R.layout.task_menu_with_arrow,
|
||||
activity.dragLayer,
|
||||
false
|
||||
) as TaskMenuViewWithArrow<*>
|
||||
|
||||
return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignSecondRow)
|
||||
@@ -63,11 +65,11 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
)
|
||||
constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet,
|
||||
defStyleAttr: Int
|
||||
) : super(context, attrs, defStyleAttr)
|
||||
|
||||
init {
|
||||
clipToOutline = true
|
||||
@@ -91,10 +93,10 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
|
||||
private var optionMeasuredHeight = 0
|
||||
private val arrowHorizontalPadding: Int
|
||||
get() = if (taskView.isFocusedTask)
|
||||
resources.getDimensionPixelSize(R.dimen.task_menu_horizontal_padding)
|
||||
else
|
||||
0
|
||||
get() =
|
||||
if (taskView.isFocusedTask)
|
||||
resources.getDimensionPixelSize(R.dimen.task_menu_horizontal_padding)
|
||||
else 0
|
||||
|
||||
private var iconView: IconView? = null
|
||||
private var scrim: View? = null
|
||||
@@ -139,19 +141,20 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
}
|
||||
|
||||
private fun addScrim() {
|
||||
scrim = View(context).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
setBackgroundColor(Themes.getAttrColor(context, R.attr.overviewScrimColor))
|
||||
alpha = 0f
|
||||
}
|
||||
scrim =
|
||||
View(context).apply {
|
||||
layoutParams =
|
||||
FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
setBackgroundColor(Themes.getAttrColor(context, R.attr.overviewScrimColor))
|
||||
alpha = 0f
|
||||
}
|
||||
popupContainer.addView(scrim)
|
||||
}
|
||||
|
||||
/** @return true if successfully able to populate task view menu, false otherwise
|
||||
*/
|
||||
/** @return true if successfully able to populate task view menu, false otherwise */
|
||||
private fun populateMenu(): Boolean {
|
||||
// Icon may not be loaded
|
||||
if (taskContainer.task.icon == null) return false
|
||||
@@ -162,9 +165,9 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
|
||||
private fun addMenuOptions() {
|
||||
// Add the options
|
||||
TaskOverlayFactory
|
||||
.getEnabledShortcuts(taskView, taskContainer)
|
||||
.forEach { this.addMenuOption(it) }
|
||||
TaskOverlayFactory.getEnabledShortcuts(taskView, taskContainer).forEach {
|
||||
this.addMenuOption(it)
|
||||
}
|
||||
|
||||
// Add the spaces between items
|
||||
val divider = ShapeDrawable(RectShape())
|
||||
@@ -185,9 +188,9 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
}
|
||||
|
||||
private fun addMenuOption(menuOption: SystemShortcut<*>) {
|
||||
val menuOptionView = mActivityContext.layoutInflater.inflate(
|
||||
R.layout.task_view_menu_option, this, false
|
||||
) as LinearLayout
|
||||
val menuOptionView =
|
||||
mActivityContext.layoutInflater.inflate(R.layout.task_view_menu_option, this, false)
|
||||
as LinearLayout
|
||||
menuOption.setIconAndLabelFor(
|
||||
menuOptionView.findViewById(R.id.icon),
|
||||
menuOptionView.findViewById(R.id.text)
|
||||
@@ -230,24 +233,25 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the iconView from taskView to dragLayer so it can stay on top of the scrim.
|
||||
* It needs to be called after [getTargetObjectLocation] because [mTempRect] needs to be
|
||||
* populated.
|
||||
* Copy the iconView from taskView to dragLayer so it can stay on top of the scrim. It needs to
|
||||
* be called after [getTargetObjectLocation] because [mTempRect] needs to be populated.
|
||||
*/
|
||||
private fun copyIconToDragLayer(insets: Rect) {
|
||||
iconView = IconView(context).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
taskContainer.iconView.width,
|
||||
taskContainer.iconView.height
|
||||
)
|
||||
x = mTempRect.left.toFloat() - insets.left
|
||||
y = mTempRect.top.toFloat() - insets.top
|
||||
drawable = taskContainer.iconView.drawable
|
||||
setDrawableSize(
|
||||
taskContainer.iconView.drawableWidth,
|
||||
taskContainer.iconView.drawableHeight
|
||||
)
|
||||
}
|
||||
iconView =
|
||||
IconView(context).apply {
|
||||
layoutParams =
|
||||
FrameLayout.LayoutParams(
|
||||
taskContainer.iconView.width,
|
||||
taskContainer.iconView.height
|
||||
)
|
||||
x = mTempRect.left.toFloat() - insets.left
|
||||
y = mTempRect.top.toFloat() - insets.top
|
||||
drawable = taskContainer.iconView.drawable
|
||||
setDrawableSize(
|
||||
taskContainer.iconView.drawableWidth,
|
||||
taskContainer.iconView.drawableHeight
|
||||
)
|
||||
}
|
||||
|
||||
popupContainer.addView(iconView)
|
||||
}
|
||||
@@ -281,12 +285,13 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
// which means the arrow is left aligned with the menu
|
||||
val rightAlignedMenuStartX = mTempRect.left - widthWithArrow
|
||||
val leftAlignedMenuStartX = mTempRect.right + extraHorizontalSpace
|
||||
mIsLeftAligned = if (mIsRtl) {
|
||||
rightAlignedMenuStartX + insets.left < 0
|
||||
} else {
|
||||
leftAlignedMenuStartX + (widthWithArrow - extraHorizontalSpace) + insets.left <
|
||||
mIsLeftAligned =
|
||||
if (mIsRtl) {
|
||||
rightAlignedMenuStartX + insets.left < 0
|
||||
} else {
|
||||
leftAlignedMenuStartX + (widthWithArrow - extraHorizontalSpace) + insets.left <
|
||||
dragLayer.width - insets.right
|
||||
}
|
||||
}
|
||||
|
||||
var menuStartX = if (mIsLeftAligned) leftAlignedMenuStartX else rightAlignedMenuStartX
|
||||
|
||||
@@ -311,8 +316,8 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
override fun addArrow() {
|
||||
popupContainer.addView(mArrow)
|
||||
mArrow.x = getArrowX()
|
||||
mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2) +
|
||||
extraSpaceForSecondRowAlignment
|
||||
mArrow.y =
|
||||
y + (optionMeasuredHeight / 2) - (mArrowHeight / 2) + extraSpaceForSecondRowAlignment
|
||||
|
||||
updateArrowColor()
|
||||
|
||||
@@ -322,22 +327,19 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
}
|
||||
|
||||
private fun getArrowX(): Float {
|
||||
return if (mIsLeftAligned)
|
||||
x - mArrowHeight
|
||||
else
|
||||
x + measuredWidth + mArrowOffsetVertical
|
||||
return if (mIsLeftAligned) x - mArrowHeight else x + measuredWidth + mArrowOffsetVertical
|
||||
}
|
||||
|
||||
override fun updateArrowColor() {
|
||||
mArrow.background = RoundedArrowDrawable(
|
||||
mArrowWidth.toFloat(),
|
||||
mArrowHeight.toFloat(),
|
||||
mArrowPointRadius.toFloat(),
|
||||
mIsLeftAligned,
|
||||
mArrowColor
|
||||
)
|
||||
mArrow.background =
|
||||
RoundedArrowDrawable(
|
||||
mArrowWidth.toFloat(),
|
||||
mArrowHeight.toFloat(),
|
||||
mArrowPointRadius.toFloat(),
|
||||
mIsLeftAligned,
|
||||
mArrowColor
|
||||
)
|
||||
elevation = mElevation
|
||||
mArrow.elevation = mElevation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+71
-47
@@ -8,38 +8,29 @@ import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.launcher3.DeviceProfile
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.taskbar.TaskbarManager
|
||||
import java.lang.IllegalStateException
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import com.android.launcher3.R
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class NavButtonLayoutFactoryTest {
|
||||
|
||||
@Mock
|
||||
lateinit var mockDeviceProfile: DeviceProfile
|
||||
@Mock
|
||||
lateinit var mockParentButtonContainer: FrameLayout
|
||||
@Mock
|
||||
lateinit var mockNavLayout: LinearLayout
|
||||
@Mock
|
||||
lateinit var mockStartContextualLayout: ViewGroup
|
||||
@Mock
|
||||
lateinit var mockEndContextualLayout: ViewGroup
|
||||
@Mock
|
||||
lateinit var mockResources: Resources
|
||||
@Mock
|
||||
lateinit var mockBackButton: ImageView
|
||||
@Mock
|
||||
lateinit var mockRecentsButton: ImageView
|
||||
@Mock
|
||||
lateinit var mockHomeButton: ImageView
|
||||
@Mock lateinit var mockDeviceProfile: DeviceProfile
|
||||
@Mock lateinit var mockParentButtonContainer: FrameLayout
|
||||
@Mock lateinit var mockNavLayout: LinearLayout
|
||||
@Mock lateinit var mockStartContextualLayout: ViewGroup
|
||||
@Mock lateinit var mockEndContextualLayout: ViewGroup
|
||||
@Mock lateinit var mockResources: Resources
|
||||
@Mock lateinit var mockBackButton: ImageView
|
||||
@Mock lateinit var mockRecentsButton: ImageView
|
||||
@Mock lateinit var mockHomeButton: ImageView
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@@ -53,11 +44,11 @@ class NavButtonLayoutFactoryTest {
|
||||
|
||||
// Init top level layout
|
||||
whenever(mockParentButtonContainer.findViewById<LinearLayout>(R.id.end_nav_buttons))
|
||||
.thenReturn(mockNavLayout)
|
||||
.thenReturn(mockNavLayout)
|
||||
whenever(mockParentButtonContainer.findViewById<ViewGroup>(R.id.end_contextual_buttons))
|
||||
.thenReturn(mockEndContextualLayout)
|
||||
.thenReturn(mockEndContextualLayout)
|
||||
whenever(mockParentButtonContainer.findViewById<ViewGroup>(R.id.start_contextual_buttons))
|
||||
.thenReturn(mockStartContextualLayout)
|
||||
.thenReturn(mockStartContextualLayout)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,8 +56,12 @@ class NavButtonLayoutFactoryTest {
|
||||
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
|
||||
mockDeviceProfile.isTaskbarPresent = true
|
||||
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
|
||||
getLayoutter(isKidsMode = true, isInSetup = false, isThreeButtonNav = false,
|
||||
phoneMode = false)
|
||||
getLayoutter(
|
||||
isKidsMode = true,
|
||||
isInSetup = false,
|
||||
isThreeButtonNav = false,
|
||||
phoneMode = false
|
||||
)
|
||||
assert(layoutter is KidsNavLayoutter)
|
||||
}
|
||||
|
||||
@@ -75,8 +70,12 @@ class NavButtonLayoutFactoryTest {
|
||||
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
|
||||
mockDeviceProfile.isTaskbarPresent = true
|
||||
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
|
||||
getLayoutter(isKidsMode = false, isInSetup = true, isThreeButtonNav = false,
|
||||
phoneMode = false)
|
||||
getLayoutter(
|
||||
isKidsMode = false,
|
||||
isInSetup = true,
|
||||
isThreeButtonNav = false,
|
||||
phoneMode = false
|
||||
)
|
||||
assert(layoutter is SetupNavLayoutter)
|
||||
}
|
||||
|
||||
@@ -85,8 +84,12 @@ class NavButtonLayoutFactoryTest {
|
||||
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
|
||||
mockDeviceProfile.isTaskbarPresent = true
|
||||
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
|
||||
getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = false,
|
||||
phoneMode = false)
|
||||
getLayoutter(
|
||||
isKidsMode = false,
|
||||
isInSetup = false,
|
||||
isThreeButtonNav = false,
|
||||
phoneMode = false
|
||||
)
|
||||
assert(layoutter is TaskbarNavLayoutter)
|
||||
}
|
||||
|
||||
@@ -94,8 +97,12 @@ class NavButtonLayoutFactoryTest {
|
||||
fun noValidLayoutForLargeScreenTaskbarNotPresent() {
|
||||
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
|
||||
mockDeviceProfile.isTaskbarPresent = false
|
||||
getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = false,
|
||||
phoneMode = false)
|
||||
getLayoutter(
|
||||
isKidsMode = false,
|
||||
isInSetup = false,
|
||||
isThreeButtonNav = false,
|
||||
phoneMode = false
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -103,8 +110,12 @@ class NavButtonLayoutFactoryTest {
|
||||
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
|
||||
mockDeviceProfile.isTaskbarPresent = false
|
||||
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
|
||||
getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = true,
|
||||
phoneMode = true)
|
||||
getLayoutter(
|
||||
isKidsMode = false,
|
||||
isInSetup = false,
|
||||
isThreeButtonNav = true,
|
||||
phoneMode = true
|
||||
)
|
||||
assert(layoutter is PhonePortraitNavLayoutter)
|
||||
}
|
||||
|
||||
@@ -114,8 +125,12 @@ class NavButtonLayoutFactoryTest {
|
||||
mockDeviceProfile.isTaskbarPresent = false
|
||||
setDeviceProfileLandscape()
|
||||
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
|
||||
getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = true,
|
||||
phoneMode = true)
|
||||
getLayoutter(
|
||||
isKidsMode = false,
|
||||
isInSetup = false,
|
||||
isThreeButtonNav = true,
|
||||
phoneMode = true
|
||||
)
|
||||
assert(layoutter is PhoneLandscapeNavLayoutter)
|
||||
}
|
||||
|
||||
@@ -123,8 +138,12 @@ class NavButtonLayoutFactoryTest {
|
||||
fun noValidLayoutForPhoneGestureNav() {
|
||||
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
|
||||
mockDeviceProfile.isTaskbarPresent = false
|
||||
getLayoutter(isKidsMode = false, isInSetup = false, isThreeButtonNav = false,
|
||||
phoneMode = true)
|
||||
getLayoutter(
|
||||
isKidsMode = false,
|
||||
isInSetup = false,
|
||||
isThreeButtonNav = false,
|
||||
phoneMode = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun setDeviceProfileLandscape() {
|
||||
@@ -134,15 +153,20 @@ class NavButtonLayoutFactoryTest {
|
||||
landscapeField.set(mockDeviceProfile, true)
|
||||
}
|
||||
|
||||
private fun getLayoutter(isKidsMode: Boolean, isInSetup: Boolean,
|
||||
isThreeButtonNav: Boolean, phoneMode: Boolean):
|
||||
NavButtonLayoutFactory.NavButtonLayoutter {
|
||||
private fun getLayoutter(
|
||||
isKidsMode: Boolean,
|
||||
isInSetup: Boolean,
|
||||
isThreeButtonNav: Boolean,
|
||||
phoneMode: Boolean
|
||||
): NavButtonLayoutFactory.NavButtonLayoutter {
|
||||
return NavButtonLayoutFactory.getUiLayoutter(
|
||||
deviceProfile = mockDeviceProfile,
|
||||
navButtonsView = mockParentButtonContainer,
|
||||
resources = mockResources,
|
||||
isKidsMode = isKidsMode, isInSetup = isInSetup,
|
||||
isThreeButtonNav = isThreeButtonNav, phoneMode = phoneMode
|
||||
deviceProfile = mockDeviceProfile,
|
||||
navButtonsView = mockParentButtonContainer,
|
||||
resources = mockResources,
|
||||
isKidsMode = isKidsMode,
|
||||
isInSetup = isInSetup,
|
||||
isThreeButtonNav = isThreeButtonNav,
|
||||
phoneMode = phoneMode
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,15 +27,13 @@ import com.android.systemui.shared.recents.model.ThumbnailData
|
||||
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
|
||||
import com.android.wm.shell.util.SplitBounds
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlin.math.roundToInt
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.mock
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Test for FullscreenDrawParams class.
|
||||
*/
|
||||
/** Test for FullscreenDrawParams class. */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
|
||||
@@ -61,15 +59,29 @@ class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
|
||||
val currentRotation = 0
|
||||
val isRtl = false
|
||||
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
|
||||
canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
|
||||
isRtl)
|
||||
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(
|
||||
previewRect,
|
||||
mThumbnailData,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
dp.widthPx,
|
||||
dp.heightPx,
|
||||
dp.taskbarSize,
|
||||
dp.isTablet,
|
||||
currentRotation,
|
||||
isRtl
|
||||
)
|
||||
params.setProgress(
|
||||
/* fullscreenProgress= */ 1.0f,
|
||||
/* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f,
|
||||
/* previewWidth= */ 0,
|
||||
dp,
|
||||
mPreviewPositionHelper
|
||||
)
|
||||
|
||||
val expectedClippedInsets = RectF(0f, 0f, 0f, dp.taskbarSize * TASK_SCALE)
|
||||
assertThat(params.mCurrentDrawnInsets)
|
||||
.isEqualTo(expectedClippedInsets)
|
||||
assertThat(params.mCurrentDrawnInsets).isEqualTo(expectedClippedInsets)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,25 +95,42 @@ class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
|
||||
val isRtl = false
|
||||
// portrait/vertical split apps
|
||||
val dividerSize = 10
|
||||
val splitBounds = SplitBounds(
|
||||
val splitBounds =
|
||||
SplitBounds(
|
||||
Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
|
||||
Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
|
||||
0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
|
||||
0 /*lefTopTaskId*/,
|
||||
0 /*rightBottomTaskId*/
|
||||
)
|
||||
mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
|
||||
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
|
||||
canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
|
||||
isRtl)
|
||||
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(
|
||||
previewRect,
|
||||
mThumbnailData,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
dp.widthPx,
|
||||
dp.heightPx,
|
||||
dp.taskbarSize,
|
||||
dp.isTablet,
|
||||
currentRotation,
|
||||
isRtl
|
||||
)
|
||||
params.setProgress(
|
||||
/* fullscreenProgress= */ 1.0f,
|
||||
/* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f,
|
||||
/* previewWidth= */ 0,
|
||||
dp,
|
||||
mPreviewPositionHelper
|
||||
)
|
||||
|
||||
// Probably unhelpful, but also unclear how to test otherwise ¯\_(ツ)_/¯
|
||||
val fullscreenTaskHeight = dp.heightPx *
|
||||
(1 - (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent))
|
||||
val fullscreenTaskHeight =
|
||||
dp.heightPx * (1 - (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent))
|
||||
val canvasScreenRatio = canvasHeight / fullscreenTaskHeight
|
||||
val expectedBottomHint = dp.taskbarSize * canvasScreenRatio
|
||||
assertThat(params.mCurrentDrawnInsets.bottom)
|
||||
.isWithin(1f).of(expectedBottomHint)
|
||||
assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of(expectedBottomHint)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -115,20 +144,37 @@ class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
|
||||
val isRtl = false
|
||||
// portrait/vertical split apps
|
||||
val dividerSize = 10
|
||||
val splitBounds = SplitBounds(
|
||||
val splitBounds =
|
||||
SplitBounds(
|
||||
Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
|
||||
Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
|
||||
0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
|
||||
0 /*lefTopTaskId*/,
|
||||
0 /*rightBottomTaskId*/
|
||||
)
|
||||
mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_TOP_OR_LEFT)
|
||||
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
|
||||
canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
|
||||
isRtl)
|
||||
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(
|
||||
previewRect,
|
||||
mThumbnailData,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
dp.widthPx,
|
||||
dp.heightPx,
|
||||
dp.taskbarSize,
|
||||
dp.isTablet,
|
||||
currentRotation,
|
||||
isRtl
|
||||
)
|
||||
params.setProgress(
|
||||
/* fullscreenProgress= */ 1.0f,
|
||||
/* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f,
|
||||
/* previewWidth= */ 0,
|
||||
dp,
|
||||
mPreviewPositionHelper
|
||||
)
|
||||
|
||||
assertThat(params.mCurrentDrawnInsets.bottom)
|
||||
.isWithin(1f).of((0f))
|
||||
assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of((0f))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -142,20 +188,37 @@ class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
|
||||
val isRtl = false
|
||||
// portrait/vertical split apps
|
||||
val dividerSize = 10
|
||||
val splitBounds = SplitBounds(
|
||||
val splitBounds =
|
||||
SplitBounds(
|
||||
Rect(0, 0, (dp.widthPx - dividerSize) / 2, dp.heightPx),
|
||||
Rect((dp.widthPx + dividerSize) / 2, 0, dp.widthPx, dp.heightPx),
|
||||
0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
|
||||
0 /*lefTopTaskId*/,
|
||||
0 /*rightBottomTaskId*/
|
||||
)
|
||||
mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
|
||||
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
|
||||
canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
|
||||
isRtl)
|
||||
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(
|
||||
previewRect,
|
||||
mThumbnailData,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
dp.widthPx,
|
||||
dp.heightPx,
|
||||
dp.taskbarSize,
|
||||
dp.isTablet,
|
||||
currentRotation,
|
||||
isRtl
|
||||
)
|
||||
params.setProgress(
|
||||
/* fullscreenProgress= */ 1.0f,
|
||||
/* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f,
|
||||
/* previewWidth= */ 0,
|
||||
dp,
|
||||
mPreviewPositionHelper
|
||||
)
|
||||
|
||||
assertThat(params.mCurrentDrawnInsets.bottom)
|
||||
.isWithin(1f).of((dp.taskbarSize * TASK_SCALE))
|
||||
assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of((dp.taskbarSize * TASK_SCALE))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -168,14 +231,28 @@ class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
|
||||
val currentRotation = 0
|
||||
val isRtl = false
|
||||
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
|
||||
canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
|
||||
isRtl)
|
||||
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(
|
||||
previewRect,
|
||||
mThumbnailData,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
dp.widthPx,
|
||||
dp.heightPx,
|
||||
dp.taskbarSize,
|
||||
dp.isTablet,
|
||||
currentRotation,
|
||||
isRtl
|
||||
)
|
||||
params.setProgress(
|
||||
/* fullscreenProgress= */ 1.0f,
|
||||
/* parentScale= */ 1.0f,
|
||||
/* taskViewScale= */ 1.0f,
|
||||
/* previewWidth= */ 0,
|
||||
dp,
|
||||
mPreviewPositionHelper
|
||||
)
|
||||
|
||||
val expectedClippedInsets = RectF(0f, 0f, 0f, 0f)
|
||||
assertThat(params.mCurrentDrawnInsets)
|
||||
.isEqualTo(expectedClippedInsets)
|
||||
assertThat(params.mCurrentDrawnInsets).isEqualTo(expectedClippedInsets)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.junit.runner.RunWith
|
||||
class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated
|
||||
* but it doesn't need to change QSB width or remove icons
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated but it
|
||||
* doesn't need to change QSB width or remove icons
|
||||
*/
|
||||
@Test
|
||||
fun distribute_border_space_when_space_is_enough_portrait() {
|
||||
@@ -51,8 +51,8 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, and recalculating spaces
|
||||
* it still needs to remove icons for everything to fit
|
||||
* This is a case when after setting the hotseat, and recalculating spaces it still needs to
|
||||
* remove icons for everything to fit
|
||||
*/
|
||||
@Test
|
||||
fun decrease_num_of_icons_when_not_enough_space_portrait() {
|
||||
@@ -73,8 +73,8 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated
|
||||
* but it doesn't need to change QSB width or remove icons
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated but it
|
||||
* doesn't need to change QSB width or remove icons
|
||||
*/
|
||||
@Test
|
||||
fun distribute_border_space_when_space_is_enough_landscape() {
|
||||
@@ -94,8 +94,8 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when the hotseat spans a certain amount of columns
|
||||
* and the nav buttons push the hotseat to the side, but not enough to change the border space.
|
||||
* This is a case when the hotseat spans a certain amount of columns and the nav buttons push
|
||||
* the hotseat to the side, but not enough to change the border space.
|
||||
*/
|
||||
@Test
|
||||
fun nav_buttons_dont_interfere_with_required_hotseat_width() {
|
||||
@@ -118,9 +118,7 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
assertThat(dp.hotseatQsbWidth).isEqualTo(1233)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, the QSB width needs to be changed to fit
|
||||
*/
|
||||
/** This is a case when after setting the hotseat, the QSB width needs to be changed to fit */
|
||||
@Test
|
||||
fun decrease_qsb_when_not_enough_space_landscape() {
|
||||
initializeVarsForTablet(isGestureMode = false, isLandscape = true)
|
||||
|
||||
@@ -9,12 +9,17 @@ object LauncherPrefs {
|
||||
fun getPrefs(context: Context): SharedPreferences {
|
||||
// Use application context for shared preferences, so that we use a single cached instance
|
||||
return context.applicationContext.getSharedPreferences(
|
||||
LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||
LauncherFiles.SHARED_PREFERENCES_KEY,
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDevicePrefs(context: Context): SharedPreferences {
|
||||
// Use application context for shared preferences, so that we use a single cached instance
|
||||
return context.applicationContext.getSharedPreferences(
|
||||
LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||
}}
|
||||
LauncherFiles.DEVICE_PREFERENCES_KEY,
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,15 @@ import com.android.launcher3.R
|
||||
|
||||
object DimensionUtils {
|
||||
/**
|
||||
* Point where x is width, and y is height of taskbar based on provided [deviceProfile]
|
||||
* x or y could also be -1 to indicate there is no dimension specified
|
||||
* Point where x is width, and y is height of taskbar based on provided [deviceProfile] x or y
|
||||
* could also be -1 to indicate there is no dimension specified
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getTaskbarPhoneDimensions(deviceProfile: DeviceProfile, res: Resources,
|
||||
isPhoneMode: Boolean): Point {
|
||||
fun getTaskbarPhoneDimensions(
|
||||
deviceProfile: DeviceProfile,
|
||||
res: Resources,
|
||||
isPhoneMode: Boolean
|
||||
): Point {
|
||||
val p = Point()
|
||||
// Taskbar for large screen
|
||||
if (!isPhoneMode) {
|
||||
@@ -57,4 +60,4 @@ object DimensionUtils {
|
||||
p.y = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
return p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.launcher3.DeviceProfile.DEFAULT_PROVIDER
|
||||
import com.android.launcher3.util.DisplayController.Info
|
||||
import com.android.launcher3.util.WindowBounds
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import org.junit.Before
|
||||
import org.mockito.ArgumentMatchers.any
|
||||
import org.mockito.Mockito.mock
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
abstract class DeviceProfileBaseTest {
|
||||
@@ -49,31 +49,36 @@ abstract class DeviceProfileBaseTest {
|
||||
isGestureMode = true
|
||||
}
|
||||
|
||||
protected fun newDP(): DeviceProfile = DeviceProfile(
|
||||
context,
|
||||
inv,
|
||||
info,
|
||||
windowBounds,
|
||||
SparseArray(),
|
||||
isMultiWindowMode,
|
||||
transposeLayoutWithOrientation,
|
||||
useTwoPanels,
|
||||
isGestureMode,
|
||||
DEFAULT_PROVIDER
|
||||
)
|
||||
protected fun newDP(): DeviceProfile =
|
||||
DeviceProfile(
|
||||
context,
|
||||
inv,
|
||||
info,
|
||||
windowBounds,
|
||||
SparseArray(),
|
||||
isMultiWindowMode,
|
||||
transposeLayoutWithOrientation,
|
||||
useTwoPanels,
|
||||
isGestureMode,
|
||||
DEFAULT_PROVIDER
|
||||
)
|
||||
|
||||
protected fun initializeVarsForPhone(isGestureMode: Boolean = true,
|
||||
isVerticalBar: Boolean = false) {
|
||||
val (x, y) = if (isVerticalBar)
|
||||
Pair(2400, 1080)
|
||||
else
|
||||
Pair(1080, 2400)
|
||||
protected fun initializeVarsForPhone(
|
||||
isGestureMode: Boolean = true,
|
||||
isVerticalBar: Boolean = false
|
||||
) {
|
||||
val (x, y) = if (isVerticalBar) Pair(2400, 1080) else Pair(1080, 2400)
|
||||
|
||||
windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(
|
||||
if (isVerticalBar) 118 else 0,
|
||||
if (isVerticalBar) 74 else 118,
|
||||
if (!isGestureMode && isVerticalBar) 126 else 0,
|
||||
if (isGestureMode) 63 else if (isVerticalBar) 0 else 126))
|
||||
windowBounds =
|
||||
WindowBounds(
|
||||
Rect(0, 0, x, y),
|
||||
Rect(
|
||||
if (isVerticalBar) 118 else 0,
|
||||
if (isVerticalBar) 74 else 118,
|
||||
if (!isGestureMode && isVerticalBar) 126 else 0,
|
||||
if (isGestureMode) 63 else if (isVerticalBar) 0 else 126
|
||||
)
|
||||
)
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(false)
|
||||
whenever(info.getDensityDpi()).thenReturn(420)
|
||||
@@ -82,79 +87,76 @@ abstract class DeviceProfileBaseTest {
|
||||
this.isGestureMode = isGestureMode
|
||||
transposeLayoutWithOrientation = true
|
||||
|
||||
inv = InvariantDeviceProfile().apply {
|
||||
numRows = 5
|
||||
numColumns = 4
|
||||
numSearchContainerColumns = 4
|
||||
inv =
|
||||
InvariantDeviceProfile().apply {
|
||||
numRows = 5
|
||||
numColumns = 4
|
||||
numSearchContainerColumns = 4
|
||||
|
||||
iconSize = floatArrayOf(60f, 54f, 60f, 60f)
|
||||
iconTextSize = FloatArray(4) { 14f }
|
||||
deviceType = InvariantDeviceProfile.TYPE_PHONE
|
||||
iconSize = floatArrayOf(60f, 54f, 60f, 60f)
|
||||
iconTextSize = FloatArray(4) { 14f }
|
||||
deviceType = InvariantDeviceProfile.TYPE_PHONE
|
||||
|
||||
minCellSize = listOf(
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f)
|
||||
).toTypedArray()
|
||||
minCellSize =
|
||||
listOf(
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f)
|
||||
)
|
||||
.toTypedArray()
|
||||
|
||||
borderSpaces = listOf(
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f)
|
||||
).toTypedArray()
|
||||
borderSpaces =
|
||||
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f))
|
||||
.toTypedArray()
|
||||
|
||||
numFolderRows = 3
|
||||
numFolderColumns = 3
|
||||
folderStyle = R.style.FolderDefaultStyle
|
||||
numFolderRows = 3
|
||||
numFolderColumns = 3
|
||||
folderStyle = R.style.FolderDefaultStyle
|
||||
|
||||
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
|
||||
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
|
||||
|
||||
horizontalMargin = FloatArray(4) { 22f }
|
||||
horizontalMargin = FloatArray(4) { 22f }
|
||||
|
||||
allAppsCellSize = listOf(
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f)
|
||||
).toTypedArray()
|
||||
allAppsIconSize = floatArrayOf(60f, 60f, 60f, 60f)
|
||||
allAppsIconTextSize = FloatArray(4) { 14f }
|
||||
allAppsBorderSpaces = listOf(
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f)
|
||||
).toTypedArray()
|
||||
allAppsCellSize =
|
||||
listOf(
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f)
|
||||
)
|
||||
.toTypedArray()
|
||||
allAppsIconSize = floatArrayOf(60f, 60f, 60f, 60f)
|
||||
allAppsIconTextSize = FloatArray(4) { 14f }
|
||||
allAppsBorderSpaces =
|
||||
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f))
|
||||
.toTypedArray()
|
||||
|
||||
numShownHotseatIcons = 4
|
||||
numShownHotseatIcons = 4
|
||||
|
||||
numDatabaseHotseatIcons = 4
|
||||
numDatabaseHotseatIcons = 4
|
||||
|
||||
hotseatColumnSpan = IntArray(4) { 4 }
|
||||
hotseatBarBottomSpace = FloatArray(4) { 48f }
|
||||
hotseatQsbSpace = FloatArray(4) { 36f }
|
||||
hotseatColumnSpan = IntArray(4) { 4 }
|
||||
hotseatBarBottomSpace = FloatArray(4) { 48f }
|
||||
hotseatQsbSpace = FloatArray(4) { 36f }
|
||||
|
||||
numAllAppsColumns = 4
|
||||
numAllAppsColumns = 4
|
||||
|
||||
isScalable = true
|
||||
isScalable = true
|
||||
|
||||
inlineQsb = BooleanArray(4) { false }
|
||||
inlineQsb = BooleanArray(4) { false }
|
||||
|
||||
devicePaddingId = R.xml.paddings_handhelds
|
||||
}
|
||||
devicePaddingId = R.xml.paddings_handhelds
|
||||
}
|
||||
}
|
||||
|
||||
protected fun initializeVarsForTablet(isLandscape: Boolean = false,
|
||||
isGestureMode: Boolean = true) {
|
||||
val (x, y) = if (isLandscape)
|
||||
Pair(2560, 1600)
|
||||
else
|
||||
Pair(1600, 2560)
|
||||
protected fun initializeVarsForTablet(
|
||||
isLandscape: Boolean = false,
|
||||
isGestureMode: Boolean = true
|
||||
) {
|
||||
val (x, y) = if (isLandscape) Pair(2560, 1600) else Pair(1600, 2560)
|
||||
|
||||
windowBounds =
|
||||
WindowBounds(Rect(0, 0, x, y), Rect(0, 104, 0, 0))
|
||||
windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(0, 104, 0, 0))
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(true)
|
||||
whenever(info.getDensityDpi()).thenReturn(320)
|
||||
@@ -163,85 +165,77 @@ abstract class DeviceProfileBaseTest {
|
||||
this.isGestureMode = isGestureMode
|
||||
useTwoPanels = false
|
||||
|
||||
inv = InvariantDeviceProfile().apply {
|
||||
numRows = 5
|
||||
numColumns = 6
|
||||
numSearchContainerColumns = 3
|
||||
inv =
|
||||
InvariantDeviceProfile().apply {
|
||||
numRows = 5
|
||||
numColumns = 6
|
||||
numSearchContainerColumns = 3
|
||||
|
||||
iconSize = FloatArray(4) { 60f }
|
||||
iconTextSize = FloatArray(4) { 14f }
|
||||
deviceType = InvariantDeviceProfile.TYPE_TABLET
|
||||
iconSize = FloatArray(4) { 60f }
|
||||
iconTextSize = FloatArray(4) { 14f }
|
||||
deviceType = InvariantDeviceProfile.TYPE_TABLET
|
||||
|
||||
minCellSize = listOf(
|
||||
PointF(102f, 120f),
|
||||
PointF(120f, 104f),
|
||||
PointF(102f, 120f),
|
||||
PointF(102f, 120f)
|
||||
).toTypedArray()
|
||||
minCellSize =
|
||||
listOf(
|
||||
PointF(102f, 120f),
|
||||
PointF(120f, 104f),
|
||||
PointF(102f, 120f),
|
||||
PointF(102f, 120f)
|
||||
)
|
||||
.toTypedArray()
|
||||
|
||||
borderSpaces = listOf(
|
||||
PointF(16f, 64f),
|
||||
PointF(64f, 16f),
|
||||
PointF(16f, 64f),
|
||||
PointF(16f, 64f)
|
||||
).toTypedArray()
|
||||
borderSpaces =
|
||||
listOf(PointF(16f, 64f), PointF(64f, 16f), PointF(16f, 64f), PointF(16f, 64f))
|
||||
.toTypedArray()
|
||||
|
||||
numFolderRows = 3
|
||||
numFolderColumns = 3
|
||||
folderStyle = R.style.FolderDefaultStyle
|
||||
numFolderRows = 3
|
||||
numFolderColumns = 3
|
||||
folderStyle = R.style.FolderDefaultStyle
|
||||
|
||||
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
|
||||
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
|
||||
|
||||
horizontalMargin = floatArrayOf(54f, 120f, 54f, 54f)
|
||||
horizontalMargin = floatArrayOf(54f, 120f, 54f, 54f)
|
||||
|
||||
allAppsCellSize = listOf(
|
||||
PointF(96f, 142f),
|
||||
PointF(126f, 126f),
|
||||
PointF(96f, 142f),
|
||||
PointF(96f, 142f)
|
||||
).toTypedArray()
|
||||
allAppsIconSize = FloatArray(4) { 60f }
|
||||
allAppsIconTextSize = FloatArray(4) { 14f }
|
||||
allAppsBorderSpaces = listOf(
|
||||
PointF(8f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(8f, 16f),
|
||||
PointF(8f, 16f)
|
||||
).toTypedArray()
|
||||
allAppsCellSize =
|
||||
listOf(
|
||||
PointF(96f, 142f),
|
||||
PointF(126f, 126f),
|
||||
PointF(96f, 142f),
|
||||
PointF(96f, 142f)
|
||||
)
|
||||
.toTypedArray()
|
||||
allAppsIconSize = FloatArray(4) { 60f }
|
||||
allAppsIconTextSize = FloatArray(4) { 14f }
|
||||
allAppsBorderSpaces =
|
||||
listOf(PointF(8f, 16f), PointF(16f, 16f), PointF(8f, 16f), PointF(8f, 16f))
|
||||
.toTypedArray()
|
||||
|
||||
numShownHotseatIcons = 6
|
||||
numShownHotseatIcons = 6
|
||||
|
||||
numDatabaseHotseatIcons = 6
|
||||
numDatabaseHotseatIcons = 6
|
||||
|
||||
hotseatColumnSpan = intArrayOf(6, 4, 6, 6)
|
||||
hotseatBarBottomSpace = floatArrayOf(36f, 40f, 36f, 36f)
|
||||
hotseatQsbSpace = FloatArray(4) { 32f }
|
||||
hotseatColumnSpan = intArrayOf(6, 4, 6, 6)
|
||||
hotseatBarBottomSpace = floatArrayOf(36f, 40f, 36f, 36f)
|
||||
hotseatQsbSpace = FloatArray(4) { 32f }
|
||||
|
||||
numAllAppsColumns = 6
|
||||
numAllAppsColumns = 6
|
||||
|
||||
isScalable = true
|
||||
devicePaddingId = R.xml.paddings_6x5
|
||||
isScalable = true
|
||||
devicePaddingId = R.xml.paddings_6x5
|
||||
|
||||
inlineQsb = booleanArrayOf(
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
)
|
||||
inlineQsb = booleanArrayOf(false, true, false, false)
|
||||
|
||||
devicePaddingId = R.xml.paddings_handhelds
|
||||
}
|
||||
devicePaddingId = R.xml.paddings_handhelds
|
||||
}
|
||||
}
|
||||
|
||||
protected fun initializeVarsForTwoPanel(isLandscape: Boolean = false,
|
||||
isGestureMode: Boolean = true) {
|
||||
val (x, y) = if (isLandscape)
|
||||
Pair(2208, 1840)
|
||||
else
|
||||
Pair(1840, 2208)
|
||||
protected fun initializeVarsForTwoPanel(
|
||||
isLandscape: Boolean = false,
|
||||
isGestureMode: Boolean = true
|
||||
) {
|
||||
val (x, y) = if (isLandscape) Pair(2208, 1840) else Pair(1840, 2208)
|
||||
|
||||
windowBounds = WindowBounds(Rect(0, 0, x, y),
|
||||
Rect(0, 110, 0, 0))
|
||||
windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(0, 110, 0, 0))
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(true)
|
||||
whenever(info.getDensityDpi()).thenReturn(420)
|
||||
@@ -250,74 +244,63 @@ abstract class DeviceProfileBaseTest {
|
||||
this.isGestureMode = isGestureMode
|
||||
useTwoPanels = true
|
||||
|
||||
inv = InvariantDeviceProfile().apply {
|
||||
numRows = 4
|
||||
numColumns = 4
|
||||
numSearchContainerColumns = 4
|
||||
inv =
|
||||
InvariantDeviceProfile().apply {
|
||||
numRows = 4
|
||||
numColumns = 4
|
||||
numSearchContainerColumns = 4
|
||||
|
||||
iconSize = floatArrayOf(60f, 52f, 52f, 60f)
|
||||
iconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
|
||||
deviceType = InvariantDeviceProfile.TYPE_MULTI_DISPLAY
|
||||
iconSize = floatArrayOf(60f, 52f, 52f, 60f)
|
||||
iconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
|
||||
deviceType = InvariantDeviceProfile.TYPE_MULTI_DISPLAY
|
||||
|
||||
minCellSize = listOf(
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(68f, 116f),
|
||||
PointF(80f, 102f)
|
||||
).toTypedArray()
|
||||
minCellSize =
|
||||
listOf(
|
||||
PointF(80f, 104f),
|
||||
PointF(80f, 104f),
|
||||
PointF(68f, 116f),
|
||||
PointF(80f, 102f)
|
||||
)
|
||||
.toTypedArray()
|
||||
|
||||
borderSpaces = listOf(
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 20f),
|
||||
PointF(20f, 20f)
|
||||
).toTypedArray()
|
||||
borderSpaces =
|
||||
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 20f), PointF(20f, 20f))
|
||||
.toTypedArray()
|
||||
|
||||
numFolderRows = 3
|
||||
numFolderColumns = 3
|
||||
folderStyle = R.style.FolderDefaultStyle
|
||||
numFolderRows = 3
|
||||
numFolderColumns = 3
|
||||
folderStyle = R.style.FolderDefaultStyle
|
||||
|
||||
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
|
||||
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
|
||||
|
||||
horizontalMargin = floatArrayOf(21.5f, 21.5f, 22.5f, 30.5f)
|
||||
horizontalMargin = floatArrayOf(21.5f, 21.5f, 22.5f, 30.5f)
|
||||
|
||||
allAppsCellSize = listOf(
|
||||
PointF(0f, 0f),
|
||||
PointF(0f, 0f),
|
||||
PointF(68f, 104f),
|
||||
PointF(80f, 104f)
|
||||
).toTypedArray()
|
||||
allAppsIconSize = floatArrayOf(60f, 60f, 52f, 60f)
|
||||
allAppsIconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
|
||||
allAppsBorderSpaces = listOf(
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 16f),
|
||||
PointF(16f, 28f),
|
||||
PointF(20f, 16f)
|
||||
).toTypedArray()
|
||||
allAppsCellSize =
|
||||
listOf(PointF(0f, 0f), PointF(0f, 0f), PointF(68f, 104f), PointF(80f, 104f))
|
||||
.toTypedArray()
|
||||
allAppsIconSize = floatArrayOf(60f, 60f, 52f, 60f)
|
||||
allAppsIconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
|
||||
allAppsBorderSpaces =
|
||||
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 28f), PointF(20f, 16f))
|
||||
.toTypedArray()
|
||||
|
||||
numShownHotseatIcons = 6
|
||||
numShownHotseatIcons = 6
|
||||
|
||||
numDatabaseHotseatIcons = 6
|
||||
numDatabaseHotseatIcons = 6
|
||||
|
||||
hotseatColumnSpan = IntArray(4) { 6 }
|
||||
hotseatBarBottomSpace = floatArrayOf(48f, 48f, 36f, 20f)
|
||||
hotseatQsbSpace = floatArrayOf(36f, 36f, 36f, 28f)
|
||||
hotseatColumnSpan = IntArray(4) { 6 }
|
||||
hotseatBarBottomSpace = floatArrayOf(48f, 48f, 36f, 20f)
|
||||
hotseatQsbSpace = floatArrayOf(36f, 36f, 36f, 28f)
|
||||
|
||||
numAllAppsColumns = 6
|
||||
numDatabaseAllAppsColumns = 6
|
||||
numAllAppsColumns = 6
|
||||
numDatabaseAllAppsColumns = 6
|
||||
|
||||
isScalable = true
|
||||
isScalable = true
|
||||
|
||||
inlineQsb = booleanArrayOf(
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
)
|
||||
inlineQsb = booleanArrayOf(false, false, false, false)
|
||||
|
||||
devicePaddingId = R.xml.paddings_handhelds
|
||||
}
|
||||
devicePaddingId = R.xml.paddings_handhelds
|
||||
}
|
||||
}
|
||||
|
||||
fun dump(dp: DeviceProfile): String {
|
||||
@@ -327,4 +310,4 @@ abstract class DeviceProfileBaseTest {
|
||||
printWriter.flush()
|
||||
return stringWriter.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,7 @@ import com.android.launcher3.util.IntSparseArrayMap
|
||||
import com.android.launcher3.util.LauncherModelHelper
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Base class for workspace related tests.
|
||||
*/
|
||||
/** Base class for workspace related tests. */
|
||||
abstract class AbstractWorkspaceModelTest {
|
||||
companion object {
|
||||
val emptyScreenSpaces = listOf(Rect(0, 0, 5, 5))
|
||||
@@ -64,10 +62,7 @@ abstract class AbstractWorkspaceModelTest {
|
||||
mModelHelper.destroy()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets up workspaces with the given screen IDs with some items and a 2x2 space.
|
||||
*/
|
||||
/** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
|
||||
fun setupWorkspaces(screenIdsWithItems: List<Int>) {
|
||||
var nextItemId = 1
|
||||
screenIdsWithItems.forEach { screenId ->
|
||||
@@ -83,8 +78,7 @@ abstract class AbstractWorkspaceModelTest {
|
||||
screen1: List<Rect>? = null,
|
||||
screen2: List<Rect>? = null,
|
||||
screen3: List<Rect>? = null,
|
||||
) = listOf(screen0, screen1, screen2, screen3)
|
||||
.let(this::setupWithSpaces)
|
||||
) = listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
|
||||
|
||||
private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
|
||||
var nextItemId = 1
|
||||
@@ -110,9 +104,7 @@ abstract class AbstractWorkspaceModelTest {
|
||||
var itemId = itemStartId
|
||||
val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
|
||||
occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
|
||||
spaces.forEach { spaceRect ->
|
||||
occupancy.markCells(spaceRect, false)
|
||||
}
|
||||
spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
|
||||
mExistingScreens.add(screenId)
|
||||
mScreenOccupancy.append(screenId, occupancy)
|
||||
for (x in 0 until mIdp.numColumns) {
|
||||
@@ -139,24 +131,21 @@ abstract class AbstractWorkspaceModelTest {
|
||||
return itemId
|
||||
}
|
||||
|
||||
fun getExistingItem() = WorkspaceItemInfo()
|
||||
.apply { intent = Intent().setComponent(ComponentName("a", "b")) }
|
||||
fun getExistingItem() =
|
||||
WorkspaceItemInfo().apply { intent = Intent().setComponent(ComponentName("a", "b")) }
|
||||
|
||||
fun getNewItem(): WorkspaceItemInfo {
|
||||
val itemPackage = UUID.randomUUID().toString()
|
||||
return WorkspaceItemInfo()
|
||||
.apply { intent = Intent().setComponent(ComponentName(itemPackage, itemPackage)) }
|
||||
return WorkspaceItemInfo().apply {
|
||||
intent = Intent().setComponent(ComponentName(itemPackage, itemPackage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class NewItemSpace(
|
||||
val screenId: Int,
|
||||
val cellX: Int,
|
||||
val cellY: Int
|
||||
) {
|
||||
data class NewItemSpace(val screenId: Int, val cellX: Int, val cellY: Int) {
|
||||
fun toIntArray() = intArrayOf(screenId, cellX, cellY)
|
||||
|
||||
companion object {
|
||||
fun fromIntArray(array: kotlin.IntArray) = NewItemSpace(array[0], array[1], array[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
import com.android.launcher3.util.Executors
|
||||
import com.android.launcher3.util.IntArray
|
||||
import com.android.launcher3.util.IntSet
|
||||
import com.android.launcher3.util.same
|
||||
import com.android.launcher3.util.eq
|
||||
import com.android.launcher3.util.any
|
||||
import com.android.launcher3.util.eq
|
||||
import com.android.launcher3.util.same
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -35,31 +35,24 @@ import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Captor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
/**
|
||||
* Tests for [AddWorkspaceItemsTask]
|
||||
*/
|
||||
/** Tests for [AddWorkspaceItemsTask] */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
|
||||
@Captor
|
||||
private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
|
||||
@Captor private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
|
||||
|
||||
@Captor
|
||||
private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
|
||||
@Captor private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
|
||||
|
||||
@Mock
|
||||
private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
|
||||
|
||||
@Mock
|
||||
private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
|
||||
@Mock private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
|
||||
|
||||
@Mock private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
|
||||
|
||||
@Before
|
||||
override fun setup() {
|
||||
@@ -91,10 +84,7 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
|
||||
@Test
|
||||
fun givenNewAndExistingItems_whenExecuteTask_thenOnlyAddNewItem() {
|
||||
val itemsToAdd = arrayOf(
|
||||
getNewItem(),
|
||||
getExistingItem()
|
||||
)
|
||||
val itemsToAdd = arrayOf(getNewItem(), getExistingItem())
|
||||
givenNewItemSpaces(NewItemSpace(1, 0, 0))
|
||||
val nonEmptyScreenIds = listOf(0)
|
||||
|
||||
@@ -134,13 +124,14 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
|
||||
@Test
|
||||
fun givenMultipleItems_whenExecuteTask_thenAddThem() {
|
||||
val itemsToAdd = arrayOf(
|
||||
getNewItem(),
|
||||
getExistingItem(),
|
||||
getNewItem(),
|
||||
getNewItem(),
|
||||
getExistingItem(),
|
||||
)
|
||||
val itemsToAdd =
|
||||
arrayOf(
|
||||
getNewItem(),
|
||||
getExistingItem(),
|
||||
getNewItem(),
|
||||
getNewItem(),
|
||||
getExistingItem(),
|
||||
)
|
||||
givenNewItemSpaces(
|
||||
NewItemSpace(1, 3, 3),
|
||||
NewItemSpace(2, 0, 0),
|
||||
@@ -161,27 +152,16 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
// Items that are added to the second screen should be animated
|
||||
val itemsAddedToSecondScreen = addedItems.filter { it.itemInfo.screenId == 2 }
|
||||
assertThat(itemsAddedToSecondScreen.size).isEqualTo(2)
|
||||
itemsAddedToSecondScreen.forEach {
|
||||
assertThat(it.isAnimated).isTrue()
|
||||
}
|
||||
itemsAddedToSecondScreen.forEach { assertThat(it.isAnimated).isTrue() }
|
||||
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the item space data that will be returned from WorkspaceItemSpaceFinder.
|
||||
*/
|
||||
/** Sets up the item space data that will be returned from WorkspaceItemSpaceFinder. */
|
||||
private fun givenNewItemSpaces(vararg newItemSpaces: NewItemSpace) {
|
||||
val spaceStack = newItemSpaces.toMutableList()
|
||||
whenever(
|
||||
mWorkspaceItemSpaceFinder.findSpaceForItem(
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any()
|
||||
mWorkspaceItemSpaceFinder.findSpaceForItem(any(), any(), any(), any(), any(), any())
|
||||
)
|
||||
)
|
||||
.then { spaceStack.removeFirst().toIntArray() }
|
||||
}
|
||||
|
||||
@@ -189,20 +169,21 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
* Verifies if WorkspaceItemSpaceFinder was called with proper arguments and how many times was
|
||||
* it called.
|
||||
*/
|
||||
private fun verifyItemSpaceFinderCall(
|
||||
nonEmptyScreenIds: List<Int>,
|
||||
numberOfExpectedCall: Int
|
||||
) {
|
||||
private fun verifyItemSpaceFinderCall(nonEmptyScreenIds: List<Int>, numberOfExpectedCall: Int) {
|
||||
verify(mWorkspaceItemSpaceFinder, times(numberOfExpectedCall))
|
||||
.findSpaceForItem(
|
||||
same(mAppState), same(mModelHelper.bgDataModel),
|
||||
eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())), eq(IntArray()), eq(1), eq(1)
|
||||
same(mAppState),
|
||||
same(mModelHelper.bgDataModel),
|
||||
eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())),
|
||||
eq(IntArray()),
|
||||
eq(1),
|
||||
eq(1)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the workspaces with items, executes the task, collects the added items from the
|
||||
* model callback then returns it.
|
||||
* Sets up the workspaces with items, executes the task, collects the added items from the model
|
||||
* callback then returns it.
|
||||
*/
|
||||
private fun testAddItems(
|
||||
nonEmptyScreenIds: List<Int>,
|
||||
@@ -211,21 +192,21 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
setupWorkspaces(nonEmptyScreenIds)
|
||||
val task = newTask(*itemsToAdd)
|
||||
var updateCount = 0
|
||||
mModelHelper.executeTaskForTest(task)
|
||||
.forEach {
|
||||
updateCount++
|
||||
it.run()
|
||||
}
|
||||
mModelHelper.executeTaskForTest(task).forEach {
|
||||
updateCount++
|
||||
it.run()
|
||||
}
|
||||
|
||||
val addedItems = mutableListOf<AddedItem>()
|
||||
if (updateCount > 0) {
|
||||
verify(mDataModelCallbacks).bindAppsAdded(
|
||||
any(),
|
||||
mNotAnimatedItemArgumentCaptor.capture(), mAnimatedItemArgumentCaptor.capture()
|
||||
)
|
||||
verify(mDataModelCallbacks)
|
||||
.bindAppsAdded(
|
||||
any(),
|
||||
mNotAnimatedItemArgumentCaptor.capture(),
|
||||
mAnimatedItemArgumentCaptor.capture()
|
||||
)
|
||||
addedItems.addAll(mAnimatedItemArgumentCaptor.value.map { AddedItem(it, true) })
|
||||
addedItems.addAll(mNotAnimatedItemArgumentCaptor.value.map { AddedItem(it, false) })
|
||||
|
||||
}
|
||||
|
||||
return addedItems
|
||||
@@ -236,12 +217,10 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
|
||||
* with a mock.
|
||||
*/
|
||||
private fun newTask(vararg items: ItemInfo): AddWorkspaceItemsTask =
|
||||
items.map { Pair.create(it, Any()) }
|
||||
items
|
||||
.map { Pair.create(it, Any()) }
|
||||
.toMutableList()
|
||||
.let { AddWorkspaceItemsTask(it, mWorkspaceItemSpaceFinder) }
|
||||
}
|
||||
|
||||
private data class AddedItem(
|
||||
val itemInfo: ItemInfo,
|
||||
val isAnimated: Boolean
|
||||
)
|
||||
private data class AddedItem(val itemInfo: ItemInfo, val isAnimated: Boolean)
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.android.launcher3.model
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor;
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.graphics.Point
|
||||
import android.os.Process
|
||||
@@ -38,7 +38,7 @@ import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/** Unit tests for [GridSizeMigrationUtil] */
|
||||
/** Unit tests for [GridSizeMigrationUtil] */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class GridSizeMigrationUtilTest {
|
||||
@@ -64,19 +64,20 @@ class GridSizeMigrationUtilTest {
|
||||
context = modelHelper.sandboxContext
|
||||
db = modelHelper.provider.db
|
||||
|
||||
validPackages = setOf(
|
||||
TEST_PACKAGE,
|
||||
testPackage1,
|
||||
testPackage2,
|
||||
testPackage3,
|
||||
testPackage4,
|
||||
testPackage5,
|
||||
testPackage6,
|
||||
testPackage7,
|
||||
testPackage8,
|
||||
testPackage9,
|
||||
testPackage10
|
||||
)
|
||||
validPackages =
|
||||
setOf(
|
||||
TEST_PACKAGE,
|
||||
testPackage1,
|
||||
testPackage2,
|
||||
testPackage3,
|
||||
testPackage4,
|
||||
testPackage5,
|
||||
testPackage6,
|
||||
testPackage7,
|
||||
testPackage8,
|
||||
testPackage9,
|
||||
testPackage10
|
||||
)
|
||||
|
||||
idp = InvariantDeviceProfile.INSTANCE[context]
|
||||
val userSerial = UserCache.INSTANCE[context].getSerialNumberForUser(Process.myUserHandle())
|
||||
@@ -90,8 +91,8 @@ class GridSizeMigrationUtilTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is
|
||||
* not needed anymore
|
||||
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
|
||||
* needed anymore
|
||||
*/
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
@@ -124,25 +125,27 @@ class GridSizeMigrationUtilTest {
|
||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Check hotseat items
|
||||
var c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
var c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
assertThat(c.count).isEqualTo(idp.numDatabaseHotseatIcons)
|
||||
|
||||
@@ -163,14 +166,16 @@ class GridSizeMigrationUtilTest {
|
||||
c.close()
|
||||
|
||||
// Check workspace items
|
||||
c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(CELLX, CELLY, INTENT),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(CELLX, CELLY, INTENT),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
intentIndex = c.getColumnIndex(INTENT)
|
||||
val cellXIndex = c.getColumnIndex(CELLX)
|
||||
@@ -195,8 +200,8 @@ class GridSizeMigrationUtilTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is
|
||||
* not needed anymore
|
||||
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
|
||||
* needed anymore
|
||||
*/
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
@@ -235,39 +240,46 @@ class GridSizeMigrationUtilTest {
|
||||
val readerGridB = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
// migrate from A -> B
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
readerGridA,
|
||||
readerGridB,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
readerGridA,
|
||||
readerGridB,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Check hotseat items in grid B
|
||||
var c = context.contentResolver.query(
|
||||
var c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
// Expected hotseat items in grid B
|
||||
// 2 1 3 4
|
||||
verifyHotseat(c, idp,
|
||||
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList())
|
||||
verifyHotseat(
|
||||
c,
|
||||
idp,
|
||||
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList()
|
||||
)
|
||||
|
||||
// Check workspace items in grid B
|
||||
c = context.contentResolver.query(
|
||||
c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
var locMap = parseLocMap(context, c)
|
||||
// Expected items in grid B
|
||||
// _ _ _ _
|
||||
@@ -285,38 +297,45 @@ class GridSizeMigrationUtilTest {
|
||||
|
||||
// migrate from B -> A
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
readerGridB,
|
||||
readerGridA,
|
||||
5,
|
||||
Point(5, 5),
|
||||
DeviceGridState(idp),
|
||||
DeviceGridState(context)
|
||||
context,
|
||||
db,
|
||||
readerGridB,
|
||||
readerGridA,
|
||||
5,
|
||||
Point(5, 5),
|
||||
DeviceGridState(idp),
|
||||
DeviceGridState(context)
|
||||
)
|
||||
// Check hotseat items in grid A
|
||||
c = context.contentResolver.query(
|
||||
c =
|
||||
context.contentResolver.query(
|
||||
TMP_CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
// Expected hotseat items in grid A
|
||||
// 1 2 _ 3 4
|
||||
verifyHotseat(c, idp, mutableListOf(
|
||||
testPackage1, testPackage2, null, testPackage3, testPackage4).toList())
|
||||
verifyHotseat(
|
||||
c,
|
||||
idp,
|
||||
mutableListOf(testPackage1, testPackage2, null, testPackage3, testPackage4).toList()
|
||||
)
|
||||
|
||||
// Check workspace items in grid A
|
||||
c = context.contentResolver.query(
|
||||
c =
|
||||
context.contentResolver.query(
|
||||
TMP_CONTENT_URI,
|
||||
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
locMap = parseLocMap(context, c)
|
||||
// Expected workspace items in grid A
|
||||
// _ _ _ _ _
|
||||
@@ -338,39 +357,46 @@ class GridSizeMigrationUtilTest {
|
||||
|
||||
// migrate from A -> B
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
readerGridA,
|
||||
readerGridB,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
readerGridA,
|
||||
readerGridB,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Check hotseat items in grid B
|
||||
c = context.contentResolver.query(
|
||||
c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
// Expected hotseat items in grid B
|
||||
// 2 1 3 4
|
||||
verifyHotseat(c, idp,
|
||||
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList())
|
||||
verifyHotseat(
|
||||
c,
|
||||
idp,
|
||||
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList()
|
||||
)
|
||||
|
||||
// Check workspace items in grid B
|
||||
c = context.contentResolver.query(
|
||||
c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, CELLX, CELLY, INTENT),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
locMap = parseLocMap(context, c)
|
||||
// Expected workspace items in grid B
|
||||
// _ _ _ _
|
||||
@@ -406,7 +432,7 @@ class GridSizeMigrationUtilTest {
|
||||
val locMap = mutableMapOf<String, Triple<Int, Int, Int>>()
|
||||
while (c.moveToNext()) {
|
||||
locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
|
||||
Triple(c.getInt(screenIndex), c.getInt(cellXIndex), c.getInt(cellYIndex))
|
||||
Triple(c.getInt(screenIndex), c.getInt(cellXIndex), c.getInt(cellYIndex))
|
||||
}
|
||||
c.close()
|
||||
return locMap.toMap()
|
||||
@@ -414,12 +440,13 @@ class GridSizeMigrationUtilTest {
|
||||
|
||||
@Test
|
||||
fun migrateToLargerHotseat() {
|
||||
val srcHotseatItems = intArrayOf(
|
||||
modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
|
||||
modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
|
||||
modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
|
||||
modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
|
||||
)
|
||||
val srcHotseatItems =
|
||||
intArrayOf(
|
||||
modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
|
||||
modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
|
||||
modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
|
||||
modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
|
||||
)
|
||||
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
|
||||
idp.numDatabaseHotseatIcons = 6
|
||||
idp.numColumns = 4
|
||||
@@ -427,25 +454,27 @@ class GridSizeMigrationUtilTest {
|
||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Check hotseat items
|
||||
val c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
val c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
assertThat(c.count.toLong()).isEqualTo(numSrcDatabaseHotseatIcons.toLong())
|
||||
val screenIndex = c.getColumnIndex(SCREEN)
|
||||
@@ -483,25 +512,27 @@ class GridSizeMigrationUtilTest {
|
||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Check hotseat items
|
||||
val c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
val c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(SCREEN, INTENT),
|
||||
"container=$CONTAINER_HOTSEAT",
|
||||
null,
|
||||
SCREEN,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
assertThat(c.count.toLong()).isEqualTo(idp.numDatabaseHotseatIcons.toLong())
|
||||
val screenIndex = c.getColumnIndex(SCREEN)
|
||||
@@ -527,8 +558,8 @@ class GridSizeMigrationUtilTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrating from a smaller grid to a large one should keep the pages
|
||||
* if the column difference is less than 2
|
||||
* Migrating from a smaller grid to a large one should keep the pages if the column difference
|
||||
* is less than 2
|
||||
*/
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
@@ -549,25 +580,27 @@ class GridSizeMigrationUtilTest {
|
||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Get workspace items
|
||||
val c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(INTENT, SCREEN),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
val c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(INTENT, SCREEN),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
val intentIndex = c.getColumnIndex(INTENT)
|
||||
val screenIndex = c.getColumnIndex(SCREEN)
|
||||
|
||||
@@ -589,8 +622,8 @@ class GridSizeMigrationUtilTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrating from a smaller grid to a large one should reflow the pages
|
||||
* if the column difference is more than 2
|
||||
* Migrating from a smaller grid to a large one should reflow the pages if the column difference
|
||||
* is more than 2
|
||||
*/
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
@@ -610,25 +643,27 @@ class GridSizeMigrationUtilTest {
|
||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Get workspace items
|
||||
val c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(INTENT, SCREEN),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
val c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(INTENT, SCREEN),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
val intentIndex = c.getColumnIndex(INTENT)
|
||||
val screenIndex = c.getColumnIndex(SCREEN)
|
||||
@@ -651,9 +686,7 @@ class GridSizeMigrationUtilTest {
|
||||
disableNewMigrationLogic()
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrating from a larger grid to a smaller, we reflow from page 0
|
||||
*/
|
||||
/** Migrating from a larger grid to a smaller, we reflow from page 0 */
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun migrateFromLargerGrid() {
|
||||
@@ -672,25 +705,27 @@ class GridSizeMigrationUtilTest {
|
||||
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
|
||||
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
|
||||
GridSizeMigrationUtil.migrate(
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
context,
|
||||
db,
|
||||
srcReader,
|
||||
destReader,
|
||||
idp.numDatabaseHotseatIcons,
|
||||
Point(idp.numColumns, idp.numRows),
|
||||
DeviceGridState(context),
|
||||
DeviceGridState(idp)
|
||||
)
|
||||
|
||||
// Get workspace items
|
||||
val c = context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(INTENT, SCREEN),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: throw IllegalStateException()
|
||||
val c =
|
||||
context.contentResolver.query(
|
||||
CONTENT_URI,
|
||||
arrayOf(INTENT, SCREEN),
|
||||
"container=$CONTAINER_DESKTOP",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
?: throw IllegalStateException()
|
||||
val intentIndex = c.getColumnIndex(INTENT)
|
||||
val screenIndex = c.getColumnIndex(SCREEN)
|
||||
|
||||
@@ -714,11 +749,13 @@ class GridSizeMigrationUtilTest {
|
||||
}
|
||||
|
||||
private fun enableNewMigrationLogic(srcGridSize: String) {
|
||||
context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
|
||||
context
|
||||
.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putBoolean(FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.key, true)
|
||||
.commit()
|
||||
context.getSharedPreferences(LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||
context
|
||||
.getSharedPreferences(LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putString(DeviceGridState.KEY_WORKSPACE_SIZE, srcGridSize)
|
||||
.commit()
|
||||
@@ -726,9 +763,10 @@ class GridSizeMigrationUtilTest {
|
||||
}
|
||||
|
||||
private fun disableNewMigrationLogic() {
|
||||
context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
|
||||
context
|
||||
.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putBoolean(FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.key, false)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,7 @@ import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Tests for [WorkspaceItemSpaceFinder]
|
||||
*/
|
||||
/** Tests for [WorkspaceItemSpaceFinder] */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
|
||||
@@ -44,17 +42,27 @@ class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
|
||||
}
|
||||
|
||||
private fun findSpace(spanX: Int, spanY: Int): NewItemSpace =
|
||||
mItemSpaceFinder.findSpaceForItem(
|
||||
mAppState, mModelHelper.bgDataModel,
|
||||
mExistingScreens, mNewScreens, spanX, spanY
|
||||
)
|
||||
mItemSpaceFinder
|
||||
.findSpaceForItem(
|
||||
mAppState,
|
||||
mModelHelper.bgDataModel,
|
||||
mExistingScreens,
|
||||
mNewScreens,
|
||||
spanX,
|
||||
spanY
|
||||
)
|
||||
.let { NewItemSpace.fromIntArray(it) }
|
||||
|
||||
private fun assertRegionVacant(newItemSpace: NewItemSpace, spanX: Int, spanY: Int) {
|
||||
assertThat(
|
||||
mScreenOccupancy[newItemSpace.screenId]
|
||||
.isRegionVacant(newItemSpace.cellX, newItemSpace.cellY, spanX, spanY)
|
||||
).isTrue()
|
||||
mScreenOccupancy[newItemSpace.screenId].isRegionVacant(
|
||||
newItemSpace.cellX,
|
||||
newItemSpace.cellY,
|
||||
spanX,
|
||||
spanY
|
||||
)
|
||||
)
|
||||
.isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.junit.runner.RunWith
|
||||
class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated
|
||||
* but it doesn't need to change QSB width or remove icons
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated but it
|
||||
* doesn't need to change QSB width or remove icons
|
||||
*/
|
||||
@Test
|
||||
fun distribute_border_space_when_space_is_enough_portrait() {
|
||||
@@ -51,8 +51,8 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, and recalculating spaces
|
||||
* it still needs to remove icons for everything to fit
|
||||
* This is a case when after setting the hotseat, and recalculating spaces it still needs to
|
||||
* remove icons for everything to fit
|
||||
*/
|
||||
@Test
|
||||
fun decrease_num_of_icons_when_not_enough_space_portrait() {
|
||||
@@ -73,8 +73,8 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated
|
||||
* but it doesn't need to change QSB width or remove icons
|
||||
* This is a case when after setting the hotseat, the space needs to be recalculated but it
|
||||
* doesn't need to change QSB width or remove icons
|
||||
*/
|
||||
@Test
|
||||
fun distribute_border_space_when_space_is_enough_landscape() {
|
||||
@@ -94,8 +94,8 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when the hotseat spans a certain amount of columns
|
||||
* and the nav buttons push the hotseat to the side, but not enough to change the border space.
|
||||
* This is a case when the hotseat spans a certain amount of columns and the nav buttons push
|
||||
* the hotseat to the side, but not enough to change the border space.
|
||||
*/
|
||||
@Test
|
||||
fun nav_buttons_dont_interfere_with_required_hotseat_width() {
|
||||
@@ -118,9 +118,7 @@ class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
|
||||
assertThat(dp.hotseatQsbWidth).isEqualTo(1224)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a case when after setting the hotseat, the QSB width needs to be changed to fit
|
||||
*/
|
||||
/** This is a case when after setting the hotseat, the QSB width needs to be changed to fit */
|
||||
@Test
|
||||
fun decrease_qsb_when_not_enough_space_landscape() {
|
||||
initializeVarsForTablet(isGestureMode = false, isLandscape = true)
|
||||
|
||||
@@ -22,43 +22,41 @@ package com.android.launcher3.util
|
||||
* be null"). To fix this, we can use methods that modify the return type to be nullable. This
|
||||
* causes Kotlin to skip the null checks.
|
||||
*/
|
||||
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mockito
|
||||
|
||||
/**
|
||||
* Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
|
||||
* null is returned.
|
||||
* Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is
|
||||
* returned.
|
||||
*
|
||||
* Generic T is nullable because implicitly bounded by Any?.
|
||||
*/
|
||||
fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
|
||||
|
||||
/**
|
||||
* Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when
|
||||
* null is returned.
|
||||
* Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when null is
|
||||
* returned.
|
||||
*
|
||||
* Generic T is nullable because implicitly bounded by Any?.
|
||||
*/
|
||||
fun <T> same(obj: T): T = Mockito.same<T>(obj)
|
||||
|
||||
/**
|
||||
* Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
|
||||
* null is returned.
|
||||
* Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when null is
|
||||
* returned.
|
||||
*
|
||||
* Generic T is nullable because implicitly bounded by Any?.
|
||||
*/
|
||||
fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
|
||||
|
||||
inline fun <reified T> any(): T = any(T::class.java)
|
||||
|
||||
/**
|
||||
* Kotlin type-inferred version of Mockito.nullable()
|
||||
*/
|
||||
/** Kotlin type-inferred version of Mockito.nullable() */
|
||||
inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
|
||||
|
||||
/**
|
||||
* Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
|
||||
* when null is returned.
|
||||
* Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException when
|
||||
* null is returned.
|
||||
*
|
||||
* Generic T is nullable because implicitly bounded by Any?.
|
||||
*/
|
||||
@@ -82,8 +80,9 @@ inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
|
||||
/**
|
||||
* A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when
|
||||
* kotlin tests are mocking kotlin objects and the methods take non-null parameters:
|
||||
*
|
||||
* ```
|
||||
* java.lang.NullPointerException: capture() must not be null
|
||||
* ```
|
||||
*/
|
||||
class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
|
||||
private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
|
||||
@@ -102,15 +101,15 @@ inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
|
||||
|
||||
/**
|
||||
* Helper function for creating and using a single-use ArgumentCaptor in kotlin.
|
||||
*
|
||||
* ```
|
||||
* val captor = argumentCaptor<Foo>()
|
||||
* verify(...).someMethod(captor.capture())
|
||||
* val captured = captor.value
|
||||
*
|
||||
* ```
|
||||
* becomes:
|
||||
*
|
||||
* ```
|
||||
* val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
|
||||
*
|
||||
* ```
|
||||
* NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
|
||||
*/
|
||||
inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
|
||||
|
||||
@@ -30,18 +30,18 @@ class MultiPropertyFactoryTest {
|
||||
|
||||
private val received = mutableListOf<Float>()
|
||||
|
||||
private val receiveProperty: FloatProperty<Any> = object : FloatProperty<Any>("receive") {
|
||||
override fun setValue(obj: Any?, value: Float) {
|
||||
received.add(value)
|
||||
private val receiveProperty: FloatProperty<Any> =
|
||||
object : FloatProperty<Any>("receive") {
|
||||
override fun setValue(obj: Any?, value: Float) {
|
||||
received.add(value)
|
||||
}
|
||||
override fun get(o: Any): Float {
|
||||
return 0f
|
||||
}
|
||||
}
|
||||
override fun get(o: Any): Float {
|
||||
return 0f
|
||||
}
|
||||
}
|
||||
|
||||
private val factory = MultiPropertyFactory(null, receiveProperty, 3) {
|
||||
x: Float, y: Float -> x + y
|
||||
}
|
||||
private val factory =
|
||||
MultiPropertyFactory(null, receiveProperty, 3) { x: Float, y: Float -> x + y }
|
||||
|
||||
private val p1 = factory.get(0)
|
||||
private val p2 = factory.get(1)
|
||||
|
||||
@@ -18,9 +18,9 @@ package com.android.launcher3.util
|
||||
|
||||
import android.view.InputDevice
|
||||
import android.view.MotionEvent
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
|
||||
Reference in New Issue
Block a user