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:
Tim Peng
2020-03-13 14:10:40 +08:00
parent 8ee5045d68
commit 36c4949414
7 changed files with 113 additions and 27 deletions

View File

@@ -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();
} }
} }

View File

@@ -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();
}
}
};
} }

View File

@@ -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();
} }

View File

@@ -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());
}); });
} }

View File

@@ -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

View File

@@ -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();
}
} }

View File

@@ -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);
}
} }