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