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