Merge changes I9b6121a7,I31a47234 into udc-qpr-dev

* changes:
  Add a shell command interface for layouts.
  Add layout manager
This commit is contained in:
Aaron Liu
2023-06-30 18:20:03 +00:00
committed by Android (Google) Code Review
13 changed files with 613 additions and 37 deletions

View File

@@ -32,7 +32,6 @@ import android.widget.ImageView;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.settingslib.Utils;
@@ -126,7 +125,6 @@ public class LockIconView extends FrameLayout implements Dumpable {
/**
* Set the location of the lock icon.
*/
@VisibleForTesting
public void setCenterLocation(@NonNull Point center, float radius, int drawablePadding) {
mLockIconCenter = center;
mRadius = radius;

View File

@@ -60,6 +60,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -387,15 +388,17 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
private void updateLockIconLocation() {
final float scaleFactor = mAuthController.getScaleFactor();
final int scaledPadding = (int) (mDefaultPaddingPx * scaleFactor);
if (mUdfpsSupported) {
mView.setCenterLocation(mAuthController.getUdfpsLocation(),
mAuthController.getUdfpsRadius(), scaledPadding);
} else {
mView.setCenterLocation(
new Point((int) mWidthPixels / 2,
(int) (mHeightPixels
- ((mBottomPaddingPx + sLockIconRadiusPx) * scaleFactor))),
if (!mFeatureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
if (mUdfpsSupported) {
mView.setCenterLocation(mAuthController.getUdfpsLocation(),
mAuthController.getUdfpsRadius(), scaledPadding);
} else {
mView.setCenterLocation(
new Point((int) mWidthPixels / 2,
(int) (mHeightPixels
- ((mBottomPaddingPx + sLockIconRadiusPx) * scaleFactor))),
sLockIconRadiusPx * scaleFactor, scaledPadding);
}
}
}

View File

@@ -54,6 +54,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.FlagsModule;
import com.android.systemui.keyboard.KeyboardModule;
import com.android.systemui.keyguard.ui.view.layout.LockscreenLayoutModule;
import com.android.systemui.log.dagger.LogModule;
import com.android.systemui.log.dagger.MonitorLog;
import com.android.systemui.log.table.TableLogBuffer;
@@ -178,6 +179,7 @@ import javax.inject.Named;
GarbageMonitorModule.class,
KeyboardModule.class,
LetterboxModule.class,
LockscreenLayoutModule.class,
LogModule.class,
MediaProjectionModule.class,
MotionToolModule.class,

View File

@@ -26,6 +26,8 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.KeyguardLayoutManager
import com.android.systemui.keyguard.ui.view.layout.KeyguardLayoutManagerCommandListener
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.shade.NotificationShadeWindowView
import com.android.systemui.statusbar.KeyguardIndicationController
@@ -42,6 +44,8 @@ constructor(
private val notificationShadeWindowView: NotificationShadeWindowView,
private val featureFlags: FeatureFlags,
private val indicationController: KeyguardIndicationController,
private val keyguardLayoutManager: KeyguardLayoutManager,
private val keyguardLayoutManagerCommandListener: KeyguardLayoutManagerCommandListener,
) : CoreStartable {
private var indicationAreaHandle: DisposableHandle? = null
@@ -51,6 +55,8 @@ constructor(
notificationShadeWindowView.requireViewById(R.id.notification_panel) as ViewGroup
bindIndicationArea(notificationPanel)
bindLockIconView(notificationPanel)
keyguardLayoutManager.layoutViews()
keyguardLayoutManagerCommandListener.start()
}
fun bindIndicationArea(legacyParent: ViewGroup) {

View File

@@ -19,10 +19,7 @@ package com.android.systemui.keyguard.ui.view
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import com.android.keyguard.LockIconView
import com.android.systemui.R
@@ -31,7 +28,7 @@ class KeyguardRootView(
context: Context,
private val attrs: AttributeSet?,
) :
FrameLayout(
ConstraintLayout(
context,
attrs,
) {
@@ -43,31 +40,11 @@ class KeyguardRootView(
private fun addIndicationTextArea() {
val view = KeyguardIndicationArea(context, attrs)
addView(
view,
FrameLayout.LayoutParams(
MATCH_PARENT,
WRAP_CONTENT,
)
.apply {
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
bottomMargin = R.dimen.keyguard_indication_margin_bottom.dp()
}
)
addView(view)
}
private fun addLockIconView() {
val view = LockIconView(context, attrs).apply { id = R.id.lock_icon_view }
addView(
view,
LayoutParams(
WRAP_CONTENT,
WRAP_CONTENT,
)
)
}
private fun Int.dp(): Int {
return context.resources.getDimensionPixelSize(this)
addView(view)
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.systemui.keyguard.ui.view.layout
import android.content.Context
import android.graphics.Point
import android.graphics.Rect
import android.util.DisplayMetrics
import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
import androidx.constraintlayout.widget.ConstraintSet.END
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.biometrics.AuthController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import javax.inject.Inject
/**
* Positions elements of the lockscreen to the default position.
*
* This will be the most common use case for phones in portrait mode.
*/
@SysUISingleton
class DefaultLockscreenLayout
@Inject
constructor(
private val authController: AuthController,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val windowManager: WindowManager,
private val context: Context,
) : LockscreenLayout {
override val id: String = DEFAULT
override fun layoutIndicationArea(rootView: KeyguardRootView) {
val indicationArea = rootView.findViewById<View>(R.id.keyguard_indication_area) ?: return
rootView.getConstraintSet().apply {
constrainWidth(indicationArea.id, MATCH_PARENT)
constrainHeight(indicationArea.id, WRAP_CONTENT)
connect(
indicationArea.id,
BOTTOM,
PARENT_ID,
BOTTOM,
R.dimen.keyguard_indication_margin_bottom.dp()
)
connect(indicationArea.id, START, PARENT_ID, START)
connect(indicationArea.id, END, PARENT_ID, END)
applyTo(rootView)
}
}
override fun layoutLockIcon(rootView: KeyguardRootView) {
val isUdfpsSupported = keyguardUpdateMonitor.isUdfpsSupported
val scaleFactor: Float = authController.scaleFactor
val mBottomPaddingPx = R.dimen.lock_icon_margin_bottom.dp()
val mDefaultPaddingPx = R.dimen.lock_icon_padding.dp()
val scaledPadding: Int = (mDefaultPaddingPx * scaleFactor).toInt()
val bounds = windowManager.currentWindowMetrics.bounds
val widthPixels = bounds.right.toFloat()
val heightPixels = bounds.bottom.toFloat()
val defaultDensity =
DisplayMetrics.DENSITY_DEVICE_STABLE.toFloat() /
DisplayMetrics.DENSITY_DEFAULT.toFloat()
val lockIconRadiusPx = (defaultDensity * 36).toInt()
if (isUdfpsSupported) {
authController.udfpsLocation?.let { udfpsLocation ->
centerLockIcon(udfpsLocation, authController.udfpsRadius, scaledPadding, rootView)
}
} else {
centerLockIcon(
Point(
(widthPixels / 2).toInt(),
(heightPixels - ((mBottomPaddingPx + lockIconRadiusPx) * scaleFactor)).toInt()
),
lockIconRadiusPx * scaleFactor,
scaledPadding,
rootView
)
}
}
@VisibleForTesting
internal fun centerLockIcon(
center: Point,
radius: Float,
drawablePadding: Int,
rootView: KeyguardRootView,
) {
val lockIconView = rootView.findViewById<View>(R.id.lock_icon_view) ?: return
val lockIcon = lockIconView.findViewById<View>(R.id.lock_icon) ?: return
lockIcon.setPadding(drawablePadding, drawablePadding, drawablePadding, drawablePadding)
val sensorRect =
Rect().apply {
set(
center.x - radius.toInt(),
center.y - radius.toInt(),
center.x + radius.toInt(),
center.y + radius.toInt(),
)
}
rootView.getConstraintSet().apply {
constrainWidth(lockIconView.id, sensorRect.right - sensorRect.left)
constrainHeight(lockIconView.id, sensorRect.bottom - sensorRect.top)
connect(lockIconView.id, TOP, PARENT_ID, TOP, sensorRect.top)
connect(lockIconView.id, START, PARENT_ID, START, sensorRect.left)
applyTo(rootView)
}
}
private fun Int.dp(): Int {
return context.resources.getDimensionPixelSize(this)
}
private fun ConstraintLayout.getConstraintSet(): ConstraintSet {
val cs = ConstraintSet()
cs.clone(this)
return cs
}
companion object {
const val DEFAULT = "default"
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.systemui.keyguard.ui.view.layout
import android.content.res.Configuration
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.DefaultLockscreenLayout.Companion.DEFAULT
import com.android.systemui.statusbar.policy.ConfigurationController
import javax.inject.Inject
/**
* Manages layout changes for the lockscreen.
*
* To add a layout, add an entry to the map with a unique id and call #transitionToLayout(string).
*/
@SysUISingleton
class KeyguardLayoutManager
@Inject
constructor(
configurationController: ConfigurationController,
layouts: Set<@JvmSuppressWildcards LockscreenLayout>,
private val keyguardRootView: KeyguardRootView,
) {
internal val layoutIdMap: Map<String, LockscreenLayout> = layouts.associateBy { it.id }
private var layout: LockscreenLayout? = layoutIdMap[DEFAULT]
init {
configurationController.addCallback(
object : ConfigurationController.ConfigurationListener {
override fun onConfigChanged(newConfig: Configuration?) {
layoutViews()
}
}
)
}
/**
* Transitions to a layout.
*
* @param layoutId
* @return whether the transition has succeeded.
*/
fun transitionToLayout(layoutId: String): Boolean {
layout = layoutIdMap[layoutId] ?: return false
layoutViews()
return true
}
fun layoutViews() {
layout?.layoutViews(keyguardRootView)
}
companion object {
const val TAG = "KeyguardLayoutManager"
}
}
interface LockscreenLayout {
val id: String
fun layoutViews(rootView: KeyguardRootView) {
// Clear constraints.
ConstraintSet()
.apply {
clone(rootView)
knownIds.forEach { getConstraint(it).layout.copyFrom(ConstraintSet.Layout()) }
}
.applyTo(rootView)
layoutIndicationArea(rootView)
layoutLockIcon(rootView)
}
fun layoutIndicationArea(rootView: KeyguardRootView)
fun layoutLockIcon(rootView: KeyguardRootView)
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.keyguard.ui.view.layout
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import java.io.PrintWriter
import javax.inject.Inject
/** Uses $ adb shell cmd statusbar layout <LayoutId> */
class KeyguardLayoutManagerCommandListener
@Inject
constructor(
private val commandRegistry: CommandRegistry,
private val keyguardLayoutManager: KeyguardLayoutManager
) {
private val layoutCommand = KeyguardLayoutManagerCommand()
fun start() {
commandRegistry.registerCommand(COMMAND) { layoutCommand }
}
internal inner class KeyguardLayoutManagerCommand : Command {
override fun execute(pw: PrintWriter, args: List<String>) {
val arg = args.getOrNull(0)
if (arg == null || arg.lowercase() == "help") {
help(pw)
return
}
if (keyguardLayoutManager.transitionToLayout(arg)) {
pw.println("Transition succeeded!")
} else {
pw.println("Invalid argument! To see available layout ids, run:")
pw.println("$ adb shell cmd statusbar layout help")
}
}
override fun help(pw: PrintWriter) {
pw.println("Usage: $ adb shell cmd statusbar layout <layoutId>")
pw.println("Existing Layout Ids: ")
keyguardLayoutManager.layoutIdMap.forEach { entry -> pw.println("${entry.key}") }
}
}
companion object {
internal const val COMMAND = "layout"
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.systemui.keyguard.ui.view.layout
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoSet
@Module
abstract class LockscreenLayoutModule {
@Binds
@IntoSet
abstract fun bindDefaultLayout(
defaultLockscreenLayout: DefaultLockscreenLayout
): LockscreenLayout
}

View File

@@ -19,6 +19,7 @@ package com.android.keyguard;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR;
import static com.android.systemui.flags.Flags.MIGRATE_LOCK_ICON;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
@@ -143,6 +144,7 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
mFeatureFlags = new FakeFeatureFlags();
mFeatureFlags.set(FACE_AUTH_REFACTOR, false);
mFeatureFlags.set(MIGRATE_LOCK_ICON, false);
mUnderTest = new LockIconViewController(
mLockIconView,
mStatusBarStateController,

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.systemui.keyguard.ui.view.layout
import android.graphics.Point
import android.view.ViewGroup
import android.view.WindowManager
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.monet.utils.ArgbSubject.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Answers
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@RunWith(JUnit4::class)
@SmallTest
class DefaultLockscreenLayoutTest : SysuiTestCase() {
private lateinit var defaultLockscreenLayout: DefaultLockscreenLayout
private lateinit var rootView: KeyguardRootView
@Mock private lateinit var authController: AuthController
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var windowManager: WindowManager
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
rootView = KeyguardRootView(context, null)
defaultLockscreenLayout =
DefaultLockscreenLayout(authController, keyguardUpdateMonitor, windowManager, context)
}
@Test
fun testLayoutViews_KeyguardIndicationArea() {
defaultLockscreenLayout.layoutViews(rootView)
val constraint = getViewConstraint(R.id.keyguard_indication_area)
assertThat(constraint.layout.bottomToBottom).isEqualTo(ConstraintSet.PARENT_ID)
assertThat(constraint.layout.startToStart).isEqualTo(ConstraintSet.PARENT_ID)
assertThat(constraint.layout.endToEnd).isEqualTo(ConstraintSet.PARENT_ID)
assertThat(constraint.layout.mWidth).isEqualTo(ViewGroup.LayoutParams.MATCH_PARENT)
assertThat(constraint.layout.mHeight).isEqualTo(ViewGroup.LayoutParams.WRAP_CONTENT)
}
@Test
fun testLayoutViews_lockIconView() {
defaultLockscreenLayout.layoutViews(rootView)
val constraint = getViewConstraint(R.id.lock_icon_view)
assertThat(constraint.layout.topToTop).isEqualTo(ConstraintSet.PARENT_ID)
assertThat(constraint.layout.startToStart).isEqualTo(ConstraintSet.PARENT_ID)
}
@Test
fun testCenterLockIcon() {
defaultLockscreenLayout.centerLockIcon(Point(5, 6), 1F, 5, rootView)
val constraint = getViewConstraint(R.id.lock_icon_view)
assertThat(constraint.layout.mWidth).isEqualTo(2)
assertThat(constraint.layout.mHeight).isEqualTo(2)
assertThat(constraint.layout.topToTop).isEqualTo(ConstraintSet.PARENT_ID)
assertThat(constraint.layout.startToStart).isEqualTo(ConstraintSet.PARENT_ID)
assertThat(constraint.layout.topMargin).isEqualTo(5)
assertThat(constraint.layout.startMargin).isEqualTo(4)
}
/** Get the ConstraintLayout constraint of the view. */
private fun getViewConstraint(viewId: Int): ConstraintSet.Constraint {
val constraintSet = ConstraintSet()
constraintSet.clone(rootView)
return constraintSet.getConstraint(viewId)
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.keyguard.ui.view.layout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
import java.io.PrintWriter
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@RunWith(JUnit4::class)
@SmallTest
class KeyguardLayoutManagerCommandListenerTest : SysuiTestCase() {
private lateinit var keyguardLayoutManagerCommandListener: KeyguardLayoutManagerCommandListener
@Mock private lateinit var commandRegistry: CommandRegistry
@Mock private lateinit var keyguardLayoutManager: KeyguardLayoutManager
@Mock private lateinit var pw: PrintWriter
private lateinit var command: () -> Command
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
keyguardLayoutManagerCommandListener =
KeyguardLayoutManagerCommandListener(
commandRegistry,
keyguardLayoutManager,
)
keyguardLayoutManagerCommandListener.start()
command =
withArgCaptor<() -> Command> {
verify(commandRegistry).registerCommand(eq("layout"), capture())
}
}
@Test
fun testHelp() {
command().execute(pw, listOf("help"))
verify(pw, atLeastOnce()).println(anyString())
verify(keyguardLayoutManager, never()).transitionToLayout(anyString())
}
@Test
fun testBlank() {
command().execute(pw, listOf())
verify(pw, atLeastOnce()).println(anyString())
verify(keyguardLayoutManager, never()).transitionToLayout(anyString())
}
@Test
fun testValidArg() {
bindFakeIdMapToLayoutManager()
command().execute(pw, listOf("fake"))
verify(keyguardLayoutManager).transitionToLayout("fake")
}
private fun bindFakeIdMapToLayoutManager() {
val map = mapOf("fake" to mock(LockscreenLayout::class.java))
whenever(keyguardLayoutManager.layoutIdMap).thenReturn(map)
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.systemui.keyguard.ui.view.layout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.DefaultLockscreenLayout.Companion.DEFAULT
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@RunWith(JUnit4::class)
@SmallTest
class KeyguardLayoutManagerTest : SysuiTestCase() {
private lateinit var keyguardLayoutManager: KeyguardLayoutManager
@Mock lateinit var configurationController: ConfigurationController
@Mock lateinit var defaultLockscreenLayout: DefaultLockscreenLayout
@Mock lateinit var keyguardRootView: KeyguardRootView
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
whenever(defaultLockscreenLayout.id).thenReturn(DEFAULT)
keyguardLayoutManager =
KeyguardLayoutManager(
configurationController,
setOf(defaultLockscreenLayout),
keyguardRootView
)
}
@Test
fun testDefaultLayout() {
keyguardLayoutManager.transitionToLayout(DEFAULT)
verify(defaultLockscreenLayout).layoutViews(keyguardRootView)
}
@Test
fun testTransitionToLayout_validId() {
assertThat(keyguardLayoutManager.transitionToLayout(DEFAULT)).isTrue()
}
@Test
fun testTransitionToLayout_invalidId() {
assertThat(keyguardLayoutManager.transitionToLayout("abc")).isFalse()
}
}