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

Commit 2f0a41a1 authored by Jernej Virag's avatar Jernej Virag Committed by Android (Google) Code Review
Browse files

Merge "Fix memory leak of MediaControlPanel" into udc-dev

parents 09917cd2 d560fba3
Loading
Loading
Loading
Loading
+17 −0
Original line number Original line Diff line number Diff line
@@ -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() {
+4 −13
Original line number Original line Diff line number Diff line
@@ -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);
+20 −0
Original line number Original line Diff line number Diff line
@@ -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.
     *
     *
+2 −11
Original line number Original line Diff line number Diff line
@@ -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()