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.dump.DumpManager 25 import com.android.systemui.plugins.qs.QS 26 import com.android.systemui.res.R 27 import com.android.systemui.statusbar.policy.ConfigurationController 28 import com.android.systemui.statusbar.policy.SplitShadeStateController 29 import dagger.assisted.Assisted 30 import dagger.assisted.AssistedFactory 31 import dagger.assisted.AssistedInject 32 import kotlin.math.max 33 34 /** Responsible for the QS components during the lockscreen shade transition. */ 35 class LockscreenShadeQsTransitionController 36 @AssistedInject 37 constructor( 38 context: Context, 39 configurationController: ConfigurationController, 40 dumpManager: DumpManager, 41 @Assisted private val qsProvider: () -> QS?, 42 splitShadeStateController: SplitShadeStateController 43 ) : 44 AbstractLockscreenShadeTransitionController( 45 context, 46 configurationController, 47 dumpManager, 48 splitShadeStateController 49 ) { 50 51 private val qs: QS? 52 get() = qsProvider() 53 54 /** 55 * The progress fraction of the QS transition during lockscreen shade expansion. 56 * 57 * Note that this value might be 0 for some time when the expansion is already in progress, 58 * since there is a transition start delay for QS on some device configurations. For this 59 * reason, don't use this value to check whether the shade expansion is in progress. 60 */ 61 @FloatRange(from = 0.0, to = 1.0) 62 var qsTransitionFraction = 0f 63 private set 64 65 /** 66 * The fraction of the QS "squish" transition progress during lockscreen shade expansion. 67 * 68 * Note that in some device configurations (large screens) this value can start at a value 69 * greater than 0. For this reason don't use this value to check whether the QS transition has 70 * started or not. 71 */ 72 @FloatRange(from = 0.0, to = 1.0) 73 var qsSquishTransitionFraction = 0f 74 private set 75 76 /** 77 * The drag down amount, in pixels __for the QS transition__, also taking into account the 78 * [qsTransitionStartDelay]. 79 * 80 * Since it takes into account the start delay, it is __not__ the same as the raw drag down 81 * amount from the shade expansion. 82 */ 83 @Px private var qsDragDownAmount = 0f 84 85 /** 86 * Distance it takes for the QS transition to complete during the lockscreen shade expansion. 87 */ 88 @Px private var qsTransitionDistance = 0 89 90 /** Distance delay for the QS transition to start during the lockscreen shade expansion. */ 91 @Px private var qsTransitionStartDelay = 0 92 93 /** 94 * Distance that it takes to complete the QS "squish" transition during the lockscreen shade 95 * expansion. 96 */ 97 @Px private var qsSquishTransitionDistance = 0 98 99 /** 100 * Whether the transition to full shade is in progress. Might be `true` even though 101 * [qsTransitionFraction] is still 0, due to [qsTransitionStartDelay]. 102 */ 103 private var isTransitioningToFullShade = false 104 105 /** 106 * The fraction at which the QS "squish" transition should start during the lockscreen shade 107 * expansion. 108 * 109 * 0 is fully collapsed, 1 is fully expanded. 110 */ 111 @FloatRange(from = 0.0, to = 1.0) private var qsSquishStartFraction = 0f 112 updateResourcesnull113 override fun updateResources() { 114 qsTransitionDistance = 115 context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_distance) 116 qsTransitionStartDelay = 117 context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_delay) 118 qsSquishTransitionDistance = 119 context.resources.getDimensionPixelSize( 120 R.dimen.lockscreen_shade_qs_squish_transition_distance 121 ) 122 qsSquishStartFraction = 123 context.resources.getFloat(R.dimen.lockscreen_shade_qs_squish_start_fraction) 124 125 qsSquishTransitionFraction = max(qsSquishTransitionFraction, qsSquishStartFraction) 126 } 127 onDragDownAmountChangednull128 override fun onDragDownAmountChanged(dragDownAmount: Float) { 129 qsDragDownAmount = dragDownAmount - qsTransitionStartDelay 130 qsTransitionFraction = MathUtils.saturate(qsDragDownAmount / qsTransitionDistance) 131 qsSquishTransitionFraction = 132 MathUtils.lerp( 133 /* start= */ qsSquishStartFraction, 134 /* stop= */ 1f, 135 /* amount= */ MathUtils.saturate(qsDragDownAmount / qsSquishTransitionDistance) 136 ) 137 isTransitioningToFullShade = dragDownAmount > 0.0f 138 qs?.setTransitionToFullShadeProgress( 139 isTransitioningToFullShade, 140 qsTransitionFraction, 141 qsSquishTransitionFraction 142 ) 143 } 144 dumpnull145 override fun dump(pw: IndentingPrintWriter) { 146 pw.println( 147 """ 148 Resources: 149 qsTransitionDistance: $qsTransitionDistance 150 qsTransitionStartDelay: $qsTransitionStartDelay 151 qsSquishTransitionDistance: $qsSquishTransitionDistance 152 qsSquishStartFraction: $qsSquishStartFraction 153 State: 154 dragDownAmount: $dragDownAmount 155 qsDragDownAmount: $qsDragDownAmount 156 qsDragFraction: $qsTransitionFraction 157 qsSquishFraction: $qsSquishTransitionFraction 158 isTransitioningToFullShade: $isTransitioningToFullShade 159 """ 160 .trimIndent() 161 ) 162 } 163 164 @AssistedFactory interfacenull165 fun interface Factory { 166 fun create(qsProvider: () -> QS?): LockscreenShadeQsTransitionController 167 } 168 } 169