11ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev/* 21ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * Copyright (C) 2016 The Android Open Source Project 31ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * 41ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * Licensed under the Apache License, Version 2.0 (the "License"); 51ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * you may not use this file except in compliance with the License. 61ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * You may obtain a copy of the License at 71ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * 81ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * http://www.apache.org/licenses/LICENSE-2.0 91ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * 101ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * Unless required by applicable law or agreed to in writing, software 111ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * distributed under the License is distributed on an "AS IS" BASIS, 121ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * See the License for the specific language governing permissions and 141ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * limitations under the License. 151ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev */ 162a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsevpackage android.car.cluster.demorenderer; 171ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 181ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.content.Context; 191ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.media.MediaMetadata; 201ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.media.session.MediaController; 211ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.media.session.MediaSessionManager; 221ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.media.session.MediaSessionManager.OnActiveSessionsChangedListener; 231ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.media.session.PlaybackState; 241ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport android.util.Log; 251ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 261ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport java.lang.ref.WeakReference; 271ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsevimport java.util.List; 281ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 291ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev/** 301ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev * Reports current media status to instrument cluster renderer. 311ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev */ 322a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsevpublic class MediaStateMonitor { 331ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 342a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev private final static String TAG = MediaStateMonitor.class.getSimpleName(); 351ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 361ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private final Context mContext; 371ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private final MediaListener mMediaListener; 381ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private MediaController mPrimaryMediaController; 391ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private OnActiveSessionsChangedListener mActiveSessionsChangedListener; 401ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private MediaSessionManager mMediaSessionManager; 412a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev private MediaStateListener mListener; 421ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 432a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev public MediaStateMonitor(Context context, MediaStateListener listener) { 442a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mListener = listener; 451ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mContext = context; 462a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mMediaListener = new MediaListener(this); 472a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mActiveSessionsChangedListener = controllers -> onActiveSessionsChanged(controllers); 481ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class); 491ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mMediaSessionManager.addOnActiveSessionsChangedListener( 501ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mActiveSessionsChangedListener, null); 511ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 521ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev onActiveSessionsChanged(mMediaSessionManager.getActiveSessions(null)); 531ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 541ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 551ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private void onActiveSessionsChanged(List<MediaController> controllers) { 561ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev Log.d(TAG, "onActiveSessionsChanged, controllers found: " + controllers.size()); 571ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev MediaController newPrimaryController = null; 581ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (controllers.size() > 0) { 591ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev newPrimaryController = controllers.get(0); 601ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (mPrimaryMediaController == newPrimaryController) { 611ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev // Primary media controller has not been changed. 621ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev return; 631ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 641ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 651ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 661ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev releasePrimaryMediaController(); 671ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 681ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (newPrimaryController != null) { 691ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mPrimaryMediaController = newPrimaryController; 701ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mPrimaryMediaController.registerCallback(mMediaListener); 711ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 721ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev updateRendererMediaStatusIfAvailable(); 731ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 741ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev for (MediaController m : controllers) { 751ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev Log.d(TAG, m + ": " + m.getPackageName()); 761ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 771ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 781ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 791ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev public void release() { 801ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev releasePrimaryMediaController(); 811ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (mActiveSessionsChangedListener != null) { 821ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mMediaSessionManager.removeOnActiveSessionsChangedListener( 831ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mActiveSessionsChangedListener); 841ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mActiveSessionsChangedListener = null; 851ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 861ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mMediaSessionManager = null; 871ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 881ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 891ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private void releasePrimaryMediaController() { 901ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (mPrimaryMediaController != null) { 911ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mPrimaryMediaController.unregisterCallback(mMediaListener); 921ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mPrimaryMediaController = null; 931ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 941ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 951ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 961ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private void updateRendererMediaStatusIfAvailable() { 972a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mListener.onMetadataChanged( 982a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mPrimaryMediaController == null ? null : mPrimaryMediaController.getMetadata()); 992a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mListener.onPlaybackStateChanged( 1002a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mPrimaryMediaController == null 1012a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev ? null : mPrimaryMediaController.getPlaybackState()); 1021ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1031ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 1041ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private void onPlaybackStateChanged(PlaybackState state) { 1052a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mListener.onPlaybackStateChanged(state); 1061ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1071ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 1081ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private void onMetadataChanged(MediaMetadata metadata) { 1092a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev mListener.onMetadataChanged(metadata); 1101ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1111ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 1122a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev public interface MediaStateListener { 1132a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev void onPlaybackStateChanged(PlaybackState playbackState); 1142a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev void onMetadataChanged(MediaMetadata metadata); 1152a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev } 1162a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev 1172a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev 1181ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev private static class MediaListener extends MediaController.Callback { 1192a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev private final WeakReference<MediaStateMonitor> mServiceRef; 1201ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 1212a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev MediaListener(MediaStateMonitor service) { 1221ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev mServiceRef = new WeakReference<>(service); 1231ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1241ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 1251ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev @Override 1261ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev public void onPlaybackStateChanged(PlaybackState state) { 1272a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev MediaStateMonitor service = mServiceRef.get(); 1281ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (service != null) { 1291ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev service.onPlaybackStateChanged(state); 1301ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1311ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1321ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev 1331ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev @Override 1341ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev public void onMetadataChanged(MediaMetadata metadata) { 1352a295e60b8486ddc292f1dc8b87f270e312620c1Pavel Maltsev MediaStateMonitor service = mServiceRef.get(); 1361ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev if (service != null) { 1371ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev service.onMetadataChanged(metadata); 1381ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1391ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1401ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev } 1411ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev} 142