Merge "MediaRouter2: Remove sendControlRequest"
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 47ffd3e..5566e0e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1643,8 +1643,9 @@
}
private void updateScreenMatrixForEmbeddedHierarchy() {
+ getBoundsOnScreen(mTmpRect, true);
mTmpMatrix.reset();
- mTmpMatrix.setTranslate(mScreenRect.left, mScreenRect.top);
+ mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top);
mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth,
mScreenRect.height() / (float) mSurfaceHeight);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 9837e1c..12fc3a6 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -64,7 +64,12 @@
*
* <p>The media router API is not thread-safe; all interactions with it must be
* done from the main thread of the process.</p>
+ *
+ * <p>
+ * We recommend using {@link android.media.MediaRouter2} APIs for new applications.
+ * </p>
*/
+//TODO: Link androidx.media2.MediaRouter when we are ready.
@SystemService(Context.MEDIA_ROUTER_SERVICE)
public class MediaRouter {
private static final String TAG = "MediaRouter";
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 4db1109..bd00201 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -34,6 +34,7 @@
import android.media.tv.tuner.filter.Filter.Type;
import android.media.tv.tuner.filter.FilterCallback;
import android.media.tv.tuner.filter.TimeFilter;
+import android.media.tv.tuner.frontend.Atsc3PlpInfo;
import android.media.tv.tuner.frontend.FrontendInfo;
import android.media.tv.tuner.frontend.FrontendSettings;
import android.media.tv.tuner.frontend.FrontendStatus;
@@ -511,6 +512,90 @@
}
}
+ private void onLocked() {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onLocked());
+ }
+ }
+
+ private void onScanStopped() {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onScanStopped());
+ }
+ }
+
+ private void onProgress(int percent) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onProgress(percent));
+ }
+ }
+
+ private void onFrequenciesReport(int[] frequency) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onFrequenciesReport(frequency));
+ }
+ }
+
+ private void onSymbolRates(int[] rate) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onSymbolRates(rate));
+ }
+ }
+
+ private void onHierarchy(int hierarchy) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onHierarchy(hierarchy));
+ }
+ }
+
+ private void onSignalType(int signalType) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onSignalType(signalType));
+ }
+ }
+
+ private void onPlpIds(int[] plpIds) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onPlpIds(plpIds));
+ }
+ }
+
+ private void onGroupIds(int[] groupIds) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onGroupIds(groupIds));
+ }
+ }
+
+ private void onInputStreamIds(int[] inputStreamIds) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onInputStreamIds(inputStreamIds));
+ }
+ }
+
+ private void onDvbsStandard(int dvbsStandandard) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onDvbsStandard(dvbsStandandard));
+ }
+ }
+
+ private void onDvbtStandard(int dvbtStandard) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onDvbtStandard(dvbtStandard));
+ }
+ }
+
+ private void onAnalogSifStandard(int sif) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onAnalogSifStandard(sif));
+ }
+ }
+
+ private void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> mScanCallback.onAtsc3PlpInfos(atsc3PlpInfos));
+ }
+ }
+
/**
* Opens a filter object based on the given types and buffer size.
*
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index ac59003..f4d2d03 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -108,6 +108,7 @@
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_0::ITuner;
using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
@@ -249,14 +250,152 @@
(jint)frontendEventType);
return Void();
}
-Return<void> FrontendCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
- ALOGD("FrontendCallback::onDiseqcMessage");
- return Void();
-}
-Return<void> FrontendCallback::onScanMessage(
- FrontendScanMessageType type, const FrontendScanMessage& /*message*/) {
+Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message) {
ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+ switch(type) {
+ case FrontendScanMessageType::LOCKED: {
+ if (message.isLocked()) {
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onLocked", "()V"));
+ }
+ break;
+ }
+ case FrontendScanMessageType::END: {
+ if (message.isEnd()) {
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onScanStopped", "()V"));
+ }
+ break;
+ }
+ case FrontendScanMessageType::PROGRESS_PERCENT: {
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onProgress", "(I)V"),
+ (jint) message.progressPercent());
+ break;
+ }
+ case FrontendScanMessageType::FREQUENCY: {
+ std::vector<uint32_t> v = message.frequencies();
+ jintArray freqs = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
+ freqs);
+ break;
+ }
+ case FrontendScanMessageType::SYMBOL_RATE: {
+ std::vector<uint32_t> v = message.symbolRates();
+ jintArray symbolRates = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
+ symbolRates);
+ break;
+ }
+ case FrontendScanMessageType::HIERARCHY: {
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onHierarchy", "(I)V"),
+ (jint) message.hierarchy());
+ break;
+ }
+ case FrontendScanMessageType::ANALOG_TYPE: {
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onSignalType", "(I)V"),
+ (jint) message.analogType());
+ break;
+ }
+ case FrontendScanMessageType::PLP_IDS: {
+ std::vector<uint8_t> v = message.plpIds();
+ std::vector<jint> jintV(v.begin(), v.end());
+ jintArray plpIds = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
+
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onPlpIds", "([I)V"),
+ plpIds);
+ break;
+ }
+ case FrontendScanMessageType::GROUP_IDS: {
+ std::vector<uint8_t> v = message.groupIds();
+ std::vector<jint> jintV(v.begin(), v.end());
+ jintArray groupIds = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
+
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onGroupIds", "([I)V"),
+ groupIds);
+ break;
+ }
+ case FrontendScanMessageType::INPUT_STREAM_IDS: {
+ std::vector<uint16_t> v = message.inputStreamIds();
+ std::vector<jint> jintV(v.begin(), v.end());
+ jintArray streamIds = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
+
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
+ streamIds);
+ break;
+ }
+ case FrontendScanMessageType::STANDARD: {
+ FrontendScanMessage::Standard std = message.std();
+ jint standard;
+ if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
+ standard = (jint) std.sStd();
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
+ standard);
+ } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) {
+ standard = (jint) std.tStd();
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
+ standard);
+ } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
+ standard = (jint) std.sifStd();
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
+ standard);
+ }
+ break;
+ }
+ case FrontendScanMessageType::ATSC3_PLP_INFO: {
+ jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpInfo");
+ jmethodID init = env->GetMethodID(plpClazz, "<init>", "(IZ)V");
+ std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos();
+ jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
+
+ for (int i = 0; i < plpInfos.size(); i++) {
+ auto info = plpInfos[i];
+ jint plpId = (jint) info.plpId;
+ jboolean lls = (jboolean) info.bLlsFlag;
+
+ jobject obj = env->NewObject(plpClazz, init, plpId, lls);
+ env->SetObjectArrayElement(array, i, obj);
+ }
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onAtsc3PlpInfos", "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
+ array);
+ break;
+ }
+ }
return Void();
}
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index cfe99b3..d899bbd 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -109,7 +109,6 @@
FrontendCallback(jweak tunerObj, FrontendId id);
virtual Return<void> onEvent(FrontendEventType frontendEventType);
- virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
virtual Return<void> onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message);
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 8e4a982..5ff88ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -33,6 +33,7 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -83,10 +84,179 @@
* Get current device that played media.
* @return MediaDevice
*/
- public MediaDevice getCurrentConnectedDevice() {
+ MediaDevice getCurrentConnectedDevice() {
return mCurrentConnectedDevice;
}
+ /**
+ * Transfer MediaDevice for media without package name.
+ */
+ boolean connectDeviceWithoutPackageName(MediaDevice device) {
+ boolean isConnected = false;
+ final List<RoutingSessionInfo> infos = mRouterManager.getActiveSessions();
+ if (infos.size() > 0) {
+ final RoutingSessionInfo info = infos.get(0);
+ final MediaRouter2Manager.RoutingController controller =
+ mRouterManager.getControllerForSession(info);
+
+ controller.transferToRoute(device.mRouteInfo);
+ isConnected = true;
+ }
+ return isConnected;
+ }
+
+ /**
+ * Add a MediaDevice to let it play current media.
+ *
+ * @param device MediaDevice
+ * @return If add device successful return {@code true}, otherwise return {@code false}
+ */
+ boolean addDeviceToPlayMedia(MediaDevice device) {
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.w(TAG, "addDeviceToPlayMedia() package name is null or empty!");
+ return false;
+ }
+
+ final RoutingSessionInfo info = getRoutingSessionInfo();
+ if (info != null && info.getSelectableRoutes().contains(device.mRouteInfo.getId())) {
+ mRouterManager.getControllerForSession(info).selectRoute(device.mRouteInfo);
+ return true;
+ }
+
+ Log.w(TAG, "addDeviceToPlayMedia() Ignoring selecting a non-selectable device : "
+ + device.getName());
+
+ return false;
+ }
+
+ private RoutingSessionInfo getRoutingSessionInfo() {
+ for (RoutingSessionInfo info : mRouterManager.getRoutingSessions(mPackageName)) {
+ if (TextUtils.equals(info.getClientPackageName(), mPackageName)) {
+ return info;
+ }
+ }
+
+ Log.w(TAG, "RoutingSessionInfo() cannot found match packagename : " + mPackageName);
+ return null;
+ }
+
+ /**
+ * Remove a {@code device} from current media.
+ *
+ * @param device MediaDevice
+ * @return If device stop successful return {@code true}, otherwise return {@code false}
+ */
+ boolean removeDeviceFromPlayMedia(MediaDevice device) {
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.w(TAG, "removeDeviceFromMedia() package name is null or empty!");
+ return false;
+ }
+
+ final RoutingSessionInfo info = getRoutingSessionInfo();
+ if (info != null && info.getSelectedRoutes().contains(device.mRouteInfo.getId())) {
+ mRouterManager.getControllerForSession(info).deselectRoute(device.mRouteInfo);
+ return true;
+ }
+
+ Log.w(TAG, "removeDeviceFromMedia() Ignoring deselecting a non-deselectable device : "
+ + device.getName());
+
+ return false;
+ }
+
+ /**
+ * Get the MediaDevice list that can be added to current media.
+ *
+ * @return list of MediaDevice
+ */
+ List<MediaDevice> getSelectableMediaDevice() {
+ final List<MediaDevice> deviceList = new ArrayList<>();
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.w(TAG, "getSelectableMediaDevice() package name is null or empty!");
+ return deviceList;
+ }
+
+ final RoutingSessionInfo info = getRoutingSessionInfo();
+ if (info != null) {
+ for (MediaRoute2Info route : mRouterManager.getControllerForSession(info)
+ .getSelectableRoutes()) {
+ deviceList.add(new InfoMediaDevice(mContext, mRouterManager,
+ route, mPackageName));
+ }
+ return deviceList;
+ }
+
+ Log.w(TAG, "getSelectableMediaDevice() cannot found selectable MediaDevice from : "
+ + mPackageName);
+
+ return deviceList;
+ }
+
+ /**
+ * Adjust the volume of {@link android.media.RoutingSessionInfo}.
+ *
+ * @param volume the value of volume
+ */
+ void adjustSessionVolume(int volume) {
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.w(TAG, "adjustSessionVolume() package name is null or empty!");
+ return;
+ }
+
+ final RoutingSessionInfo info = getRoutingSessionInfo();
+ if (info != null) {
+ Log.d(TAG, "adjustSessionVolume() adjust volume : " + volume + ", with : "
+ + mPackageName);
+ mRouterManager.setSessionVolume(info, volume);
+ return;
+ }
+
+ Log.w(TAG, "adjustSessionVolume() can't found corresponding RoutingSession with : "
+ + mPackageName);
+ }
+
+ /**
+ * Gets the maximum volume of the {@link android.media.RoutingSessionInfo}.
+ *
+ * @return maximum volume of the session, and return -1 if not found.
+ */
+ public int getSessionVolumeMax() {
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.w(TAG, "getSessionVolumeMax() package name is null or empty!");
+ return -1;
+ }
+
+ final RoutingSessionInfo info = getRoutingSessionInfo();
+ if (info != null) {
+ return info.getVolumeMax();
+ }
+
+ Log.w(TAG, "getSessionVolumeMax() can't found corresponding RoutingSession with : "
+ + mPackageName);
+ return -1;
+ }
+
+ /**
+ * Gets the current volume of the {@link android.media.RoutingSessionInfo}.
+ *
+ * @return current volume of the session, and return -1 if not found.
+ */
+ public int getSessionVolume() {
+ if (TextUtils.isEmpty(mPackageName)) {
+ Log.w(TAG, "getSessionVolume() package name is null or empty!");
+ return -1;
+ }
+
+ final RoutingSessionInfo info = getRoutingSessionInfo();
+ if (info != null) {
+ return info.getVolume();
+ }
+
+ Log.w(TAG, "getSessionVolume() can't found corresponding RoutingSession with : "
+ + mPackageName);
+ return -1;
+ }
+
private void refreshDevices() {
mMediaDevices.clear();
mCurrentConnectedDevice = null;
@@ -150,23 +320,6 @@
}
}
- /**
- * Transfer MediaDevice for media without package name.
- */
- public boolean connectDeviceWithoutPackageName(MediaDevice device) {
- boolean isConnected = false;
- final List<RoutingSessionInfo> infos = mRouterManager.getActiveSessions();
- if (infos.size() > 0) {
- final RoutingSessionInfo info = infos.get(0);
- final MediaRouter2Manager.RoutingController controller =
- mRouterManager.getControllerForSession(info);
-
- controller.transferToRoute(device.mRouteInfo);
- isConnected = true;
- }
- return isConnected;
- }
-
class RouterManagerCallback extends MediaRouter2Manager.Callback {
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index f8db70a..fc373a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -252,6 +252,62 @@
return devices;
}
+ /**
+ * Add a MediaDevice to let it play current media.
+ *
+ * @param device MediaDevice
+ * @return If add device successful return {@code true}, otherwise return {@code false}
+ */
+ public boolean addDeviceToPlayMedia(MediaDevice device) {
+ return mInfoMediaManager.addDeviceToPlayMedia(device);
+ }
+
+ /**
+ * Remove a {@code device} from current media.
+ *
+ * @param device MediaDevice
+ * @return If device stop successful return {@code true}, otherwise return {@code false}
+ */
+ public boolean removeDeviceFromPlayMedia(MediaDevice device) {
+ return mInfoMediaManager.removeDeviceFromPlayMedia(device);
+ }
+
+ /**
+ * Get the MediaDevice list that can be added to current media.
+ *
+ * @return list of MediaDevice
+ */
+ public List<MediaDevice> getSelectableMediaDevice() {
+ return mInfoMediaManager.getSelectableMediaDevice();
+ }
+
+ /**
+ * Adjust the volume of session.
+ *
+ * @param volume the value of volume
+ */
+ public void adjustSessionVolume(int volume) {
+ mInfoMediaManager.adjustSessionVolume(volume);
+ }
+
+ /**
+ * Gets the maximum volume of the {@link android.media.RoutingSessionInfo}.
+ *
+ * @return maximum volume of the session, and return -1 if not found.
+ */
+ public int getSessionVolumeMax() {
+ return mInfoMediaManager.getSessionVolumeMax();
+ }
+
+ /**
+ * Gets the current volume of the {@link android.media.RoutingSessionInfo}.
+ *
+ * @return current volume of the session, and return -1 if not found.
+ */
+ public int getSessionVolume() {
+ return mInfoMediaManager.getSessionVolume();
+ }
+
private MediaDevice updateCurrentConnectedDevice() {
MediaDevice phoneMediaDevice = null;
for (MediaDevice device : mMediaDevices) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index 8b815bf..9668629 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -28,6 +28,7 @@
import android.media.RoutingSessionInfo;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.testutils.shadow.ShadowRouter2Manager;
import org.junit.Before;
import org.junit.Test;
@@ -36,15 +37,18 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowRouter2Manager.class})
public class InfoMediaManagerTest {
private static final String TEST_PACKAGE_NAME = "com.test.packagename";
private static final String TEST_ID = "test_id";
+ private static final String TEST_NAME = "test_name";
@Mock
private MediaRouter2Manager mRouterManager;
@@ -53,6 +57,7 @@
private InfoMediaManager mInfoMediaManager;
private Context mContext;
+ private ShadowRouter2Manager mShadowRouter2Manager;
@Before
public void setUp() {
@@ -61,22 +66,8 @@
mInfoMediaManager =
new InfoMediaManager(mContext, TEST_PACKAGE_NAME, null, mLocalBluetoothManager);
- mInfoMediaManager.mRouterManager = mRouterManager;
- }
-
- @Test
- public void stopScan_shouldRemoveCallback() {
- mInfoMediaManager.stopScan();
-
- verify(mRouterManager).unregisterCallback(mInfoMediaManager.mMediaRouterCallback);
- }
-
- @Test
- public void startScan_shouldAddCallback() {
- mInfoMediaManager.startScan();
-
- verify(mRouterManager).registerCallback(mInfoMediaManager.mExecutor,
- mInfoMediaManager.mMediaRouterCallback);
+ mShadowRouter2Manager = ShadowRouter2Manager.getShadow();
+ mInfoMediaManager.mRouterManager = MediaRouter2Manager.getInstance(mContext);
}
@Test
@@ -87,7 +78,7 @@
final List<MediaRoute2Info> routes = new ArrayList<>();
routes.add(info);
- when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(routes);
+ mShadowRouter2Manager.setAvailableRoutes(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
@@ -108,7 +99,7 @@
final List<MediaRoute2Info> routes = new ArrayList<>();
routes.add(info);
- when(mRouterManager.getAllRoutes()).thenReturn(routes);
+ mShadowRouter2Manager.setAllRoutes(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
@@ -129,7 +120,7 @@
final List<MediaRoute2Info> routes = new ArrayList<>();
routes.add(info);
- when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(routes);
+ mShadowRouter2Manager.setAvailableRoutes(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
@@ -157,7 +148,7 @@
final List<MediaRoute2Info> routes = new ArrayList<>();
routes.add(info);
- when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(routes);
+ mShadowRouter2Manager.setAvailableRoutes(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
@@ -178,7 +169,7 @@
final List<MediaRoute2Info> routes = new ArrayList<>();
routes.add(info);
- when(mRouterManager.getAllRoutes()).thenReturn(routes);
+ mShadowRouter2Manager.setAllRoutes(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
@@ -194,12 +185,12 @@
@Test
public void connectDeviceWithoutPackageName_noSession_returnFalse() {
final MediaRoute2Info info = mock(MediaRoute2Info.class);
- final MediaDevice device = new InfoMediaDevice(mContext, mRouterManager, info,
- TEST_PACKAGE_NAME);
+ final MediaDevice device = new InfoMediaDevice(mContext, mInfoMediaManager.mRouterManager,
+ info, TEST_PACKAGE_NAME);
final List<RoutingSessionInfo> infos = new ArrayList<>();
- when(mRouterManager.getActiveSessions()).thenReturn(infos);
+ mShadowRouter2Manager.setActiveSessions(infos);
assertThat(mInfoMediaManager.connectDeviceWithoutPackageName(device)).isFalse();
}
@@ -239,10 +230,212 @@
assertThat(mediaDevice).isNull();
mInfoMediaManager.mPackageName = "";
- mInfoMediaManager.mMediaRouterCallback.onRoutesChanged(routes);
+ mInfoMediaManager.mMediaRouterCallback.onRoutesRemoved(routes);
final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0);
assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size());
}
+
+ @Test
+ public void addDeviceToPlayMedia_packageNameIsNull_returnFalse() {
+ mInfoMediaManager.mPackageName = null;
+ final MediaDevice device = mock(MediaDevice.class);
+
+ assertThat(mInfoMediaManager.addDeviceToPlayMedia(device)).isFalse();
+ }
+
+ @Test
+ public void addDeviceToPlayMedia_containSelectableRoutes_returnTrue() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
+ final MediaDevice device =
+ new InfoMediaDevice(mContext, mInfoMediaManager.mRouterManager, route2Info,
+ TEST_PACKAGE_NAME);
+
+ final List<String> list = new ArrayList<>();
+ list.add(TEST_ID);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(info.getSelectableRoutes()).thenReturn(list);
+ when(route2Info.getId()).thenReturn(TEST_ID);
+ when(route2Info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ assertThat(mInfoMediaManager.addDeviceToPlayMedia(device)).isTrue();
+ }
+
+ @Test
+ public void addDeviceToPlayMedia_notContainSelectableRoutes_returnFalse() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
+ final MediaDevice device =
+ new InfoMediaDevice(mContext, mInfoMediaManager.mRouterManager, route2Info,
+ TEST_PACKAGE_NAME);
+
+ final List<String> list = new ArrayList<>();
+ list.add("fake_id");
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(info.getSelectableRoutes()).thenReturn(list);
+ when(route2Info.getId()).thenReturn(TEST_ID);
+ when(route2Info.getName()).thenReturn(TEST_NAME);
+ when(route2Info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ assertThat(mInfoMediaManager.addDeviceToPlayMedia(device)).isFalse();
+ }
+
+ @Test
+ public void removeDeviceFromMedia_packageNameIsNull_returnFalse() {
+ mInfoMediaManager.mPackageName = null;
+ final MediaDevice device = mock(MediaDevice.class);
+
+ assertThat(mInfoMediaManager.removeDeviceFromPlayMedia(device)).isFalse();
+ }
+
+ @Test
+ public void removeDeviceFromMedia_containSelectedRoutes_returnTrue() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
+ final MediaDevice device =
+ new InfoMediaDevice(mContext, mInfoMediaManager.mRouterManager, route2Info,
+ TEST_PACKAGE_NAME);
+
+ final List<String> list = new ArrayList<>();
+ list.add(TEST_ID);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(info.getSelectedRoutes()).thenReturn(list);
+ when(route2Info.getId()).thenReturn(TEST_ID);
+ when(route2Info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ assertThat(mInfoMediaManager.removeDeviceFromPlayMedia(device)).isTrue();
+ }
+
+ @Test
+ public void removeDeviceFromMedia_notContainSelectedRoutes_returnFalse() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
+ final MediaDevice device =
+ new InfoMediaDevice(mContext, mInfoMediaManager.mRouterManager, route2Info,
+ TEST_PACKAGE_NAME);
+
+ final List<String> list = new ArrayList<>();
+ list.add("fake_id");
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(info.getSelectedRoutes()).thenReturn(list);
+ when(route2Info.getId()).thenReturn(TEST_ID);
+ when(route2Info.getName()).thenReturn(TEST_NAME);
+ when(route2Info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ assertThat(mInfoMediaManager.removeDeviceFromPlayMedia(device)).isFalse();
+ }
+
+ @Test
+ public void getSelectableMediaDevice_packageNameIsNull_returnFalse() {
+ mInfoMediaManager.mPackageName = null;
+
+ assertThat(mInfoMediaManager.getSelectableMediaDevice()).isEmpty();
+ }
+
+ @Test
+ public void getSelectableMediaDevice_notContainPackageName_returnEmpty() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn("com.fake.packagename");
+
+ assertThat(mInfoMediaManager.getSelectableMediaDevice()).isEmpty();
+ }
+
+ @Test
+ public void adjustSessionVolume_packageNameIsNull_noCrash() {
+ mInfoMediaManager.mPackageName = null;
+
+ mInfoMediaManager.adjustSessionVolume(10);
+ }
+
+ @Test
+ public void getSessionVolumeMax_packageNameIsNull_returnNotFound() {
+ mInfoMediaManager.mPackageName = null;
+
+ assertThat(mInfoMediaManager.getSessionVolumeMax()).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionVolumeMax_containPackageName_returnMaxVolume() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ mInfoMediaManager.getSessionVolumeMax();
+
+ verify(info).getVolumeMax();
+ }
+
+ @Test
+ public void getSessionVolumeMax_notContainPackageName_returnNotFound() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn("com.fake.packagename");
+
+ assertThat(mInfoMediaManager.getSessionVolumeMax()).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionVolume_packageNameIsNull_returnNotFound() {
+ mInfoMediaManager.mPackageName = null;
+
+ assertThat(mInfoMediaManager.getSessionVolume()).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionVolume_containPackageName_returnMaxVolume() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ mInfoMediaManager.getSessionVolume();
+
+ verify(info).getVolume();
+ }
+
+ @Test
+ public void getSessionVolume_notContainPackageName_returnNotFound() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(info);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+ when(info.getClientPackageName()).thenReturn("com.fake.packagename");
+
+ assertThat(mInfoMediaManager.getSessionVolume()).isEqualTo(-1);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java
new file mode 100644
index 0000000..db0cb06
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java
@@ -0,0 +1,77 @@
+/*
+ * 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.settingslib.testutils.shadow;
+
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
+import android.media.RoutingSessionInfo;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.List;
+
+@Implements(MediaRouter2Manager.class)
+public class ShadowRouter2Manager {
+
+ private List<MediaRoute2Info> mAvailableRoutes;
+ private List<MediaRoute2Info> mAllRoutes;
+ private List<RoutingSessionInfo> mActiveSessions;
+ private List<RoutingSessionInfo> mRoutingSessions;
+
+ @Implementation
+ protected List<MediaRoute2Info> getAvailableRoutes(String packageName) {
+ return mAvailableRoutes;
+ }
+
+ public void setAvailableRoutes(List<MediaRoute2Info> infos) {
+ mAvailableRoutes = infos;
+ }
+
+ @Implementation
+ protected List<MediaRoute2Info> getAllRoutes() {
+ return mAllRoutes;
+ }
+
+ public void setAllRoutes(List<MediaRoute2Info> infos) {
+ mAllRoutes = infos;
+ }
+
+ @Implementation
+ protected List<RoutingSessionInfo> getActiveSessions() {
+ return mActiveSessions;
+ }
+
+ public void setActiveSessions(List<RoutingSessionInfo> infos) {
+ mActiveSessions = infos;
+ }
+
+ @Implementation
+ protected List<RoutingSessionInfo> getRoutingSessions(String packageName) {
+ return mRoutingSessions;
+ }
+
+ public void setRoutingSessions(List<RoutingSessionInfo> infos) {
+ mRoutingSessions = infos;
+ }
+
+ public static ShadowRouter2Manager getShadow() {
+ return (ShadowRouter2Manager) Shadow.extract(
+ MediaRouter2Manager.getInstance(RuntimeEnvironment.application));
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e77d8ae..2a2ab4b 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1813,12 +1813,12 @@
*/
private int deliverToCurrentTopIfNeeded(ActivityStack topStack) {
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
- final boolean dontStart = top != null && mStartActivity.resultTo == null
+ final boolean dontStart = top != null
&& top.mActivityComponent.equals(mStartActivity.mActivityComponent)
&& top.mUserId == mStartActivity.mUserId
&& top.attachedToProcess()
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
+ || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
// This allows home activity to automatically launch on secondary display when
// display added, if home was the top activity on default display, instead of
// sending new intent to the home activity on default display.
@@ -2049,8 +2049,6 @@
&& !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
- sendNewTaskResultRequestIfNeeded();
-
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
@@ -2232,6 +2230,8 @@
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
}
+
+ sendNewTaskResultRequestIfNeeded();
}
private void computeSourceStack() {