Merge "Rename layout -> blueprint and add "sections"" into udc-qpr-dev
diff --git a/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml b/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml
index 65ee8b3..636f479 100644
--- a/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml
+++ b/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml
@@ -25,13 +25,13 @@
android:orientation="horizontal"
android:gravity="center_vertical"
android:background="@drawable/keyguard_settings_popup_menu_background"
- android:padding="12dp">
+ android:padding="@dimen/keyguard_settings_popup_menu_padding">
<ImageView
android:id="@+id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_marginEnd="8dp"
+ android:layout_width="@dimen/keyguard_settings_popup_menu_icon_height"
+ android:layout_height="@dimen/keyguard_settings_popup_menu_icon_width"
+ android:layout_marginEnd="@dimen/keyguard_settings_popup_menu_icon_end_margin"
android:tint="?androidprv:attr/materialColorOnSecondaryFixed"
android:importantForAccessibility="no"
tools:ignore="UseAppTint" />
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index 76b073e..1a0c7f9 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -181,6 +181,10 @@
mLockIcon.setImageState(getLockIconState(mIconType, mAod), true);
}
+ public ImageView getLockIcon() {
+ return mLockIcon;
+ }
+
private void addLockIconImageView(Context context, AttributeSet attrs) {
mLockIcon = new ImageView(context, attrs);
mLockIcon.setId(R.id.lock_icon);
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 5459718..4845a61 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -417,7 +417,10 @@
private void updateLockIconLocation() {
final float scaleFactor = mAuthController.getScaleFactor();
final int scaledPadding = (int) (mDefaultPaddingPx * scaleFactor);
- if (!mFeatureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
+ if (mFeatureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
+ mView.getLockIcon().setPadding(scaledPadding, scaledPadding, scaledPadding,
+ scaledPadding);
+ } else {
if (mUdfpsSupported) {
mView.setCenterLocation(mAuthController.getUdfpsLocation(),
mAuthController.getUdfpsRadius(), scaledPadding);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 3c42a29..f73a602 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -54,7 +54,7 @@
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.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule;
import com.android.systemui.log.dagger.LogModule;
import com.android.systemui.log.dagger.MonitorLog;
import com.android.systemui.log.table.TableLogBuffer;
@@ -179,7 +179,7 @@
GarbageMonitorModule.class,
KeyboardModule.class,
LetterboxModule.class,
- LockscreenLayoutModule.class,
+ KeyguardBlueprintModule.class,
LogModule.class,
MediaProjectionModule.class,
MediaProjectionTaskSwitcherModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 4495943..6213265c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -26,27 +26,28 @@
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.binder.KeyguardAmbientIndicationAreaViewBinder
+import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardSettingsViewBinder
import com.android.systemui.keyguard.ui.view.KeyguardRootView
+import com.android.systemui.keyguard.ui.view.layout.KeyguardBlueprintCommandListener
import com.android.systemui.keyguard.ui.viewmodel.KeyguardAmbientIndicationViewModel
-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.KeyguardBlueprintViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSettingsMenuViewModel
+import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.shade.NotificationShadeWindowView
import com.android.systemui.statusbar.KeyguardIndicationController
+import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.SharedNotificationContainerBinder
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
-import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import javax.inject.Inject
@@ -68,9 +69,8 @@
private val notificationShadeWindowView: NotificationShadeWindowView,
private val featureFlags: FeatureFlags,
private val indicationController: KeyguardIndicationController,
- private val keyguardLayoutManager: KeyguardLayoutManager,
- private val keyguardLayoutManagerCommandListener: KeyguardLayoutManagerCommandListener,
- private val keyguardQuickAffordancesCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
+ private val keyguardQuickAffordancesCombinedViewModel:
+ KeyguardQuickAffordancesCombinedViewModel,
private val falsingManager: FalsingManager,
private val vibratorHelper: VibratorHelper,
private val keyguardStateController: KeyguardStateController,
@@ -78,6 +78,8 @@
private val activityStarter: ActivityStarter,
private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
private val chipbarCoordinator: ChipbarCoordinator,
+ private val keyguardBlueprintCommandListener: KeyguardBlueprintCommandListener,
+ private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
) : CoreStartable {
private var rootViewHandle: DisposableHandle? = null
@@ -100,8 +102,8 @@
bindAmbientIndicationArea()
bindSettingsPopupMenu()
- keyguardLayoutManager.layoutViews()
- keyguardLayoutManagerCommandListener.start()
+ KeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel)
+ keyguardBlueprintCommandListener.start()
}
fun setupNotificationStackScrollLayout(legacyParent: ViewGroup) {
@@ -125,8 +127,6 @@
leftShortcutHandle?.onConfigurationChanged()
rightShortcutHandle?.onConfigurationChanged()
ambientIndicationAreaHandle?.onConfigurationChanged()
-
- keyguardLayoutManager.layoutViews()
}
fun bindIndicationArea() {
@@ -152,14 +152,15 @@
private fun bindKeyguardRootView() {
rootViewHandle?.dispose()
- rootViewHandle = KeyguardRootViewBinder.bind(
- keyguardRootView,
- keyguardRootViewModel,
- featureFlags,
- occludingAppDeviceEntryMessageViewModel,
- chipbarCoordinator,
- keyguardStateController,
- )
+ rootViewHandle =
+ KeyguardRootViewBinder.bind(
+ keyguardRootView,
+ keyguardRootViewModel,
+ featureFlags,
+ occludingAppDeviceEntryMessageViewModel,
+ chipbarCoordinator,
+ keyguardStateController,
+ )
}
private fun bindLockIconView(legacyParent: ViewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
new file mode 100644
index 0000000..059f72b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.data.repository
+
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
+import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule
+import java.io.PrintWriter
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.launch
+
+/**
+ * Manages blueprint changes for the lockscreen.
+ *
+ * To add a blueprint, create a class that implements LockscreenBlueprint and bind it to the map in
+ * the dagger module:
+ *
+ * A Blueprint determines how the layout should be constrained on a high level.
+ *
+ * A Section is a modular piece of code that implements the constraints. The blueprint uses the
+ * sections to define the constraints.
+ *
+ * @see KeyguardBlueprintModule
+ */
+@SysUISingleton
+class KeyguardBlueprintRepository
+@Inject
+constructor(
+ configurationRepository: ConfigurationRepository,
+ blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>,
+ @Application private val applicationScope: CoroutineScope,
+) {
+ private val blueprintIdMap: Map<String, KeyguardBlueprint> = blueprints.associateBy { it.id }
+ private val _blueprint: MutableSharedFlow<KeyguardBlueprint> = MutableSharedFlow(replay = 1)
+ val blueprint: Flow<KeyguardBlueprint> = _blueprint.asSharedFlow()
+
+ init {
+ applyBlueprint(blueprintIdMap[DEFAULT]!!)
+ applicationScope.launch {
+ configurationRepository.onAnyConfigurationChange.collect { refreshBlueprint() }
+ }
+ }
+
+ /**
+ * Emits the blueprint value to the collectors.
+ *
+ * @param blueprintId
+ * @return whether the transition has succeeded.
+ */
+ fun applyBlueprint(blueprintId: String?): Boolean {
+ val blueprint = blueprintIdMap[blueprintId] ?: return false
+ applyBlueprint(blueprint)
+ return true
+ }
+
+ /** Emits the blueprint value to the collectors. */
+ fun applyBlueprint(blueprint: KeyguardBlueprint?) {
+ blueprint?.let { _blueprint.tryEmit(it) }
+ }
+
+ /** Re-emits the last emitted blueprint value if possible. */
+ fun refreshBlueprint() {
+ if (_blueprint.replayCache.isNotEmpty()) {
+ _blueprint.tryEmit(_blueprint.replayCache.last())
+ }
+ }
+
+ /** Prints all available blueprints to the PrintWriter. */
+ fun printBlueprints(pw: PrintWriter) {
+ blueprintIdMap.forEach { entry -> pw.println("${entry.key}") }
+ }
+}
+
+/** Determines the constraints for the ConstraintSet in the lockscreen root view. */
+interface KeyguardBlueprint {
+ val id: String
+
+ fun apply(constraintSet: ConstraintSet)
+}
+
+/**
+ * Lower level modules that determine constraints for a particular section in the lockscreen root
+ * view.
+ */
+interface KeyguardSection {
+ fun apply(constraintSet: ConstraintSet)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
new file mode 100644
index 0000000..390ad7e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
+import javax.inject.Inject
+
+@SysUISingleton
+class KeyguardBlueprintInteractor
+@Inject
+constructor(private val keyguardBlueprintRepository: KeyguardBlueprintRepository) {
+ val blueprint = keyguardBlueprintRepository.blueprint
+
+ /**
+ * Transitions to a blueprint.
+ *
+ * @param blueprintId
+ * @return whether the transition has succeeded.
+ */
+ fun transitionToBlueprint(blueprintId: String): Boolean {
+ return keyguardBlueprintRepository.applyBlueprint(blueprintId)
+ }
+
+ /** Re-emits the blueprint value to the collectors. */
+ fun refreshBlueprint() {
+ keyguardBlueprintRepository.refreshBlueprint()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
new file mode 100644
index 0000000..23b80b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.binder
+
+import android.os.Trace
+import android.util.Log
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.keyguard.ui.view.KeyguardRootView
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import kotlinx.coroutines.launch
+
+class KeyguardBlueprintViewBinder {
+ companion object {
+ private const val TAG = "KeyguardBlueprintViewBinder"
+
+ fun bind(keyguardRootView: KeyguardRootView, viewModel: KeyguardBlueprintViewModel) {
+ keyguardRootView.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ launch {
+ viewModel.blueprint.collect { blueprint ->
+ Trace.beginSection("KeyguardBlueprintController#applyBlueprint")
+ Log.d(TAG, "applying blueprint: $blueprint")
+ ConstraintSet().apply {
+ clone(keyguardRootView)
+ val emptyLayout = ConstraintSet.Layout()
+ knownIds.forEach { getConstraint(it).layout.copyFrom(emptyLayout) }
+ blueprint?.apply(this)
+ applyTo(keyguardRootView)
+ }
+ Trace.endSection()
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 3e6e158..58bc552 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -44,11 +44,13 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
+import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
import com.android.systemui.keyguard.ui.view.KeyguardRootView
-import com.android.systemui.keyguard.ui.view.layout.KeyguardLayoutManager
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel
@@ -90,12 +92,13 @@
private val lockscreenSmartspaceController: LockscreenSmartspaceController,
private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
private val featureFlags: FeatureFlags,
- private val keyguardLayoutManager: KeyguardLayoutManager,
private val falsingManager: FalsingManager,
private val vibratorHelper: VibratorHelper,
private val indicationController: KeyguardIndicationController,
private val keyguardRootViewModel: KeyguardRootViewModel,
@Assisted bundle: Bundle,
+ private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
+ private val keyguardBlueprintInteractor: KeyguardBlueprintInteractor,
) {
val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
@@ -129,17 +132,17 @@
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
keyguardRootViewModel.enablePreviewMode(
initiallySelectedSlotId =
- bundle.getString(
- KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID,
- ),
+ bundle.getString(
+ KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID,
+ ),
shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance,
)
} else {
bottomAreaViewModel.enablePreviewMode(
initiallySelectedSlotId =
- bundle.getString(
- KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID,
- ),
+ bundle.getString(
+ KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID,
+ ),
shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance,
)
}
@@ -169,7 +172,8 @@
),
)
setupShortcuts(keyguardRootView)
- keyguardLayoutManager.layoutViews(keyguardRootView)
+ KeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel)
+ keyguardBlueprintInteractor.refreshBlueprint()
} else {
setUpBottomArea(rootView)
}
@@ -309,7 +313,7 @@
false,
) as KeyguardBottomAreaView
bottomAreaView.init(
- viewModel = bottomAreaViewModel,
+ viewModel = bottomAreaViewModel,
)
parentView.addView(
bottomAreaView,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
index 65fe990..e60901f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
@@ -19,10 +19,10 @@
import android.content.Context
import android.util.AttributeSet
-import androidx.constraintlayout.widget.ConstraintLayout
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.res.ResourcesCompat
import com.android.keyguard.LockIconView
import com.android.systemui.R
@@ -62,8 +62,9 @@
}
private fun addLeftShortcut() {
- val view = LaunchableImageView(context, attrs)
- .apply {
+ val padding = resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_padding)
+ val view =
+ LaunchableImageView(context, attrs).apply {
id = R.id.start_button
scaleType = ImageView.ScaleType.FIT_CENTER
background =
@@ -79,13 +80,15 @@
context.theme
)
visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
}
addView(view)
}
private fun addRightShortcut() {
- val view = LaunchableImageView(context, attrs)
- .apply {
+ val padding = resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_padding)
+ val view =
+ LaunchableImageView(context, attrs).apply {
id = R.id.end_button
scaleType = ImageView.ScaleType.FIT_CENTER
background =
@@ -101,20 +104,19 @@
context.theme
)
visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
}
addView(view)
}
private fun addSettingsPopupMenu() {
- val view = LayoutInflater.from(context).inflate(
- R.layout.keyguard_settings_popup_menu,
- this,
- false
- )
- .apply {
- id = R.id.keyguard_settings_button
- visibility = GONE
- }
+ val view =
+ LayoutInflater.from(context)
+ .inflate(R.layout.keyguard_settings_popup_menu, this, false)
+ .apply {
+ id = R.id.keyguard_settings_button
+ visibility = GONE
+ }
addView(view)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/DefaultLockscreenLayout.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/DefaultLockscreenLayout.kt
deleted file mode 100644
index 6be45c7..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/DefaultLockscreenLayout.kt
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.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.ViewGroup.MarginLayoutParams
-import android.view.WindowManager
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-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.LEFT
-import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
-import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
-import androidx.constraintlayout.widget.ConstraintSet.RIGHT
-import androidx.constraintlayout.widget.ConstraintSet.START
-import androidx.constraintlayout.widget.ConstraintSet.TOP
-import androidx.core.view.setPadding
-import androidx.core.view.updateLayoutParams
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R
-import com.android.systemui.animation.view.LaunchableLinearLayout
-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)
- }
- }
-
- override fun layoutShortcuts(rootView: KeyguardRootView) {
- val leftShortcut = rootView.findViewById<View>(R.id.start_button) ?: return
- val rightShortcut = rootView.findViewById<View>(R.id.end_button) ?: return
- val width =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width)
- val height =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
- val horizontalOffsetMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_horizontal_offset)
- val verticalOffsetMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset)
- val padding =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_padding)
-
- leftShortcut.apply {
- updateLayoutParams<MarginLayoutParams> {
- marginStart = horizontalOffsetMargin
- bottomMargin = verticalOffsetMargin
- }
- setPadding(padding)
- }
-
- rightShortcut.apply {
- updateLayoutParams<MarginLayoutParams> {
- marginEnd = horizontalOffsetMargin
- bottomMargin = verticalOffsetMargin
- }
- setPadding(padding)
- }
-
- rootView.getConstraintSet().apply {
- constrainWidth(leftShortcut.id, width)
- constrainHeight(leftShortcut.id, height)
- connect(leftShortcut.id, LEFT, PARENT_ID, LEFT)
- connect(leftShortcut.id, BOTTOM, PARENT_ID, BOTTOM)
-
- constrainWidth(rightShortcut.id, width)
- constrainHeight(rightShortcut.id, height)
- connect(rightShortcut.id, RIGHT, PARENT_ID, RIGHT)
- connect(rightShortcut.id, BOTTOM, PARENT_ID, BOTTOM)
- applyTo(rootView)
- }
- }
-
- override fun layoutAmbientIndicationArea(rootView: KeyguardRootView) {
- val ambientIndicationContainer =
- rootView.findViewById<View>(R.id.ambient_indication_container) ?: return
- val lockIconView = rootView.findViewById<View>(R.id.lock_icon_view) ?: return
- val indicationArea = rootView.findViewById<View>(R.id.keyguard_indication_area) ?: return
-
- rootView.getConstraintSet().apply {
- constrainWidth(ambientIndicationContainer.id, MATCH_PARENT)
-
- if (keyguardUpdateMonitor.isUdfpsSupported) {
- //constrain below udfps and above indication area
- constrainHeight(ambientIndicationContainer.id, MATCH_CONSTRAINT)
- connect(ambientIndicationContainer.id, TOP, lockIconView.id, BOTTOM)
- connect(ambientIndicationContainer.id, BOTTOM, indicationArea.id, TOP)
- connect(ambientIndicationContainer.id, LEFT, PARENT_ID, LEFT)
- connect(ambientIndicationContainer.id, RIGHT, PARENT_ID, RIGHT)
- } else {
- //constrain above lock icon
- constrainHeight(ambientIndicationContainer.id, WRAP_CONTENT)
- connect(ambientIndicationContainer.id, BOTTOM, lockIconView.id, TOP)
- connect(ambientIndicationContainer.id, LEFT, PARENT_ID, LEFT)
- connect(ambientIndicationContainer.id, RIGHT, PARENT_ID, RIGHT)
- }
-
- applyTo(rootView)
- }
- }
-
- override fun layoutSettingsPopupMenu(rootView: KeyguardRootView) {
- val popupMenu =
- rootView.findViewById<LaunchableLinearLayout>(R.id.keyguard_settings_button) ?: return
- val icon = popupMenu.findViewById<ImageView>(R.id.icon) ?: return
- val textView = popupMenu.findViewById<TextView>(R.id.text) ?: return
- val horizontalOffsetMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_horizontal_offset)
-
- icon.updateLayoutParams<LinearLayout.LayoutParams> {
- height =
- context
- .resources
- .getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_icon_height)
- width =
- context
- .resources
- .getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_icon_width)
- marginEnd =
- context
- .resources
- .getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_icon_end_margin)
- }
-
- textView.updateLayoutParams<LinearLayout.LayoutParams> {
- height = WRAP_CONTENT
- width = WRAP_CONTENT
- }
-
- popupMenu.updateLayoutParams<MarginLayoutParams> {
- bottomMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset)
- marginStart = horizontalOffsetMargin
- marginEnd = horizontalOffsetMargin
- }
- popupMenu.setPadding(
- context.resources.getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_padding)
- )
-
- rootView.getConstraintSet().apply {
- constrainWidth(popupMenu.id, WRAP_CONTENT)
- constrainHeight(popupMenu.id, WRAP_CONTENT)
- constrainMinHeight(
- popupMenu.id,
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
- )
- connect(popupMenu.id, LEFT, PARENT_ID, LEFT)
- connect(popupMenu.id, RIGHT, PARENT_ID, RIGHT)
- connect(popupMenu.id, BOTTOM, PARENT_ID, BOTTOM)
-
- applyTo(rootView)
- }
- }
-
- private fun Int.dp(): Int {
- return context.resources.getDimensionPixelSize(this)
- }
-
- private fun ConstraintLayout.getConstraintSet(): ConstraintSet =
- ConstraintSet().also {
- it.clone(this)
- }
-
- companion object {
- const val DEFAULT = "default"
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerCommandListener.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListener.kt
similarity index 64%
rename from packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerCommandListener.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListener.kt
index b351ea8..36d21f1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerCommandListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListener.kt
@@ -16,17 +16,20 @@
package com.android.systemui.keyguard.ui.view.layout
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
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
+/** Uses $ adb shell cmd statusbar blueprint <BlueprintId> */
+class KeyguardBlueprintCommandListener
@Inject
constructor(
private val commandRegistry: CommandRegistry,
- private val keyguardLayoutManager: KeyguardLayoutManager
+ private val keyguardBlueprintRepository: KeyguardBlueprintRepository,
+ private val keyguardBlueprintInteractor: KeyguardBlueprintInteractor,
) {
private val layoutCommand = KeyguardLayoutManagerCommand()
@@ -42,22 +45,22 @@
return
}
- if (keyguardLayoutManager.transitionToLayout(arg)) {
+ if (keyguardBlueprintInteractor.transitionToBlueprint(arg)) {
pw.println("Transition succeeded!")
} else {
- pw.println("Invalid argument! To see available layout ids, run:")
- pw.println("$ adb shell cmd statusbar layout help")
+ pw.println("Invalid argument! To see available blueprint ids, run:")
+ pw.println("$ adb shell cmd statusbar blueprint 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}") }
+ pw.println("Usage: $ adb shell cmd statusbar blueprint <blueprintId>")
+ pw.println("Existing Blueprint Ids: ")
+ keyguardBlueprintRepository.printBlueprints(pw)
}
}
companion object {
- internal const val COMMAND = "layout"
+ internal const val COMMAND = "blueprint"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManager.kt
deleted file mode 100644
index 6973cd9..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManager.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.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(rootView: KeyguardRootView = keyguardRootView) {
- layout?.layoutViews(rootView)
- }
-
- 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)
- layoutShortcuts(rootView)
- layoutAmbientIndicationArea(rootView)
- layoutSettingsPopupMenu(rootView)
- }
- fun layoutIndicationArea(rootView: KeyguardRootView)
- fun layoutLockIcon(rootView: KeyguardRootView)
- fun layoutShortcuts(rootView: KeyguardRootView)
- fun layoutAmbientIndicationArea(rootView: KeyguardRootView)
- fun layoutSettingsPopupMenu(rootView: KeyguardRootView)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/ShortcutsBesideUdfpsLockscreenLayout.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/ShortcutsBesideUdfpsLockscreenLayout.kt
deleted file mode 100644
index 569762d..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/ShortcutsBesideUdfpsLockscreenLayout.kt
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.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
-import android.view.ViewGroup.LayoutParams.MATCH_PARENT
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import android.view.WindowManager
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-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.LEFT
-import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
-import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
-import androidx.constraintlayout.widget.ConstraintSet.RIGHT
-import androidx.constraintlayout.widget.ConstraintSet.START
-import androidx.constraintlayout.widget.ConstraintSet.TOP
-import androidx.core.view.setPadding
-import androidx.core.view.updateLayoutParams
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R
-import com.android.systemui.animation.view.LaunchableLinearLayout
-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 ShortcutsBesideUdfpsLockscreenLayout
-@Inject
-constructor(
- private val authController: AuthController,
- private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
- private val windowManager: WindowManager,
- private val context: Context,
-) : LockscreenLayout {
- override val id: String = SHORTCUTS_BESIDE_UDFPS
-
- 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)
- }
- }
-
- override fun layoutShortcuts(rootView: KeyguardRootView) {
- val leftShortcut = rootView.findViewById<View>(R.id.start_button) ?: return
- val rightShortcut = rootView.findViewById<View>(R.id.end_button) ?: return
- val lockIconView = rootView.findViewById<View>(R.id.lock_icon_view) ?: return
- val udfpsSupported = keyguardUpdateMonitor.isUdfpsSupported
- val width =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width)
- val height =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
- val horizontalOffsetMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_horizontal_offset)
- val verticalOffsetMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset)
- val padding =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_padding)
-
- if (!udfpsSupported) {
- leftShortcut.apply {
- updateLayoutParams<ViewGroup.MarginLayoutParams> {
- marginStart = horizontalOffsetMargin
- bottomMargin = verticalOffsetMargin
- }
- setPadding(padding)
- }
-
- rightShortcut.apply {
- updateLayoutParams<ViewGroup.MarginLayoutParams> {
- marginEnd = horizontalOffsetMargin
- bottomMargin = verticalOffsetMargin
- }
- setPadding(padding)
- }
- }
-
- rootView.getConstraintSet().apply {
- if (udfpsSupported) {
- constrainWidth(leftShortcut.id, width)
- constrainHeight(leftShortcut.id, height)
- connect(leftShortcut.id, LEFT, PARENT_ID, LEFT)
- connect(leftShortcut.id, RIGHT, lockIconView.id, LEFT)
- connect(leftShortcut.id, TOP, lockIconView.id, TOP)
- connect(leftShortcut.id, BOTTOM, lockIconView.id, BOTTOM)
-
- constrainWidth(rightShortcut.id, width)
- constrainHeight(rightShortcut.id, height)
- connect(rightShortcut.id, RIGHT, PARENT_ID, RIGHT)
- connect(rightShortcut.id, LEFT, lockIconView.id, RIGHT)
- connect(rightShortcut.id, TOP, lockIconView.id, TOP)
- connect(rightShortcut.id, BOTTOM, lockIconView.id, BOTTOM)
- } else {
- constrainWidth(leftShortcut.id, width)
- constrainHeight(leftShortcut.id, height)
- connect(leftShortcut.id, LEFT, PARENT_ID, LEFT)
- connect(leftShortcut.id, BOTTOM, PARENT_ID, BOTTOM)
-
- constrainWidth(rightShortcut.id, width)
- constrainHeight(rightShortcut.id, height)
- connect(rightShortcut.id, RIGHT, PARENT_ID, RIGHT)
- connect(rightShortcut.id, BOTTOM, PARENT_ID, BOTTOM)
- }
- applyTo(rootView)
- }
- }
-
- override fun layoutAmbientIndicationArea(rootView: KeyguardRootView) {
- val ambientIndicationContainer =
- rootView.findViewById<View>(R.id.ambient_indication_container) ?: return
- val lockIconView = rootView.findViewById<View>(R.id.lock_icon_view) ?: return
- val indicationArea = rootView.findViewById<View>(R.id.keyguard_indication_area) ?: return
-
- rootView.getConstraintSet().apply {
- constrainWidth(ambientIndicationContainer.id, MATCH_PARENT)
-
- if (keyguardUpdateMonitor.isUdfpsSupported) {
- //constrain below udfps and above indication area
- constrainHeight(ambientIndicationContainer.id, MATCH_CONSTRAINT)
- connect(ambientIndicationContainer.id, TOP, lockIconView.id, BOTTOM)
- connect(ambientIndicationContainer.id, BOTTOM, indicationArea.id, TOP)
- connect(ambientIndicationContainer.id, LEFT, PARENT_ID, LEFT)
- connect(ambientIndicationContainer.id, RIGHT, PARENT_ID, RIGHT)
- } else {
- //constrain above lock icon
- constrainHeight(ambientIndicationContainer.id, WRAP_CONTENT)
- connect(ambientIndicationContainer.id, BOTTOM, lockIconView.id, TOP)
- connect(ambientIndicationContainer.id, LEFT, PARENT_ID, LEFT)
- connect(ambientIndicationContainer.id, RIGHT, PARENT_ID, RIGHT)
- }
- applyTo(rootView)
- }
- }
-
- override fun layoutSettingsPopupMenu(rootView: KeyguardRootView) {
- val popupMenu =
- rootView.findViewById<LaunchableLinearLayout>(R.id.keyguard_settings_button) ?: return
- val icon = popupMenu.findViewById<ImageView>(R.id.icon) ?: return
- val textView = popupMenu.findViewById<TextView>(R.id.text) ?: return
- val horizontalOffsetMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_horizontal_offset)
-
- icon.updateLayoutParams<LinearLayout.LayoutParams> {
- height =
- context
- .resources
- .getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_icon_height)
- width =
- context
- .resources
- .getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_icon_width)
- marginEnd =
- context
- .resources
- .getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_icon_end_margin)
- }
-
- textView.updateLayoutParams<LinearLayout.LayoutParams> {
- height = WRAP_CONTENT
- width = WRAP_CONTENT
- }
-
- popupMenu.updateLayoutParams<ViewGroup.MarginLayoutParams> {
- bottomMargin =
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset)
- marginStart = horizontalOffsetMargin
- marginEnd = horizontalOffsetMargin
- }
- popupMenu.setPadding(
- context.resources.getDimensionPixelSize(R.dimen.keyguard_settings_popup_menu_padding)
- )
-
- rootView.getConstraintSet().apply {
- constrainWidth(popupMenu.id, WRAP_CONTENT)
- constrainHeight(popupMenu.id, WRAP_CONTENT)
- constrainMinHeight(
- popupMenu.id,
- context.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
- )
- connect(popupMenu.id, LEFT, PARENT_ID, LEFT)
- connect(popupMenu.id, RIGHT, PARENT_ID, RIGHT)
- connect(popupMenu.id, BOTTOM, PARENT_ID, BOTTOM)
-
- applyTo(rootView)
- }
- }
-
- private fun Int.dp(): Int {
- return context.resources.getDimensionPixelSize(this)
- }
-
- private fun ConstraintLayout.getConstraintSet(): ConstraintSet =
- ConstraintSet().also {
- it.clone(this)
- }
-
- companion object {
- const val SHORTCUTS_BESIDE_UDFPS = "shortcutsBesideUdfps"
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
new file mode 100644
index 0000000..5538fe7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.blueprints
+
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprint
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultLockIconSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
+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
+@JvmSuppressWildcards
+class DefaultKeyguardBlueprint
+@Inject
+constructor(
+ private val defaultIndicationAreaSection: DefaultIndicationAreaSection,
+ private val defaultLockIconSection: DefaultLockIconSection,
+ private val defaultShortcutsSection: DefaultShortcutsSection,
+ private val defaultAmbientIndicationAreaSection: DefaultAmbientIndicationAreaSection,
+ private val defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
+) : KeyguardBlueprint {
+ override val id: String = DEFAULT
+
+ override fun apply(constraintSet: ConstraintSet) {
+ defaultIndicationAreaSection.apply(constraintSet)
+ defaultLockIconSection.apply(constraintSet)
+ defaultShortcutsSection.apply(constraintSet)
+ defaultAmbientIndicationAreaSection.apply(constraintSet)
+ defaultSettingsPopupMenuSection.apply(constraintSet)
+ }
+
+ companion object {
+ const val DEFAULT = "default"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/LockscreenLayoutModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt
similarity index 61%
rename from packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/LockscreenLayoutModule.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt
index c0447af..fefe679 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/LockscreenLayoutModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/KeyguardBlueprintModule.kt
@@ -15,23 +15,24 @@
*
*/
-package com.android.systemui.keyguard.ui.view.layout
+package com.android.systemui.keyguard.ui.view.layout.blueprints
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprint
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoSet
@Module
-abstract class LockscreenLayoutModule {
+abstract class KeyguardBlueprintModule {
@Binds
@IntoSet
- abstract fun bindDefaultLayout(
- defaultLockscreenLayout: DefaultLockscreenLayout
- ): LockscreenLayout
+ abstract fun bindDefaultBlueprint(
+ defaultLockscreenBlueprint: DefaultKeyguardBlueprint
+ ): KeyguardBlueprint
@Binds
@IntoSet
- abstract fun bindShortcutsBesideUdfpsLockscreenLayout(
- shortcutsBesideUdfpsLockscreenLayout: ShortcutsBesideUdfpsLockscreenLayout
- ): LockscreenLayout
+ abstract fun bindShortcutsBesideUdfpsLockscreenBlueprint(
+ shortcutsBesideUdfpsLockscreenBlueprint: ShortcutsBesideUdfpsKeyguardBlueprint
+ ): KeyguardBlueprint
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
new file mode 100644
index 0000000..19410e4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.blueprints
+
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprint
+import com.android.systemui.keyguard.ui.view.layout.sections.AlignShortcutsToUdfpsSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultLockIconSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
+import javax.inject.Inject
+
+/** Vertically aligns the shortcuts with the udfps. */
+@SysUISingleton
+class ShortcutsBesideUdfpsKeyguardBlueprint
+@Inject
+constructor(
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val defaultIndicationAreaSection: DefaultIndicationAreaSection,
+ private val defaultLockIconSection: DefaultLockIconSection,
+ private val defaultAmbientIndicationAreaSection: DefaultAmbientIndicationAreaSection,
+ private val defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
+ private val alignShortcutsToUdfpsSection: AlignShortcutsToUdfpsSection,
+ private val defaultShortcutsSection: DefaultShortcutsSection,
+) : KeyguardBlueprint {
+ override val id: String = SHORTCUTS_BESIDE_UDFPS
+
+ override fun apply(constraintSet: ConstraintSet) {
+ defaultIndicationAreaSection.apply(constraintSet)
+ defaultLockIconSection.apply(constraintSet)
+ defaultAmbientIndicationAreaSection.apply(constraintSet)
+ defaultSettingsPopupMenuSection.apply(constraintSet)
+ if (keyguardUpdateMonitor.isUdfpsSupported) {
+ alignShortcutsToUdfpsSection.apply(constraintSet)
+ } else {
+ defaultShortcutsSection.apply(constraintSet)
+ }
+ }
+
+ companion object {
+ const val SHORTCUTS_BESIDE_UDFPS = "shortcutsBesideUdfps"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
new file mode 100644
index 0000000..156b9f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.sections
+
+import android.content.res.Resources
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.LEFT
+import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
+import androidx.constraintlayout.widget.ConstraintSet.RIGHT
+import androidx.constraintlayout.widget.ConstraintSet.TOP
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.data.repository.KeyguardSection
+import javax.inject.Inject
+
+class AlignShortcutsToUdfpsSection @Inject constructor(@Main private val resources: Resources) :
+ KeyguardSection {
+ override fun apply(constraintSet: ConstraintSet) {
+ val width = resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width)
+ val height = resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
+
+ constraintSet.apply {
+ constrainWidth(R.id.start_button, width)
+ constrainHeight(R.id.start_button, height)
+ connect(R.id.start_button, LEFT, PARENT_ID, LEFT)
+ connect(R.id.start_button, RIGHT, R.id.lock_icon_view, LEFT)
+ connect(R.id.start_button, TOP, R.id.lock_icon_view, TOP)
+ connect(R.id.start_button, BOTTOM, R.id.lock_icon_view, BOTTOM)
+
+ constrainWidth(R.id.end_button, width)
+ constrainHeight(R.id.end_button, height)
+ connect(R.id.end_button, RIGHT, PARENT_ID, RIGHT)
+ connect(R.id.end_button, LEFT, R.id.lock_icon_view, RIGHT)
+ connect(R.id.end_button, TOP, R.id.lock_icon_view, TOP)
+ connect(R.id.end_button, BOTTOM, R.id.lock_icon_view, BOTTOM)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
new file mode 100644
index 0000000..abf25a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.sections
+
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.END
+import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
+import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
+import androidx.constraintlayout.widget.ConstraintSet.START
+import androidx.constraintlayout.widget.ConstraintSet.TOP
+import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
+import com.android.systemui.keyguard.data.repository.KeyguardSection
+import javax.inject.Inject
+
+class DefaultAmbientIndicationAreaSection
+@Inject
+constructor(private val keyguardUpdateMonitor: KeyguardUpdateMonitor) : KeyguardSection {
+ override fun apply(constraintSet: ConstraintSet) {
+ constraintSet.apply {
+ constrainWidth(R.id.ambient_indication_container, MATCH_PARENT)
+
+ if (keyguardUpdateMonitor.isUdfpsSupported) {
+ // constrain below udfps and above indication area
+ constrainHeight(R.id.ambient_indication_container, MATCH_CONSTRAINT)
+ connect(R.id.ambient_indication_container, TOP, R.id.lock_icon_view, BOTTOM)
+ connect(
+ R.id.ambient_indication_container,
+ BOTTOM,
+ R.id.keyguard_indication_area,
+ TOP
+ )
+ connect(R.id.ambient_indication_container, START, PARENT_ID, START)
+ connect(R.id.ambient_indication_container, END, PARENT_ID, END)
+ } else {
+ // constrain above lock icon
+ constrainHeight(R.id.ambient_indication_container, WRAP_CONTENT)
+ connect(R.id.ambient_indication_container, BOTTOM, R.id.lock_icon_view, TOP)
+ connect(R.id.ambient_indication_container, START, PARENT_ID, START)
+ connect(R.id.ambient_indication_container, END, PARENT_ID, END)
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
new file mode 100644
index 0000000..dee7ed5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.sections
+
+import android.content.Context
+import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.R
+import com.android.systemui.keyguard.data.repository.KeyguardSection
+import javax.inject.Inject
+
+class DefaultIndicationAreaSection @Inject constructor(private val context: Context) :
+ KeyguardSection {
+ private val indicationAreaViewId = R.id.keyguard_indication_area
+
+ override fun apply(constraintSet: ConstraintSet) {
+ constraintSet.apply {
+ constrainWidth(indicationAreaViewId, ViewGroup.LayoutParams.MATCH_PARENT)
+ constrainHeight(indicationAreaViewId, ViewGroup.LayoutParams.WRAP_CONTENT)
+ connect(
+ indicationAreaViewId,
+ ConstraintSet.BOTTOM,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.BOTTOM,
+ context.resources.getDimensionPixelSize(R.dimen.keyguard_indication_margin_bottom)
+ )
+ connect(
+ indicationAreaViewId,
+ ConstraintSet.START,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.START
+ )
+ connect(
+ indicationAreaViewId,
+ ConstraintSet.END,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.END
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
new file mode 100644
index 0000000..461faec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
@@ -0,0 +1,116 @@
+/*
+ * 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.sections
+
+import android.content.Context
+import android.graphics.Point
+import android.graphics.Rect
+import android.util.DisplayMetrics
+import android.view.WindowManager
+import androidx.annotation.VisibleForTesting
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
+import com.android.systemui.biometrics.AuthController
+import com.android.systemui.keyguard.data.repository.KeyguardSection
+import javax.inject.Inject
+
+class DefaultLockIconSection
+@Inject
+constructor(
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val authController: AuthController,
+ private val windowManager: WindowManager,
+ private val context: Context,
+) : KeyguardSection {
+ private val lockIconViewId = R.id.lock_icon_view
+
+ override fun apply(constraintSet: ConstraintSet) {
+ val isUdfpsSupported = keyguardUpdateMonitor.isUdfpsSupported
+ val scaleFactor: Float = authController.scaleFactor
+ val mBottomPaddingPx =
+ context.resources.getDimensionPixelSize(R.dimen.lock_icon_margin_bottom)
+ val mDefaultPaddingPx = context.resources.getDimensionPixelSize(R.dimen.lock_icon_padding)
+ 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,
+ constraintSet
+ )
+ }
+ } else {
+ centerLockIcon(
+ Point(
+ (widthPixels / 2).toInt(),
+ (heightPixels - ((mBottomPaddingPx + lockIconRadiusPx) * scaleFactor)).toInt()
+ ),
+ lockIconRadiusPx * scaleFactor,
+ scaledPadding,
+ constraintSet,
+ )
+ }
+ }
+
+ @VisibleForTesting
+ internal fun centerLockIcon(
+ center: Point,
+ radius: Float,
+ drawablePadding: Int,
+ constraintSet: ConstraintSet
+ ) {
+ val sensorRect =
+ Rect().apply {
+ set(
+ center.x - radius.toInt(),
+ center.y - radius.toInt(),
+ center.x + radius.toInt(),
+ center.y + radius.toInt(),
+ )
+ }
+
+ constraintSet.apply {
+ constrainWidth(lockIconViewId, sensorRect.right - sensorRect.left)
+ constrainHeight(lockIconViewId, sensorRect.bottom - sensorRect.top)
+ connect(
+ lockIconViewId,
+ ConstraintSet.TOP,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.TOP,
+ sensorRect.top
+ )
+ connect(
+ lockIconViewId,
+ ConstraintSet.START,
+ ConstraintSet.PARENT_ID,
+ ConstraintSet.START,
+ sensorRect.left
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
new file mode 100644
index 0000000..ad1e4f8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.sections
+
+import android.content.res.Resources
+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.WRAP_CONTENT
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.data.repository.KeyguardSection
+import javax.inject.Inject
+
+class DefaultSettingsPopupMenuSection @Inject constructor(@Main private val resources: Resources) :
+ KeyguardSection {
+ override fun apply(constraintSet: ConstraintSet) {
+ val horizontalOffsetMargin =
+ resources.getDimensionPixelSize(R.dimen.keyguard_affordance_horizontal_offset)
+
+ constraintSet.apply {
+ constrainWidth(R.id.keyguard_settings_button, WRAP_CONTENT)
+ constrainHeight(R.id.keyguard_settings_button, WRAP_CONTENT)
+ constrainMinHeight(
+ R.id.keyguard_settings_button,
+ resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
+ )
+ connect(R.id.keyguard_settings_button, START, PARENT_ID, START, horizontalOffsetMargin)
+ connect(R.id.keyguard_settings_button, END, PARENT_ID, END, horizontalOffsetMargin)
+ connect(
+ R.id.keyguard_settings_button,
+ BOTTOM,
+ PARENT_ID,
+ BOTTOM,
+ resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset)
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
new file mode 100644
index 0000000..db4653d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.sections
+
+import android.content.res.Resources
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.LEFT
+import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
+import androidx.constraintlayout.widget.ConstraintSet.RIGHT
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.data.repository.KeyguardSection
+import javax.inject.Inject
+
+class DefaultShortcutsSection @Inject constructor(@Main private val resources: Resources) :
+ KeyguardSection {
+ override fun apply(constraintSet: ConstraintSet) {
+ val width = resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width)
+ val height = resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height)
+ val horizontalOffsetMargin =
+ resources.getDimensionPixelSize(R.dimen.keyguard_affordance_horizontal_offset)
+ val verticalOffsetMargin =
+ resources.getDimensionPixelSize(R.dimen.keyguard_affordance_vertical_offset)
+
+ constraintSet.apply {
+ constrainWidth(R.id.start_button, width)
+ constrainHeight(R.id.start_button, height)
+ connect(R.id.start_button, LEFT, PARENT_ID, LEFT, horizontalOffsetMargin)
+ connect(R.id.start_button, BOTTOM, PARENT_ID, BOTTOM, verticalOffsetMargin)
+
+ constrainWidth(R.id.end_button, width)
+ constrainHeight(R.id.end_button, height)
+ connect(R.id.end_button, RIGHT, PARENT_ID, RIGHT, horizontalOffsetMargin)
+ connect(R.id.end_button, BOTTOM, PARENT_ID, BOTTOM, verticalOffsetMargin)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
new file mode 100644
index 0000000..5e9e553
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
+import javax.inject.Inject
+
+@SysUISingleton
+class KeyguardBlueprintViewModel
+@Inject
+constructor(keyguardBlueprintInteractor: KeyguardBlueprintInteractor) {
+ val blueprint = keyguardBlueprintInteractor.blueprint
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
new file mode 100644
index 0000000..66ead14
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
@@ -0,0 +1,104 @@
+/*
+ * 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.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
+import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+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.MockitoAnnotations
+
+@RunWith(JUnit4::class)
+@SmallTest
+class KeyguardBlueprintRepositoryTest : SysuiTestCase() {
+ private lateinit var underTest: KeyguardBlueprintRepository
+ @Mock lateinit var configurationRepository: ConfigurationRepository
+ @Mock lateinit var defaultLockscreenBlueprint: DefaultKeyguardBlueprint
+ private val testDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+ private val configurationFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ whenever(defaultLockscreenBlueprint.id).thenReturn(DEFAULT)
+ whenever(configurationRepository.onAnyConfigurationChange).thenReturn(configurationFlow)
+ underTest =
+ KeyguardBlueprintRepository(
+ configurationRepository,
+ setOf(defaultLockscreenBlueprint),
+ testScope.backgroundScope,
+ )
+ }
+
+ @Test
+ fun testApplyBlueprint_DefaultLayout() {
+ testScope.runTest {
+ val blueprint by collectLastValue(underTest.blueprint)
+ runCurrent()
+ underTest.applyBlueprint(defaultLockscreenBlueprint)
+ runCurrent()
+ assertThat(blueprint).isEqualTo(defaultLockscreenBlueprint)
+ }
+ }
+
+ @Test
+ fun testConfigurationChange() {
+ testScope.runTest {
+ val blueprint by collectLastValue(underTest.blueprint)
+ runCurrent()
+ configurationFlow.tryEmit(Unit)
+ runCurrent()
+ assertThat(blueprint).isEqualTo(defaultLockscreenBlueprint)
+ }
+ }
+
+ @Test
+ fun testRefreshBlueprint() {
+ testScope.runTest {
+ val blueprint by collectLastValue(underTest.blueprint)
+ runCurrent()
+ underTest.refreshBlueprint()
+ runCurrent()
+ assertThat(blueprint).isEqualTo(defaultLockscreenBlueprint)
+ }
+ }
+
+ @Test
+ fun testTransitionToLayout_validId() {
+ assertThat(underTest.applyBlueprint(DEFAULT)).isTrue()
+ }
+ @Test
+ fun testTransitionToLayout_invalidId() {
+ assertThat(underTest.applyBlueprint("abc")).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
new file mode 100644
index 0000000..b8a2e9d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardBlueprintInteractorTest : SysuiTestCase() {
+ private lateinit var underTest: KeyguardBlueprintInteractor
+
+ @Mock private lateinit var keyguardBlueprintRepository: KeyguardBlueprintRepository
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ underTest = KeyguardBlueprintInteractor(keyguardBlueprintRepository)
+ }
+
+ @Test
+ fun testRefreshBlueprint() {
+ underTest.refreshBlueprint()
+ verify(keyguardBlueprintRepository).refreshBlueprint()
+ }
+
+ @Test
+ fun testTransitionToBlueprint() {
+ underTest.transitionToBlueprint("abc")
+ verify(keyguardBlueprintRepository).applyBlueprint("abc")
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/DefaultLockscreenLayoutTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/DefaultLockscreenLayoutTest.kt
deleted file mode 100644
index c771356..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/DefaultLockscreenLayoutTest.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.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.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.keyguard.ui.view.KeyguardRootView
-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.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(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var windowManager: WindowManager
-
- @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
-
- @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)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerCommandListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt
similarity index 66%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerCommandListenerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt
index 145b2fd..bb73dc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerCommandListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListenerTest.kt
@@ -18,10 +18,11 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
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
@@ -31,32 +32,33 @@
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
+class KeyguardBlueprintCommandListenerTest : SysuiTestCase() {
+ private lateinit var keyguardBlueprintCommandListener: KeyguardBlueprintCommandListener
@Mock private lateinit var commandRegistry: CommandRegistry
- @Mock private lateinit var keyguardLayoutManager: KeyguardLayoutManager
+ @Mock private lateinit var keyguardBlueprintRepository: KeyguardBlueprintRepository
+ @Mock private lateinit var keyguardBlueprintInteractor: KeyguardBlueprintInteractor
@Mock private lateinit var pw: PrintWriter
private lateinit var command: () -> Command
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- keyguardLayoutManagerCommandListener =
- KeyguardLayoutManagerCommandListener(
+ keyguardBlueprintCommandListener =
+ KeyguardBlueprintCommandListener(
commandRegistry,
- keyguardLayoutManager,
+ keyguardBlueprintRepository,
+ keyguardBlueprintInteractor,
)
- keyguardLayoutManagerCommandListener.start()
+ keyguardBlueprintCommandListener.start()
command =
withArgCaptor<() -> Command> {
- verify(commandRegistry).registerCommand(eq("layout"), capture())
+ verify(commandRegistry).registerCommand(eq("blueprint"), capture())
}
}
@@ -64,25 +66,19 @@
fun testHelp() {
command().execute(pw, listOf("help"))
verify(pw, atLeastOnce()).println(anyString())
- verify(keyguardLayoutManager, never()).transitionToLayout(anyString())
+ verify(keyguardBlueprintInteractor, never()).transitionToBlueprint(anyString())
}
@Test
fun testBlank() {
command().execute(pw, listOf())
verify(pw, atLeastOnce()).println(anyString())
- verify(keyguardLayoutManager, never()).transitionToLayout(anyString())
+ verify(keyguardBlueprintInteractor, never()).transitionToBlueprint(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)
+ verify(keyguardBlueprintInteractor).transitionToBlueprint("fake")
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerTest.kt
deleted file mode 100644
index 95b2030..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/KeyguardLayoutManagerTest.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.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()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
new file mode 100644
index 0000000..66631dc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.blueprints
+
+import androidx.constraintlayout.widget.ConstraintSet
+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.sections.DefaultAmbientIndicationAreaSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultLockIconSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
+import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
+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 DefaultKeyguardBlueprintTest : SysuiTestCase() {
+ private lateinit var underTest: DefaultKeyguardBlueprint
+ private lateinit var rootView: KeyguardRootView
+ @Mock private lateinit var defaultIndicationAreaSection: DefaultIndicationAreaSection
+ @Mock private lateinit var defaultLockIconSection: DefaultLockIconSection
+ @Mock private lateinit var defaultShortcutsSection: DefaultShortcutsSection
+ @Mock
+ private lateinit var defaultAmbientIndicationAreaSection: DefaultAmbientIndicationAreaSection
+ @Mock private lateinit var defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ rootView = KeyguardRootView(context, null)
+ underTest =
+ DefaultKeyguardBlueprint(
+ defaultIndicationAreaSection,
+ defaultLockIconSection,
+ defaultShortcutsSection,
+ defaultAmbientIndicationAreaSection,
+ defaultSettingsPopupMenuSection,
+ )
+ }
+
+ @Test
+ fun apply() {
+ val cs = ConstraintSet()
+ underTest.apply(cs)
+ verify(defaultIndicationAreaSection).apply(cs)
+ verify(defaultLockIconSection).apply(cs)
+ verify(defaultShortcutsSection).apply(cs)
+ verify(defaultAmbientIndicationAreaSection).apply(cs)
+ verify(defaultSettingsPopupMenuSection).apply(cs)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
new file mode 100644
index 0000000..3dcc03d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.sections
+
+import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+@SmallTest
+class DefaultIndicationAreaSectionTest : SysuiTestCase() {
+ private val underTest = DefaultIndicationAreaSection(context)
+
+ @Test
+ fun apply() {
+ val cs = ConstraintSet()
+ underTest.apply(cs)
+
+ val constraint = cs.getConstraint(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)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
new file mode 100644
index 0000000..1444f8d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
@@ -0,0 +1,77 @@
+/*
+ * 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.sections
+
+import android.graphics.Point
+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.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.Answers
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@RunWith(JUnit4::class)
+@SmallTest
+class DefaultLockIconSectionTest : SysuiTestCase() {
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var authController: AuthController
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var windowManager: WindowManager
+ private lateinit var underTest: DefaultLockIconSection
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ DefaultLockIconSection(keyguardUpdateMonitor, authController, windowManager, context)
+ }
+
+ @Test
+ fun apply() {
+ val cs = ConstraintSet()
+ underTest.apply(cs)
+
+ val constraint = cs.getConstraint(R.id.lock_icon_view)
+
+ assertThat(constraint.layout.topToTop).isEqualTo(ConstraintSet.PARENT_ID)
+ assertThat(constraint.layout.startToStart).isEqualTo(ConstraintSet.PARENT_ID)
+ }
+
+ @Test
+ fun testCenterLockIcon() {
+ val cs = ConstraintSet()
+ underTest.centerLockIcon(Point(5, 6), 1F, 5, cs)
+
+ val constraint = cs.getConstraint(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)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
new file mode 100644
index 0000000..a18b033
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
+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 KeyguardBlueprintViewModelTest : SysuiTestCase() {
+ @Mock private lateinit var keyguardBlueprintInteractor: KeyguardBlueprintInteractor
+ private lateinit var undertest: KeyguardBlueprintViewModel
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ undertest =
+ KeyguardBlueprintViewModel(keyguardBlueprintInteractor = keyguardBlueprintInteractor)
+ }
+
+ @Test
+ fun testBlueprintFlow() {
+ verify(keyguardBlueprintInteractor).blueprint
+ }
+}