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