Merge changes I9b6121a7,I31a47234 into udc-qpr-dev
* changes: Add a shell command interface for layouts. Add layout manager
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user