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

Commit cf2170fb authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge changes I07beea6b,Ibedd556f into main

* changes:
  Modes tile: open settings on long press
  Add legacy ModesTile
parents d26e2461 78fbaef0
Loading
Loading
Loading
Loading
+49 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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.qs.tiles.impl.modes.domain.interactor

import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.google.common.truth.Truth
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableFlags(android.app.Flags.FLAG_MODES_UI)
class ModesTileUserActionInteractorTest : SysuiTestCase() {
    private val inputHandler = FakeQSTileIntentUserInputHandler()

    val underTest = ModesTileUserActionInteractor(inputHandler)

    @Test
    fun handleLongClick() = runTest {
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false)))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            Truth.assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
        }
    }
}
+117 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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.qs.tiles

import android.app.Flags
import android.content.Intent
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.repeatOnLifecycle
import com.android.internal.logging.MetricsLogger
import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QSTile.BooleanState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.QsEventLogger
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.qs.tiles.impl.modes.domain.interactor.ModesTileDataInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.interactor.ModesTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.impl.modes.ui.ModesTileMapper
import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
import javax.inject.Inject
import kotlinx.coroutines.launch

class ModesTile
@Inject
constructor(
    host: QSHost,
    uiEventLogger: QsEventLogger,
    @Background backgroundLooper: Looper,
    @Main mainHandler: Handler,
    falsingManager: FalsingManager,
    metricsLogger: MetricsLogger,
    statusBarStateController: StatusBarStateController,
    activityStarter: ActivityStarter,
    qsLogger: QSLogger,
    qsTileConfigProvider: QSTileConfigProvider,
    dataInteractor: ModesTileDataInteractor,
    private val tileMapper: ModesTileMapper,
    private val userActionInteractor: ModesTileUserActionInteractor,
) :
    QSTileImpl<BooleanState>(
        host,
        uiEventLogger,
        backgroundLooper,
        mainHandler,
        falsingManager,
        metricsLogger,
        statusBarStateController,
        activityStarter,
        qsLogger
    ) {

    private lateinit var tileState: QSTileState
    private val config = qsTileConfigProvider.getConfig(TILE_SPEC)

    init {
        lifecycle.coroutineScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
                dataInteractor.tileData().collect { refreshState(it) }
            }
        }
    }

    override fun isAvailable(): Boolean = Flags.modesUi()

    override fun getTileLabel(): CharSequence = tileState.label

    override fun newTileState() = BooleanState()

    override fun handleClick(expandable: Expandable?) {
        // TODO(b/346519570) open dialog
    }

    override fun getLongClickIntent(): Intent = userActionInteractor.longClickIntent

    override fun handleUpdateState(booleanState: BooleanState?, arg: Any?) {
        if (arg is ModesTileModel) {
            tileState = tileMapper.map(config, arg)

            booleanState?.apply {
                state = tileState.activationState.legacyState
                icon = ResourceIcon.get(tileState.iconRes ?: R.drawable.qs_dnd_icon_off)
                label = tileLabel
                secondaryLabel = tileState.secondaryLabel
                contentDescription = tileState.contentDescription
            }
        }
    }

    companion object {
        const val TILE_SPEC = "modes"
    }
}
+8 −3
Original line number Original line Diff line number Diff line
@@ -38,9 +38,14 @@ class ModesTileDataInteractor @Inject constructor(val zenModeRepository: ZenMode
    override fun tileData(
    override fun tileData(
        user: UserHandle,
        user: UserHandle,
        triggers: Flow<DataUpdateTrigger>
        triggers: Flow<DataUpdateTrigger>
    ): Flow<ModesTileModel> {
    ): Flow<ModesTileModel> = tileData()
        return zenModeActive.map { ModesTileModel(isActivated = it) }

    }
    /**
     * An adapted version of the base class' [tileData] method for use in an old-style tile.
     *
     * TODO(b/299909989): Remove after the transition.
     */
    fun tileData() = zenModeActive.map { ModesTileModel(isActivated = it) }


    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi())
    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi())
}
}
+11 −3
Original line number Original line Diff line number Diff line
@@ -16,14 +16,22 @@


package com.android.systemui.qs.tiles.impl.modes.domain.interactor
package com.android.systemui.qs.tiles.impl.modes.domain.interactor


import android.content.Intent
import android.provider.Settings
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import javax.inject.Inject
import javax.inject.Inject


class ModesTileUserActionInteractor @Inject constructor() :
class ModesTileUserActionInteractor
    QSTileUserActionInteractor<ModesTileModel> {
@Inject
constructor(
    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
) : QSTileUserActionInteractor<ModesTileModel> {
    val longClickIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)

    override suspend fun handleInput(input: QSTileInput<ModesTileModel>) {
    override suspend fun handleInput(input: QSTileInput<ModesTileModel>) {
        with(input) {
        with(input) {
            when (action) {
            when (action) {
@@ -31,7 +39,7 @@ class ModesTileUserActionInteractor @Inject constructor() :
                    // TODO(b/346519570) open dialog
                    // TODO(b/346519570) open dialog
                }
                }
                is QSTileUserAction.LongClick -> {
                is QSTileUserAction.LongClick -> {
                    // TODO(b/346519570) open settings
                    qsTileIntentUserActionHandler.handle(action.expandable, longClickIntent)
                }
                }
            }
            }
        }
        }
+6 −2
Original line number Original line Diff line number Diff line
@@ -34,13 +34,17 @@ constructor(
) : QSTileDataToStateMapper<ModesTileModel> {
) : QSTileDataToStateMapper<ModesTileModel> {
    override fun map(config: QSTileConfig, data: ModesTileModel): QSTileState =
    override fun map(config: QSTileConfig, data: ModesTileModel): QSTileState =
        QSTileState.build(resources, theme, config.uiConfig) {
        QSTileState.build(resources, theme, config.uiConfig) {
            val iconRes =
            iconRes =
                if (data.isActivated) {
                if (data.isActivated) {
                    R.drawable.qs_dnd_icon_on
                    R.drawable.qs_dnd_icon_on
                } else {
                } else {
                    R.drawable.qs_dnd_icon_off
                    R.drawable.qs_dnd_icon_off
                }
                }
            val icon = Icon.Loaded(resources.getDrawable(iconRes, theme), contentDescription = null)
            val icon =
                Icon.Loaded(
                    resources.getDrawable(iconRes!!, theme),
                    contentDescription = null,
                )
            this.icon = { icon }
            this.icon = { icon }
            if (data.isActivated) {
            if (data.isActivated) {
                activationState = QSTileState.ActivationState.ACTIVE
                activationState = QSTileState.ActivationState.ACTIVE
Loading