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

Commit 976207c4 authored by Aaron Liu's avatar Aaron Liu Committed by Android (Google) Code Review
Browse files

Merge "Decouple blueprints with preview renderer." into main

parents 3147778d b6c2815b
Loading
Loading
Loading
Loading
+0 −82
Original line number Diff line number Diff line
/*
 * 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 androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.launch

/**
 * Binds the existing blueprint to the constraint layout that previews keyguard.
 *
 * This view binder should only inflate and add relevant views and apply the constraints. Actual
 * data binding should be done in {@link KeyguardPreviewRenderer}
 */
class PreviewKeyguardBlueprintViewBinder {
    companion object {

        /**
         * Binds the existing blueprint to the constraint layout that previews keyguard.
         *
         * @param constraintLayout The root view to bind to
         * @param viewModel The instance of the view model that contains flows we collect on.
         * @param finishedAddViewCallback Called when we have finished inflating the views.
         */
        fun bind(
            constraintLayout: ConstraintLayout,
            viewModel: KeyguardBlueprintViewModel,
            finishedAddViewCallback: () -> Unit
        ): DisposableHandle {
            return constraintLayout.repeatWhenAttached {
                repeatOnLifecycle(Lifecycle.State.CREATED) {
                    launch {
                        viewModel.blueprint.collect { blueprint ->
                            val prevBluePrint = viewModel.currentBluePrint
                            Trace.beginSection("PreviewKeyguardBlueprint#applyBlueprint")

                            ConstraintSet().apply {
                                clone(constraintLayout)
                                val emptyLayout = ConstraintSet.Layout()
                                knownIds.forEach { getConstraint(it).layout.copyFrom(emptyLayout) }
                                blueprint.applyConstraints(this)
                                // Add and remove views of sections that are not contained by the
                                // other.
                                blueprint.replaceViews(
                                    prevBluePrint,
                                    constraintLayout,
                                    bindData = false
                                )
                                applyTo(constraintLayout)
                            }

                            viewModel.currentBluePrint = blueprint
                            finishedAddViewCallback.invoke()
                            Trace.endSection()
                        }
                    }
                }
            }
        }
    }
}
+55 −71
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.view.isInvisible
import com.android.keyguard.ClockEventController
import com.android.keyguard.KeyguardClockSwitch
@@ -54,15 +55,12 @@ import com.android.systemui.communal.ui.viewmodel.CommunalTutorialIndicatorViewM
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
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.binder.KeyguardRootViewBinder
import com.android.systemui.keyguard.ui.binder.PreviewKeyguardBlueprintViewBinder
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel
@@ -124,19 +122,18 @@ constructor(
    private val broadcastDispatcher: BroadcastDispatcher,
    private val lockscreenSmartspaceController: LockscreenSmartspaceController,
    private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
    private val featureFlags: FeatureFlagsClassic,
    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 occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
    private val chipbarCoordinator: ChipbarCoordinator,
    private val screenOffAnimationController: ScreenOffAnimationController,
    private val shadeInteractor: ShadeInteractor,
    private val secureSettings: SecureSettings,
    private val communalTutorialViewModel: CommunalTutorialIndicatorViewModel,
    private val defaultShortcutsSection: DefaultShortcutsSection,
) {
    val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
    private val width: Int = bundle.getInt(KEY_VIEW_WIDTH)
@@ -393,8 +390,6 @@ constructor(

        setUpUdfps(previewContext, rootView)

        disposables.add(
            PreviewKeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) {
        if (keyguardBottomAreaRefactor()) {
            setupShortcuts(keyguardRootView)
        }
@@ -409,16 +404,18 @@ constructor(
        }

        setUpSmartspace(previewContext, rootView)
                smartSpaceView?.let {
                    KeyguardPreviewSmartspaceViewBinder.bind(it, smartspaceViewModel)
                }

        smartSpaceView?.let { KeyguardPreviewSmartspaceViewBinder.bind(it, smartspaceViewModel) }
        setupCommunalTutorialIndicator(keyguardRootView)
    }
        )
    }

    private fun setupShortcuts(keyguardRootView: ConstraintLayout) {
        // Add shortcuts
        val cs = ConstraintSet()
        cs.clone(keyguardRootView)
        defaultShortcutsSection.addViews(keyguardRootView)
        defaultShortcutsSection.applyConstraints(cs)
        cs.applyTo(keyguardRootView)

        keyguardRootView.findViewById<LaunchableImageView?>(R.id.start_button)?.let { imageView ->
            shortcutsBindings.add(
                KeyguardQuickAffordanceViewBinder.bind(
@@ -476,27 +473,17 @@ constructor(
    }

    private fun setUpClock(previewContext: Context, parentView: ViewGroup) {
        largeClockHostView =
            if (KeyguardShadeMigrationNssl.isEnabled) {
                parentView.requireViewById<FrameLayout>(R.id.lockscreen_clock_view_large)
            } else {
                val hostView = FrameLayout(previewContext)
                hostView.layoutParams =
        val resources = parentView.resources
        largeClockHostView = FrameLayout(previewContext)
        largeClockHostView.layoutParams =
            FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT,
            )
                parentView.addView(hostView)
                hostView
            }
        parentView.addView(largeClockHostView)
        largeClockHostView.isInvisible = true

        smallClockHostView =
            if (KeyguardShadeMigrationNssl.isEnabled) {
                parentView.requireViewById<FrameLayout>(R.id.lockscreen_clock_view)
            } else {
                val resources = parentView.resources
                val hostView = FrameLayout(previewContext)
        smallClockHostView = FrameLayout(previewContext)
        val layoutParams =
            FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
@@ -509,9 +496,8 @@ constructor(
                resources.getDimensionPixelSize(
                    com.android.systemui.customization.R.dimen.small_clock_padding_top
                )
                hostView.layoutParams = layoutParams

                hostView.setPaddingRelative(
        smallClockHostView.layoutParams = layoutParams
        smallClockHostView.setPaddingRelative(
            resources.getDimensionPixelSize(
                com.android.systemui.customization.R.dimen.clock_padding_start
            ),
@@ -519,10 +505,8 @@ constructor(
            0,
            0
        )
                hostView.clipChildren = false
                parentView.addView(hostView)
                hostView
            }
        smallClockHostView.clipChildren = false
        parentView.addView(smallClockHostView)
        smallClockHostView.isInvisible = true

        // TODO (b/283465254): Move the listeners to KeyguardClockRepository