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

Commit 2d7764b1 authored by Iavor-Valentin Iftime's avatar Iavor-Valentin Iftime Committed by Android (Google) Code Review
Browse files

Merge "Broadcast device audio connection intents"

parents a2aced51 1913ebd9
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -154,6 +154,8 @@ import java.util.concurrent.atomic.AtomicBoolean;


        mPreferredDeviceforComm = null;
        mPreferredDeviceforComm = null;
        initCommunicationStrategyId();
        initCommunicationStrategyId();

        mSystemServer.registerUserStartedReceiver(mContext);
    }
    }


    /*package*/ Context getContext() {
    /*package*/ Context getContext() {
@@ -993,6 +995,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
        }
        }
    }
    }


    /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
        mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent);
    }

    /*package*/ void dump(PrintWriter pw, String prefix) {
    /*package*/ void dump(PrintWriter pw, String prefix) {
        if (mBrokerHandler != null) {
        if (mBrokerHandler != null) {
            pw.println(prefix + "Message handler (watch for unhandled messages):");
            pw.println(prefix + "Message handler (watch for unhandled messages):");
+1 −3
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.server.audio;
package com.android.server.audio;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
@@ -37,7 +36,6 @@ import android.media.MediaMetrics;
import android.os.Binder;
import android.os.Binder;
import android.os.RemoteCallbackList;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -1270,7 +1268,7 @@ public class AudioDeviceInventory {


        final long ident = Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        try {
        try {
            ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_CURRENT);
            mDeviceBroker.broadcastStickyIntentToCurrentProfileGroup(intent);
        } finally {
        } finally {
            Binder.restoreCallingIdentity(ident);
            Binder.restoreCallingIdentity(ident);
        }
        }
+6 −2
Original line number Original line Diff line number Diff line
@@ -5591,7 +5591,9 @@ public class AudioService extends IAudioService.Stub
                profile, suppressNoisyIntent, a2dpVolume);
                profile, suppressNoisyIntent, a2dpVolume);
    }
    }


    /*package*/ void setMusicMute(boolean mute) {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void setMusicMute(boolean mute) {
        mStreamStates[AudioSystem.STREAM_MUSIC].muteInternally(mute);
        mStreamStates[AudioSystem.STREAM_MUSIC].muteInternally(mute);
    }
    }


@@ -7071,7 +7073,9 @@ public class AudioService extends IAudioService.Stub
        }
        }
    }
    }


    /*package*/ void checkMusicActive(int deviceType, String caller) {
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void checkMusicActive(int deviceType, String caller) {
        if (mSafeMediaVolumeDevices.contains(deviceType)) {
        if (mSafeMediaVolumeDevices.contains(deviceType)) {
            sendMsg(mAudioHandler,
            sendMsg(mAudioHandler,
                    MSG_CHECK_MUSIC_ACTIVE,
                    MSG_CHECK_MUSIC_ACTIVE,
+63 −0
Original line number Original line Diff line number Diff line
@@ -18,11 +18,20 @@ package com.android.server.audio;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Binder;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;


import java.util.Objects;
import java.util.Objects;


@@ -82,4 +91,58 @@ public class SystemServerAdapter {
            Binder.restoreCallingIdentity(ident);
            Binder.restoreCallingIdentity(ident);
        }
        }
    }
    }

    /**
     * Send sticky broadcast to current user's profile group (including current user)
     */
    @VisibleForTesting
    public void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
        int[] profileIds = LocalServices.getService(
                ActivityManagerInternal.class).getCurrentProfileIds();
        for (int userId : profileIds) {
            ActivityManager.broadcastStickyIntent(intent, userId);
        }
    }

    /**
     * Broadcast sticky intents when a profile is started. This is needed because newly created
     * profiles would not receive the intents until the next state change.
     */
    /*package*/ void registerUserStartedReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_STARTED);
        context.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                            UserHandle.USER_NULL);
                    if (userId == UserHandle.USER_NULL) {
                        return;
                    }

                    UserManager userManager = context.getSystemService(UserManager.class);
                    final UserInfo profileParent = userManager.getProfileParent(userId);
                    if (profileParent == null) {
                        return;
                    }

                    // get sticky intents from parent and broadcast them to the started profile
                    broadcastProfileParentStickyIntent(context, AudioManager.ACTION_HDMI_AUDIO_PLUG,
                            userId, profileParent.id);
                    broadcastProfileParentStickyIntent(context, AudioManager.ACTION_HEADSET_PLUG,
                            userId, profileParent.id);
                }
            }
        }, UserHandle.ALL, filter, null, null);
    }

    private void broadcastProfileParentStickyIntent(Context context, String intentAction,
            int profileId, int parentId) {
        Intent intent = context.registerReceiverAsUser(/*receiver*/ null, UserHandle.of(parentId),
                new IntentFilter(intentAction), /*broadcastPermission*/ null, /*scheduler*/ null);
        if (intent != null) {
            ActivityManager.broadcastStickyIntent(intent, profileId);
        }
    }
}
}
+29 −3
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.server.audio;


import static org.mockito.Mockito.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
@@ -27,6 +28,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.AudioSystem;
import android.util.Log;
import android.util.Log;
@@ -58,7 +60,7 @@ public class AudioDeviceBrokerTest {
    @Mock private AudioService mMockAudioService;
    @Mock private AudioService mMockAudioService;
    @Spy private AudioDeviceInventory mSpyDevInventory;
    @Spy private AudioDeviceInventory mSpyDevInventory;
    @Spy private AudioSystemAdapter mSpyAudioSystem;
    @Spy private AudioSystemAdapter mSpyAudioSystem;
    private SystemServerAdapter mSystemServer;
    @Spy private SystemServerAdapter mSpySystemServer;


    private BluetoothDevice mFakeBtDevice;
    private BluetoothDevice mFakeBtDevice;


@@ -69,9 +71,9 @@ public class AudioDeviceBrokerTest {
        mMockAudioService = mock(AudioService.class);
        mMockAudioService = mock(AudioService.class);
        mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
        mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
        mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem));
        mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem));
        mSystemServer = new NoOpSystemServerAdapter();
        mSpySystemServer = spy(new NoOpSystemServerAdapter());
        mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory,
        mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory,
                mSystemServer);
                mSpySystemServer);
        mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker);
        mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker);


        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -172,6 +174,30 @@ public class AudioDeviceBrokerTest {
                true);
                true);
    }
    }


    /**
     * Test that device wired state intents are broadcasted on connection state change
     * @throws Exception
     */
    @Test
    public void testSetWiredDeviceConnectionState() throws Exception {
        Log.i(TAG, "starting postSetWiredDeviceConnectionState");

        final String address = "testAddress";
        final String name = "testName";
        final String caller = "testCaller";

        doNothing().when(mSpySystemServer).broadcastStickyIntentToCurrentProfileGroup(
                any(Intent.class));

        mSpyDevInventory.setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
                AudioService.CONNECTION_STATE_CONNECTED, address, name, caller);
        Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);

        // Verify that the sticky intent is broadcasted
        verify(mSpySystemServer, times(1)).broadcastStickyIntentToCurrentProfileGroup(
                any(Intent.class));
    }

    private void doTestConnectionDisconnectionReconnection(int delayAfterDisconnection,
    private void doTestConnectionDisconnectionReconnection(int delayAfterDisconnection,
            boolean mockMediaPlayback, boolean guaranteeSingleConnection) throws Exception {
            boolean mockMediaPlayback, boolean guaranteeSingleConnection) throws Exception {
        when(mMockAudioService.getDeviceForStream(AudioManager.STREAM_MUSIC))
        when(mMockAudioService.getDeviceForStream(AudioManager.STREAM_MUSIC))