1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.car.cluster.sample; 17 18 import static com.android.car.cluster.sample.DebugUtil.DEBUG; 19 20 import android.content.Context; 21 import android.media.MediaMetadata; 22 import android.media.session.MediaController; 23 import android.media.session.MediaSessionManager; 24 import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener; 25 import android.media.session.PlaybackState; 26 import android.util.Log; 27 28 import java.lang.ref.WeakReference; 29 import java.util.List; 30 31 /** 32 * Reports current media status to instrument cluster renderer through {@link MediaStateListener} 33 */ 34 public class MediaStateMonitor { 35 36 private final static String TAG = DebugUtil.getTag(MediaStateMonitor.class); 37 38 private final Context mContext; 39 private final MediaListener mMediaListener; 40 private MediaController mPrimaryMediaController; 41 private OnActiveSessionsChangedListener mActiveSessionsChangedListener; 42 private MediaSessionManager mMediaSessionManager; 43 private MediaStateListener mListener; 44 45 public MediaStateMonitor(Context context, MediaStateListener listener) { 46 mListener = listener; 47 mContext = context; 48 mMediaListener = new MediaListener(this); 49 mActiveSessionsChangedListener = controllers -> onActiveSessionsChanged(controllers); 50 mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class); 51 mMediaSessionManager.addOnActiveSessionsChangedListener( 52 mActiveSessionsChangedListener, null); 53 54 onActiveSessionsChanged(mMediaSessionManager.getActiveSessions(null)); 55 } 56 57 private void onActiveSessionsChanged(List<MediaController> controllers) { 58 if (DEBUG) { 59 Log.d(TAG, "onActiveSessionsChanged, controllers found: " + controllers.size()); 60 } 61 MediaController newPrimaryController = null; 62 if (!controllers.isEmpty()) { 63 newPrimaryController = controllers.get(0); 64 if (mPrimaryMediaController == newPrimaryController) { 65 // Primary media controller has not been changed. 66 return; 67 } 68 } 69 70 releasePrimaryMediaController(); 71 72 if (newPrimaryController != null) { 73 mPrimaryMediaController = newPrimaryController; 74 mPrimaryMediaController.registerCallback(mMediaListener); 75 mListener.onMediaAppChanged( 76 new MediaAppInfo(mContext, mPrimaryMediaController.getPackageName())); 77 } 78 updateRendererMediaStatusIfAvailable(); 79 } 80 81 public void release() { 82 releasePrimaryMediaController(); 83 if (mActiveSessionsChangedListener != null) { 84 mMediaSessionManager.removeOnActiveSessionsChangedListener( 85 mActiveSessionsChangedListener); 86 mActiveSessionsChangedListener = null; 87 } 88 mMediaSessionManager = null; 89 } 90 91 private void releasePrimaryMediaController() { 92 if (mPrimaryMediaController != null) { 93 mPrimaryMediaController.unregisterCallback(mMediaListener); 94 mPrimaryMediaController = null; 95 } 96 } 97 98 private void updateRendererMediaStatusIfAvailable() { 99 mListener.onMetadataChanged( 100 mPrimaryMediaController == null ? null : mPrimaryMediaController.getMetadata()); 101 mListener.onPlaybackStateChanged( 102 mPrimaryMediaController == null 103 ? null : mPrimaryMediaController.getPlaybackState()); 104 } 105 106 private void onPlaybackStateChanged(PlaybackState state) { 107 mListener.onPlaybackStateChanged(state); 108 } 109 110 private void onMetadataChanged(MediaMetadata metadata) { 111 mListener.onMetadataChanged(metadata); 112 } 113 114 public interface MediaStateListener { 115 void onPlaybackStateChanged(PlaybackState playbackState); 116 void onMetadataChanged(MediaMetadata metadata); 117 void onMediaAppChanged(MediaAppInfo mediaAppPackage); 118 } 119 120 private static class MediaListener extends MediaController.Callback { 121 private final WeakReference<MediaStateMonitor> mServiceRef; 122 123 MediaListener(MediaStateMonitor service) { 124 mServiceRef = new WeakReference<>(service); 125 } 126 127 @Override 128 public void onPlaybackStateChanged(PlaybackState state) { 129 MediaStateMonitor service = mServiceRef.get(); 130 if (service != null) { 131 service.onPlaybackStateChanged(state); 132 } 133 } 134 135 @Override 136 public void onMetadataChanged(MediaMetadata metadata) { 137 MediaStateMonitor service = mServiceRef.get(); 138 if (service != null) { 139 service.onMetadataChanged(metadata); 140 } 141 } 142 } 143 } 144