Remove code duplications

Also prevent callback be called before SysMRP created

Test: pass MediaRouter cts
Change-Id: I0cde791fc73a33de5d42dcb6e550016644301ffd
This commit is contained in:
Sungsoo Lim
2020-02-12 11:00:06 +09:00
parent e8d6f95b29
commit ea1eaf74f3
2 changed files with 81 additions and 105 deletions

View File

@@ -166,6 +166,20 @@ class BluetoothRouteProvider {
}
}
@Nullable
MediaRoute2Info getSelectedRoute() {
return (mSelectedRoute == null) ? null : mSelectedRoute.route;
}
@NonNull
List<MediaRoute2Info> getTransferableRoutes() {
List<MediaRoute2Info> routes = getAllBluetoothRoutes();
if (mSelectedRoute != null) {
routes.remove(mSelectedRoute.route);
}
return routes;
}
@NonNull
List<MediaRoute2Info> getAllBluetoothRoutes() {
ArrayList<MediaRoute2Info> routes = new ArrayList<>();
@@ -175,9 +189,12 @@ class BluetoothRouteProvider {
return routes;
}
@Nullable
String getSelectedRouteId() {
return mSelectedRoute == null ? null : mSelectedRoute.route.getId();
boolean setSelectedRouteVolume(int volume) {
if (mSelectedRoute == null) return false;
mSelectedRoute.route = new MediaRoute2Info.Builder(mSelectedRoute.route)
.setVolume(volume)
.build();
return true;
}
private void notifyBluetoothRoutesUpdated() {

View File

@@ -19,7 +19,6 @@ package com.android.server.media;
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -42,15 +41,13 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* Provides routes for local playbacks such as phone speaker, wired headset, or Bluetooth speakers.
*/
// TODO: check thread safety. We may need to use lock to protect variables.
class SystemMediaRoute2Provider extends MediaRoute2Provider {
private static final String TAG = "MR2SystemProvider";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -68,19 +65,16 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
SystemMediaRoute2Provider.class.getPackageName$(),
SystemMediaRoute2Provider.class.getName());
@GuardedBy("mLock")
private String mSelectedRouteId;
MediaRoute2Info mDefaultRoute;
@NonNull List<MediaRoute2Info> mBluetoothRoutes = Collections.EMPTY_LIST;
final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
@Override
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
mHandler.post(new Runnable() {
@Override public void run() {
updateAudioRoutes(newRoutes);
}
mHandler.post(() -> {
updateDefaultRoute(newRoutes);
notifyProviderState();
});
}
};
@@ -97,11 +91,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
AudioRoutesInfo newAudioRoutes = null;
try {
newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
} catch (RemoteException e) {
}
updateDefaultRoute(newAudioRoutes);
initializeDefaultRoute();
mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> {
mBluetoothRoutes = routes;
publishRoutes();
publishProviderState();
boolean sessionInfoChanged;
synchronized (mLock) {
@@ -111,7 +109,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
notifySessionInfoUpdated();
}
});
initializeSessionInfo();
mHandler.post(() -> notifyProviderState());
//TODO: clean up this
// This is required because it is not instantiated in the main thread and
// BluetoothRoutesUpdatedListener can be called before here
synchronized (mLock) {
updateSessionInfosIfNeededLocked();
}
mContext.registerReceiver(new VolumeChangeReceiver(),
new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
@@ -164,65 +170,21 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
// Do nothing since we don't support grouping volume yet.
}
private void initializeDefaultRoute() {
mDefaultRoute = new MediaRoute2Info.Builder(
DEFAULT_ROUTE_ID,
mContext.getResources().getText(R.string.default_audio_route_name).toString())
.setVolumeHandling(mAudioManager.isVolumeFixed()
? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
.setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
.addFeature(FEATURE_LIVE_AUDIO)
.addFeature(FEATURE_LIVE_VIDEO)
.build();
AudioRoutesInfo newAudioRoutes = null;
try {
newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
} catch (RemoteException e) {
}
if (newAudioRoutes != null) {
// This will select the active BT route if there is one and the current
// selected route is the default system route, or if there is no selected
// route yet.
updateAudioRoutes(newAudioRoutes);
}
}
private void initializeSessionInfo() {
mBluetoothRoutes = mBtRouteProvider.getAllBluetoothRoutes();
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
builder.addRoute(mDefaultRoute);
for (MediaRoute2Info route : mBluetoothRoutes) {
builder.addRoute(route);
}
setProviderState(builder.build());
mHandler.post(() -> notifyProviderState());
//TODO: clean up this
// This is required because it is not instantiated in the main thread and
// BluetoothRoutesUpdatedListener can be called before this function
synchronized (mLock) {
updateSessionInfosIfNeededLocked();
}
}
private void updateAudioRoutes(AudioRoutesInfo newRoutes) {
private void updateDefaultRoute(AudioRoutesInfo newRoutes) {
int name = R.string.default_audio_route_name;
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0
|| (newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
name = com.android.internal.R.string.default_audio_route_name_headphones;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
name = com.android.internal.R.string.default_audio_route_name_hdmi;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
name = com.android.internal.R.string.default_audio_route_name_usb;
if (newRoutes != null) {
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0
|| (newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
name = com.android.internal.R.string.default_audio_route_name_headphones;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
name = com.android.internal.R.string.default_audio_route_name_hdmi;
} else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
name = com.android.internal.R.string.default_audio_route_name_usb;
}
}
mDefaultRoute = new MediaRoute2Info.Builder(
DEFAULT_ROUTE_ID, mContext.getResources().getText(name).toString())
.setVolumeHandling(mAudioManager.isVolumeFixed()
@@ -232,9 +194,20 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
.setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
.addFeature(FEATURE_LIVE_AUDIO)
.addFeature(FEATURE_LIVE_VIDEO)
.setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
.build();
updateProviderState();
}
publishRoutes();
private void updateProviderState() {
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
builder.addRoute(mDefaultRoute);
if (mBtRouteProvider != null) {
for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
builder.addRoute(route);
}
}
setProviderState(builder.build());
}
/**
@@ -246,21 +219,21 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
SYSTEM_SESSION_ID, "" /* clientPackageName */)
.setSystemSession(true);
String activeBtDeviceAddress = mBtRouteProvider.getSelectedRouteId();
mSelectedRouteId = TextUtils.isEmpty(activeBtDeviceAddress) ? mDefaultRoute.getId()
: activeBtDeviceAddress;
builder.addSelectedRoute(mSelectedRouteId);
if (!TextUtils.isEmpty(activeBtDeviceAddress)) {
MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute();
if (selectedRoute == null) {
selectedRoute = mDefaultRoute;
} else {
builder.addTransferableRoute(mDefaultRoute.getId());
}
mSelectedRouteId = selectedRoute.getId();
builder.addSelectedRoute(mSelectedRouteId);
for (MediaRoute2Info route : mBluetoothRoutes) {
if (!TextUtils.equals(mSelectedRouteId, route.getId())) {
builder.addTransferableRoute(route.getId());
}
for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
builder.addTransferableRoute(route.getId());
}
RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build();
if (Objects.equals(oldSessionInfo, newSessionInfo)) {
return false;
@@ -271,13 +244,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
}
}
void publishRoutes() {
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
builder.addRoute(mDefaultRoute);
for (MediaRoute2Info route : mBluetoothRoutes) {
builder.addRoute(route);
}
setAndNotifyProviderState(builder.build());
void publishProviderState() {
updateProviderState();
notifyProviderState();
}
void notifySessionInfoUpdated() {
@@ -306,24 +275,14 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
if (newVolume != oldVolume) {
String activeBtDeviceAddress = mBtRouteProvider.getSelectedRouteId();
if (!TextUtils.isEmpty(activeBtDeviceAddress)) {
for (int i = mBluetoothRoutes.size() - 1; i >= 0; i--) {
MediaRoute2Info route = mBluetoothRoutes.get(i);
if (TextUtils.equals(activeBtDeviceAddress, route.getId())) {
mBluetoothRoutes.set(i,
new MediaRoute2Info.Builder(route)
.setVolume(newVolume)
.build());
break;
}
}
} else {
if (TextUtils.equals(mDefaultRoute.getId(), mSelectedRouteId)) {
mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
.setVolume(newVolume)
.build();
} else {
mBtRouteProvider.setSelectedRouteVolume(newVolume);
}
publishRoutes();
publishProviderState();
}
}
}