Merge "Fix memory leak of MediaControlPanel" into udc-dev
This commit is contained in:
@@ -21,6 +21,8 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.database.ContentObserver
|
||||||
|
import android.provider.Settings
|
||||||
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
|
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.MathUtils
|
import android.util.MathUtils
|
||||||
@@ -64,6 +66,7 @@ import com.android.systemui.util.Utils
|
|||||||
import com.android.systemui.util.animation.UniqueObjectHostView
|
import com.android.systemui.util.animation.UniqueObjectHostView
|
||||||
import com.android.systemui.util.animation.requiresRemeasuring
|
import com.android.systemui.util.animation.requiresRemeasuring
|
||||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||||
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
import com.android.systemui.util.time.SystemClock
|
import com.android.systemui.util.time.SystemClock
|
||||||
import com.android.systemui.util.traceSection
|
import com.android.systemui.util.traceSection
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
@@ -105,6 +108,7 @@ constructor(
|
|||||||
private val mediaFlags: MediaFlags,
|
private val mediaFlags: MediaFlags,
|
||||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||||
|
private val globalSettings: GlobalSettings,
|
||||||
) : Dumpable {
|
) : Dumpable {
|
||||||
/** The current width of the carousel */
|
/** The current width of the carousel */
|
||||||
var currentCarouselWidth: Int = 0
|
var currentCarouselWidth: Int = 0
|
||||||
@@ -169,6 +173,13 @@ constructor(
|
|||||||
|
|
||||||
private var carouselLocale: Locale? = null
|
private var carouselLocale: Locale? = null
|
||||||
|
|
||||||
|
private val animationScaleObserver: ContentObserver =
|
||||||
|
object : ContentObserver(null) {
|
||||||
|
override fun onChange(selfChange: Boolean) {
|
||||||
|
MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether the media card currently has the "expanded" layout */
|
/** Whether the media card currently has the "expanded" layout */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
var currentlyExpanded = true
|
var currentlyExpanded = true
|
||||||
@@ -529,6 +540,12 @@ constructor(
|
|||||||
listenForAnyStateToGoneKeyguardTransition(this)
|
listenForAnyStateToGoneKeyguardTransition(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies all active players about animation scale changes.
|
||||||
|
globalSettings.registerContentObserver(
|
||||||
|
Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
|
||||||
|
animationScaleObserver
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inflateSettingsButton() {
|
private fun inflateSettingsButton() {
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.ContentObserver;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BlendMode;
|
import android.graphics.BlendMode;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@@ -252,13 +251,6 @@ public class MediaControlPanel {
|
|||||||
private boolean mWasPlaying = false;
|
private boolean mWasPlaying = false;
|
||||||
private boolean mButtonClicked = false;
|
private boolean mButtonClicked = false;
|
||||||
|
|
||||||
private ContentObserver mAnimationScaleObserver = new ContentObserver(null) {
|
|
||||||
@Override
|
|
||||||
public void onChange(boolean selfChange) {
|
|
||||||
updateAnimatorDurationScale();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new control panel
|
* Initialize a new control panel
|
||||||
*
|
*
|
||||||
@@ -318,10 +310,6 @@ public class MediaControlPanel {
|
|||||||
mFeatureFlags = featureFlags;
|
mFeatureFlags = featureFlags;
|
||||||
|
|
||||||
mGlobalSettings = globalSettings;
|
mGlobalSettings = globalSettings;
|
||||||
mGlobalSettings.registerContentObserver(
|
|
||||||
Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
|
|
||||||
mAnimationScaleObserver
|
|
||||||
);
|
|
||||||
updateAnimatorDurationScale();
|
updateAnimatorDurationScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +393,10 @@ public class MediaControlPanel {
|
|||||||
updateSeekBarVisibility();
|
updateSeekBarVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAnimatorDurationScale() {
|
/**
|
||||||
|
* Reloads animator duration scale.
|
||||||
|
*/
|
||||||
|
void updateAnimatorDurationScale() {
|
||||||
if (mSeekBarObserver != null) {
|
if (mSeekBarObserver != null) {
|
||||||
mSeekBarObserver.setAnimationEnabled(
|
mSeekBarObserver.setAnimationEnabled(
|
||||||
mGlobalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f);
|
mGlobalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f);
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ package com.android.systemui.media.controls.ui
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.database.ContentObserver
|
||||||
import android.os.LocaleList
|
import android.os.LocaleList
|
||||||
|
import android.provider.Settings
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
import android.util.MathUtils.abs
|
import android.util.MathUtils.abs
|
||||||
@@ -56,6 +58,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor
|
|||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.mockito.capture
|
import com.android.systemui.util.mockito.capture
|
||||||
import com.android.systemui.util.mockito.eq
|
import com.android.systemui.util.mockito.eq
|
||||||
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
import com.android.systemui.util.time.FakeSystemClock
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Provider
|
import javax.inject.Provider
|
||||||
@@ -113,6 +116,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
|
|||||||
@Mock lateinit var mediaFlags: MediaFlags
|
@Mock lateinit var mediaFlags: MediaFlags
|
||||||
@Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
@Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||||
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||||
|
@Mock lateinit var globalSettings: GlobalSettings
|
||||||
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
|
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
|
||||||
@Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener>
|
@Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener>
|
||||||
@Captor
|
@Captor
|
||||||
@@ -120,6 +124,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
|
|||||||
@Captor lateinit var visualStabilityCallback: ArgumentCaptor<OnReorderingAllowedListener>
|
@Captor lateinit var visualStabilityCallback: ArgumentCaptor<OnReorderingAllowedListener>
|
||||||
@Captor lateinit var keyguardCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
|
@Captor lateinit var keyguardCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
|
||||||
@Captor lateinit var hostStateCallback: ArgumentCaptor<MediaHostStatesManager.Callback>
|
@Captor lateinit var hostStateCallback: ArgumentCaptor<MediaHostStatesManager.Callback>
|
||||||
|
@Captor lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver>
|
||||||
|
|
||||||
private val clock = FakeSystemClock()
|
private val clock = FakeSystemClock()
|
||||||
private lateinit var mediaCarouselController: MediaCarouselController
|
private lateinit var mediaCarouselController: MediaCarouselController
|
||||||
@@ -148,6 +153,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
|
|||||||
mediaFlags,
|
mediaFlags,
|
||||||
keyguardUpdateMonitor,
|
keyguardUpdateMonitor,
|
||||||
KeyguardTransitionInteractor(transitionRepository, TestScope().backgroundScope),
|
KeyguardTransitionInteractor(transitionRepository, TestScope().backgroundScope),
|
||||||
|
globalSettings
|
||||||
)
|
)
|
||||||
verify(configurationController).addCallback(capture(configListener))
|
verify(configurationController).addCallback(capture(configListener))
|
||||||
verify(mediaDataManager).addListener(capture(listener))
|
verify(mediaDataManager).addListener(capture(listener))
|
||||||
@@ -160,6 +166,11 @@ class MediaCarouselControllerTest : SysuiTestCase() {
|
|||||||
whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData)
|
whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData)
|
||||||
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
|
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
|
||||||
MediaPlayerData.clear()
|
MediaPlayerData.clear()
|
||||||
|
verify(globalSettings)
|
||||||
|
.registerContentObserver(
|
||||||
|
eq(Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE)),
|
||||||
|
settingsObserverCaptor.capture()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -873,6 +884,15 @@ class MediaCarouselControllerTest : SysuiTestCase() {
|
|||||||
assertTrue(stateUpdated)
|
assertTrue(stateUpdated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAnimationScaleChanged_mediaControlPanelsNotified() {
|
||||||
|
MediaPlayerData.addMediaPlayer("key", DATA, panel, clock, isSsReactivated = false)
|
||||||
|
|
||||||
|
globalSettings.putFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 0f)
|
||||||
|
settingsObserverCaptor.value!!.onChange(false)
|
||||||
|
verify(panel).updateAnimatorDurationScale()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method when a configuration change occurs.
|
* Helper method when a configuration change occurs.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import android.content.Intent
|
|||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.database.ContentObserver
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
@@ -113,7 +112,6 @@ import org.junit.runner.RunWith
|
|||||||
import org.mockito.ArgumentCaptor
|
import org.mockito.ArgumentCaptor
|
||||||
import org.mockito.ArgumentMatchers.anyInt
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
import org.mockito.ArgumentMatchers.anyLong
|
import org.mockito.ArgumentMatchers.anyLong
|
||||||
import org.mockito.Captor
|
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.anyString
|
import org.mockito.Mockito.anyString
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
@@ -239,7 +237,6 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
this.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, false)
|
this.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, false)
|
||||||
}
|
}
|
||||||
@Mock private lateinit var globalSettings: GlobalSettings
|
@Mock private lateinit var globalSettings: GlobalSettings
|
||||||
@Captor private lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver>
|
|
||||||
|
|
||||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||||
|
|
||||||
@@ -281,7 +278,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
lockscreenUserManager,
|
lockscreenUserManager,
|
||||||
broadcastDialogController,
|
broadcastDialogController,
|
||||||
fakeFeatureFlag,
|
fakeFeatureFlag,
|
||||||
globalSettings,
|
globalSettings
|
||||||
) {
|
) {
|
||||||
override fun loadAnimator(
|
override fun loadAnimator(
|
||||||
animId: Int,
|
animId: Int,
|
||||||
@@ -292,12 +289,6 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(globalSettings)
|
|
||||||
.registerContentObserver(
|
|
||||||
eq(Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE)),
|
|
||||||
settingsObserverCaptor.capture()
|
|
||||||
)
|
|
||||||
|
|
||||||
initGutsViewHolderMocks()
|
initGutsViewHolderMocks()
|
||||||
initMediaViewHolderMocks()
|
initMediaViewHolderMocks()
|
||||||
|
|
||||||
@@ -986,7 +977,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
// When the setting changes,
|
// When the setting changes,
|
||||||
globalSettings.putFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 0f)
|
globalSettings.putFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 0f)
|
||||||
settingsObserverCaptor.value!!.onChange(false)
|
player.updateAnimatorDurationScale()
|
||||||
|
|
||||||
// Then the seekbar is set to not animate
|
// Then the seekbar is set to not animate
|
||||||
assertThat(seekBarObserver.animationEnabled).isFalse()
|
assertThat(seekBarObserver.animationEnabled).isFalse()
|
||||||
|
|||||||
Reference in New Issue
Block a user