summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2023-07-20 10:54:22 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-07-20 10:54:22 +0000
commit066951a123542d5ce48b663ddfc1b69235ccc834 (patch)
treebec9689c5a9c1e08589d34882ec6131889386eb5
parent1f04a112250e19ef2499322d7fa2195dd74483b3 (diff)
parent1dde493feac0e216cf5ae83c8a13054f2abc0ffa (diff)
Merge "PSS: Fix MediaProjectionTaskView leaking in KeyguardController" into udc-qpr-dev
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt26
4 files changed, 73 insertions, 9 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index 8d3c6d5d4947..8f884d24ad21 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -30,6 +30,9 @@ import android.os.IBinder
import android.os.ResultReceiver
import android.os.UserHandle
import android.view.ViewGroup
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider
@@ -54,7 +57,11 @@ class MediaProjectionAppSelectorActivity(
/** This is used to override the dependency in a screenshot test */
@VisibleForTesting
private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)?
-) : ChooserActivity(), MediaProjectionAppSelectorView, MediaProjectionAppSelectorResultHandler {
+) :
+ ChooserActivity(),
+ MediaProjectionAppSelectorView,
+ MediaProjectionAppSelectorResultHandler,
+ LifecycleOwner {
@Inject
constructor(
@@ -62,6 +69,8 @@ class MediaProjectionAppSelectorActivity(
activityLauncher: AsyncActivityLauncher
) : this(componentFactory, activityLauncher, listControllerFactory = null)
+ private val lifecycleRegistry = LifecycleRegistry(this)
+ override val lifecycle = lifecycleRegistry
private lateinit var configurationController: ConfigurationController
private lateinit var controller: MediaProjectionAppSelectorController
private lateinit var recentsViewController: MediaProjectionRecentsViewController
@@ -75,7 +84,9 @@ class MediaProjectionAppSelectorActivity(
override fun getLayoutResource() = R.layout.media_projection_app_selector
public override fun onCreate(bundle: Bundle?) {
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
component = componentFactory.create(activity = this, view = this, resultHandler = this)
+ component.lifecycleObservers.forEach { lifecycle.addObserver(it) }
// Create a separate configuration controller for this activity as the configuration
// might be different from the global one
@@ -96,6 +107,26 @@ class MediaProjectionAppSelectorActivity(
controller.init()
}
+ override fun onStart() {
+ super.onStart()
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
+ }
+
+ override fun onPause() {
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+ super.onPause()
+ }
+
+ override fun onStop() {
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
+ super.onStop()
+ }
+
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
configurationController.onConfigurationChanged(newConfig)
@@ -152,6 +183,8 @@ class MediaProjectionAppSelectorActivity(
}
override fun onDestroy() {
+ lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ component.lifecycleObservers.forEach { lifecycle.removeObserver(it) }
// onDestroy is also called when an app is selected, in that case we only want to send
// RECORD_CONTENT_TASK but not RECORD_CANCEL
if (!taskSelected) {
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index 3088d8b58023..11538fadf24e 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -20,6 +20,7 @@ import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.os.UserHandle
+import androidx.lifecycle.DefaultLifecycleObserver
import com.android.launcher3.icons.IconFactory
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.media.MediaProjectionAppSelectorActivity
@@ -46,6 +47,7 @@ import dagger.Provides
import dagger.Subcomponent
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
+import dagger.multibindings.IntoSet
import javax.inject.Qualifier
import javax.inject.Scope
import kotlinx.coroutines.CoroutineScope
@@ -100,6 +102,12 @@ interface MediaProjectionAppSelectorModule {
@MediaProjectionAppSelectorScope
fun bindAppIconLoader(impl: IconLoaderLibAppIconLoader): AppIconLoader
+ @Binds
+ @IntoSet
+ fun taskPreviewSizeProviderAsLifecycleObserver(
+ impl: TaskPreviewSizeProvider
+ ): DefaultLifecycleObserver
+
companion object {
@Provides
@MediaProjectionAppSelector
@@ -166,4 +174,5 @@ interface MediaProjectionAppSelectorComponent {
@get:PersonalProfile val personalProfileUserHandle: UserHandle
@MediaProjectionAppSelector val configurationController: ConfigurationController
+ val lifecycleObservers: Set<DefaultLifecycleObserver>
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
index 89f66b7daaf8..864d35af41b4 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
@@ -21,6 +21,8 @@ import android.content.res.Configuration
import android.graphics.Rect
import android.view.WindowInsets.Type
import android.view.WindowManager
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
@@ -35,18 +37,22 @@ class TaskPreviewSizeProvider
constructor(
private val context: Context,
private val windowManager: WindowManager,
- configurationController: ConfigurationController
-) : CallbackController<TaskPreviewSizeListener>, ConfigurationListener {
+ private val configurationController: ConfigurationController,
+) : CallbackController<TaskPreviewSizeListener>, ConfigurationListener, DefaultLifecycleObserver {
/** Returns the size of the task preview on the screen in pixels */
val size: Rect = calculateSize()
private val listeners = arrayListOf<TaskPreviewSizeListener>()
- init {
+ override fun onCreate(owner: LifecycleOwner) {
configurationController.addCallback(this)
}
+ override fun onDestroy(owner: LifecycleOwner) {
+ configurationController.removeCallback(this)
+ }
+
override fun onConfigChanged(newConfig: Configuration) {
val newSize = calculateSize()
if (newSize != size) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt
index 01ffdcd580c0..ee3b80ac932e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt
@@ -26,6 +26,7 @@ import android.view.WindowInsets
import android.view.WindowManager
import android.view.WindowMetrics
import androidx.core.view.WindowInsetsCompat.Type
+import androidx.lifecycle.LifecycleOwner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
@@ -41,9 +42,10 @@ import org.junit.Test
@SmallTest
class TaskPreviewSizeProviderTest : SysuiTestCase() {
- private val mockContext: Context = mock()
- private val resources: Resources = mock()
- private val windowManager: WindowManager = mock()
+ private val lifecycleOwner = mock<LifecycleOwner>()
+ private val mockContext = mock<Context>()
+ private val resources = mock<Resources>()
+ private val windowManager = mock<WindowManager>()
private val sizeUpdates = arrayListOf<Rect>()
private val testConfigurationController = FakeConfigurationController()
@@ -76,7 +78,7 @@ class TaskPreviewSizeProviderTest : SysuiTestCase() {
@Test
fun size_phoneDisplayAndRotate_emitsSizeUpdate() {
givenDisplay(width = 400, height = 600, isTablet = false)
- createSizeProvider()
+ createSizeProvider().also { it.onCreate(lifecycleOwner) }
givenDisplay(width = 600, height = 400, isTablet = false)
testConfigurationController.onConfigurationChanged(Configuration())
@@ -87,7 +89,7 @@ class TaskPreviewSizeProviderTest : SysuiTestCase() {
@Test
fun size_phoneDisplayAndRotateConfigurationChange_returnsUpdatedSize() {
givenDisplay(width = 400, height = 600, isTablet = false)
- val sizeProvider = createSizeProvider()
+ val sizeProvider = createSizeProvider().also { it.onCreate(lifecycleOwner) }
givenDisplay(width = 600, height = 400, isTablet = false)
testConfigurationController.onConfigurationChanged(Configuration())
@@ -95,6 +97,20 @@ class TaskPreviewSizeProviderTest : SysuiTestCase() {
assertThat(sizeProvider.size).isEqualTo(Rect(0, 0, 150, 100))
}
+ @Test
+ fun size_phoneDisplayAndRotateConfigurationChange_afterChooserDestroyed_doesNotUpdate() {
+ givenDisplay(width = 400, height = 600, isTablet = false)
+ val sizeProvider = createSizeProvider()
+ val previousSize = Rect(sizeProvider.size)
+
+ sizeProvider.onCreate(lifecycleOwner)
+ sizeProvider.onDestroy(lifecycleOwner)
+ givenDisplay(width = 600, height = 400, isTablet = false)
+ testConfigurationController.onConfigurationChanged(Configuration())
+
+ assertThat(sizeProvider.size).isEqualTo(previousSize)
+ }
+
private fun givenTaskbarSize(size: Int) {
val windowInsets =
WindowInsets.Builder()