18ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik/*
28ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Copyright (C) 2014 The Android Open Source Project
38ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
48ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Licensed under the Apache License, Version 2.0 (the "License");
58ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * you may not use this file except in compliance with the License.
68ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * You may obtain a copy of the License at
78ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
88ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *      http://www.apache.org/licenses/LICENSE-2.0
98ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik *
108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Unless required by applicable law or agreed to in writing, software
118ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * distributed under the License is distributed on an "AS IS" BASIS,
128ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * See the License for the specific language governing permissions and
148ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * limitations under the License.
158ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik */
16bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpackage com.android.onemedia;
17bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
18bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Context;
19bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Intent;
2045f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandlerimport android.graphics.Bitmap;
2145f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandlerimport android.media.MediaMetadata;
2242ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSession;
2303fce072cac092923e10a6b5f09fcde333375f9eRoboErikimport android.media.session.MediaSession.QueueItem;
2442ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSessionManager;
258ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.media.session.PlaybackState;
26bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.Bundle;
278b4bffcac996b4083e720310a09d315ca1c4a000RoboErikimport android.os.RemoteException;
28c785a78fb483fe54012175c53d3758b2412de7b9RoboErikimport android.os.SystemClock;
29bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.util.Log;
30bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.view.KeyEvent;
31bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
32bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport com.android.onemedia.playback.LocalRenderer;
33bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport com.android.onemedia.playback.Renderer;
3407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport com.android.onemedia.playback.RequestUtils;
3507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
3607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport java.util.ArrayList;
37ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brownimport java.util.List;
38bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
39bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpublic class PlayerSession {
408ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    private static final String TAG = "PlayerSession";
41bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
4242ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    protected MediaSession mSession;
43bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    protected Context mContext;
4407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    protected Renderer mRenderer;
4542ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    protected MediaSession.Callback mCallback;
468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    protected Renderer.Listener mRenderListener;
4745f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    protected MediaMetadata.Builder mMetadataBuilder;
4803fce072cac092923e10a6b5f09fcde333375f9eRoboErik    protected ArrayList<MediaSession.QueueItem> mQueue;
4903fce072cac092923e10a6b5f09fcde333375f9eRoboErik    protected boolean mUseQueue;
508ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
518ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    protected PlaybackState mPlaybackState;
528ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    protected Listener mListener;
5307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
5407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    private String mContent;
55bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
56bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public PlayerSession(Context context) {
57bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mContext = context;
58bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer = new LocalRenderer(context, null);
5907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mCallback = new SessionCb();
60bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderListener = new RenderListener();
61c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        PlaybackState.Builder psBob = new PlaybackState.Builder();
62c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        psBob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY);
63c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        mPlaybackState = psBob.build();
6403fce072cac092923e10a6b5f09fcde333375f9eRoboErik        mQueue = new ArrayList<MediaSession.QueueItem>();
65bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
66bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer.registerListener(mRenderListener);
6745f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler
6845f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        initMetadata();
69bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
70bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
71bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void createSession() {
72ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown        releaseSession();
73ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown
7442ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik        MediaSessionManager man = (MediaSessionManager) mContext
75bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik                .getSystemService(Context.MEDIA_SESSION_SERVICE);
76bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
77ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown
788b4bffcac996b4083e720310a09d315ca1c4a000RoboErik        mSession = new MediaSession(mContext, "OneMedia");
79477d1197c3c25c01ace7ea4494437c23720a2eb3RoboErik        mSession.setCallback(mCallback);
80c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik        mSession.setPlaybackState(mPlaybackState);
81477d1197c3c25c01ace7ea4494437c23720a2eb3RoboErik        mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
82477d1197c3c25c01ace7ea4494437c23720a2eb3RoboErik                | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
83a8f951462791a16f47e8c07e552232f31dcefac5RoboErik        mSession.setActive(true);
8445f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        updateMetadata();
85bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
86bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
87bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void onDestroy() {
88ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown        releaseSession();
89bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        if (mRenderer != null) {
90bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mRenderer.unregisterListener(mRenderListener);
91bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik            mRenderer.onDestroy();
92bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
93bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
94bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
95ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown    private void releaseSession() {
96ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown        if (mSession != null) {
97ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown            mSession.release();
98ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown            mSession = null;
99ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown        }
100ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown    }
101ff0215dd64e5fd4ff366930747e7943fcc40c4abJeff Brown
1028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    public void setListener(Listener listener) {
1038ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        mListener = listener;
1048ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    }
1058ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
106dba34ba35cd2042d9a8fecfda56e2abe7a680badJeff Brown    public MediaSession.Token getSessionToken() {
107bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        return mSession.getSessionToken();
108bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
109bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
110bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setContent(Bundle request) {
111bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer.setContent(request);
11207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik        mContent = request.getString(RequestUtils.EXTRA_KEY_SOURCE);
113bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
114bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
115bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    public void setNextContent(Bundle request) {
116bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        mRenderer.setNextContent(request);
117bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
118bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
11945f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    public void setIcon(Bitmap icon) {
12045f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        mMetadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, icon);
12103fce072cac092923e10a6b5f09fcde333375f9eRoboErik        mQueue.clear();
12203fce072cac092923e10a6b5f09fcde333375f9eRoboErik        mQueue.add(new QueueItem(mMetadataBuilder.build().getDescription(), 11));
12345f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        updateMetadata();
12445f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    }
12545f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler
12645f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    private void updateMetadata() {
12745f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        // This is a mild abuse of metadata and shouldn't be duplicated in real
12845f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        // code
12945f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        if (mSession != null && mSession.isActive()) {
13045f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler            mSession.setMetadata(mMetadataBuilder.build());
13103fce072cac092923e10a6b5f09fcde333375f9eRoboErik            // Just toggle the queue every time we update for testing
13203fce072cac092923e10a6b5f09fcde333375f9eRoboErik            mSession.setQueue(mUseQueue ? mQueue : null);
13303fce072cac092923e10a6b5f09fcde333375f9eRoboErik            mSession.setQueueTitle(mUseQueue ? "Queue title" : null);
13403fce072cac092923e10a6b5f09fcde333375f9eRoboErik            mUseQueue = !mUseQueue;
13545f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        }
13645f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    }
13745f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler
13807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    private void updateState(int newState) {
13979fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik        float rate = newState == PlaybackState.STATE_PLAYING ? 1 : 0;
140f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik        long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
141c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
142c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        bob.setState(newState, position, rate, SystemClock.elapsedRealtime());
143c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        bob.setErrorMessage(null);
144c785a78fb483fe54012175c53d3758b2412de7b9RoboErik        mPlaybackState = bob.build();
145c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik        mSession.setPlaybackState(mPlaybackState);
14607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik    }
14707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik
14845f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    private void initMetadata() {
14945f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        mMetadataBuilder = new MediaMetadata.Builder();
15045f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        mMetadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE,
15145f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler                "OneMedia display title");
15245f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler        mMetadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE,
15345f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler                "OneMedia display subtitle");
15403fce072cac092923e10a6b5f09fcde333375f9eRoboErik
15503fce072cac092923e10a6b5f09fcde333375f9eRoboErik        mQueue.add(new QueueItem(mMetadataBuilder.build().getDescription(), 11));
15645f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler    }
15745f7ee8201efbda59b57b1fe637a1b9ffef25bb6Daniel Sandler
1588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    public interface Listener {
1598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPlayStateChanged(PlaybackState state);
1608ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    }
1618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
1628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    private class RenderListener implements Renderer.Listener {
163bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
164bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
165bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onError(int type, int extra, Bundle extras, Throwable error) {
1668ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
167c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
168c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            bob.setState(PlaybackState.STATE_ERROR, -1, 0, 0);
1698ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (error != null) {
170c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                bob.setErrorMessage(error.getLocalizedMessage());
1718ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
172c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            mPlaybackState = bob.build();
173c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mSession.setPlaybackState(mPlaybackState);
1748ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (mListener != null) {
1758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlayStateChanged(mPlaybackState);
1768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
177bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
178bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
179bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
180bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onStateChanged(int newState) {
181f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            long position = -1;
182f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            if (mRenderer != null) {
183f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik                position = mRenderer.getSeekPosition();
184f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            }
185c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            int pbState;
186c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            float rate = 0;
187c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            String errorMsg = null;
1888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            switch (newState) {
1898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_ENDED:
1908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_STOPPED:
191c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    pbState = PlaybackState.STATE_STOPPED;
1928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_INIT:
1948ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_PREPARING:
195c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    pbState = PlaybackState.STATE_BUFFERING;
1968ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
1978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_ERROR:
198c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    pbState = PlaybackState.STATE_ERROR;
1998ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
2008ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_PAUSED:
201c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    pbState = PlaybackState.STATE_PAUSED;
2028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
2038ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                case Renderer.STATE_PLAYING:
204c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    pbState = PlaybackState.STATE_PLAYING;
205c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    rate = 1;
2068ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
2078ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                default:
208c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    pbState = PlaybackState.STATE_ERROR;
209c785a78fb483fe54012175c53d3758b2412de7b9RoboErik                    errorMsg = "unknown state";
2108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                    break;
2118ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
212c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
213c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            bob.setState(pbState, position, rate, SystemClock.elapsedRealtime());
214c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            bob.setErrorMessage(errorMsg);
215c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            mPlaybackState = bob.build();
216c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mSession.setPlaybackState(mPlaybackState);
2178ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (mListener != null) {
2188ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlayStateChanged(mPlaybackState);
2198ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
220bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
221bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
222bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
223bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onBufferingUpdate(int percent) {
224bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
225bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
226bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
227bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onFocusLost() {
2288ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
229f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik            long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
230c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
231c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            bob.setState(PlaybackState.STATE_PAUSED, position, 0, SystemClock.elapsedRealtime());
232c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            bob.setErrorMessage(null);
233c785a78fb483fe54012175c53d3758b2412de7b9RoboErik            mPlaybackState = bob.build();
234c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik            mSession.setPlaybackState(mPlaybackState);
2358ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            if (mListener != null) {
2368ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik                mListener.onPlayStateChanged(mPlaybackState);
2378ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            }
238bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
239bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
240bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
241bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        public void onNextStarted() {
242bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        }
243bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
244bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik    }
245bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik
24642ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik    private class SessionCb extends MediaSession.Callback {
247bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik        @Override
2488ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPlay() {
2498ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mRenderer.onPlay();
2508ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
2518ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik
2528ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        @Override
2538ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        public void onPause() {
2548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik            mRenderer.onPause();
2558ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik        }
2568ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik    }
257bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik}
258