- This CL before, output switcher panel will show default icon if there are no media session or album art. This CL will hide the icon if there are no media session or album art. - Add test case Bug: 161495909 Test: make -j42 RunSettingsRoboTests Change-Id: I5f80158b12f89c8499fb97d0b203ebeffefbc18b
250 lines
7.9 KiB
Java
250 lines
7.9 KiB
Java
/*
|
|
* Copyright (C) 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.settings.panel;
|
|
|
|
import static androidx.lifecycle.Lifecycle.Event.ON_START;
|
|
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
|
|
|
|
import static com.android.settings.media.MediaOutputSlice.MEDIA_PACKAGE_NAME;
|
|
import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI;
|
|
|
|
import android.app.settings.SettingsEnums;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.graphics.Bitmap;
|
|
import android.media.MediaMetadata;
|
|
import android.media.session.MediaController;
|
|
import android.media.session.MediaSessionManager;
|
|
import android.media.session.PlaybackState;
|
|
import android.net.Uri;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import androidx.core.graphics.drawable.IconCompat;
|
|
import androidx.lifecycle.LifecycleObserver;
|
|
import androidx.lifecycle.OnLifecycleEvent;
|
|
|
|
import com.android.internal.annotations.VisibleForTesting;
|
|
import com.android.settings.R;
|
|
import com.android.settings.Utils;
|
|
import com.android.settingslib.media.InfoMediaDevice;
|
|
import com.android.settingslib.media.LocalMediaManager;
|
|
import com.android.settingslib.media.MediaDevice;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Represents the Media output Panel.
|
|
*
|
|
* <p>
|
|
* Displays Media output item
|
|
* </p>
|
|
*/
|
|
public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceCallback,
|
|
LifecycleObserver {
|
|
|
|
private static final String TAG = "MediaOutputPanel";
|
|
|
|
private final Context mContext;
|
|
private final String mPackageName;
|
|
|
|
@VisibleForTesting
|
|
LocalMediaManager mLocalMediaManager;
|
|
|
|
private PanelContentCallback mCallback;
|
|
private boolean mIsCustomizedButtonUsed = true;
|
|
private MediaSessionManager mMediaSessionManager;
|
|
private MediaController mMediaController;
|
|
|
|
public static MediaOutputPanel create(Context context, String packageName) {
|
|
return new MediaOutputPanel(context, packageName);
|
|
}
|
|
|
|
private MediaOutputPanel(Context context, String packageName) {
|
|
mContext = context.getApplicationContext();
|
|
mPackageName = TextUtils.isEmpty(packageName) ? "" : packageName;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence getTitle() {
|
|
if (mMediaController != null) {
|
|
final MediaMetadata metadata = mMediaController.getMetadata();
|
|
if (metadata != null) {
|
|
return metadata.getDescription().getTitle();
|
|
}
|
|
}
|
|
return mContext.getText(R.string.media_volume_title);
|
|
}
|
|
|
|
@Override
|
|
public CharSequence getSubTitle() {
|
|
if (mMediaController != null) {
|
|
final MediaMetadata metadata = mMediaController.getMetadata();
|
|
if (metadata != null) {
|
|
return metadata.getDescription().getSubtitle();
|
|
}
|
|
}
|
|
return mContext.getText(R.string.media_output_panel_title);
|
|
}
|
|
|
|
@Override
|
|
public IconCompat getIcon() {
|
|
if (mMediaController == null) {
|
|
return null;
|
|
}
|
|
final MediaMetadata metadata = mMediaController.getMetadata();
|
|
if (metadata != null) {
|
|
final Bitmap bitmap = metadata.getDescription().getIconBitmap();
|
|
if (bitmap != null) {
|
|
final Bitmap roundBitmap = Utils.convertCornerRadiusBitmap(mContext, bitmap,
|
|
(float) mContext.getResources().getDimensionPixelSize(
|
|
R.dimen.output_switcher_panel_icon_corner_radius));
|
|
|
|
return IconCompat.createWithBitmap(roundBitmap);
|
|
}
|
|
}
|
|
Log.d(TAG, "Media meta data does not contain icon information");
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public List<Uri> getSlices() {
|
|
final List<Uri> uris = new ArrayList<>();
|
|
MEDIA_OUTPUT_SLICE_URI =
|
|
MEDIA_OUTPUT_SLICE_URI
|
|
.buildUpon()
|
|
.clearQuery()
|
|
.appendQueryParameter(MEDIA_PACKAGE_NAME, mPackageName)
|
|
.build();
|
|
uris.add(MEDIA_OUTPUT_SLICE_URI);
|
|
return uris;
|
|
}
|
|
|
|
@Override
|
|
public Intent getSeeMoreIntent() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean isCustomizedButtonUsed() {
|
|
return mIsCustomizedButtonUsed;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence getCustomizedButtonTitle() {
|
|
return mContext.getText(R.string.service_stop);
|
|
}
|
|
|
|
@Override
|
|
public void onClickCustomizedButton() {
|
|
mLocalMediaManager.releaseSession();
|
|
}
|
|
|
|
@Override
|
|
public void registerCallback(PanelContentCallback callback) {
|
|
mCallback = callback;
|
|
}
|
|
|
|
@Override
|
|
public int getMetricsCategory() {
|
|
return SettingsEnums.PANEL_MEDIA_OUTPUT;
|
|
}
|
|
|
|
@Override
|
|
public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
|
|
dispatchCustomButtonStateChanged();
|
|
}
|
|
|
|
@Override
|
|
public void onDeviceListUpdate(List<MediaDevice> devices) {
|
|
dispatchCustomButtonStateChanged();
|
|
}
|
|
|
|
@Override
|
|
public void onDeviceAttributesChanged() {
|
|
dispatchCustomButtonStateChanged();
|
|
}
|
|
|
|
private void dispatchCustomButtonStateChanged() {
|
|
hideCustomButtonIfNecessary();
|
|
if (mCallback != null) {
|
|
mCallback.onCustomizedButtonStateChanged();
|
|
}
|
|
}
|
|
|
|
private void hideCustomButtonIfNecessary() {
|
|
final MediaDevice device = mLocalMediaManager.getCurrentConnectedDevice();
|
|
mIsCustomizedButtonUsed = device instanceof InfoMediaDevice;
|
|
}
|
|
|
|
@OnLifecycleEvent(ON_START)
|
|
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);
|
|
mCallback.onHeaderChanged();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (mMediaController == null) {
|
|
Log.d(TAG, "No media controller for " + mPackageName);
|
|
}
|
|
if (mLocalMediaManager == null) {
|
|
mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null);
|
|
}
|
|
mLocalMediaManager.registerCallback(this);
|
|
mLocalMediaManager.startScan();
|
|
}
|
|
|
|
@OnLifecycleEvent(ON_STOP)
|
|
public void onStop() {
|
|
if (mMediaController != null) {
|
|
mMediaController.unregisterCallback(mCb);
|
|
}
|
|
mLocalMediaManager.unregisterCallback(this);
|
|
mLocalMediaManager.stopScan();
|
|
}
|
|
|
|
@Override
|
|
public int getViewType() {
|
|
return PanelContent.VIEW_TYPE_SLIDER_LARGE_ICON;
|
|
}
|
|
|
|
private final MediaController.Callback mCb = new MediaController.Callback() {
|
|
@Override
|
|
public void onMetadataChanged(MediaMetadata metadata) {
|
|
if (mCallback != null) {
|
|
mCallback.onHeaderChanged();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onPlaybackStateChanged(PlaybackState state) {
|
|
final int playState = state.getState();
|
|
if (mCallback != null && (playState == PlaybackState.STATE_STOPPED
|
|
|| playState == PlaybackState.STATE_PAUSED)) {
|
|
mCallback.forceClose();
|
|
}
|
|
}
|
|
};
|
|
}
|