MediaRouter / src / com.example.android.mediarouter / provider /

SampleMediaRouteProvider.java

1
/*
2
 * Copyright (C) 2013 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
 */
16
 
17
package com.example.android.mediarouter.provider;
18
 
19
import android.app.PendingIntent;
20
import android.content.Context;
21
import android.content.Intent;
22
import android.content.IntentFilter;
23
import android.content.IntentFilter.MalformedMimeTypeException;
24
import android.content.res.Resources;
25
import android.media.AudioManager;
26
import android.media.MediaRouter;
27
import android.net.Uri;
28
import android.os.Bundle;
29
import android.support.v7.media.MediaControlIntent;
30
import android.support.v7.media.MediaRouteDescriptor;
31
import android.support.v7.media.MediaRouteProvider;
32
import android.support.v7.media.MediaRouteProviderDescriptor;
33
import android.support.v7.media.MediaRouter.ControlRequestCallback;
34
import android.support.v7.media.MediaSessionStatus;
35
import android.util.Log;
36
 
37
import com.example.android.mediarouter.player.Player;
38
import com.example.android.mediarouter.player.PlaylistItem;
39
import com.example.android.mediarouter.R;
40
import com.example.android.mediarouter.player.SessionManager;
41
 
42
import java.util.ArrayList;
43
 
44
/**
45
 * Demonstrates how to create a custom media route provider.
46
 *
47
 * @see SampleMediaRouteProviderService
48
 */
49
public final class SampleMediaRouteProvider extends MediaRouteProvider {
50
    private static final String TAG = "SampleMediaRouteProvider";
51
 
52
    private static final String FIXED_VOLUME_ROUTE_ID = "fixed";
53
    private static final String VARIABLE_VOLUME_BASIC_ROUTE_ID = "variable_basic";
54
    private static final String VARIABLE_VOLUME_QUEUING_ROUTE_ID = "variable_queuing";
55
    private static final String VARIABLE_VOLUME_SESSION_ROUTE_ID = "variable_session";
56
    private static final int VOLUME_MAX = 10;
57
 
58
    /**
59
     * A custom media control intent category for special requests that are
60
     * supported by this provider's routes.
61
     */
62
    public static final String CATEGORY_SAMPLE_ROUTE =
63
            "com.example.android.mediarouteprovider.CATEGORY_SAMPLE_ROUTE";
64
 
65
    /**
66
     * A custom media control intent action for special requests that are
67
     * supported by this provider's routes.
68
     * <p>
69
     * This particular request is designed to return a bundle of not very
70
     * interesting statistics for demonstration purposes.
71
     * </p>
72
     *
73
     * @see #DATA_PLAYBACK_COUNT
74
     */
75
    public static final String ACTION_GET_STATISTICS =
76
            "com.example.android.mediarouteprovider.ACTION_GET_STATISTICS";
77
 
78
    /**
79
     * {@link #ACTION_GET_STATISTICS} result data: Number of times the
80
     * playback action was invoked.
81
     */
82
    public static final String DATA_PLAYBACK_COUNT =
83
            "com.example.android.mediarouteprovider.EXTRA_PLAYBACK_COUNT";
84
 
85
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
86
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_QUEUING;
87
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_SESSION;
88
 
89
    static {
90
        IntentFilter f1 = new IntentFilter();
91
        f1.addCategory(CATEGORY_SAMPLE_ROUTE);
92
        f1.addAction(ACTION_GET_STATISTICS);
93
 
94
        IntentFilter f2 = new IntentFilter();
95
        f2.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
96
        f2.addAction(MediaControlIntent.ACTION_PLAY);
97
        f2.addDataScheme("http");
98
        f2.addDataScheme("https");
99
        f2.addDataScheme("rtsp");
100
        f2.addDataScheme("file");
101
        addDataTypeUnchecked(f2, "video/*");
102
 
103
        IntentFilter f3 = new IntentFilter();
104
        f3.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
105
        f3.addAction(MediaControlIntent.ACTION_SEEK);
106
        f3.addAction(MediaControlIntent.ACTION_GET_STATUS);
107
        f3.addAction(MediaControlIntent.ACTION_PAUSE);
108
        f3.addAction(MediaControlIntent.ACTION_RESUME);
109
        f3.addAction(MediaControlIntent.ACTION_STOP);
110
 
111
        IntentFilter f4 = new IntentFilter();
112
        f4.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
113
        f4.addAction(MediaControlIntent.ACTION_ENQUEUE);
114
        f4.addDataScheme("http");
115
        f4.addDataScheme("https");
116
        f4.addDataScheme("rtsp");
117
        f4.addDataScheme("file");
118
        addDataTypeUnchecked(f4, "video/*");
119
 
120
        IntentFilter f5 = new IntentFilter();
121
        f5.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
122
        f5.addAction(MediaControlIntent.ACTION_REMOVE);
123
 
124
        IntentFilter f6 = new IntentFilter();
125
        f6.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
126
        f6.addAction(MediaControlIntent.ACTION_START_SESSION);
127
        f6.addAction(MediaControlIntent.ACTION_GET_SESSION_STATUS);
128
        f6.addAction(MediaControlIntent.ACTION_END_SESSION);
129
 
130
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
131
        CONTROL_FILTERS_BASIC.add(f1);
132
        CONTROL_FILTERS_BASIC.add(f2);
133
        CONTROL_FILTERS_BASIC.add(f3);
134
 
135
        CONTROL_FILTERS_QUEUING =
136
                new ArrayList<IntentFilter>(CONTROL_FILTERS_BASIC);
137
        CONTROL_FILTERS_QUEUING.add(f4);
138
        CONTROL_FILTERS_QUEUING.add(f5);
139
 
140
        CONTROL_FILTERS_SESSION =
141
                new ArrayList<IntentFilter>(CONTROL_FILTERS_QUEUING);
142
        CONTROL_FILTERS_SESSION.add(f6);
143
    }
144
 
145
    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
146
        try {
147
            filter.addDataType(type);
148
        } catch (MalformedMimeTypeException ex) {
149
            throw new RuntimeException(ex);
150
        }
151
    }
152
 
153
    private int mVolume = 5;
154
    private int mEnqueueCount;
155
 
156
    public SampleMediaRouteProvider(Context context) {
157
        super(context);
158
 
159
        publishRoutes();
160
    }
161
 
162
    @Override
163
    public RouteController onCreateRouteController(String routeId) {
164
        return new SampleRouteController(routeId);
165
    }
166
 
167
    private void publishRoutes() {
168
        Resources r = getContext().getResources();
169
 
170
        MediaRouteDescriptor routeDescriptor1 = new MediaRouteDescriptor.Builder(
171
                FIXED_VOLUME_ROUTE_ID,
172
                r.getString(R.string.fixed_volume_route_name))
173
                .setDescription(r.getString(R.string.sample_route_description))
174
                .addControlFilters(CONTROL_FILTERS_BASIC)
175
                .setPlaybackStream(AudioManager.STREAM_MUSIC)
176
                .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
177
                .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED)
178
                .setVolume(VOLUME_MAX)
179
                .build();
180
 
181
        MediaRouteDescriptor routeDescriptor2 = new MediaRouteDescriptor.Builder(
182
                VARIABLE_VOLUME_BASIC_ROUTE_ID,
183
                r.getString(R.string.variable_volume_basic_route_name))
184
                .setDescription(r.getString(R.string.sample_route_description))
185
                .addControlFilters(CONTROL_FILTERS_BASIC)
186
                .setPlaybackS
tream(AudioManager.STREAM_MUSIC)
187
                .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
188
                .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
189
                .setVolumeMax(VOLUME_MAX)
190
                .setVolume(mVolume)
191
                .build();
192
 
193
        MediaRouteDescriptor routeDescriptor3 = new MediaRouteDescriptor.Builder(
194
                VARIABLE_VOLUME_QUEUING_ROUTE_ID,
195
                r.getString(R.string.variable_volume_queuing_route_name))
196
                .setDescription(r.getString(R.string.sample_route_description))
197
                .addControlFilters(CONTROL_FILTERS_QUEUING)
198
                .setPlaybackStream(AudioManager.STREAM_MUSIC)
199
                .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
200
                .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
201
                .setVolumeMax(VOLUME_MAX)
202
                .setVolume(mVolume)
203
                .build();
204
 
205
        MediaRouteDescriptor routeDescriptor4 = new MediaRouteDescriptor.Builder(
206
                VARIABLE_VOLUME_SESSION_ROUTE_ID,
207
                r.getString(R.string.variable_volume_session_route_name))
208
                .setDescription(r.getString(R.string.sample_route_description))
209
                .addControlFilters(CONTROL_FILTERS_SESSION)
210
                .setPlaybackStream(AudioManager.STREAM_MUSIC)
211
                .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
212
                .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
213
                .setVolumeMax(VOLUME_MAX)
214
                .setVolume(mVolume)
215
                .build();
216
 
217
        MediaRouteProviderDescriptor providerDescriptor =
218
                new MediaRouteProviderDescriptor.Builder()
219
                .addRoute(routeDescriptor1)
220
                .addRoute(routeDescriptor2)
221
                .addRoute(routeDescriptor3)
222
                .addRoute(routeDescriptor4)
223
                .build();
224
        setDescriptor(providerDescriptor);
225
    }
226
 
227
    private final class SampleRouteController extends MediaRouteProvider.RouteController {
228
        private final String mRouteId;
229
        private final SessionManager mSessionManager = new SessionManager("mrp");
230
        private final Player mPlayer;
231
        private PendingIntent mSessionReceiver;
232
 
233
        public SampleRouteController(String routeId) {
234
            mRouteId = routeId;
235
            mPlayer = Player.create(getContext(), null);
236
            mSessionManager.setPlayer(mPlayer);
237
            mSessionManager.setCallback(new SessionManager.Callback() {
238
                @Override
239
                public void onStatusChanged() {
240
                }
241
 
242
                @Override
243
                public void onItemChanged(PlaylistItem item) {
244
                    handleStatusChange(item);
245
                }
246
            });
247
            Log.d(TAG, mRouteId + ": Controller created");
248
        }
249
 
250
        @Override
251
        public void onRelease() {
252
           
 Log.d(TAG, mRouteId + ": Controller released");
253
            mPlayer.release();
254
        }
255
 
256
        @Override
257
        public void onSelect() {
258
            Log.d(TAG, mRouteId + ": Selected");
259
            mPlayer.connect(null);
260
        }
261
 
262
        @Override
263
        public void onUnselect() {
264
            Log.d(TAG, mRouteId + ": Unselected");
265
            mPlayer.release();
266
        }
267
 
268
        @Override
269
        public void onSetVolume(int volume) {
270
            Log.d(TAG, mRouteId + ": Set volume to " + volume);
271
            if (!mRouteId.equals(FIXED_VOLUME_ROUTE_ID)) {
272
                setVolumeInternal(volume);
273
            }
274
        }
275
 
276
        @Override
277
        public void onUpdateVolume(int delta) {
278
            Log.d(TAG, mRouteId + ": Update volume by " + delta);
279
            if (!mRouteId.equals(FIXED_VOLUME_ROUTE_ID)) {
280
                setVolumeInternal(mVolume + delta);
281
            }
282
        }
283
 
284
        @Override
285
        public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
286
            Log.d(TAG, mRouteId + ": Received control request " + intent);
287
            String action = intent.getAction();
288
            if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
289
                boolean success = false;
290
                if (action.equals(MediaControlIntent.ACTION_PLAY)) {
291
                    success = handlePlay(intent, callback);
292
                } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
293
                    success = handleEnqueue(intent, callback);
294
                } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
295
                    success = handleRemove(intent, callback);
296
                } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
297
                    success = handleSeek(intent, callback);
298
                } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
299
                    success = handleGetStatus(intent, callback);
300
                } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
301
                    success = handlePause(intent, callback);
302
                } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
303
                    success = handleResume(intent, callback);
304
                } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
305
                    success = handleStop(intent, callback);
306
                } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
307
                    success = handleStartSession(intent, callback);
308
                } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
309
                    success = handleGetSessionStatus(intent, callback);
310
                } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
311
                    success = handleEndSession(intent, callback);
312
                }
313
                Log.d(TAG, mSessionManager.toString());
314
                return success;
315
            }
316
 
317
            if (action.equals(ACTION_GET_STATISTICS)
318
                    && intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) {
319
                Bundle data = new Bundle();
320
                data.putInt(DATA_PLAYBACK_COUNT, mEnqueueCount);
321
                if (callback != null) {
322
                    callback.onResult(data);
323
                }
324
                return true;
325
            }
326
            return false;
327
        }
328
 
329
        private void setVolumeInternal(int volume) {
330
            if (volume >= 0 && volume <= VOLUME_MAX) {
331
                mVolume = volume;
332
                Log.d(TAG, mRouteId + ": New volume is " + mVolume);
333
                AudioManager audioManager =
334
                        (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE);
335
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
336
                publishRoutes();
337
            }
338
        }
339
 
340
        private boolean handlePlay(Intent intent, ControlRequestCallback callback) {
341
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
342
            if (sid != null && !sid.equals(mSessionManager.getSessionId())) {
343
                Log.d(TAG, "handlePlay fails because of bad sid="+sid);
344
                return false;
345
            }
346
            if (mSessionManager.hasSession()) {
347
                mSessionManager.stop();
348
            }
349
            return handleEnqueue(intent, callback);
350
        }
351
 
352
        private boolean handleEnqueue(Intent intent, ControlRequestCallback callback) {
353
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
354
            if (sid != null && !sid.equals(mSessionManager.getSessionId())) {
355
                Log.d(TAG, "handleEnqueue fails because of bad sid="+sid);
356
                return false;
357
            }
358
 
359
            Uri uri = intent.getData();
360
            if (uri == null) {
361
                Log.d(TAG, "handleEnqueue fails because of bad uri="+uri);
362
                return false;
363
            }
364
 
365
            boolean enqueue = intent.getAction().equals(MediaControlIntent.ACTION_ENQUEUE);
366
            String mime = intent.getType();
367
            long pos = intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0);
368
            Bundle metadata = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_METADATA);
369
            Bundle headers = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_HTTP_HEADERS);
370
            PendingIntent receiver = (PendingIntent)intent.getParcelableExtra(
371
                    MediaControlIntent.EXTRA_ITEM_STATUS_UPDATE_RECEIVER);
372
 
373
            Log.d(TAG, mRouteId + ": Received " + (enqueue?"enqueue":"play") + " request"
374
                    + ", uri=" + uri
375
                    + ", mime=" + mime
376
                    + ", sid=" + sid
377
                    + ", pos=" + pos
378
                    + ", metadata=" + metadata
379
                    + ", headers=" + headers
380
                    + ", receiver=" + receiver);
381
            PlaylistItem item = mSessionManager.add(uri, mime, receiver);
382
            if (callback != null) {
383
                if (item != null) {
384
                    Bundle result = new Bundle();
385
                    result.putString(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
386
                    result.putString(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
387
                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
388
                            item.getStatus().asBundle());
389
                    callback.onResult(result);
390
                } else {
391
                    callback.onError("Failed to open " + uri.toString(), null);
392
                }
393
            }
394
            mEnqueueCount +=1;
395
            return true;
396
        }
397
 
398
        private boolean handleRemove(Intent intent, ControlRequestCallback callback) {
399
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
400
            if (sid == null || !sid.equals(mSessionManager.getSessionId())) {
401
                return false;
402
            }
403
 
404
            String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
405
            PlaylistItem item = mSessionManager.remove(iid);
406
            if (callback != null) {
407
                if (item != null) {
408
                    Bundle result = new Bundle();
409
                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
410
                            item.getStatus().asBundle());
411
                    callback.onResult(result);
412
                } else {
413
                    callback.onError("Failed to remove" +
414
                            ", sid=" + sid + ", iid=" + iid, null);
415
                }
416
            }
417
            return (item != null);
418
        }
419
 
420
        private boolean handleSeek(Intent intent, ControlRequestCallback callback) {
421
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
422
            if (sid == null || !sid.equals(mSessionManager.getSessionId())) {
423
                return false;
424
            }
425
 
426
            String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
427
            long pos = intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0);
428
            Log.d(TAG, mRouteId + ": Received seek request, pos=" + pos);
429
            PlaylistItem item = mSessionManager.seek(iid, pos);
430
            if (callback != null) {
431
                if (item != null) {
432
                    Bundle result = new Bundle();
433
                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
434
                            item.getStatus().asBundle());
435
                    callback.onResult(result);
436
                } else {
437
                    callback.onError("Failed to seek" +
438
                            ", sid=" + sid + ", iid=" + iid + ", pos=" + pos, null);
439
                }
440
            }
441
            return (item != null);
442
        }
443
 
444
        private boolean handleGetStatus(Intent intent, ControlRequestCallback callback) {
445
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
446
            String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
447
            Log.d(TAG, mRouteId + ": Received getStatus request, si
d=" + sid + ", iid=" + iid);
448
            PlaylistItem item = mSessionManager.getStatus(iid);
449
            if (callback != null) {
450
                if (item != null) {
451
                    Bundle result = new Bundle();
452
                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
453
                            item.getStatus().asBundle());
454
                    callback.onResult(result);
455
                } else {
456
                    callback.onError("Failed to get status" +
457
                            ", sid=" + sid + ", iid=" + iid, null);
458
                }
459
            }
460
            return (item != null);
461
        }
462
 
463
        private boolean handlePause(Intent intent, ControlRequestCallback callback) {
464
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
465
            boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId());
466
            mSessionManager.pause();
467
            if (callback != null) {
468
                if (success) {
469
                    callback.onResult(new Bundle());
470
                    handleSessionStatusChange(sid);
471
                } else {
472
                    callback.onError("Failed to pause, sid=" + sid, null);
473
                }
474
            }
475
            return success;
476
        }
477
 
478
        private boolean handleResume(Intent intent, ControlRequestCallback callback) {
479
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
480
            boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId());
481
            mSessionManager.resume();
482
            if (callback != null) {
483
                if (success) {
484
                    callback.onResult(new Bundle());
485
                    handleSessionStatusChange(sid);
486
                } else {
487
                    callback.onError("Failed to resume, sid=" + sid, null);
488
                }
489
            }
490
            return success;
491
        }
492
 
493
        private boolean handleStop(Intent intent, ControlRequestCallback callback) {
494
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
495
            boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId());
496
            mSessionManager.stop();
497
            if (callback != null) {
498
                if (success) {
499
                    callback.onResult(new Bundle());
500
                    handleSessionStatusChange(sid);
501
                } else {
502
                    callback.onError("Failed to stop, sid=" + sid, null);
503
                }
504
            }
505
            return success;
506
        }
507
 
508
        private boolean handleStartSession(Intent intent, ControlRequestCallback callback) {
509
            String sid = mSessionManager.startSession();
510
            Log.d(TAG, "StartSession returns sessionId "+sid);
511
            if (callback != null) {
512
                if (sid != null) {
513
                    Bundle result = new Bundle();
514
                    result.putString(MediaControlIntent.EXTRA_SESSION_ID, sid);
515
                    result.putBundle(MediaControlIntent.EXTRA_SESSION_STATUS,
516
                            mSessionManager.getSessionStatus(sid).asBundle());
517
                    callback.onResult(result);
518
                    mSessionReceiver = (PendingIntent)intent.getParcelableExtra(
519
                            MediaControlIntent.EXTRA_SESSION_STATUS_UPDATE_RECEIVER);
520
                    handleSessionStatusChange(sid);
521
                } else {
522
                    callback.onError("Failed to start session.", null);
523
                }
524
            }
525
            return (sid != null);
526
        }
527
 
528
        private boolean handleGetSessionStatus(Intent intent, ControlRequestCallback callback) {
529
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
530
 
531
            MediaSessionStatus sessionStatus = mSessionManager.getSessionStatus(sid);
532
            if (callback != null) {
533
                if (sessionStatus != null) {
534
                    Bundle result = new Bundle();
535
                    result.putBundle(MediaControlIntent.EXTRA_SESSION_STATUS,
536
                            mSessionManager.getSessionStatus(sid).asBundle());
537
                    callback.onResult(result);
538
                } else {
539
                    callback.onError("Failed to get session status, sid=" + sid, null);
540
                }
541
            }
542
            return (sessionStatus != null);
543
        }
544
 
545
        private boolean handleEndSession(Intent intent, ControlRequestCallback callback) {
546
            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
547
            boolean success = (sid != null) && sid.equals(mSessionManager.getSessionId())
548
                    && mSessionManager.endSession();
549
            if (callback != null) {
550
                if (success) {
551
                    Bundle result = new Bundle();
552
                    MediaSessionStatus sessionStatus = new MediaSessionStatus.Builder(
553
                            MediaSessionStatus.SESSION_STATE_ENDED).build();
554
                    result.putBundle(MediaControlIntent.EXTRA_SESSION_STATUS, sessionStatus.asBundle());
555
                    callback.onResult(result);
556
                    handleSessionStatusChange(sid);
557
                    mSessionReceiver = null;
558
                } else {
559
                    callback.onError("Failed to end session, sid=" + sid, null);
560
                }
561
            }
562
            return success;
563
        }
564
 
565
        private void handleStatusChange(PlaylistItem item) {
566
            if (item == null) {
567
                item = mSessionManager.getCurrentItem();
568
            }
569
            if (item != null) {
570
                PendingIntent receiver = item.getUpdateReceiver();
571
                if (receiver != null) {
572
                    Intent intent = new Intent();
573
                    intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
574
                    intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
575
                    intent.putExtra(MediaControlIntent.EXTRA_ITEM_STATUS,
576
                            item.getStatus().asBundle());
577
                    try {
578
                        receiver.send(getContext(), 0, intent);
579
                        Log.d(TAG, mRouteId + ": Sending status update from provider");
580
                    } catch (PendingIntent.CanceledException e) {
581
                        Log.d(TAG, mRouteId + ": Failed to send status update!");
582
                    }
583
                }
584
            }
585
        }
586
 
587
        private void handleSessionStatusChange(String sid) {
588
            if (mSessionReceiver != null) {
589
                Intent intent = new Intent();
590
                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, sid);
591
                intent.putExtra(MediaControlIntent.EXTRA_SESSION_STATUS,
592
                        mSessionManager.getSessionStatus(sid).asBundle());
593
                try {
594
                    mSessionReceiver.send(getContext(), 0, intent);
595
                    Log.d(TAG, mRouteId + ": Sending session status update from provider");
596
                } catch (PendingIntent.CanceledException e) {
597
                    Log.d(TAG, mRouteId + ": Failed to send session status update!");
598
                }
599
            }
600
        }
601
    }
602
}