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

Commit 206e3d8f authored by Lucas Silva's avatar Lucas Silva Committed by Android (Google) Code Review
Browse files

Merge "Add posturing noop implementation" into main

parents 74714d5c f31938e3
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.communal.posturing.domain.interactor

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.posturing.data.repository.fake
import com.android.systemui.communal.posturing.data.repository.posturingRepository
import com.android.systemui.communal.posturing.shared.model.PosturedState
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class PosturingInteractorTest : SysuiTestCase() {

    private val kosmos = testKosmos().useUnconfinedTestDispatcher()

    private val underTest by lazy { kosmos.posturingInteractor }

    @Test
    fun testNoDebugOverride() =
        kosmos.runTest {
            val postured by collectLastValue(underTest.postured)
            assertThat(postured).isFalse()

            posturingRepository.fake.setPosturedState(PosturedState.Postured(1f))
            assertThat(postured).isTrue()
        }

    @Test
    fun testOverriddenByDebugValue() =
        kosmos.runTest {
            val postured by collectLastValue(underTest.postured)
            assertThat(postured).isFalse()

            underTest.setValueForDebug(PosturedState.NotPostured)
            posturingRepository.fake.setPosturedState(PosturedState.Postured(1f))

            // Repository value is overridden by debug value
            assertThat(postured).isFalse()

            underTest.setValueForDebug(PosturedState.Unknown)
            assertThat(postured).isTrue()
        }
}
+103 −0
Original line number Diff line number Diff line
@@ -18,21 +18,53 @@ package com.android.systemui.communal

import android.annotation.SuppressLint
import android.app.DreamManager
import android.service.dreams.Flags.allowDreamWhenPostured
import com.android.app.tracing.coroutines.launchInTraced
import com.android.systemui.CoreStartable
import com.android.systemui.communal.posturing.domain.interactor.PosturingInteractor
import com.android.systemui.communal.posturing.shared.model.PosturedState
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.dagger.CommunalTableLog
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.onEach

@SysUISingleton
class DevicePosturingCommandListener
class DevicePosturingListener
@Inject
constructor(private val commandRegistry: CommandRegistry, private val dreamManager: DreamManager) :
    CoreStartable {
constructor(
    private val commandRegistry: CommandRegistry,
    private val dreamManager: DreamManager,
    private val interactor: PosturingInteractor,
    @Background private val bgScope: CoroutineScope,
    @CommunalTableLog private val tableLogBuffer: TableLogBuffer,
) : CoreStartable {
    private val command = DevicePosturingCommand()

    @SuppressLint("MissingPermission")
    override fun start() {
        if (!allowDreamWhenPostured()) {
            return
        }

        interactor.postured
            .distinctUntilChanged()
            .logDiffsForTable(
                tableLogBuffer = tableLogBuffer,
                columnPrefix = "",
                columnName = "postured",
                initialValue = false,
            )
            .onEach { postured -> dreamManager.setDevicePostured(postured) }
            .launchInTraced("$TAG#collectPostured", bgScope)

        commandRegistry.registerCommand(COMMAND_ROOT) { command }
    }

@@ -45,22 +77,27 @@ constructor(private val commandRegistry: CommandRegistry, private val dreamManag
                return
            }

            val state =
                when (arg.lowercase()) {
                "true" -> dreamManager.setDevicePostured(true)
                "false" -> dreamManager.setDevicePostured(false)
                    "true" -> PosturedState.Postured(confidence = 1f)
                    "false" -> PosturedState.NotPostured
                    "clear" -> PosturedState.Unknown
                    else -> {
                        pw.println("Invalid argument!")
                        help(pw)
                        null
                    }
                }
            state?.let { interactor.setValueForDebug(it) }
        }

        override fun help(pw: PrintWriter) {
            pw.println("Usage: $ adb shell cmd statusbar device-postured <true|false>")
            pw.println("Usage: $ adb shell cmd statusbar device-postured <true|false|clear>")
        }
    }

    private companion object {
        const val COMMAND_ROOT = "device-postured"
        const val TAG = "DevicePosturingListener"
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import com.android.systemui.communal.CommunalDreamStartable
import com.android.systemui.communal.CommunalMetricsStartable
import com.android.systemui.communal.CommunalOngoingContentStartable
import com.android.systemui.communal.CommunalSceneStartable
import com.android.systemui.communal.DevicePosturingCommandListener
import com.android.systemui.communal.DevicePosturingListener
import com.android.systemui.communal.log.CommunalLoggerStartable
import com.android.systemui.communal.widgets.CommunalAppWidgetHostStartable
import com.android.systemui.dagger.qualifiers.PerUser
@@ -71,6 +71,6 @@ interface CommunalStartableModule {

    @Binds
    @IntoMap
    @ClassKey(DevicePosturingCommandListener::class)
    fun bindDevicePosturingCommandListener(impl: DevicePosturingCommandListener): CoreStartable
    @ClassKey(DevicePosturingListener::class)
    fun bindDevicePosturingistener(impl: DevicePosturingListener): CoreStartable
}
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.communal.posturing.dagger

import com.android.systemui.communal.posturing.data.repository.NoOpPosturingRepository
import com.android.systemui.communal.posturing.data.repository.PosturingRepository
import dagger.Binds
import dagger.Module

/** Module providing a reference implementation of the posturing signal. */
@Module
interface NoopPosturingModule {
    /** Binds a reference implementation of the posturing repository */
    @Binds fun bindPosturingRepository(impl: NoOpPosturingRepository): PosturingRepository
}
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.communal.posturing.data.repository

import com.android.systemui.communal.posturing.shared.model.PosturedState
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow

@SysUISingleton
class NoOpPosturingRepository @Inject constructor() : PosturingRepository {
    override val posturedState: Flow<PosturedState> =
        MutableStateFlow(PosturedState.Unknown).asStateFlow()
}
Loading