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

Commit 1daaf097 authored by Anton Potapov's avatar Anton Potapov
Browse files

Prevent notifying Callbacks.onStateChanged twice when receiving...

Prevent notifying Callbacks.onStateChanged twice when receiving VOLUME_CHANGED_ACTION broadcast event

Flag: EXEMPT BUGFIX
Test: atest VolumeDialogControllerImplTestKt
Test: manual on foldable
Fixes: 365221635
Change-Id: I72cc5ec74b627a96a31e85267a583f8543d286a9
parent 70e721f9
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
        mVolumeController.setDeviceInteractive(false);
        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
                WakefulnessLifecycle.WAKEFULNESS_AWAKE);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI, true);
        verify(mCallback, never()).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED, false,
                LOCK_TASK_MODE_NONE);
    }
@@ -182,7 +182,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
        mVolumeController.setDeviceInteractive(true);
        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
                WakefulnessLifecycle.WAKEFULNESS_AWAKE);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI, true);
        verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED, false,
                LOCK_TASK_MODE_NONE);
    }
@@ -192,11 +192,11 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
        mVolumeController.setDeviceInteractive(true);
        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
                WakefulnessLifecycle.WAKEFULNESS_AWAKE);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI, true);
        mVolumeController.setDeviceInteractive(false);
        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
                WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI, true);
        verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED, false,
                LOCK_TASK_MODE_NONE);
    }
@@ -210,7 +210,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
                AudioManager.DEVICE_OUT_BLE_HEADSET);

        mVolumeController.onVolumeChangedW(
                AudioManager.STREAM_VOICE_CALL, AudioManager.FLAG_SHOW_UI);
                AudioManager.STREAM_VOICE_CALL, AudioManager.FLAG_SHOW_UI, true);

        verify(mCallback, times(1)).onStateChanged(any());
    }
@@ -224,7 +224,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
                AudioManager.DEVICE_OUT_BLUETOOTH_A2DP);

        mVolumeController.onVolumeChangedW(
                AudioManager.STREAM_VOICE_CALL, AudioManager.FLAG_SHOW_UI);
                AudioManager.STREAM_VOICE_CALL, AudioManager.FLAG_SHOW_UI, true);

        verify(mCallback, never()).onStateChanged(any());
    }
@@ -241,14 +241,16 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
                .thenReturn(AudioManager.DEVICE_NONE);

        mVolumeController.mInAudioSharing = true;
        mVolumeController.onVolumeChangedW(AudioManager.STREAM_MUSIC, AudioManager.FLAG_SHOW_UI);
        mVolumeController.onVolumeChangedW(
                AudioManager.STREAM_MUSIC, AudioManager.FLAG_SHOW_UI, true);
        verify(mCallback).onStateChanged(stateCaptor.capture());
        assertThat(stateCaptor.getValue().states.contains(AudioManager.STREAM_MUSIC)).isTrue();
        assertThat(stateCaptor.getValue().states.get(AudioManager.STREAM_MUSIC).routedToBluetooth)
                .isTrue();

        mVolumeController.mInAudioSharing = false;
        mVolumeController.onVolumeChangedW(AudioManager.STREAM_MUSIC, AudioManager.FLAG_SHOW_UI);
        mVolumeController.onVolumeChangedW(
                AudioManager.STREAM_MUSIC, AudioManager.FLAG_SHOW_UI, true);
        verify(mCallback, times(2)).onStateChanged(stateCaptor.capture());
        assertThat(stateCaptor.getValue().states.contains(AudioManager.STREAM_MUSIC)).isTrue();
        assertThat(stateCaptor.getValue().states.get(AudioManager.STREAM_MUSIC).routedToBluetooth)
+24 −1
Original line number Diff line number Diff line
@@ -18,12 +18,15 @@ package com.android.systemui.volume

import android.app.activityManager
import android.app.keyguardManager
import android.content.Intent
import android.content.applicationContext
import android.content.packageManager
import android.content.testableContext
import android.media.AudioManager
import android.media.IVolumeController
import android.os.Handler
import android.os.looper
import android.os.testableLooper
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
@@ -34,6 +37,8 @@ import androidx.test.filters.SmallTest
import com.android.settingslib.volume.data.model.VolumeControllerEvent
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.broadcast.broadcastDispatcherContext
import com.android.systemui.dump.dumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.wakefulnessLifecycle
@@ -81,10 +86,11 @@ class VolumeDialogControllerImplTestKt : SysuiTestCase() {
            audioRepository.init()
            threadFactory =
                FakeThreadFactory(FakeExecutor(fakeSystemClock)).apply { setLooper(looper) }
            broadcastDispatcherContext = testableContext
            underTest =
                VolumeDialogControllerImpl(
                        applicationContext,
                        mock {},
                        broadcastDispatcher,
                        mock {
                            on { ringerMode }.thenReturn(mock<RingerModeLiveData> {})
                            on { ringerModeInternal }.thenReturn(mock<RingerModeLiveData> {})
@@ -111,6 +117,23 @@ class VolumeDialogControllerImplTestKt : SysuiTestCase() {
                    }
        }

    @Test
    fun broadcastEvent_sendsChangesOnce() =
        with(kosmos) {
            testScope.runTest {
                whenever(audioManager.getLastAudibleStreamVolume(any())).thenReturn(1)
                broadcastDispatcher.sendIntentToMatchingReceiversOnly(
                    applicationContext,
                    Intent(AudioManager.ACTION_VOLUME_CHANGED).apply {
                        putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.STREAM_SYSTEM)
                    },
                )
                testableLooper.processAllMessages()

                verify(callbacks) { 1 * { onStateChanged(any()) } }
            }
        }

    @Test
    @EnableFlags(Flags.FLAG_USE_VOLUME_CONTROLLER)
    fun useVolumeControllerEnabled_listensToVolumeController() =
+5 −5
Original line number Diff line number Diff line
@@ -552,7 +552,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
                && mShowVolumeDialog;
    }

    boolean onVolumeChangedW(int stream, int flags) {
    boolean onVolumeChangedW(int stream, int flags, boolean sendChanges) {
        final boolean showUI = shouldShowUI(flags);
        final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
        final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
@@ -564,7 +564,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
        int lastAudibleStreamVolume = getAudioManagerStreamVolume(stream);
        changed |= updateStreamLevelW(stream, lastAudibleStreamVolume);
        changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream);
        if (changed) {
        if (changed && sendChanges) {
            mCallbacks.onStateChanged(mState);
        }
        if (showUI) {
@@ -950,7 +950,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case VOLUME_CHANGED: onVolumeChangedW(msg.arg1, msg.arg2); break;
                case VOLUME_CHANGED: onVolumeChangedW(msg.arg1, msg.arg2, true); break;
                case DISMISS_REQUESTED: onDismissRequestedW(msg.arg1); break;
                case GET_STATE: onGetStateW(); break;
                case SET_RINGER_MODE: onSetRingerModeW(msg.arg1, msg.arg2 != 0); break;
@@ -1307,7 +1307,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
                if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
                        + " oldLevel=" + oldLevel);
                if (stream != STREAM_UNKNOWN) {
                    changed |= onVolumeChangedW(stream, 0);
                    changed |= onVolumeChangedW(stream, 0, false);
                }
            } else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
@@ -1320,7 +1320,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
                        + stream + " devices=" + devices + " oldDevices=" + oldDevices);
                if (stream != STREAM_UNKNOWN) {
                    changed |= checkRoutedToBluetoothW(stream);
                    changed |= onVolumeChangedW(stream, 0);
                    changed |= onVolumeChangedW(stream, 0, false);
                }
            } else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+4 −3
Original line number Diff line number Diff line
@@ -21,11 +21,12 @@ import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testCase

val Kosmos.looper by Fixture {
    val testableLooper = TestableLooper.get(testCase)
    checkNotNull(testableLooper) {
val Kosmos.testableLooper: TestableLooper by Fixture {
    checkNotNull(TestableLooper.get(testCase)) {
        "TestableLooper is null, make sure the test class is annotated with RunWithLooper"
    }
}
val Kosmos.looper: Looper by Fixture {
    checkNotNull(testableLooper.looper) {
        "TestableLooper.getLooper() is returning null, make sure the test class is annotated " +
            "with RunWithLooper"
+4 −2
Original line number Diff line number Diff line
@@ -16,19 +16,21 @@

package com.android.systemui.broadcast

import com.android.systemui.SysuiTestableContext
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.util.mockito.mock

var Kosmos.broadcastDispatcherContext: SysuiTestableContext by Kosmos.Fixture { mock() }
val Kosmos.broadcastDispatcher by
    Kosmos.Fixture {
        FakeBroadcastDispatcher(
            context = mock(),
            context = broadcastDispatcherContext,
            mainExecutor = mock(),
            broadcastRunningLooper = mock(),
            broadcastRunningExecutor = mock(),
            dumpManager = mock(),
            logger = mock(),
            userTracker = mock(),
            shouldFailOnLeakedReceiver = false
            shouldFailOnLeakedReceiver = false,
        )
    }