Merge "Revert "MediaRouter: Add SystemMediaRoute2Provider to publish default route""
This commit is contained in:
committed by
Android (Google) Code Review
commit
c80c3cac7e
@@ -82,11 +82,6 @@ public class MediaRouterManagerTest {
|
||||
public static final String CATEGORY_SPECIAL =
|
||||
"com.android.mediarouteprovider.CATEGORY_SPECIAL";
|
||||
|
||||
// system routes
|
||||
private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
|
||||
private static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
|
||||
private static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
|
||||
|
||||
private static final int TIMEOUT_MS = 5000;
|
||||
|
||||
private Context mContext;
|
||||
@@ -95,17 +90,13 @@ public class MediaRouterManagerTest {
|
||||
private Executor mExecutor;
|
||||
private String mPackageName;
|
||||
|
||||
private static final List<String> CATEGORIES_ALL = new ArrayList();
|
||||
private static final List<String> CATEGORIES_SPECIAL = new ArrayList();
|
||||
private static final List<String> CATEGORIES_LIVE_AUDIO = new ArrayList<>();
|
||||
private static final List<String> CONTROL_CATEGORIES_ALL = new ArrayList();
|
||||
private static final List<String> CONTROL_CATEGORIES_SPECIAL = new ArrayList();
|
||||
static {
|
||||
CATEGORIES_ALL.add(CATEGORY_SAMPLE);
|
||||
CATEGORIES_ALL.add(CATEGORY_SPECIAL);
|
||||
CATEGORIES_ALL.add(CATEGORY_LIVE_AUDIO);
|
||||
CONTROL_CATEGORIES_ALL.add(CATEGORY_SAMPLE);
|
||||
CONTROL_CATEGORIES_ALL.add(CATEGORY_SPECIAL);
|
||||
|
||||
CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL);
|
||||
|
||||
CATEGORIES_LIVE_AUDIO.add(CATEGORY_LIVE_AUDIO);
|
||||
CONTROL_CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL);
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -162,7 +153,7 @@ public class MediaRouterManagerTest {
|
||||
mRouter2.registerCallback(mExecutor, routerCallback);
|
||||
|
||||
Map<String, MediaRoute2Info> routes =
|
||||
waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
MediaRouter2Manager.Callback callback = new MediaRouter2Manager.Callback() {
|
||||
@@ -196,7 +187,7 @@ public class MediaRouterManagerTest {
|
||||
mManager.registerCallback(mExecutor, mockCallback);
|
||||
|
||||
Map<String, MediaRoute2Info> routes =
|
||||
waitAndGetRoutesWithManager(CATEGORIES_SPECIAL);
|
||||
waitAndGetRoutesWithManager(CONTROL_CATEGORIES_SPECIAL);
|
||||
|
||||
Assert.assertEquals(1, routes.size());
|
||||
Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
|
||||
@@ -212,7 +203,7 @@ public class MediaRouterManagerTest {
|
||||
MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
|
||||
mRouter2.registerCallback(mExecutor, mockCallback);
|
||||
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_SPECIAL);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_SPECIAL);
|
||||
|
||||
Assert.assertEquals(1, routes.size());
|
||||
Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
|
||||
@@ -228,7 +219,7 @@ public class MediaRouterManagerTest {
|
||||
mManager.registerCallback(mExecutor, managerCallback);
|
||||
mRouter2.registerCallback(mExecutor, routerCallback);
|
||||
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
|
||||
|
||||
MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
|
||||
assertNotNull(routeToSelect);
|
||||
@@ -251,7 +242,7 @@ public class MediaRouterManagerTest {
|
||||
|
||||
mRouter2.registerCallback(mExecutor, routerCallback);
|
||||
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
|
||||
|
||||
awaitOnRouteChangedManager(
|
||||
() -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1)),
|
||||
@@ -273,7 +264,7 @@ public class MediaRouterManagerTest {
|
||||
|
||||
@Test
|
||||
public void testControlVolumeWithRouter() throws Exception {
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
|
||||
|
||||
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
|
||||
int originalVolume = volRoute.getVolume();
|
||||
@@ -295,7 +286,7 @@ public class MediaRouterManagerTest {
|
||||
MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
|
||||
|
||||
mRouter2.registerCallback(mExecutor, mockCallback);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
|
||||
|
||||
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
|
||||
int originalVolume = volRoute.getVolume();
|
||||
@@ -318,7 +309,7 @@ public class MediaRouterManagerTest {
|
||||
public void testVolumeHandling() throws Exception {
|
||||
MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
|
||||
mRouter2.registerCallback(mExecutor, mockCallback);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
|
||||
|
||||
MediaRoute2Info fixedVolumeRoute = routes.get(ROUTE_ID_FIXED_VOLUME);
|
||||
MediaRoute2Info variableVolumeRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
|
||||
@@ -330,13 +321,6 @@ public class MediaRouterManagerTest {
|
||||
mRouter2.unregisterCallback(mockCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultRoute() throws Exception {
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_LIVE_AUDIO);
|
||||
|
||||
assertNotNull(routes.get(DEFAULT_ROUTE_ID));
|
||||
}
|
||||
|
||||
Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> controlCategories) throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
MediaRouter2.Callback callback = new MediaRouter2.Callback() {
|
||||
@@ -433,7 +417,6 @@ public class MediaRouterManagerTest {
|
||||
static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
|
||||
Map<String, MediaRoute2Info> routeMap = new HashMap<>();
|
||||
for (MediaRoute2Info route : routes) {
|
||||
// intentionally not route.getUniqueId() for convenience.
|
||||
routeMap.put(route.getId(), route);
|
||||
}
|
||||
return routeMap;
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.media.MediaRoute2Info;
|
||||
import android.media.MediaRoute2ProviderInfo;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
abstract class MediaRoute2Provider {
|
||||
final ComponentName mComponentName;
|
||||
final String mUniqueId;
|
||||
|
||||
private Callback mCallback;
|
||||
private MediaRoute2ProviderInfo mProviderInfo;
|
||||
|
||||
MediaRoute2Provider(@NonNull ComponentName componentName) {
|
||||
mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
|
||||
mUniqueId = componentName.flattenToShortString();
|
||||
}
|
||||
|
||||
public void setCallback(MediaRoute2ProviderProxy.Callback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public abstract void requestSelectRoute(String packageName, String routeId, int seq);
|
||||
public abstract void unselectRoute(String packageName, String routeId);
|
||||
public abstract void sendControlRequest(MediaRoute2Info route, Intent request);
|
||||
public abstract void requestSetVolume(MediaRoute2Info route, int volume);
|
||||
public abstract void requestUpdateVolume(MediaRoute2Info route, int delta);
|
||||
|
||||
@NonNull
|
||||
public String getUniqueId() {
|
||||
return mUniqueId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MediaRoute2ProviderInfo getProviderInfo() {
|
||||
return mProviderInfo;
|
||||
}
|
||||
|
||||
void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) {
|
||||
//TODO: check if info is not updated
|
||||
if (info == null) {
|
||||
mProviderInfo = null;
|
||||
} else {
|
||||
mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
|
||||
.setUniqueId(mUniqueId)
|
||||
.build();
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onProviderStateChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasComponentName(String packageName, String className) {
|
||||
return mComponentName.getPackageName().equals(packageName)
|
||||
&& mComponentName.getClassName().equals(className);
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onProviderStateChanged(MediaRoute2Provider provider);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -41,14 +42,20 @@ import java.util.Objects;
|
||||
/**
|
||||
* Maintains a connection to a particular media route provider service.
|
||||
*/
|
||||
final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements ServiceConnection {
|
||||
final class MediaRoute2ProviderProxy implements ServiceConnection {
|
||||
private static final String TAG = "MR2ProviderProxy";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final Context mContext;
|
||||
private final ComponentName mComponentName;
|
||||
private final String mUniqueId;
|
||||
private final int mUserId;
|
||||
private final Handler mHandler;
|
||||
|
||||
private Callback mCallback;
|
||||
|
||||
private MediaRoute2ProviderInfo mProviderInfo;
|
||||
|
||||
// Connection state
|
||||
private boolean mRunning;
|
||||
private boolean mBound;
|
||||
@@ -57,8 +64,9 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
|
||||
MediaRoute2ProviderProxy(@NonNull Context context, @NonNull ComponentName componentName,
|
||||
int userId) {
|
||||
super(componentName);
|
||||
mContext = Objects.requireNonNull(context, "Context must not be null.");
|
||||
mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
|
||||
mUniqueId = componentName.flattenToShortString();
|
||||
mUserId = userId;
|
||||
mHandler = new Handler();
|
||||
}
|
||||
@@ -72,7 +80,10 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
pw.println(prefix + " mConnectionReady=" + mConnectionReady);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCallback(Callback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void requestSelectRoute(String packageName, String routeId, int seq) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.requestSelectRoute(packageName, routeId, seq);
|
||||
@@ -80,7 +91,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unselectRoute(String packageName, String routeId) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.unselectRoute(packageName, routeId);
|
||||
@@ -88,7 +98,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendControlRequest(MediaRoute2Info route, Intent request) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.sendControlRequest(route.getId(), request);
|
||||
@@ -96,7 +105,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestSetVolume(MediaRoute2Info route, int volume) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.requestSetVolume(route.getId(), volume);
|
||||
@@ -104,7 +112,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestUpdateVolume(MediaRoute2Info route, int delta) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.requestUpdateVolume(route.getId(), delta);
|
||||
@@ -112,6 +119,16 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getUniqueId() {
|
||||
return mUniqueId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MediaRoute2ProviderInfo getProviderInfo() {
|
||||
return mProviderInfo;
|
||||
}
|
||||
|
||||
public boolean hasComponentName(String packageName, String className) {
|
||||
return mComponentName.getPackageName().equals(packageName)
|
||||
&& mComponentName.getClassName().equals(className);
|
||||
@@ -253,6 +270,20 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
setAndNotifyProviderInfo(info);
|
||||
}
|
||||
|
||||
private void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) {
|
||||
//TODO: check if info is not updated
|
||||
if (info == null) {
|
||||
mProviderInfo = null;
|
||||
} else {
|
||||
mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
|
||||
.setUniqueId(mUniqueId)
|
||||
.build();
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
|
||||
}
|
||||
}
|
||||
|
||||
private void disconnect() {
|
||||
if (mActiveConnection != null) {
|
||||
mConnectionReady = false;
|
||||
@@ -267,6 +298,10 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
return "Service connection " + mComponentName.flattenToShortString();
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onProviderStateChanged(@NonNull MediaRoute2ProviderProxy provider);
|
||||
}
|
||||
|
||||
private final class Connection implements DeathRecipient {
|
||||
private final IMediaRoute2Provider mProvider;
|
||||
private final ProviderClient mClient;
|
||||
|
||||
@@ -728,15 +728,14 @@ class MediaRouter2ServiceImpl {
|
||||
|
||||
static final class UserHandler extends Handler implements
|
||||
MediaRoute2ProviderWatcher.Callback,
|
||||
MediaRoute2Provider.Callback {
|
||||
MediaRoute2ProviderProxy.Callback {
|
||||
|
||||
private final WeakReference<MediaRouter2ServiceImpl> mServiceRef;
|
||||
private final UserRecord mUserRecord;
|
||||
private final MediaRoute2ProviderWatcher mWatcher;
|
||||
|
||||
//TODO: Make this thread-safe.
|
||||
private final SystemMediaRoute2Provider mSystemProvider;
|
||||
private final ArrayList<MediaRoute2Provider> mMediaProviders =
|
||||
private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders =
|
||||
new ArrayList<>();
|
||||
private final List<MediaRoute2ProviderInfo> mProviderInfos = new ArrayList<>();
|
||||
|
||||
@@ -747,8 +746,6 @@ class MediaRouter2ServiceImpl {
|
||||
super(Looper.getMainLooper(), null, true);
|
||||
mServiceRef = new WeakReference<>(service);
|
||||
mUserRecord = userRecord;
|
||||
mSystemProvider = new SystemMediaRoute2Provider(service.mContext, this);
|
||||
mMediaProviders.add(mSystemProvider);
|
||||
mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this,
|
||||
this, mUserRecord.mUserId);
|
||||
}
|
||||
@@ -780,7 +777,7 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderStateChanged(@NonNull MediaRoute2Provider provider) {
|
||||
public void onProviderStateChanged(@NonNull MediaRoute2ProviderProxy provider) {
|
||||
sendMessage(PooledLambda.obtainMessage(UserHandler::updateProvider, this, provider));
|
||||
}
|
||||
|
||||
@@ -793,7 +790,7 @@ class MediaRouter2ServiceImpl {
|
||||
controlHints, seq));
|
||||
}
|
||||
|
||||
private void updateProvider(MediaRoute2Provider provider) {
|
||||
private void updateProvider(MediaRoute2ProviderProxy provider) {
|
||||
int providerIndex = getProviderInfoIndex(provider.getUniqueId());
|
||||
MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
|
||||
MediaRoute2ProviderInfo prevInfo =
|
||||
@@ -957,7 +954,7 @@ class MediaRouter2ServiceImpl {
|
||||
|
||||
private void requestSelectRoute(String clientPackageName, MediaRoute2Info route, int seq) {
|
||||
if (route != null) {
|
||||
MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Ignoring to select route of unknown provider " + route);
|
||||
} else {
|
||||
@@ -968,7 +965,7 @@ class MediaRouter2ServiceImpl {
|
||||
|
||||
private void unselectRoute(String clientPackageName, MediaRoute2Info route) {
|
||||
if (route != null) {
|
||||
MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Ignoring to unselect route of unknown provider " + route);
|
||||
} else {
|
||||
@@ -978,21 +975,21 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
|
||||
private void sendControlRequest(MediaRoute2Info route, Intent request) {
|
||||
final MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
|
||||
if (provider != null) {
|
||||
provider.sendControlRequest(route, request);
|
||||
}
|
||||
}
|
||||
|
||||
private void requestSetVolume(MediaRoute2Info route, int volume) {
|
||||
final MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
|
||||
if (provider != null) {
|
||||
provider.requestSetVolume(route, volume);
|
||||
}
|
||||
}
|
||||
|
||||
private void requestUpdateVolume(MediaRoute2Info route, int delta) {
|
||||
final MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
|
||||
if (provider != null) {
|
||||
provider.requestUpdateVolume(route, delta);
|
||||
}
|
||||
@@ -1156,8 +1153,8 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private MediaRoute2Provider findProvider(String providerId) {
|
||||
for (MediaRoute2Provider provider : mMediaProviders) {
|
||||
private MediaRoute2ProviderProxy findProvider(String providerId) {
|
||||
for (MediaRoute2ProviderProxy provider : mMediaProviders) {
|
||||
if (TextUtils.equals(provider.getUniqueId(), providerId)) {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioRoutesInfo;
|
||||
import android.media.IAudioRoutesObserver;
|
||||
import android.media.IAudioService;
|
||||
import android.media.MediaRoute2Info;
|
||||
import android.media.MediaRoute2ProviderInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* Provides routes for local playbacks such as phone speaker, wired headset, or Bluetooth speakers.
|
||||
*/
|
||||
class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
||||
private static final String TAG = "MR2SystemProvider";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
|
||||
private static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE";
|
||||
|
||||
// TODO: Move these to a proper place
|
||||
public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
|
||||
public static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
|
||||
|
||||
private final AudioManager mAudioManager;
|
||||
private final IAudioService mAudioService;
|
||||
private final Handler mHandler;
|
||||
private final Context mContext;
|
||||
|
||||
private static ComponentName sComponentName = new ComponentName(
|
||||
SystemMediaRoute2Provider.class.getPackageName$(),
|
||||
SystemMediaRoute2Provider.class.getName());
|
||||
|
||||
//TODO: Clean up these when audio manager support multiple bt devices
|
||||
MediaRoute2Info mDefaultRoute;
|
||||
MediaRoute2Info mBluetoothA2dpRoute;
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
SystemMediaRoute2Provider(Context context, Callback callback) {
|
||||
super(sComponentName);
|
||||
setCallback(callback);
|
||||
|
||||
mContext = context;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
mAudioService = IAudioService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.AUDIO_SERVICE));
|
||||
|
||||
initializeRoutes();
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void requestSelectRoute(@NonNull String packageName, @NonNull String routeId, int seq) {
|
||||
try {
|
||||
mAudioService.setBluetoothA2dpOn(
|
||||
!TextUtils.equals(routeId, mDefaultRoute.getId()));
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Error changing Bluetooth A2DP route");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void unselectRoute(@NonNull String packageName, @NonNull String routeId) {
|
||||
// does nothing..?
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void sendControlRequest(@NonNull MediaRoute2Info route, @NonNull Intent request) {
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void requestSetVolume(MediaRoute2Info route, int volume) {
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void requestUpdateVolume(MediaRoute2Info route, int delta) {
|
||||
}
|
||||
|
||||
void initializeRoutes() {
|
||||
//TODO: adds necessary info
|
||||
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))
|
||||
.addSupportedCategory(CATEGORY_LIVE_AUDIO)
|
||||
.addSupportedCategory(CATEGORY_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);
|
||||
}
|
||||
|
||||
publishRoutes();
|
||||
}
|
||||
|
||||
void updateAudioRoutes(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;
|
||||
}
|
||||
|
||||
mDefaultRoute = new MediaRoute2Info.Builder(
|
||||
DEFAULT_ROUTE_ID, mContext.getResources().getText(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))
|
||||
.addSupportedCategory(CATEGORY_LIVE_AUDIO)
|
||||
.addSupportedCategory(CATEGORY_LIVE_VIDEO)
|
||||
.build();
|
||||
|
||||
if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
|
||||
mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
|
||||
if (mCurAudioRoutesInfo.bluetoothName != null) {
|
||||
//TODO: mark as bluetooth once MediaRoute2Info has device type
|
||||
mBluetoothA2dpRoute = new MediaRoute2Info.Builder(BLUETOOTH_ROUTE_ID,
|
||||
mCurAudioRoutesInfo.bluetoothName.toString())
|
||||
.setDescription(mContext.getResources().getText(
|
||||
R.string.bluetooth_a2dp_audio_route_name).toString())
|
||||
.addSupportedCategory(CATEGORY_LIVE_AUDIO)
|
||||
.build();
|
||||
} else if (mBluetoothA2dpRoute != null) {
|
||||
mBluetoothA2dpRoute = null;
|
||||
}
|
||||
}
|
||||
|
||||
publishRoutes();
|
||||
}
|
||||
void publishRoutes() {
|
||||
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder()
|
||||
.addRoute(mDefaultRoute);
|
||||
if (mBluetoothA2dpRoute != null) {
|
||||
builder.addRoute(mBluetoothA2dpRoute);
|
||||
}
|
||||
setAndNotifyProviderInfo(builder.build());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user