1 /* 2 * Copyright (C) 2023 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 package com.android.systemui.unfold.data.repository 17 18 import com.android.systemui.unfold.data.repository.FoldStateRepository.FoldUpdate 19 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED 20 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN 21 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN 22 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING 23 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING 24 import com.android.systemui.unfold.updates.FoldStateProvider 25 import javax.inject.Inject 26 import kotlinx.coroutines.channels.Channel 27 import kotlinx.coroutines.channels.awaitClose 28 import kotlinx.coroutines.flow.Flow 29 import kotlinx.coroutines.flow.buffer 30 import kotlinx.coroutines.flow.callbackFlow 31 32 /** 33 * Allows to subscribe to main events related to fold/unfold process such as hinge angle update, 34 * start folding/unfolding, screen availability 35 */ 36 interface FoldStateRepository { 37 /** Latest fold update, as described by [FoldStateProvider.FoldUpdate]. */ 38 val foldUpdate: Flow<FoldUpdate> 39 40 /** Provides the hinge angle while the fold/unfold is in progress. */ 41 val hingeAngle: Flow<Float> 42 43 enum class FoldUpdate { 44 START_OPENING, 45 START_CLOSING, 46 FINISH_HALF_OPEN, 47 FINISH_FULL_OPEN, 48 FINISH_CLOSED; 49 50 companion object { 51 /** Maps the old [FoldStateProvider.FoldUpdate] to [FoldStateRepository.FoldUpdate]. */ fromFoldUpdateIdnull52 fun fromFoldUpdateId(@FoldStateProvider.FoldUpdate oldId: Int): FoldUpdate { 53 return when (oldId) { 54 FOLD_UPDATE_START_OPENING -> START_OPENING 55 FOLD_UPDATE_START_CLOSING -> START_CLOSING 56 FOLD_UPDATE_FINISH_HALF_OPEN -> FINISH_HALF_OPEN 57 FOLD_UPDATE_FINISH_FULL_OPEN -> FINISH_FULL_OPEN 58 FOLD_UPDATE_FINISH_CLOSED -> FINISH_CLOSED 59 else -> error("Fold update with id $oldId is not supported") 60 } 61 } 62 } 63 } 64 } 65 66 class FoldStateRepositoryImpl 67 @Inject 68 constructor( 69 private val foldStateProvider: FoldStateProvider, 70 ) : FoldStateRepository { 71 72 override val hingeAngle: Flow<Float> 73 get() = <lambda>null74 callbackFlow { 75 val callback = 76 object : FoldStateProvider.FoldUpdatesListener { 77 override fun onHingeAngleUpdate(angle: Float) { 78 trySend(angle) 79 } 80 } 81 foldStateProvider.addCallback(callback) 82 awaitClose { foldStateProvider.removeCallback(callback) } 83 } 84 .buffer(capacity = Channel.CONFLATED) 85 86 override val foldUpdate: Flow<FoldUpdate> 87 get() = <lambda>null88 callbackFlow { 89 val callback = 90 object : FoldStateProvider.FoldUpdatesListener { 91 override fun onFoldUpdate(update: Int) { 92 trySend(FoldUpdate.fromFoldUpdateId(update)) 93 } 94 } 95 foldStateProvider.addCallback(callback) 96 awaitClose { foldStateProvider.removeCallback(callback) } 97 } 98 .buffer(capacity = Channel.CONFLATED) 99 } 100