Loading packages/SystemUI/src/com/android/systemui/screencapture/ScreenCaptureUiStartable.kt→packages/SystemUI/src/com/android/systemui/screencapture/ScreenCaptureStartable.kt +13 −8 Original line number Original line Diff line number Diff line Loading @@ -24,32 +24,36 @@ import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.display.data.repository.FocusedDisplayRepository import com.android.systemui.display.data.repository.FocusedDisplayRepository import com.android.systemui.screencapture.common.shared.model.ScreenCaptureType import com.android.systemui.screencapture.common.shared.model.ScreenCaptureType import com.android.systemui.screencapture.common.shared.model.ScreenCaptureUiState import com.android.systemui.screencapture.common.shared.model.ScreenCaptureUiState import com.android.systemui.screencapture.domain.interactor.ScreenCaptureComponentInteractor import com.android.systemui.screencapture.domain.interactor.ScreenCaptureUiInteractor import com.android.systemui.screencapture.domain.interactor.ScreenCaptureUiInteractor import com.android.systemui.screencapture.ui.ScreenCaptureUi import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @SysUISingleton @SysUISingleton class ScreenCaptureUiStartable class ScreenCaptureStartable @Inject @Inject constructor( constructor( @Application private val appScope: CoroutineScope, @Application private val appScope: CoroutineScope, private val screenCaptureComponentInteractor: ScreenCaptureComponentInteractor, private val screenCaptureUiInteractor: ScreenCaptureUiInteractor, private val screenCaptureUiInteractor: ScreenCaptureUiInteractor, private val screenCaptureUiFactory: ScreenCaptureUi.Factory, private val focusedDisplayRepository: FocusedDisplayRepository, private val focusedDisplayRepository: FocusedDisplayRepository, private val displayRepository: DisplayRepository, private val displayRepository: DisplayRepository, ) : CoreStartable { ) : CoreStartable { override fun start() { override fun start() { appScope.launch { screenCaptureComponentInteractor.initialize() } ScreenCaptureType.entries.forEach { observeUiState(it) } ScreenCaptureType.entries.forEach { observeUiState(it) } } } private fun observeUiState(type: ScreenCaptureType) { private fun observeUiState(type: ScreenCaptureType) { screenCaptureUiInteractor combine( .uiState(type) screenCaptureUiInteractor.uiState(type), .onEach { state -> screenCaptureComponentInteractor.screenCaptureComponent(type).filterNotNull(), ) { state, screenCaptureComponent -> if (state is ScreenCaptureUiState.Visible) { if (state is ScreenCaptureUiState.Visible) { val displayId = focusedDisplayRepository.focusedDisplayId.value val displayId = focusedDisplayRepository.focusedDisplayId.value val display = displayRepository.getDisplay(displayId) val display = displayRepository.getDisplay(displayId) Loading @@ -58,7 +62,8 @@ constructor( Log.e("ScreenCapture", "Couldn't find display for id=$displayId") Log.e("ScreenCapture", "Couldn't find display for id=$displayId") screenCaptureUiInteractor.hide(type) screenCaptureUiInteractor.hide(type) } else { } else { screenCaptureUiFactory screenCaptureComponent .screenCaptureUiFactory() .create(type = state.parameters.screenCaptureType, display = display) .create(type = state.parameters.screenCaptureType, display = display) .attachWindow() .attachWindow() } } Loading packages/SystemUI/src/com/android/systemui/screencapture/common/Qualifiers.kt +4 −1 Original line number Original line Diff line number Diff line Loading @@ -18,8 +18,11 @@ package com.android.systemui.screencapture.common import javax.inject.Qualifier import javax.inject.Qualifier /** Used to qualify an item as the one used by Screen Capture. */ /** Used to qualify an item as the one used by Screen Capture UI. */ @Qualifier @Qualifier @MustBeDocumented @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCaptureUi annotation class ScreenCaptureUi /** Used to qualify an item as the one used by Screen Capture. */ @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCapture packages/SystemUI/src/com/android/systemui/screencapture/common/Scopes.kt +15 −1 Original line number Original line Diff line number Diff line Loading @@ -18,8 +18,22 @@ package com.android.systemui.screencapture.common import javax.inject.Scope import javax.inject.Scope /** Scope annotation for Screen Capture scoped items within the [ScreenCaptureUiComponent]. */ /** * Scope annotation for Screen Capture scoped items within the [ScreenCaptureUiComponent]. * * This scope exists when Screen Capture UI is visible. */ @Scope @Scope @MustBeDocumented @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCaptureUiScope annotation class ScreenCaptureUiScope /** * Scope annotation for Screen Capture scoped items within the [ScreenCaptureComponent]. * * This scope exists from the first Screen Capture UI appearance throughout the capturing. */ @Scope @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCaptureScope packages/SystemUI/src/com/android/systemui/screencapture/common/ScreenCaptureComponent.kt 0 → 100644 +59 −0 Original line number Original line 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.screencapture.common import com.android.systemui.screencapture.common.shared.model.ScreenCaptureUiParameters import com.android.systemui.screencapture.ui.ScreenCaptureUi import dagger.BindsInstance import dagger.Subcomponent import kotlinx.coroutines.CoroutineScope /** * Dagger Subcomponent interface for Screen Capture. It's alive while there is an ongoing Screen * Capture or the UI is visible. */ @ScreenCaptureScope @Subcomponent(modules = [ScreenCaptureUiModule::class]) interface ScreenCaptureComponent { @ScreenCapture fun coroutineScope(): CoroutineScope fun screenCaptureUiFactory(): ScreenCaptureUi.Factory /** * Dagger Subcomponent Builder for [ScreenCaptureComponent]. * * Actual Subcomponent Builders should extend this interface and override [build] to return the * actual subcomponent type. */ @Subcomponent.Builder interface Builder { /** The [CoroutineScope] to use coroutines limited to Screen Capture sessions. */ @BindsInstance fun setScope(@ScreenCapture scope: CoroutineScope): Builder /** [ScreenCaptureUiParameters] that has been used to start capture flow. */ @BindsInstance fun setParameters(@ScreenCapture parameters: ScreenCaptureUiParameters): Builder /** * Builds this [ScreenCaptureComponent]. Actual Subcomponent Builders should override this * method with their own version that returns the actual subcomponent type. */ fun build(): ScreenCaptureComponent } } packages/SystemUI/src/com/android/systemui/screencapture/common/ScreenCaptureModule.kt +4 −42 Original line number Original line Diff line number Diff line Loading @@ -18,58 +18,20 @@ package com.android.systemui.screencapture.common import android.app.Activity import android.app.Activity import com.android.systemui.CoreStartable import com.android.systemui.CoreStartable import com.android.systemui.screencapture.ScreenCaptureUiStartable import com.android.systemui.screencapture.ScreenCaptureStartable import com.android.systemui.screencapture.cast.ScreenCaptureCastUiComponent import com.android.systemui.screencapture.common.shared.model.ScreenCaptureType import com.android.systemui.screencapture.record.ScreenCaptureRecordUiComponent import com.android.systemui.screencapture.record.smallscreen.ui.SmallScreenPostRecordingActivity import com.android.systemui.screencapture.record.smallscreen.ui.SmallScreenPostRecordingActivity import com.android.systemui.screencapture.sharescreen.ScreenCaptureShareScreenUiComponent import dagger.Binds import dagger.Binds import dagger.Module import dagger.Module import dagger.multibindings.ClassKey import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap /** @Module(subcomponents = [ScreenCaptureComponent::class]) * Top level Dagger Module for Screen Capture. * * Injects Screen Capture Subcomponents into the System UI dagger graph via * [SystemUIModule][com.android.systemui.dagger.SystemUIModule]. */ @Module( subcomponents = [ ScreenCaptureCastUiComponent::class, ScreenCaptureUiComponent::class, ScreenCaptureRecordUiComponent::class, ScreenCaptureShareScreenUiComponent::class, ] ) interface ScreenCaptureModule { interface ScreenCaptureModule { @Binds @IntoMap @ScreenCaptureTypeKey(ScreenCaptureType.CAST) fun bindCastComponentBuilder( impl: ScreenCaptureCastUiComponent.Builder ): ScreenCaptureUiComponent.Builder @Binds @IntoMap @ScreenCaptureTypeKey(ScreenCaptureType.RECORD) fun bindRecordComponentBuilder( impl: ScreenCaptureRecordUiComponent.Builder ): ScreenCaptureUiComponent.Builder @Binds @IntoMap @ScreenCaptureTypeKey(ScreenCaptureType.SHARE_SCREEN) fun bindShareScreenComponentBuilder( impl: ScreenCaptureShareScreenUiComponent.Builder ): ScreenCaptureUiComponent.Builder @Binds @Binds @IntoMap @IntoMap @ClassKey(ScreenCaptureUiStartable::class) @ClassKey(ScreenCaptureStartable::class) fun bindScreenCaptureUiStartable(impl: ScreenCaptureUiStartable): CoreStartable fun bindScreenCaptureUiStartable(impl: ScreenCaptureStartable): CoreStartable @Binds @Binds @IntoMap @IntoMap Loading Loading
packages/SystemUI/src/com/android/systemui/screencapture/ScreenCaptureUiStartable.kt→packages/SystemUI/src/com/android/systemui/screencapture/ScreenCaptureStartable.kt +13 −8 Original line number Original line Diff line number Diff line Loading @@ -24,32 +24,36 @@ import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.display.data.repository.FocusedDisplayRepository import com.android.systemui.display.data.repository.FocusedDisplayRepository import com.android.systemui.screencapture.common.shared.model.ScreenCaptureType import com.android.systemui.screencapture.common.shared.model.ScreenCaptureType import com.android.systemui.screencapture.common.shared.model.ScreenCaptureUiState import com.android.systemui.screencapture.common.shared.model.ScreenCaptureUiState import com.android.systemui.screencapture.domain.interactor.ScreenCaptureComponentInteractor import com.android.systemui.screencapture.domain.interactor.ScreenCaptureUiInteractor import com.android.systemui.screencapture.domain.interactor.ScreenCaptureUiInteractor import com.android.systemui.screencapture.ui.ScreenCaptureUi import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @SysUISingleton @SysUISingleton class ScreenCaptureUiStartable class ScreenCaptureStartable @Inject @Inject constructor( constructor( @Application private val appScope: CoroutineScope, @Application private val appScope: CoroutineScope, private val screenCaptureComponentInteractor: ScreenCaptureComponentInteractor, private val screenCaptureUiInteractor: ScreenCaptureUiInteractor, private val screenCaptureUiInteractor: ScreenCaptureUiInteractor, private val screenCaptureUiFactory: ScreenCaptureUi.Factory, private val focusedDisplayRepository: FocusedDisplayRepository, private val focusedDisplayRepository: FocusedDisplayRepository, private val displayRepository: DisplayRepository, private val displayRepository: DisplayRepository, ) : CoreStartable { ) : CoreStartable { override fun start() { override fun start() { appScope.launch { screenCaptureComponentInteractor.initialize() } ScreenCaptureType.entries.forEach { observeUiState(it) } ScreenCaptureType.entries.forEach { observeUiState(it) } } } private fun observeUiState(type: ScreenCaptureType) { private fun observeUiState(type: ScreenCaptureType) { screenCaptureUiInteractor combine( .uiState(type) screenCaptureUiInteractor.uiState(type), .onEach { state -> screenCaptureComponentInteractor.screenCaptureComponent(type).filterNotNull(), ) { state, screenCaptureComponent -> if (state is ScreenCaptureUiState.Visible) { if (state is ScreenCaptureUiState.Visible) { val displayId = focusedDisplayRepository.focusedDisplayId.value val displayId = focusedDisplayRepository.focusedDisplayId.value val display = displayRepository.getDisplay(displayId) val display = displayRepository.getDisplay(displayId) Loading @@ -58,7 +62,8 @@ constructor( Log.e("ScreenCapture", "Couldn't find display for id=$displayId") Log.e("ScreenCapture", "Couldn't find display for id=$displayId") screenCaptureUiInteractor.hide(type) screenCaptureUiInteractor.hide(type) } else { } else { screenCaptureUiFactory screenCaptureComponent .screenCaptureUiFactory() .create(type = state.parameters.screenCaptureType, display = display) .create(type = state.parameters.screenCaptureType, display = display) .attachWindow() .attachWindow() } } Loading
packages/SystemUI/src/com/android/systemui/screencapture/common/Qualifiers.kt +4 −1 Original line number Original line Diff line number Diff line Loading @@ -18,8 +18,11 @@ package com.android.systemui.screencapture.common import javax.inject.Qualifier import javax.inject.Qualifier /** Used to qualify an item as the one used by Screen Capture. */ /** Used to qualify an item as the one used by Screen Capture UI. */ @Qualifier @Qualifier @MustBeDocumented @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCaptureUi annotation class ScreenCaptureUi /** Used to qualify an item as the one used by Screen Capture. */ @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCapture
packages/SystemUI/src/com/android/systemui/screencapture/common/Scopes.kt +15 −1 Original line number Original line Diff line number Diff line Loading @@ -18,8 +18,22 @@ package com.android.systemui.screencapture.common import javax.inject.Scope import javax.inject.Scope /** Scope annotation for Screen Capture scoped items within the [ScreenCaptureUiComponent]. */ /** * Scope annotation for Screen Capture scoped items within the [ScreenCaptureUiComponent]. * * This scope exists when Screen Capture UI is visible. */ @Scope @Scope @MustBeDocumented @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCaptureUiScope annotation class ScreenCaptureUiScope /** * Scope annotation for Screen Capture scoped items within the [ScreenCaptureComponent]. * * This scope exists from the first Screen Capture UI appearance throughout the capturing. */ @Scope @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ScreenCaptureScope
packages/SystemUI/src/com/android/systemui/screencapture/common/ScreenCaptureComponent.kt 0 → 100644 +59 −0 Original line number Original line 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.screencapture.common import com.android.systemui.screencapture.common.shared.model.ScreenCaptureUiParameters import com.android.systemui.screencapture.ui.ScreenCaptureUi import dagger.BindsInstance import dagger.Subcomponent import kotlinx.coroutines.CoroutineScope /** * Dagger Subcomponent interface for Screen Capture. It's alive while there is an ongoing Screen * Capture or the UI is visible. */ @ScreenCaptureScope @Subcomponent(modules = [ScreenCaptureUiModule::class]) interface ScreenCaptureComponent { @ScreenCapture fun coroutineScope(): CoroutineScope fun screenCaptureUiFactory(): ScreenCaptureUi.Factory /** * Dagger Subcomponent Builder for [ScreenCaptureComponent]. * * Actual Subcomponent Builders should extend this interface and override [build] to return the * actual subcomponent type. */ @Subcomponent.Builder interface Builder { /** The [CoroutineScope] to use coroutines limited to Screen Capture sessions. */ @BindsInstance fun setScope(@ScreenCapture scope: CoroutineScope): Builder /** [ScreenCaptureUiParameters] that has been used to start capture flow. */ @BindsInstance fun setParameters(@ScreenCapture parameters: ScreenCaptureUiParameters): Builder /** * Builds this [ScreenCaptureComponent]. Actual Subcomponent Builders should override this * method with their own version that returns the actual subcomponent type. */ fun build(): ScreenCaptureComponent } }
packages/SystemUI/src/com/android/systemui/screencapture/common/ScreenCaptureModule.kt +4 −42 Original line number Original line Diff line number Diff line Loading @@ -18,58 +18,20 @@ package com.android.systemui.screencapture.common import android.app.Activity import android.app.Activity import com.android.systemui.CoreStartable import com.android.systemui.CoreStartable import com.android.systemui.screencapture.ScreenCaptureUiStartable import com.android.systemui.screencapture.ScreenCaptureStartable import com.android.systemui.screencapture.cast.ScreenCaptureCastUiComponent import com.android.systemui.screencapture.common.shared.model.ScreenCaptureType import com.android.systemui.screencapture.record.ScreenCaptureRecordUiComponent import com.android.systemui.screencapture.record.smallscreen.ui.SmallScreenPostRecordingActivity import com.android.systemui.screencapture.record.smallscreen.ui.SmallScreenPostRecordingActivity import com.android.systemui.screencapture.sharescreen.ScreenCaptureShareScreenUiComponent import dagger.Binds import dagger.Binds import dagger.Module import dagger.Module import dagger.multibindings.ClassKey import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap /** @Module(subcomponents = [ScreenCaptureComponent::class]) * Top level Dagger Module for Screen Capture. * * Injects Screen Capture Subcomponents into the System UI dagger graph via * [SystemUIModule][com.android.systemui.dagger.SystemUIModule]. */ @Module( subcomponents = [ ScreenCaptureCastUiComponent::class, ScreenCaptureUiComponent::class, ScreenCaptureRecordUiComponent::class, ScreenCaptureShareScreenUiComponent::class, ] ) interface ScreenCaptureModule { interface ScreenCaptureModule { @Binds @IntoMap @ScreenCaptureTypeKey(ScreenCaptureType.CAST) fun bindCastComponentBuilder( impl: ScreenCaptureCastUiComponent.Builder ): ScreenCaptureUiComponent.Builder @Binds @IntoMap @ScreenCaptureTypeKey(ScreenCaptureType.RECORD) fun bindRecordComponentBuilder( impl: ScreenCaptureRecordUiComponent.Builder ): ScreenCaptureUiComponent.Builder @Binds @IntoMap @ScreenCaptureTypeKey(ScreenCaptureType.SHARE_SCREEN) fun bindShareScreenComponentBuilder( impl: ScreenCaptureShareScreenUiComponent.Builder ): ScreenCaptureUiComponent.Builder @Binds @Binds @IntoMap @IntoMap @ClassKey(ScreenCaptureUiStartable::class) @ClassKey(ScreenCaptureStartable::class) fun bindScreenCaptureUiStartable(impl: ScreenCaptureUiStartable): CoreStartable fun bindScreenCaptureUiStartable(impl: ScreenCaptureStartable): CoreStartable @Binds @Binds @IntoMap @IntoMap Loading