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

Commit e59a3f01 authored by Behnam Heydarshahi's avatar Behnam Heydarshahi
Browse files

Migrate Work Mode Tile

Flag: aconfig com.android.systemui.qs_new_tiles DEVELOPMENT
Fixes: 301054961
Test: atest WorkModeTileDataInteractorTest WorkModeTileUserActionTest WorkModeTileMapperTest
Change-Id: I2c6854a18c1fef12a88507d06ff2b3daeee6bb63
parent 783ed50c
Loading
Loading
Loading
Loading
+93 −0
Original line number 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.work.domain.interactor

import android.os.UserHandle
import android.platform.test.annotations.EnabledOnRavenwood
import android.testing.LeakCheck
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.impl.work.domain.model.WorkModeTileModel
import com.android.systemui.utils.leaks.FakeManagedProfileController
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@EnabledOnRavenwood
@RunWith(AndroidJUnit4::class)
class WorkModeTileDataInteractorTest : SysuiTestCase() {
    private val controller = FakeManagedProfileController(LeakCheck())
    private val underTest: WorkModeTileDataInteractor = WorkModeTileDataInteractor(controller)

    @Test
    fun availability_matchesControllerHasActiveProfiles() = runTest {
        val availability by collectLastValue(underTest.availability(TEST_USER))

        assertThat(availability).isFalse()

        controller.setHasActiveProfile(true)
        assertThat(availability).isTrue()

        controller.setHasActiveProfile(false)
        assertThat(availability).isFalse()
    }

    @Test
    fun tileData_whenHasActiveProfile_matchesControllerIsEnabled() = runTest {
        controller.setHasActiveProfile(true)
        val data by
            collectLastValue(
                underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
            )

        assertThat(data).isInstanceOf(WorkModeTileModel.HasActiveProfile::class.java)
        assertThat((data as WorkModeTileModel.HasActiveProfile).isEnabled).isFalse()

        controller.isWorkModeEnabled = true
        assertThat(data).isInstanceOf(WorkModeTileModel.HasActiveProfile::class.java)
        assertThat((data as WorkModeTileModel.HasActiveProfile).isEnabled).isTrue()

        controller.isWorkModeEnabled = false
        assertThat(data).isInstanceOf(WorkModeTileModel.HasActiveProfile::class.java)
        assertThat((data as WorkModeTileModel.HasActiveProfile).isEnabled).isFalse()
    }

    @Test
    fun tileData_matchesControllerHasActiveProfile() = runTest {
        val data by
            collectLastValue(
                underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
            )
        assertThat(data).isInstanceOf(WorkModeTileModel.NoActiveProfile::class.java)

        controller.setHasActiveProfile(true)
        assertThat(data).isInstanceOf(WorkModeTileModel.HasActiveProfile::class.java)

        controller.setHasActiveProfile(false)
        assertThat(data).isInstanceOf(WorkModeTileModel.NoActiveProfile::class.java)
    }

    private companion object {
        val TEST_USER = UserHandle.of(1)!!
    }
}
+115 −0
Original line number 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.work.domain.interactor

import android.platform.test.annotations.EnabledOnRavenwood
import android.provider.Settings
import android.testing.LeakCheck
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.work.domain.model.WorkModeTileModel
import com.android.systemui.utils.leaks.FakeManagedProfileController
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@EnabledOnRavenwood
@RunWith(AndroidJUnit4::class)
class WorkModeTileUserActionInteractorTest : SysuiTestCase() {

    private val inputHandler = FakeQSTileIntentUserInputHandler()
    private val profileController = FakeManagedProfileController(LeakCheck())

    private val underTest =
        WorkModeTileUserActionInteractor(
            profileController,
            inputHandler,
        )

    @Test
    fun handleClickWhenEnabled() = runTest {
        val wasEnabled = true
        profileController.isWorkModeEnabled = wasEnabled

        underTest.handleInput(
            QSTileInputTestKtx.click(WorkModeTileModel.HasActiveProfile(wasEnabled))
        )

        assertThat(profileController.isWorkModeEnabled).isEqualTo(!wasEnabled)
    }

    @Test
    fun handleClickWhenDisabled() = runTest {
        val wasEnabled = false
        profileController.isWorkModeEnabled = wasEnabled

        underTest.handleInput(
            QSTileInputTestKtx.click(WorkModeTileModel.HasActiveProfile(wasEnabled))
        )

        assertThat(profileController.isWorkModeEnabled).isEqualTo(!wasEnabled)
    }

    @Test
    fun handleClickWhenUnavailable() = runTest {
        val wasEnabled = false
        profileController.isWorkModeEnabled = wasEnabled

        underTest.handleInput(QSTileInputTestKtx.click(WorkModeTileModel.NoActiveProfile))

        assertThat(profileController.isWorkModeEnabled).isEqualTo(wasEnabled)
    }

    @Test
    fun handleLongClickWhenDisabled() = runTest {
        val enabled = false

        underTest.handleInput(
            QSTileInputTestKtx.longClick(WorkModeTileModel.HasActiveProfile(enabled))
        )

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_MANAGED_PROFILE_SETTINGS)
        }
    }

    @Test
    fun handleLongClickWhenEnabled() = runTest {
        val enabled = true

        underTest.handleInput(
            QSTileInputTestKtx.longClick(WorkModeTileModel.HasActiveProfile(enabled))
        )

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_MANAGED_PROFILE_SETTINGS)
        }
    }

    @Test
    fun handleLongClickWhenUnavailable() = runTest {
        underTest.handleInput(QSTileInputTestKtx.longClick(WorkModeTileModel.NoActiveProfile))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledNoInputs()
    }
}
+49 −0
Original line number 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.work.domain.interactor

import android.os.UserHandle
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.work.domain.model.WorkModeTileModel
import com.android.systemui.statusbar.phone.ManagedProfileController
import com.android.systemui.util.kotlin.hasActiveWorkProfile
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

/** Observes data saver state changes providing the [WorkModeTileModel]. */
class WorkModeTileDataInteractor
@Inject
constructor(
    private val profileController: ManagedProfileController,
) : QSTileDataInteractor<WorkModeTileModel> {
    override fun tileData(
        user: UserHandle,
        triggers: Flow<DataUpdateTrigger>
    ): Flow<WorkModeTileModel> =
        profileController.hasActiveWorkProfile.map { hasActiveWorkProfile: Boolean ->
            if (hasActiveWorkProfile) {
                WorkModeTileModel.HasActiveProfile(profileController.isWorkModeEnabled)
            } else {
                WorkModeTileModel.NoActiveProfile
            }
        }

    override fun availability(user: UserHandle): Flow<Boolean> =
        profileController.hasActiveWorkProfile
}
+54 −0
Original line number 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.work.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.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.work.domain.model.WorkModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.statusbar.phone.ManagedProfileController
import javax.inject.Inject

/** Handles airplane mode tile clicks and long clicks. */
class WorkModeTileUserActionInteractor
@Inject
constructor(
    private val profileController: ManagedProfileController,
    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
) : QSTileUserActionInteractor<WorkModeTileModel> {
    override suspend fun handleInput(input: QSTileInput<WorkModeTileModel>) =
        with(input) {
            when (action) {
                is QSTileUserAction.Click -> {
                    if (data is WorkModeTileModel.HasActiveProfile) {
                        profileController.setWorkModeEnabled(!data.isEnabled)
                    }
                }
                is QSTileUserAction.LongClick -> {
                    if (data is WorkModeTileModel.HasActiveProfile) {
                        qsTileIntentUserActionHandler.handle(
                            action.view,
                            Intent(Settings.ACTION_MANAGED_PROFILE_SETTINGS)
                        )
                    }
                }
            }
        }
}
+24 −0
Original line number 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.work.domain.model

/** Work mode tile model. */
sealed interface WorkModeTileModel {
    /** @param isEnabled is true when the work mode is enabled */
    data class HasActiveProfile(val isEnabled: Boolean) : WorkModeTileModel
    data object NoActiveProfile : WorkModeTileModel
}
Loading