Output switcher header is not updated with the latest media content
-Register media controller callback -Update panel header when medadata changes -Add test cases Bug: 151396986 Test: make -j50 RunSettingsRoboTests Change-Id: Id0b8f997899a96c0c94ca6bf099e624a9e87795b
This commit is contained in:
@@ -148,7 +148,7 @@ public class MediaOutputGroupPanel implements PanelContent, LocalMediaManager.De
|
|||||||
@Override
|
@Override
|
||||||
public void onDeviceListUpdate(List<MediaDevice> devices) {
|
public void onDeviceListUpdate(List<MediaDevice> devices) {
|
||||||
if (mCallback != null) {
|
if (mCallback != null) {
|
||||||
mCallback.onGroupChanged();
|
mCallback.onHeaderChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -82,20 +82,6 @@ public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceC
|
|||||||
private MediaOutputPanel(Context context, String packageName) {
|
private MediaOutputPanel(Context context, String packageName) {
|
||||||
mContext = context.getApplicationContext();
|
mContext = context.getApplicationContext();
|
||||||
mPackageName = TextUtils.isEmpty(packageName) ? "" : packageName;
|
mPackageName = TextUtils.isEmpty(packageName) ? "" : packageName;
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(mPackageName)) {
|
|
||||||
mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class);
|
|
||||||
for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) {
|
|
||||||
if (TextUtils.equals(controller.getPackageName(), mPackageName)) {
|
|
||||||
mMediaController = controller;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mMediaController == null) {
|
|
||||||
Log.e(TAG, "Unable to find " + mPackageName + " media controller");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -228,6 +214,19 @@ public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceC
|
|||||||
|
|
||||||
@OnLifecycleEvent(ON_START)
|
@OnLifecycleEvent(ON_START)
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
|
if (!TextUtils.isEmpty(mPackageName)) {
|
||||||
|
mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class);
|
||||||
|
for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) {
|
||||||
|
if (TextUtils.equals(controller.getPackageName(), mPackageName)) {
|
||||||
|
mMediaController = controller;
|
||||||
|
mMediaController.registerCallback(mCb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mMediaController == null) {
|
||||||
|
Log.d(TAG, "No media controller for " + mPackageName);
|
||||||
|
}
|
||||||
if (mLocalMediaManager == null) {
|
if (mLocalMediaManager == null) {
|
||||||
mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null);
|
mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null);
|
||||||
}
|
}
|
||||||
@@ -237,6 +236,9 @@ public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceC
|
|||||||
|
|
||||||
@OnLifecycleEvent(ON_STOP)
|
@OnLifecycleEvent(ON_STOP)
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
|
if (mMediaController != null) {
|
||||||
|
mMediaController.unregisterCallback(mCb);
|
||||||
|
}
|
||||||
mLocalMediaManager.unregisterCallback(this);
|
mLocalMediaManager.unregisterCallback(this);
|
||||||
mLocalMediaManager.stopScan();
|
mLocalMediaManager.stopScan();
|
||||||
}
|
}
|
||||||
@@ -245,4 +247,13 @@ public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceC
|
|||||||
public int getViewType() {
|
public int getViewType() {
|
||||||
return PanelContent.VIEW_TYPE_SLIDER;
|
return PanelContent.VIEW_TYPE_SLIDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final MediaController.Callback mCb = new MediaController.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onMetadataChanged(MediaMetadata metadata) {
|
||||||
|
if (mCallback != null) {
|
||||||
|
mCallback.onHeaderChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -28,8 +28,8 @@ public interface PanelContentCallback {
|
|||||||
void onCustomizedButtonStateChanged();
|
void onCustomizedButtonStateChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It will be called when group content is changed. For example, to add/remove a device into
|
* It will be called when header content is changed. For example, to add/remove a device into
|
||||||
* a group
|
* a group
|
||||||
*/
|
*/
|
||||||
void onGroupChanged();
|
void onHeaderChanged();
|
||||||
}
|
}
|
||||||
|
@@ -426,8 +426,10 @@ public class PanelFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGroupChanged() {
|
public void onHeaderChanged() {
|
||||||
ThreadUtils.postOnMainThread(() -> {
|
ThreadUtils.postOnMainThread(() -> {
|
||||||
|
mTitleIcon.setImageIcon(mPanel.getIcon().toIcon(getContext()));
|
||||||
|
mHeaderTitle.setText(mPanel.getTitle());
|
||||||
mHeaderSubtitle.setText(mPanel.getSubTitle());
|
mHeaderSubtitle.setText(mPanel.getSubTitle());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@ public class FakePanelContent implements PanelContent {
|
|||||||
|
|
||||||
public static final Intent INTENT = new Intent();
|
public static final Intent INTENT = new Intent();
|
||||||
|
|
||||||
|
private CharSequence mTitle = TITLE;
|
||||||
private CharSequence mSubTitle;
|
private CharSequence mSubTitle;
|
||||||
private IconCompat mIcon;
|
private IconCompat mIcon;
|
||||||
private int mViewType;
|
private int mViewType;
|
||||||
@@ -51,22 +52,26 @@ public class FakePanelContent implements PanelContent {
|
|||||||
return mIcon;
|
return mIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIcon(IconCompat icon) {
|
||||||
|
mIcon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getSubTitle() {
|
public CharSequence getSubTitle() {
|
||||||
return mSubTitle;
|
return mSubTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIcon(IconCompat icon) {
|
|
||||||
mIcon = icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSubTitle(CharSequence subTitle) {
|
public void setSubTitle(CharSequence subTitle) {
|
||||||
mSubTitle = subTitle;
|
mSubTitle = subTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getTitle() {
|
public CharSequence getTitle() {
|
||||||
return TITLE;
|
return mTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(CharSequence title) {
|
||||||
|
mTitle = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -41,6 +41,7 @@ import com.android.settingslib.media.PhoneMediaDevice;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
@@ -62,7 +63,6 @@ public class MediaOutputPanelTest {
|
|||||||
private MediaController mMediaController;
|
private MediaController mMediaController;
|
||||||
@Mock
|
@Mock
|
||||||
private MediaMetadata mMediaMetadata;
|
private MediaMetadata mMediaMetadata;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private LocalMediaManager mLocalMediaManager;
|
private LocalMediaManager mLocalMediaManager;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -71,6 +71,8 @@ public class MediaOutputPanelTest {
|
|||||||
private MediaOutputPanel mPanel;
|
private MediaOutputPanel mPanel;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private List<MediaController> mMediaControllers = new ArrayList<>();
|
private List<MediaController> mMediaControllers = new ArrayList<>();
|
||||||
|
private ArgumentCaptor<MediaController.Callback> mControllerCbs =
|
||||||
|
ArgumentCaptor.forClass(MediaController.Callback.class);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -112,6 +114,7 @@ public class MediaOutputPanelTest {
|
|||||||
public void onStart_shouldRegisterCallback() {
|
public void onStart_shouldRegisterCallback() {
|
||||||
mPanel.onStart();
|
mPanel.onStart();
|
||||||
|
|
||||||
|
verify(mMediaController).registerCallback(any());
|
||||||
verify(mLocalMediaManager).registerCallback(any());
|
verify(mLocalMediaManager).registerCallback(any());
|
||||||
verify(mLocalMediaManager).startScan();
|
verify(mLocalMediaManager).startScan();
|
||||||
}
|
}
|
||||||
@@ -167,6 +170,7 @@ public class MediaOutputPanelTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTitle_withMetadata_returnArtistName() {
|
public void getTitle_withMetadata_returnArtistName() {
|
||||||
|
mPanel.onStart();
|
||||||
when(mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST)).thenReturn(TEST_ARTIST);
|
when(mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST)).thenReturn(TEST_ARTIST);
|
||||||
when(mMediaController.getMetadata()).thenReturn(mMediaMetadata);
|
when(mMediaController.getMetadata()).thenReturn(mMediaMetadata);
|
||||||
|
|
||||||
@@ -201,6 +205,7 @@ public class MediaOutputPanelTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSubTitle_withMetadata_returnAlbumName() {
|
public void getSubTitle_withMetadata_returnAlbumName() {
|
||||||
|
mPanel.onStart();
|
||||||
when(mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ALBUM)).thenReturn(TEST_ALBUM);
|
when(mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ALBUM)).thenReturn(TEST_ALBUM);
|
||||||
when(mMediaController.getMetadata()).thenReturn(mMediaMetadata);
|
when(mMediaController.getMetadata()).thenReturn(mMediaMetadata);
|
||||||
|
|
||||||
@@ -243,4 +248,15 @@ public class MediaOutputPanelTest {
|
|||||||
|
|
||||||
verify(mLocalMediaManager).releaseSession();
|
verify(mLocalMediaManager).releaseSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onMetadataChanged_verifyCallOnHeaderChanged() {
|
||||||
|
mPanel.onStart();
|
||||||
|
verify(mMediaController).registerCallback(mControllerCbs.capture());
|
||||||
|
final MediaController.Callback controllerCallbacks = mControllerCbs.getValue();
|
||||||
|
|
||||||
|
controllerCallbacks.onMetadataChanged(mMediaMetadata);
|
||||||
|
|
||||||
|
verify(mCallback).onHeaderChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,6 +41,7 @@ import com.android.settings.testutils.FakeFeatureFactory;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.robolectric.Robolectric;
|
import org.robolectric.Robolectric;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
@@ -51,7 +52,10 @@ import java.util.Objects;
|
|||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class PanelFragmentTest {
|
public class PanelFragmentTest {
|
||||||
|
|
||||||
|
private static final String TITLE = "title";
|
||||||
|
private static final String TITLE2 = "title2";
|
||||||
private static final String SUBTITLE = "subtitle";
|
private static final String SUBTITLE = "subtitle";
|
||||||
|
private static final String SUBTITLE2 = "subtitle2";
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private PanelFragment mPanelFragment;
|
private PanelFragment mPanelFragment;
|
||||||
@@ -59,6 +63,8 @@ public class PanelFragmentTest {
|
|||||||
private FakeFeatureFactory mFakeFeatureFactory;
|
private FakeFeatureFactory mFakeFeatureFactory;
|
||||||
private PanelFeatureProvider mPanelFeatureProvider;
|
private PanelFeatureProvider mPanelFeatureProvider;
|
||||||
private FakePanelContent mFakePanelContent;
|
private FakePanelContent mFakePanelContent;
|
||||||
|
private ArgumentCaptor<PanelContentCallback> mPanelContentCbs = ArgumentCaptor.forClass(
|
||||||
|
PanelContentCallback.class);
|
||||||
|
|
||||||
private final String FAKE_EXTRA = "fake_extra";
|
private final String FAKE_EXTRA = "fake_extra";
|
||||||
|
|
||||||
@@ -69,9 +75,11 @@ public class PanelFragmentTest {
|
|||||||
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
|
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
|
||||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
|
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
|
||||||
mFakePanelContent = new FakePanelContent();
|
mFakePanelContent = spy(new FakePanelContent());
|
||||||
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
|
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFakeActivity() {
|
||||||
mActivity = spy(Robolectric.buildActivity(FakeSettingsPanelActivity.class).setup().get());
|
mActivity = spy(Robolectric.buildActivity(FakeSettingsPanelActivity.class).setup().get());
|
||||||
|
|
||||||
mPanelFragment =
|
mPanelFragment =
|
||||||
@@ -86,6 +94,7 @@ public class PanelFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onCreateView_countdownLatch_setup() {
|
public void onCreateView_countdownLatch_setup() {
|
||||||
|
initFakeActivity();
|
||||||
mPanelFragment.onCreateView(LayoutInflater.from(mContext),
|
mPanelFragment.onCreateView(LayoutInflater.from(mContext),
|
||||||
new LinearLayout(mContext), null);
|
new LinearLayout(mContext), null);
|
||||||
PanelSlicesLoaderCountdownLatch countdownLatch =
|
PanelSlicesLoaderCountdownLatch countdownLatch =
|
||||||
@@ -99,6 +108,7 @@ public class PanelFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onCreate_logsOpenEvent() {
|
public void onCreate_logsOpenEvent() {
|
||||||
|
initFakeActivity();
|
||||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||||
0,
|
0,
|
||||||
SettingsEnums.PAGE_VISIBLE,
|
SettingsEnums.PAGE_VISIBLE,
|
||||||
@@ -109,6 +119,7 @@ public class PanelFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onDestroy_logCloseEvent() {
|
public void onDestroy_logCloseEvent() {
|
||||||
|
initFakeActivity();
|
||||||
mPanelFragment.onDestroyView();
|
mPanelFragment.onDestroyView();
|
||||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||||
0,
|
0,
|
||||||
@@ -120,6 +131,7 @@ public class PanelFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void panelSeeMoreClick_logsCloseEvent() {
|
public void panelSeeMoreClick_logsCloseEvent() {
|
||||||
|
initFakeActivity();
|
||||||
final View.OnClickListener listener = mPanelFragment.getSeeMoreListener();
|
final View.OnClickListener listener = mPanelFragment.getSeeMoreListener();
|
||||||
listener.onClick(null);
|
listener.onClick(null);
|
||||||
verify(mActivity).finish();
|
verify(mActivity).finish();
|
||||||
@@ -136,6 +148,7 @@ public class PanelFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void panelDoneClick_logsCloseEvent() {
|
public void panelDoneClick_logsCloseEvent() {
|
||||||
|
initFakeActivity();
|
||||||
final View.OnClickListener listener = mPanelFragment.getCloseListener();
|
final View.OnClickListener listener = mPanelFragment.getCloseListener();
|
||||||
listener.onClick(null);
|
listener.onClick(null);
|
||||||
verify(mActivity).finish();
|
verify(mActivity).finish();
|
||||||
@@ -178,10 +191,49 @@ public class PanelFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void notSupportIcon_displayDefaultHeaderLayout() {
|
public void notSupportIcon_displayDefaultHeaderLayout() {
|
||||||
final View titleView = mPanelFragment.mLayoutView.findViewById(R.id.panel_title);
|
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||||
final View panelHeader = mPanelFragment.mLayoutView.findViewById(R.id.panel_header);
|
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||||
|
activityController.setup();
|
||||||
|
final PanelFragment panelFragment = (PanelFragment)
|
||||||
|
Objects.requireNonNull(activityController
|
||||||
|
.get()
|
||||||
|
.getSupportFragmentManager()
|
||||||
|
.findFragmentById(R.id.main_content));
|
||||||
|
|
||||||
|
final View titleView = panelFragment.mLayoutView.findViewById(R.id.panel_title);
|
||||||
|
final View panelHeader = panelFragment.mLayoutView.findViewById(R.id.panel_header);
|
||||||
|
|
||||||
assertThat(panelHeader.getVisibility()).isEqualTo(View.GONE);
|
assertThat(panelHeader.getVisibility()).isEqualTo(View.GONE);
|
||||||
assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
|
assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onHeaderChanged_updateHeader_verifyTitle() {
|
||||||
|
mFakePanelContent.setIcon(IconCompat.createWithResource(mContext, R.drawable.ic_android));
|
||||||
|
mFakePanelContent.setTitle(TITLE);
|
||||||
|
mFakePanelContent.setSubTitle(SUBTITLE);
|
||||||
|
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||||
|
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||||
|
activityController.setup();
|
||||||
|
final PanelFragment panelFragment = (PanelFragment)
|
||||||
|
Objects.requireNonNull(activityController
|
||||||
|
.get()
|
||||||
|
.getSupportFragmentManager()
|
||||||
|
.findFragmentById(R.id.main_content));
|
||||||
|
final TextView headerTitle = panelFragment.mLayoutView.findViewById(R.id.header_title);
|
||||||
|
final TextView headerSubtitle = panelFragment.mLayoutView.findViewById(
|
||||||
|
R.id.header_subtitle);
|
||||||
|
|
||||||
|
assertThat(headerTitle.getText()).isEqualTo(TITLE);
|
||||||
|
assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE);
|
||||||
|
|
||||||
|
mFakePanelContent.setTitle(TITLE2);
|
||||||
|
mFakePanelContent.setSubTitle(SUBTITLE2);
|
||||||
|
verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
|
||||||
|
final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
|
||||||
|
panelContentCallbacks.onHeaderChanged();
|
||||||
|
|
||||||
|
assertThat(headerTitle.getText()).isEqualTo(TITLE2);
|
||||||
|
assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE2);
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user