1/*
2 * Copyright (C) 2014 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 */
16package com.android.onemedia;
17
18import android.app.Service;
19import android.content.Intent;
20import android.graphics.Bitmap;
21import android.media.session.MediaSession;
22import android.media.session.PlaybackState;
23import android.os.Bundle;
24import android.os.IBinder;
25import android.os.RemoteException;
26import android.util.Log;
27
28import com.android.onemedia.playback.IRequestCallback;
29import com.android.onemedia.playback.RequestUtils;
30
31import java.util.ArrayList;
32
33public class PlayerService extends Service {
34    private static final String TAG = "PlayerService";
35
36    private PlayerBinder mBinder;
37    private PlayerSession mSession;
38    private NotificationHelper mNotifyHelper;
39    private Intent mIntent;
40    private boolean mStarted = false;
41
42    private ArrayList<IPlayerCallback> mCbs = new ArrayList<IPlayerCallback>();
43
44    @Override
45    public void onCreate() {
46        Log.d(TAG, "onCreate");
47        mIntent = onCreateServiceIntent();
48        if (mSession == null) {
49            mSession = onCreatePlayerController();
50            mSession.createSession();
51            mSession.setListener(mPlayerListener);
52            mNotifyHelper = new NotificationHelper(this, mSession.mSession);
53        }
54    }
55
56    @Override
57    public IBinder onBind(Intent intent) {
58        if (mBinder == null) {
59            mBinder = new PlayerBinder();
60        }
61        return mBinder;
62    }
63
64    @Override
65    public int onStartCommand(Intent intent, int flags, int startId) {
66        Log.d(TAG, "onStartCommand");
67        return START_STICKY;
68    }
69
70    @Override
71    public void onDestroy() {
72        Log.d(TAG, "onDestroy");
73        mSession.onDestroy();
74        mSession = null;
75    }
76
77    public void onPlaybackStarted() {
78        if (!mStarted) {
79            Log.d(TAG, "Starting self");
80            startService(onCreateServiceIntent());
81            mNotifyHelper.onStart();
82            mStarted = true;
83        }
84    }
85
86    public void onPlaybackEnded() {
87        if (mStarted) {
88            Log.d(TAG, "Stopping self");
89            mNotifyHelper.onStop();
90            stopSelf();
91            mStarted = false;
92        }
93    }
94
95    protected Intent onCreateServiceIntent() {
96        return new Intent(this, PlayerService.class).setPackage(getBasePackageName());
97    }
98
99    protected PlayerSession onCreatePlayerController() {
100        return new PlayerSession(this);
101    }
102
103    protected ArrayList<String> getAllowedPackages() {
104        return null;
105    }
106
107    private final PlayerSession.Listener mPlayerListener = new PlayerSession.Listener() {
108        @Override
109        public void onPlayStateChanged(PlaybackState state) {
110            switch (state.getState()) {
111                case PlaybackState.STATE_PLAYING:
112                    onPlaybackStarted();
113                    break;
114                case PlaybackState.STATE_STOPPED:
115                case PlaybackState.STATE_ERROR:
116                    onPlaybackEnded();
117                    break;
118            }
119        }
120    };
121
122    public class PlayerBinder extends IPlayerService.Stub {
123        @Override
124        public void sendRequest(String action, Bundle params, IRequestCallback cb) {
125            if (RequestUtils.ACTION_SET_CONTENT.equals(action)) {
126                mSession.setContent(params);
127            } else if (RequestUtils.ACTION_SET_NEXT_CONTENT.equals(action)) {
128                mSession.setNextContent(params);
129            }
130        }
131
132        @Override
133        public void registerCallback(final IPlayerCallback cb) throws RemoteException {
134            if (!mCbs.contains(cb)) {
135                mCbs.add(cb);
136                cb.asBinder().linkToDeath(new IBinder.DeathRecipient() {
137                    @Override
138                    public void binderDied() {
139                        mCbs.remove(cb);
140                    }
141                }, 0);
142            }
143            try {
144                cb.onSessionChanged(getSessionToken());
145            } catch (RemoteException e) {
146                mCbs.remove(cb);
147                throw e;
148            }
149        }
150
151        @Override
152        public void unregisterCallback(IPlayerCallback cb) throws RemoteException {
153            mCbs.remove(cb);
154        }
155
156        @Override
157        public MediaSession.Token getSessionToken() throws RemoteException {
158            if (mSession == null) {
159                Log.e(TAG, "Error in PlayerService: mSession=null in getSessionToken()");
160                return null;
161            }
162            return mSession.getSessionToken();
163        }
164
165        @Override
166        public void setIcon(Bitmap icon) {
167            mSession.setIcon(icon);
168        }
169    }
170
171}
172