• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import android.media.AudioRoutesInfo;
4 import android.media.MediaRouter;
5 import android.media.MediaRouter.RouteInfo;
6 import android.os.Parcel;
7 import android.text.TextUtils;
8 import javax.annotation.Nullable;
9 import org.robolectric.annotation.Implements;
10 import org.robolectric.annotation.RealObject;
11 import org.robolectric.annotation.Resetter;
12 import org.robolectric.util.ReflectionHelpers;
13 import org.robolectric.util.ReflectionHelpers.ClassParameter;
14 
15 /** Shadow class for {@link android.media.MediaRouter}. */
16 @Implements(MediaRouter.class)
17 public class ShadowMediaRouter {
18   public static final String BLUETOOTH_DEVICE_NAME = "TestBluetoothDevice";
19 
20   private @RealObject MediaRouter realObject;
21 
22   /**
23    * Adds the Bluetooth A2DP route and ensures it's the selected route, simulating connecting a
24    * Bluetooth device.
25    */
addBluetoothRoute()26   public void addBluetoothRoute() {
27     updateBluetoothAudioRoute(BLUETOOTH_DEVICE_NAME);
28 
29     realObject.selectRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO, getBluetoothA2dpRoute());
30   }
31 
32   /** Removes the Bluetooth A2DP route, simulating disconnecting the Bluetooth device. */
removeBluetoothRoute()33   public void removeBluetoothRoute() {
34     // Android's AudioService passes a null Bluetooth device name to MediaRouter to signal that the
35     // A2DP route should be removed.
36     updateBluetoothAudioRoute(null);
37   }
38 
39   /** Returns whether the Bluetooth A2DP route is the currently selected route. */
isBluetoothRouteSelected(int type)40   public boolean isBluetoothRouteSelected(int type) {
41     return realObject.getSelectedRoute(type).equals(getBluetoothA2dpRoute());
42   }
43 
getBluetoothA2dpRoute()44   private static RouteInfo getBluetoothA2dpRoute() {
45     return ReflectionHelpers.getField(
46         ReflectionHelpers.getStaticField(MediaRouter.class, "sStatic"), "mBluetoothA2dpRoute");
47   }
48 
49   /**
50    * Updates the MediaRouter's Bluetooth audio route.
51    *
52    * @param bluetoothDeviceName the name of the Bluetooth device or null to indicate that the
53    *     already-existing Bluetooth A2DP device should be removed
54    */
updateBluetoothAudioRoute(@ullable String bluetoothDeviceName)55   private void updateBluetoothAudioRoute(@Nullable String bluetoothDeviceName) {
56     callUpdateAudioRoutes(newAudioRouteInfo(bluetoothDeviceName));
57   }
58 
59   /**
60    * Creates a new {@link AudioRoutesInfo} to be used for updating the Bluetooth audio route.
61    *
62    * @param bluetoothDeviceName the name of the Bluetooth device or null to indicate that the
63    *     already-existing Bluetooth A2DP device should be removed
64    */
newAudioRouteInfo(@ullable String bluetoothDeviceName)65   private static AudioRoutesInfo newAudioRouteInfo(@Nullable String bluetoothDeviceName) {
66     Parcel p = Parcel.obtain();
67     TextUtils.writeToParcel(bluetoothDeviceName, p, /* parcelableFlags= */ 0);
68     p.setDataPosition(0);
69     return AudioRoutesInfo.CREATOR.createFromParcel(p);
70   }
71 
callUpdateAudioRoutes(AudioRoutesInfo routesInfo)72   private void callUpdateAudioRoutes(AudioRoutesInfo routesInfo) {
73     ReflectionHelpers.callInstanceMethod(
74         ReflectionHelpers.getStaticField(MediaRouter.class, "sStatic"),
75         "updateAudioRoutes",
76         ClassParameter.from(AudioRoutesInfo.class, routesInfo));
77   }
78 
79   @Resetter
reset()80   public static void reset() {
81     ReflectionHelpers.setStaticField(MediaRouter.class, "sStatic", null);
82   }
83 }
84