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

Commit a20601f6 authored by Anton Potapov's avatar Anton Potapov
Browse files

Migrate AirplaneMode tile

Test: manual: airplane tile works the same as before the refactoring
Test: atest AirplaneModeTileDataInteractorTest
Test: atest AirplaneModeTileUserActionInteractorTest
Flag: LEGACY QS_PIPELINE_NEW_TILES DISABLED
Fixes: 301056365
Change-Id: I01e9ca652491d1203164f19ebcbb4b80b58b78f8
parent fc49c4e6
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.airplane.domain

import android.content.Context
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
import com.android.systemui.qs.tiles.impl.airplane.domain.model.AirplaneModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
import javax.inject.Inject

/** Maps [AirplaneModeTileModel] to [QSTileState]. */
class AirplaneModeMapper @Inject constructor(private val context: Context) :
    QSTileDataToStateMapper<AirplaneModeTileModel> {

    override fun map(config: QSTileConfig, data: AirplaneModeTileModel): QSTileState =
        QSTileState.build(context, config.uiConfig) {
            val icon =
                Icon.Loaded(
                    context.getDrawable(
                        if (data.isEnabled) {
                            R.drawable.qs_airplane_icon_on
                        } else {
                            R.drawable.qs_airplane_icon_off
                        }
                    )!!,
                    contentDescription = null
                )
            this.icon = { icon }
            if (data.isEnabled) {
                activationState = QSTileState.ActivationState.ACTIVE
                secondaryLabel = context.resources.getStringArray(R.array.tile_states_airplane)[2]
            } else {
                activationState = QSTileState.ActivationState.INACTIVE
                secondaryLabel = context.resources.getStringArray(R.array.tile_states_airplane)[1]
            }
            contentDescription = label
            supportedActions =
                setOf(
                    QSTileState.UserAction.CLICK,
                    QSTileState.UserAction.LONG_CLICK,
                )
        }
}
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.airplane.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.airplane.domain.model.AirplaneModeTileModel
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map

/** Observes airplane mode state changes providing the [AirplaneModeTileModel]. */
class AirplaneModeTileDataInteractor
@Inject
constructor(
    private val airplaneModeRepository: AirplaneModeRepository,
) : QSTileDataInteractor<AirplaneModeTileModel> {

    override fun tileData(
        user: UserHandle,
        triggers: Flow<DataUpdateTrigger>
    ): Flow<AirplaneModeTileModel> =
        airplaneModeRepository.isAirplaneMode.map { AirplaneModeTileModel(it) }

    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(true)
}
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.airplane.domain.interactor

import android.content.Intent
import android.provider.Settings
import android.telephony.TelephonyManager
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.airplane.domain.model.AirplaneModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import javax.inject.Inject

/** Handles airplane mode tile clicks and long clicks. */
class AirplaneModeTileUserActionInteractor
@Inject
constructor(
    private val airplaneModeInteractor: AirplaneModeInteractor,
    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
) : QSTileUserActionInteractor<AirplaneModeTileModel> {

    override suspend fun handleInput(input: QSTileInput<AirplaneModeTileModel>) =
        with(input) {
            when (action) {
                is QSTileUserAction.Click -> {
                    when (airplaneModeInteractor.setIsAirplaneMode(!data.isEnabled)) {
                        AirplaneModeInteractor.SetResult.SUCCESS -> {
                            // do nothing
                        }
                        AirplaneModeInteractor.SetResult.BLOCKED_BY_ECM -> {
                            qsTileIntentUserActionHandler.handle(
                                action.view,
                                Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS),
                            )
                        }
                    }
                }
                is QSTileUserAction.LongClick -> {
                    qsTileIntentUserActionHandler.handle(
                        action.view,
                        Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS)
                    )
                }
            }
        }
}
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.airplane.domain.model

/**
 * Airplane mode tile model.
 *
 * @param isEnabled is true when the airplane mode is enabled;
 */
@JvmInline value class AirplaneModeTileModel(val isEnabled: Boolean)
+48 −0
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package com.android.systemui.statusbar.connectivity

import android.os.UserManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.SIGNAL_CALLBACK_DEPRECATION
import com.android.systemui.qs.QsEventLogger
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.qs.tiles.AirplaneModeTile
import com.android.systemui.qs.tiles.BluetoothTile
@@ -27,6 +30,16 @@ import com.android.systemui.qs.tiles.HotspotTile
import com.android.systemui.qs.tiles.InternetTile
import com.android.systemui.qs.tiles.InternetTileNewImpl
import com.android.systemui.qs.tiles.NfcTile
import com.android.systemui.qs.tiles.base.viewmodel.QSTileViewModelFactory
import com.android.systemui.qs.tiles.impl.airplane.domain.AirplaneModeMapper
import com.android.systemui.qs.tiles.impl.airplane.domain.interactor.AirplaneModeTileDataInteractor
import com.android.systemui.qs.tiles.impl.airplane.domain.interactor.AirplaneModeTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.airplane.domain.model.AirplaneModeTileModel
import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTilePolicy
import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
import com.android.systemui.res.R
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -70,6 +83,9 @@ interface ConnectivityModule {
    @Binds @IntoMap @StringKey(NfcTile.TILE_SPEC) fun bindNfcTile(nfcTile: NfcTile): QSTileImpl<*>

    companion object {

        const val AIRPLANE_MODE_TILE_SPEC = "airplane"

        /** Inject InternetTile or InternetTileNewImpl into tileMap in QSModule */
        @Provides
        @IntoMap
@@ -84,5 +100,37 @@ interface ConnectivityModule {
            } else {
                internetTile
            }

        @Provides
        @IntoMap
        @StringKey(AIRPLANE_MODE_TILE_SPEC)
        fun provideAirplaneModeTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
            QSTileConfig(
                tileSpec = TileSpec.create(AIRPLANE_MODE_TILE_SPEC),
                uiConfig =
                    QSTileUIConfig.Resource(
                        iconRes = R.drawable.qs_airplane_icon_off,
                        labelRes = R.string.airplane_mode,
                    ),
                instanceId = uiEventLogger.getNewInstanceId(),
                policy = QSTilePolicy.Restricted(UserManager.DISALLOW_AIRPLANE_MODE),
            )

        /** Inject AirplaneModeTile into tileViewModelMap in QSModule */
        @Provides
        @IntoMap
        @StringKey(AIRPLANE_MODE_TILE_SPEC)
        fun provideAirplaneModeTileViewModel(
            factory: QSTileViewModelFactory.Static<AirplaneModeTileModel>,
            mapper: AirplaneModeMapper,
            stateInteractor: AirplaneModeTileDataInteractor,
            userActionInteractor: AirplaneModeTileUserActionInteractor
        ): QSTileViewModel =
            factory.create(
                TileSpec.create(AIRPLANE_MODE_TILE_SPEC),
                userActionInteractor,
                stateInteractor,
                mapper,
            )
    }
}
Loading