Merge "Broadcast device audio connection intents"

This commit is contained in:
Iavor-Valentin Iftime
2021-01-22 15:54:57 +00:00
committed by Android (Google) Code Review
5 changed files with 105 additions and 8 deletions

View File

@@ -154,6 +154,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
mPreferredDeviceforComm = null;
initCommunicationStrategyId();
mSystemServer.registerUserStartedReceiver(mContext);
}
/*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) {
if (mBrokerHandler != null) {
pw.println(prefix + "Message handler (watch for unhandled messages):");

View File

@@ -16,7 +16,6 @@
package com.android.server.audio;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -37,7 +36,6 @@ import android.media.MediaMetrics;
import android.os.Binder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -1270,7 +1268,7 @@ public class AudioDeviceInventory {
final long ident = Binder.clearCallingIdentity();
try {
ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_CURRENT);
mDeviceBroker.broadcastStickyIntentToCurrentProfileGroup(intent);
} finally {
Binder.restoreCallingIdentity(ident);
}

View File

@@ -5591,7 +5591,9 @@ public class AudioService extends IAudioService.Stub
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);
}
@@ -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)) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,

View File

@@ -18,11 +18,20 @@ package com.android.server.audio;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.os.Binder;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import java.util.Objects;
@@ -82,4 +91,58 @@ public class SystemServerAdapter {
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);
}
}
}

View File

@@ -17,6 +17,7 @@ package com.android.server.audio;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -27,6 +28,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.util.Log;
@@ -58,7 +60,7 @@ public class AudioDeviceBrokerTest {
@Mock private AudioService mMockAudioService;
@Spy private AudioDeviceInventory mSpyDevInventory;
@Spy private AudioSystemAdapter mSpyAudioSystem;
private SystemServerAdapter mSystemServer;
@Spy private SystemServerAdapter mSpySystemServer;
private BluetoothDevice mFakeBtDevice;
@@ -69,9 +71,9 @@ public class AudioDeviceBrokerTest {
mMockAudioService = mock(AudioService.class);
mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem));
mSystemServer = new NoOpSystemServerAdapter();
mSpySystemServer = spy(new NoOpSystemServerAdapter());
mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory,
mSystemServer);
mSpySystemServer);
mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker);
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -172,6 +174,30 @@ public class AudioDeviceBrokerTest {
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,
boolean mockMediaPlayback, boolean guaranteeSingleConnection) throws Exception {
when(mMockAudioService.getDeviceForStream(AudioManager.STREAM_MUSIC))