Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae54e5e4 authored by Matt Pietal's avatar Matt Pietal
Browse files

Add split shade blueprint

This begins the separation into a specific large screen
blueprint. Adds logic to KeyguardBlueprintInteractor to determine
which blueprint should be active, based upon configuration.

For the moment, the only thing affected is NSSL placement and will be
followed by media.

Bug: 296370020
Test: atest KeyguardBlueprintRepositoryTest
DefaultKeyguardBlueprintTest KeyguardBlueprintInteractorTest
Test: Use foldables to test layouts
Flag: LEGACY MIGRATE_NSSL DISABLED

Change-Id: I147eb91c89a32c7f1535739f0bcc79d91f29dbf6
parent 25687797
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ constructor(
    defaultCommunalWidgetSection: DefaultCommunalWidgetSection,
) : KeyguardBlueprint {
    override val id: String = COMMUNAL
    override val sections: Set<KeyguardSection> =
        setOf(
    override val sections: List<KeyguardSection> =
        listOf(
            defaultCommunalHubSection,
            defaultCommunalWidgetSection,
        )
+20 −13
Original line number Diff line number Diff line
@@ -17,33 +17,29 @@

package com.android.systemui.keyguard.data.repository

import android.util.Log
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.shared.model.KeyguardBlueprint
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 java.util.TreeMap
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:
 * the dagger module: [KeyguardBlueprintModule]
 *
 * 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
@@ -51,18 +47,16 @@ class KeyguardBlueprintRepository
constructor(
    configurationRepository: ConfigurationRepository,
    blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>,
    @Application private val applicationScope: CoroutineScope,
) {
    private val blueprintIdMap: TreeMap<String, KeyguardBlueprint> = TreeMap()
    private val _blueprint: MutableSharedFlow<KeyguardBlueprint> = MutableSharedFlow(replay = 1)
    val blueprint: Flow<KeyguardBlueprint> = _blueprint.asSharedFlow()

    val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange

    init {
        blueprintIdMap.putAll(blueprints.associateBy { it.id })
        applyBlueprint(blueprintIdMap[DEFAULT]!!)
        applicationScope.launch {
            configurationRepository.onAnyConfigurationChange.collect { refreshBlueprint() }
        }
    }

    /**
@@ -86,9 +80,18 @@ constructor(
     * @return whether the transition has succeeded.
     */
    fun applyBlueprint(blueprintId: String?): Boolean {
        val blueprint = blueprintIdMap[blueprintId] ?: return false
        val blueprint = blueprintIdMap[blueprintId]
        return if (blueprint != null) {
            applyBlueprint(blueprint)
        return true
            true
        } else {
            Log.e(
                TAG,
                "Could not find blueprint with id: $blueprintId. " +
                    "Perhaps it was not added to KeyguardBlueprintModule?"
            )
            false
        }
    }

    /** Emits the blueprint value to the collectors. */
@@ -107,4 +110,8 @@ constructor(
    fun printBlueprints(pw: PrintWriter) {
        blueprintIdMap.onEachIndexed { index, entry -> pw.println("$index: ${entry.key}") }
    }

    companion object {
        private const val TAG = "KeyguardBlueprintRepository"
    }
}
+41 −1
Original line number Diff line number Diff line
@@ -17,16 +17,56 @@

package com.android.systemui.keyguard.domain.interactor

import android.content.Context
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
import com.android.systemui.statusbar.policy.SplitShadeStateController
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch

@SysUISingleton
class KeyguardBlueprintInteractor
@Inject
constructor(private val keyguardBlueprintRepository: KeyguardBlueprintRepository) {
constructor(
    private val keyguardBlueprintRepository: KeyguardBlueprintRepository,
    @Application private val applicationScope: CoroutineScope,
    private val context: Context,
    private val splitShadeStateController: SplitShadeStateController,
) {

    val blueprint = keyguardBlueprintRepository.blueprint

    init {
        applicationScope.launch {
            keyguardBlueprintRepository.configurationChange
                .onStart { emit(Unit) }
                .collect { updateBlueprint() }
        }
    }

    /**
     * Detects when a new blueprint should be applied and calls [transitionToBlueprint]. This may
     * end up reapplying the same blueprint, which is fine as configuration may have changed.
     */
    private fun updateBlueprint() {
        val useSplitShade =
            splitShadeStateController.shouldUseSplitNotificationShade(context.resources)

        val blueprintId =
            if (useSplitShade) {
                SplitShadeKeyguardBlueprint.ID
            } else {
                DefaultKeyguardBlueprint.DEFAULT
            }

        transitionToBlueprint(blueprintId)
    }

    /**
     * Transitions to a blueprint.
     *
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import androidx.constraintlayout.widget.ConstraintSet
/** Determines the constraints for the ConstraintSet in the lockscreen root view. */
interface KeyguardBlueprint {
    val id: String
    val sections: Set<KeyguardSection>
    val sections: List<KeyguardSection>

    /**
     * Removes views of old blueprint and add views of new blueprint.
+1 −4
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSec
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
import javax.inject.Inject

/**
@@ -53,7 +52,6 @@ constructor(
    defaultStatusViewSection: DefaultStatusViewSection,
    defaultStatusBarSection: DefaultStatusBarSection,
    defaultNotificationStackScrollLayoutSection: DefaultNotificationStackScrollLayoutSection,
    splitShadeGuidelines: SplitShadeGuidelines,
    aodNotificationIconsSection: AodNotificationIconsSection,
    aodBurnInSection: AodBurnInSection,
    communalTutorialIndicatorSection: CommunalTutorialIndicatorSection,
@@ -63,7 +61,7 @@ constructor(
    override val id: String = DEFAULT

    override val sections =
        setOf(
        listOf(
            defaultIndicationAreaSection,
            defaultDeviceEntryIconSection,
            defaultShortcutsSection,
@@ -72,7 +70,6 @@ constructor(
            defaultStatusViewSection,
            defaultStatusBarSection,
            defaultNotificationStackScrollLayoutSection,
            splitShadeGuidelines,
            aodNotificationIconsSection,
            aodBurnInSection,
            communalTutorialIndicatorSection,
Loading