Loading packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -69,6 +69,7 @@ import com.android.systemui.qs.FgsManagerControllerImpl; import com.android.systemui.qs.QSFragmentStartableModule; import com.android.systemui.qs.QSFragmentStartableModule; import com.android.systemui.qs.footer.dagger.FooterActionsModule; import com.android.systemui.qs.footer.dagger.FooterActionsModule; import com.android.systemui.recents.Recents; import com.android.systemui.recents.Recents; import com.android.systemui.retail.dagger.RetailModeModule; import com.android.systemui.screenrecord.ScreenRecordModule; import com.android.systemui.screenrecord.ScreenRecordModule; import com.android.systemui.screenshot.dagger.ScreenshotModule; import com.android.systemui.screenshot.dagger.ScreenshotModule; import com.android.systemui.security.data.repository.SecurityRepositoryModule; import com.android.systemui.security.data.repository.SecurityRepositoryModule; Loading Loading @@ -179,6 +180,7 @@ import javax.inject.Named; PrivacyModule.class, PrivacyModule.class, QRCodeScannerModule.class, QRCodeScannerModule.class, QSFragmentStartableModule.class, QSFragmentStartableModule.class, RetailModeModule.class, ScreenshotModule.class, ScreenshotModule.class, SensorModule.class, SensorModule.class, SecurityRepositoryModule.class, SecurityRepositoryModule.class, Loading packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +8 −1 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.retail.domain.interactor.RetailModeInteractor; import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController; Loading @@ -45,18 +46,22 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme private final View mEditButton; private final View mEditButton; private final FalsingManager mFalsingManager; private final FalsingManager mFalsingManager; private final ActivityStarter mActivityStarter; private final ActivityStarter mActivityStarter; private final RetailModeInteractor mRetailModeInteractor; @Inject @Inject QSFooterViewController(QSFooterView view, QSFooterViewController(QSFooterView view, UserTracker userTracker, UserTracker userTracker, FalsingManager falsingManager, FalsingManager falsingManager, ActivityStarter activityStarter, ActivityStarter activityStarter, QSPanelController qsPanelController) { QSPanelController qsPanelController, RetailModeInteractor retailModeInteractor ) { super(view); super(view); mUserTracker = userTracker; mUserTracker = userTracker; mQsPanelController = qsPanelController; mQsPanelController = qsPanelController; mFalsingManager = falsingManager; mFalsingManager = falsingManager; mActivityStarter = activityStarter; mActivityStarter = activityStarter; mRetailModeInteractor = retailModeInteractor; mBuildText = mView.findViewById(R.id.build); mBuildText = mView.findViewById(R.id.build); mPageIndicator = mView.findViewById(R.id.footer_page_indicator); mPageIndicator = mView.findViewById(R.id.footer_page_indicator); Loading Loading @@ -96,6 +101,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme @Override @Override public void setVisibility(int visibility) { public void setVisibility(int visibility) { mView.setVisibility(visibility); mView.setVisibility(visibility); mEditButton .setVisibility(mRetailModeInteractor.isInRetailMode() ? View.GONE : View.VISIBLE); mEditButton.setClickable(visibility == View.VISIBLE); mEditButton.setClickable(visibility == View.VISIBLE); } } Loading packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt +34 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.UserIdInt import android.content.res.Resources import android.content.res.Resources import android.database.ContentObserver import android.database.ContentObserver import android.provider.Settings import android.provider.Settings import com.android.systemui.R import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Background Loading @@ -27,12 +28,16 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.qs.QSHost import com.android.systemui.qs.QSHost import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger import com.android.systemui.retail.data.repository.RetailModeRepository import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach Loading Loading @@ -84,6 +89,9 @@ interface TileSpecRepository { * [Settings.Secure.QS_TILES]. * [Settings.Secure.QS_TILES]. * * * All operations against [Settings] will be performed in a background thread. * All operations against [Settings] will be performed in a background thread. * * If the device is in retail mode, the tiles are fixed to the value of * [R.string.quick_settings_tiles_retail_mode]. */ */ @SysUISingleton @SysUISingleton class TileSpecSettingsRepository class TileSpecSettingsRepository Loading @@ -92,9 +100,31 @@ constructor( private val secureSettings: SecureSettings, private val secureSettings: SecureSettings, @Main private val resources: Resources, @Main private val resources: Resources, private val logger: QSPipelineLogger, private val logger: QSPipelineLogger, private val retailModeRepository: RetailModeRepository, @Background private val backgroundDispatcher: CoroutineDispatcher, @Background private val backgroundDispatcher: CoroutineDispatcher, ) : TileSpecRepository { ) : TileSpecRepository { private val retailModeTiles by lazy { resources .getString(R.string.quick_settings_tiles_retail_mode) .split(DELIMITER) .map(TileSpec::create) .filter { it !is TileSpec.Invalid } } @OptIn(ExperimentalCoroutinesApi::class) override fun tilesSpecs(userId: Int): Flow<List<TileSpec>> { override fun tilesSpecs(userId: Int): Flow<List<TileSpec>> { return retailModeRepository.retailMode.flatMapLatest { inRetailMode -> if (inRetailMode) { logger.logUsingRetailTiles() flowOf(retailModeTiles) } else { settingsTiles(userId) } } } private fun settingsTiles(userId: Int): Flow<List<TileSpec>> { return conflatedCallbackFlow { return conflatedCallbackFlow { val observer = val observer = object : ContentObserver(null) { object : ContentObserver(null) { Loading Loading @@ -157,6 +187,10 @@ constructor( } } private suspend fun storeTiles(@UserIdInt forUser: Int, tiles: List<TileSpec>) { private suspend fun storeTiles(@UserIdInt forUser: Int, tiles: List<TileSpec>) { if (retailModeRepository.inRetailMode) { // No storing tiles when in retail mode return } val toStore = val toStore = tiles tiles .filter { it !is TileSpec.Invalid } .filter { it !is TileSpec.Invalid } Loading packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt +4 −0 Original line number Original line Diff line number Diff line Loading @@ -120,6 +120,10 @@ constructor( ) ) } } fun logUsingRetailTiles() { tileListLogBuffer.log(TILE_LIST_TAG, LogLevel.DEBUG, {}, { "Using retail tiles" }) } /** Reasons for destroying an existing tile. */ /** Reasons for destroying an existing tile. */ enum class TileDestroyedReason(val readable: String) { enum class TileDestroyedReason(val readable: String) { TILE_REMOVED("Tile removed from current set"), TILE_REMOVED("Tile removed from current set"), Loading packages/SystemUI/src/com/android/systemui/retail/dagger/RetailModeModule.kt 0 → 100644 +34 −0 Original line number Original line 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.retail.dagger import com.android.systemui.retail.data.repository.RetailModeRepository import com.android.systemui.retail.data.repository.RetailModeSettingsRepository import com.android.systemui.retail.domain.interactor.RetailModeInteractor import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl import dagger.Binds import dagger.Module @Module abstract class RetailModeModule { @Binds abstract fun bindsRetailModeRepository(impl: RetailModeSettingsRepository): RetailModeRepository @Binds abstract fun bindsRetailModeInteractor(impl: RetailModeInteractorImpl): RetailModeInteractor } Loading
packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -69,6 +69,7 @@ import com.android.systemui.qs.FgsManagerControllerImpl; import com.android.systemui.qs.QSFragmentStartableModule; import com.android.systemui.qs.QSFragmentStartableModule; import com.android.systemui.qs.footer.dagger.FooterActionsModule; import com.android.systemui.qs.footer.dagger.FooterActionsModule; import com.android.systemui.recents.Recents; import com.android.systemui.recents.Recents; import com.android.systemui.retail.dagger.RetailModeModule; import com.android.systemui.screenrecord.ScreenRecordModule; import com.android.systemui.screenrecord.ScreenRecordModule; import com.android.systemui.screenshot.dagger.ScreenshotModule; import com.android.systemui.screenshot.dagger.ScreenshotModule; import com.android.systemui.security.data.repository.SecurityRepositoryModule; import com.android.systemui.security.data.repository.SecurityRepositoryModule; Loading Loading @@ -179,6 +180,7 @@ import javax.inject.Named; PrivacyModule.class, PrivacyModule.class, QRCodeScannerModule.class, QRCodeScannerModule.class, QSFragmentStartableModule.class, QSFragmentStartableModule.class, RetailModeModule.class, ScreenshotModule.class, ScreenshotModule.class, SensorModule.class, SensorModule.class, SecurityRepositoryModule.class, SecurityRepositoryModule.class, Loading
packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +8 −1 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.retail.domain.interactor.RetailModeInteractor; import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController; Loading @@ -45,18 +46,22 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme private final View mEditButton; private final View mEditButton; private final FalsingManager mFalsingManager; private final FalsingManager mFalsingManager; private final ActivityStarter mActivityStarter; private final ActivityStarter mActivityStarter; private final RetailModeInteractor mRetailModeInteractor; @Inject @Inject QSFooterViewController(QSFooterView view, QSFooterViewController(QSFooterView view, UserTracker userTracker, UserTracker userTracker, FalsingManager falsingManager, FalsingManager falsingManager, ActivityStarter activityStarter, ActivityStarter activityStarter, QSPanelController qsPanelController) { QSPanelController qsPanelController, RetailModeInteractor retailModeInteractor ) { super(view); super(view); mUserTracker = userTracker; mUserTracker = userTracker; mQsPanelController = qsPanelController; mQsPanelController = qsPanelController; mFalsingManager = falsingManager; mFalsingManager = falsingManager; mActivityStarter = activityStarter; mActivityStarter = activityStarter; mRetailModeInteractor = retailModeInteractor; mBuildText = mView.findViewById(R.id.build); mBuildText = mView.findViewById(R.id.build); mPageIndicator = mView.findViewById(R.id.footer_page_indicator); mPageIndicator = mView.findViewById(R.id.footer_page_indicator); Loading Loading @@ -96,6 +101,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme @Override @Override public void setVisibility(int visibility) { public void setVisibility(int visibility) { mView.setVisibility(visibility); mView.setVisibility(visibility); mEditButton .setVisibility(mRetailModeInteractor.isInRetailMode() ? View.GONE : View.VISIBLE); mEditButton.setClickable(visibility == View.VISIBLE); mEditButton.setClickable(visibility == View.VISIBLE); } } Loading
packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt +34 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.UserIdInt import android.content.res.Resources import android.content.res.Resources import android.database.ContentObserver import android.database.ContentObserver import android.provider.Settings import android.provider.Settings import com.android.systemui.R import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Background Loading @@ -27,12 +28,16 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.qs.QSHost import com.android.systemui.qs.QSHost import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger import com.android.systemui.retail.data.repository.RetailModeRepository import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach Loading Loading @@ -84,6 +89,9 @@ interface TileSpecRepository { * [Settings.Secure.QS_TILES]. * [Settings.Secure.QS_TILES]. * * * All operations against [Settings] will be performed in a background thread. * All operations against [Settings] will be performed in a background thread. * * If the device is in retail mode, the tiles are fixed to the value of * [R.string.quick_settings_tiles_retail_mode]. */ */ @SysUISingleton @SysUISingleton class TileSpecSettingsRepository class TileSpecSettingsRepository Loading @@ -92,9 +100,31 @@ constructor( private val secureSettings: SecureSettings, private val secureSettings: SecureSettings, @Main private val resources: Resources, @Main private val resources: Resources, private val logger: QSPipelineLogger, private val logger: QSPipelineLogger, private val retailModeRepository: RetailModeRepository, @Background private val backgroundDispatcher: CoroutineDispatcher, @Background private val backgroundDispatcher: CoroutineDispatcher, ) : TileSpecRepository { ) : TileSpecRepository { private val retailModeTiles by lazy { resources .getString(R.string.quick_settings_tiles_retail_mode) .split(DELIMITER) .map(TileSpec::create) .filter { it !is TileSpec.Invalid } } @OptIn(ExperimentalCoroutinesApi::class) override fun tilesSpecs(userId: Int): Flow<List<TileSpec>> { override fun tilesSpecs(userId: Int): Flow<List<TileSpec>> { return retailModeRepository.retailMode.flatMapLatest { inRetailMode -> if (inRetailMode) { logger.logUsingRetailTiles() flowOf(retailModeTiles) } else { settingsTiles(userId) } } } private fun settingsTiles(userId: Int): Flow<List<TileSpec>> { return conflatedCallbackFlow { return conflatedCallbackFlow { val observer = val observer = object : ContentObserver(null) { object : ContentObserver(null) { Loading Loading @@ -157,6 +187,10 @@ constructor( } } private suspend fun storeTiles(@UserIdInt forUser: Int, tiles: List<TileSpec>) { private suspend fun storeTiles(@UserIdInt forUser: Int, tiles: List<TileSpec>) { if (retailModeRepository.inRetailMode) { // No storing tiles when in retail mode return } val toStore = val toStore = tiles tiles .filter { it !is TileSpec.Invalid } .filter { it !is TileSpec.Invalid } Loading
packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt +4 −0 Original line number Original line Diff line number Diff line Loading @@ -120,6 +120,10 @@ constructor( ) ) } } fun logUsingRetailTiles() { tileListLogBuffer.log(TILE_LIST_TAG, LogLevel.DEBUG, {}, { "Using retail tiles" }) } /** Reasons for destroying an existing tile. */ /** Reasons for destroying an existing tile. */ enum class TileDestroyedReason(val readable: String) { enum class TileDestroyedReason(val readable: String) { TILE_REMOVED("Tile removed from current set"), TILE_REMOVED("Tile removed from current set"), Loading
packages/SystemUI/src/com/android/systemui/retail/dagger/RetailModeModule.kt 0 → 100644 +34 −0 Original line number Original line 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.retail.dagger import com.android.systemui.retail.data.repository.RetailModeRepository import com.android.systemui.retail.data.repository.RetailModeSettingsRepository import com.android.systemui.retail.domain.interactor.RetailModeInteractor import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl import dagger.Binds import dagger.Module @Module abstract class RetailModeModule { @Binds abstract fun bindsRetailModeRepository(impl: RetailModeSettingsRepository): RetailModeRepository @Binds abstract fun bindsRetailModeInteractor(impl: RetailModeInteractorImpl): RetailModeInteractor }