1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar 18 19 import android.content.Context 20 import android.util.IndentingPrintWriter 21 import android.util.MathUtils 22 import androidx.annotation.FloatRange 23 import androidx.annotation.Px 24 import com.android.systemui.R 25 import com.android.systemui.dump.DumpManager 26 import com.android.systemui.plugins.qs.QS 27 import com.android.systemui.statusbar.policy.ConfigurationController 28 import dagger.assisted.Assisted 29 import dagger.assisted.AssistedFactory 30 import dagger.assisted.AssistedInject 31 import kotlin.math.max 32 33 /** Responsible for the QS components during the lockscreen shade transition. */ 34 class LockscreenShadeQsTransitionController 35 @AssistedInject 36 constructor( 37 context: Context, 38 configurationController: ConfigurationController, 39 dumpManager: DumpManager, 40 @Assisted private val qsProvider: () -> QS, 41 ) : AbstractLockscreenShadeTransitionController(context, configurationController, dumpManager) { 42 43 private val qs: QS 44 get() = qsProvider() 45 46 /** 47 * The progress fraction of the QS transition during lockscreen shade expansion. 48 * 49 * Note that this value might be 0 for some time when the expansion is already in progress, 50 * since there is a transition start delay for QS on some device configurations. For this 51 * reason, don't use this value to check whether the shade expansion is in progress. 52 */ 53 @FloatRange(from = 0.0, to = 1.0) 54 var qsTransitionFraction = 0f 55 private set 56 57 /** 58 * The fraction of the QS "squish" transition progress during lockscreen shade expansion. 59 * 60 * Note that in some device configurations (large screens) this value can start at a value 61 * greater than 0. For this reason don't use this value to check whether the QS transition has 62 * started or not. 63 */ 64 @FloatRange(from = 0.0, to = 1.0) 65 var qsSquishTransitionFraction = 0f 66 private set 67 68 /** 69 * The drag down amount, in pixels __for the QS transition__, also taking into account the 70 * [qsTransitionStartDelay]. 71 * 72 * Since it takes into account the start delay, it is __not__ the same as the raw drag down 73 * amount from the shade expansion. 74 */ 75 @Px private var qsDragDownAmount = 0f 76 77 /** 78 * Distance it takes for the QS transition to complete during the lockscreen shade expansion. 79 */ 80 @Px private var qsTransitionDistance = 0 81 82 /** Distance delay for the QS transition to start during the lockscreen shade expansion. */ 83 @Px private var qsTransitionStartDelay = 0 84 85 /** 86 * Distance that it takes to complete the QS "squish" transition during the lockscreen shade 87 * expansion. 88 */ 89 @Px private var qsSquishTransitionDistance = 0 90 91 /** 92 * Whether the transition to full shade is in progress. Might be `true` even though 93 * [qsTransitionFraction] is still 0, due to [qsTransitionStartDelay]. 94 */ 95 private var isTransitioningToFullShade = false 96 97 /** 98 * The fraction at which the QS "squish" transition should start during the lockscreen shade 99 * expansion. 100 * 101 * 0 is fully collapsed, 1 is fully expanded. 102 */ 103 @FloatRange(from = 0.0, to = 1.0) private var qsSquishStartFraction = 0f 104 105 override fun updateResources() { 106 qsTransitionDistance = 107 context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_distance) 108 qsTransitionStartDelay = 109 context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_delay) 110 qsSquishTransitionDistance = 111 context.resources.getDimensionPixelSize( 112 R.dimen.lockscreen_shade_qs_squish_transition_distance 113 ) 114 qsSquishStartFraction = 115 context.resources.getFloat(R.dimen.lockscreen_shade_qs_squish_start_fraction) 116 117 qsSquishTransitionFraction = max(qsSquishTransitionFraction, qsSquishStartFraction) 118 } 119 120 override fun onDragDownAmountChanged(dragDownAmount: Float) { 121 qsDragDownAmount = dragDownAmount - qsTransitionStartDelay 122 qsTransitionFraction = MathUtils.saturate(qsDragDownAmount / qsTransitionDistance) 123 qsSquishTransitionFraction = 124 MathUtils.lerp( 125 /* start= */ qsSquishStartFraction, 126 /* stop= */ 1f, 127 /* amount= */ MathUtils.saturate(qsDragDownAmount / qsSquishTransitionDistance) 128 ) 129 isTransitioningToFullShade = dragDownAmount > 0.0f 130 qs.setTransitionToFullShadeProgress( 131 isTransitioningToFullShade, 132 qsTransitionFraction, 133 qsSquishTransitionFraction 134 ) 135 } 136 137 override fun dump(pw: IndentingPrintWriter) { 138 pw.println( 139 """ 140 Resources: 141 qsTransitionDistance: $qsTransitionDistance 142 qsTransitionStartDelay: $qsTransitionStartDelay 143 qsSquishTransitionDistance: $qsSquishTransitionDistance 144 qsSquishStartFraction: $qsSquishStartFraction 145 State: 146 dragDownAmount: $dragDownAmount 147 qsDragDownAmount: $qsDragDownAmount 148 qsDragFraction: $qsTransitionFraction 149 qsSquishFraction: $qsSquishTransitionFraction 150 isTransitioningToFullShade: $isTransitioningToFullShade 151 """ 152 .trimIndent() 153 ) 154 } 155 156 @AssistedFactory 157 fun interface Factory { 158 fun create(qsProvider: () -> QS): LockscreenShadeQsTransitionController 159 } 160 } 161