blob: 48a0ee585ec7240de53e56535d62f89da9be5aea [file] [log] [blame]
/*
* Copyright (c) 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.media.localmediaplayer;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaDescription;
import android.media.browse.MediaBrowser;
import android.media.session.MediaSession;
import android.os.Bundle;
import android.service.media.MediaBrowserService;
import androidx.annotation.Nullable;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class LocalMediaBrowserService extends MediaBrowserService {
private static final String TAG = "LMBService";
private static final String ROOT_ID = "__ROOT__";
private static final String MEDIA_SESSION_TAG = "LOCAL_MEDIA_SESSION";
static final String FOLDERS_ID = "__FOLDERS__";
static final String ARTISTS_ID = "__ARTISTS__";
static final String ALBUMS_ID = "__ALBUMS__";
static final String GENRES_ID = "__GENRES__";
static final String ACTION_PLAY = "com.android.car.media.localmediaplayer.ACTION_PLAY";
static final String ACTION_PAUSE = "com.android.car.media.localmediaplayer.ACTION_PAUSE";
static final String ACTION_NEXT = "com.android.car.media.localmediaplayer.ACTION_NEXT";
static final String ACTION_PREV = "com.android.car.media.localmediaplayer.ACTION_PREV";
private BrowserRoot mRoot = new BrowserRoot(ROOT_ID, null);
List<MediaBrowser.MediaItem> mRootItems = new ArrayList<>();
private DataModel mDataModel;
private Player mPlayer;
private MediaSession mSession;
private String mLastCategory;
private BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == null) {
return;
}
switch (intent.getAction()) {
case ACTION_PLAY:
mPlayer.onPlay();
break;
case ACTION_PAUSE:
mPlayer.onPause();
break;
case ACTION_NEXT:
mPlayer.onSkipToNext();
break;
case ACTION_PREV:
mPlayer.onSkipToPrevious();
break;
default:
Log.w(TAG, "Ingoring intent with unknown action=" + intent);
}
}
};
private void addRootItems() {
MediaDescription folders = new MediaDescription.Builder()
.setMediaId(FOLDERS_ID)
.setTitle(getString(R.string.folders_title))
.setIconUri(Utils.getUriForResource(this, R.drawable.ic_folder))
.build();
mRootItems.add(new MediaBrowser.MediaItem(folders, MediaBrowser.MediaItem.FLAG_BROWSABLE));
MediaDescription albums = new MediaDescription.Builder()
.setMediaId(ALBUMS_ID)
.setTitle(getString(R.string.albums_title))
.setIconUri(Utils.getUriForResource(this, R.drawable.ic_album))
.build();
mRootItems.add(new MediaBrowser.MediaItem(albums, MediaBrowser.MediaItem.FLAG_BROWSABLE));
MediaDescription artists = new MediaDescription.Builder()
.setMediaId(ARTISTS_ID)
.setTitle(getString(R.string.artists_title))
.setIconUri(Utils.getUriForResource(this, R.drawable.ic_artist))
.build();
mRootItems.add(new MediaBrowser.MediaItem(artists, MediaBrowser.MediaItem.FLAG_BROWSABLE));
MediaDescription genres = new MediaDescription.Builder()
.setMediaId(GENRES_ID)
.setTitle(getString(R.string.genres_title))
.setIconUri(Utils.getUriForResource(this, R.drawable.ic_genre))
.build();
mRootItems.add(new MediaBrowser.MediaItem(genres, MediaBrowser.MediaItem.FLAG_BROWSABLE));
}
@Override
public void onCreate() {
super.onCreate();
mDataModel = new DataModel(this);
addRootItems();
mSession = new MediaSession(this, MEDIA_SESSION_TAG);
setSessionToken(mSession.getSessionToken());
mPlayer = new Player(this, mSession, mDataModel);
mSession.setCallback(mPlayer);
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
| MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
mPlayer.maybeRestoreState();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_PLAY);
filter.addAction(ACTION_PAUSE);
filter.addAction(ACTION_NEXT);
filter.addAction(ACTION_PREV);
registerReceiver(mNotificationReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
}
@Override
public void onDestroy() {
mPlayer.saveState();
mPlayer.destroy();
mSession.release();
unregisterReceiver(mNotificationReceiver);
super.onDestroy();
}
@Nullable
@Override
public BrowserRoot onGetRoot(String clientName, int clientUid, Bundle rootHints) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onGetRoot clientName=" + clientName);
}
return mRoot;
}
@Override
public void onLoadChildren(String parentId, Result<List<MediaBrowser.MediaItem>> result) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onLoadChildren parentId=" + parentId);
}
switch (parentId) {
case ROOT_ID:
result.sendResult(mRootItems);
mLastCategory = parentId;
break;
case FOLDERS_ID:
mDataModel.onQueryByFolder(parentId, result);
mLastCategory = parentId;
break;
case ALBUMS_ID:
mDataModel.onQueryByAlbum(parentId, result);
mLastCategory = parentId;
break;
case ARTISTS_ID:
mDataModel.onQueryByArtist(parentId, result);
mLastCategory = parentId;
break;
case GENRES_ID:
mDataModel.onQueryByGenre(parentId, result);
mLastCategory = parentId;
break;
default:
mDataModel.onQueryByKey(mLastCategory, parentId, result);
}
}
}