1 /* 2 * Copyright 2018 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.android.car.media.common.browse; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.UiThread; 22 import android.support.v4.media.MediaBrowserCompat; 23 24 import androidx.lifecycle.LiveData; 25 import androidx.lifecycle.ViewModelProvider; 26 27 import com.android.car.arch.common.FutureData; 28 import com.android.car.media.common.MediaItemMetadata; 29 import com.android.car.media.common.source.MediaSourceViewModel; 30 31 import java.util.List; 32 33 /** 34 * Contains observable data needed for displaying playback and browse UI. Instances can be obtained 35 * via {@link MediaBrowserViewModel.Factory} 36 */ 37 public interface MediaBrowserViewModel { 38 39 /** 40 * Possible states of the application UI 41 */ 42 enum BrowseState { 43 /** There is no content to show */ 44 EMPTY, 45 /** We are still in the process of obtaining data */ 46 LOADING, 47 /** Data has been loaded */ 48 LOADED, 49 /** The content can't be shown due an error */ 50 ERROR 51 } 52 53 /** 54 * Returns a LiveData that emits the current package name of the browser's service component. 55 */ getPackageName()56 LiveData<String> getPackageName(); 57 58 /** 59 * Returns a LiveData that emits the current {@link BrowseState} 60 */ getBrowseState()61 LiveData<BrowseState> getBrowseState(); 62 63 64 /** 65 * Fetches the MediaItemMetadatas for the current browsed id, and the loading status of the 66 * fetch operation. 67 * 68 * This LiveData will never emit {@code null}. If the data is loading, the data component of the 69 * {@link FutureData} will be null 70 * A MediaSource must be selected and its MediaBrowser connected, otherwise the FutureData will 71 * always contain a {@code null} data value. 72 * 73 * @return a LiveData that emits a FutureData that contains the loading status and the 74 * MediaItemMetadatas for the current browsed id 75 */ getBrowsedMediaItems()76 LiveData<FutureData<List<MediaItemMetadata>>> getBrowsedMediaItems(); 77 78 /** 79 * Fetches the MediaItemMetadatas for the current search query, and the loading status of the 80 * fetch operation. 81 * 82 * See {@link #getBrowsedMediaItems()} 83 */ getSearchedMediaItems()84 LiveData<FutureData<List<MediaItemMetadata>>> getSearchedMediaItems(); 85 86 87 /** 88 * Returns a LiveData that emits whether the media browser supports search. This wil never emit 89 * {@code null} 90 */ supportsSearch()91 LiveData<Boolean> supportsSearch(); 92 93 /** 94 * Gets the content style display type of browsable elements in this media browser, set at the 95 * browse root 96 */ rootBrowsableHint()97 LiveData<Integer> rootBrowsableHint(); 98 99 /** 100 * Gets the content style display type of playable elements in this media browser, set at the 101 * browse root 102 */ rootPlayableHint()103 LiveData<Integer> rootPlayableHint(); 104 105 /** 106 * A {@link MediaBrowserViewModel} whose selected browse ID may be changed. 107 */ 108 interface WithMutableBrowseId extends MediaBrowserViewModel { 109 110 /** 111 * Set the current item to be browsed. If available, the list of items will be emitted by 112 * {@link #getBrowsedMediaItems()}. 113 */ 114 @UiThread setCurrentBrowseId(@onNull String browseId)115 void setCurrentBrowseId(@NonNull String browseId); 116 117 /** 118 * Set the current item to be searched for. If available, the list of items will be emitted 119 * by {@link #getBrowsedMediaItems()}. 120 */ 121 @UiThread search(@ullable String query)122 void search(@Nullable String query); 123 } 124 125 /** 126 * Creates and/or fetches {@link MediaBrowserViewModel} instances. 127 */ 128 class Factory { 129 130 private static final String KEY_BROWSER_ROOT = 131 "com.android.car.media.common.browse.MediaBrowserViewModel.Factory.browserRoot"; 132 133 /** 134 * Returns an initialized {@link MediaBrowserViewModel.WithMutableBrowseId} with the 135 * provided connected media browser. The provided {@code mediaBrowser} does not need to be 136 * from the same scope as {@code viewModelProvider}. 137 */ 138 @NonNull getInstanceWithMediaBrowser( @onNull String key, @NonNull ViewModelProvider viewModelProvider, @NonNull LiveData<MediaBrowserCompat> mediaBrowser)139 public static MediaBrowserViewModel.WithMutableBrowseId getInstanceWithMediaBrowser( 140 @NonNull String key, 141 @NonNull ViewModelProvider viewModelProvider, 142 @NonNull LiveData<MediaBrowserCompat> mediaBrowser) { 143 MutableMediaBrowserViewModel viewModel = 144 viewModelProvider.get(key, MutableMediaBrowserViewModel.class); 145 initMediaBrowser(mediaBrowser, viewModel); 146 return viewModel; 147 } 148 149 /** 150 * Fetch an initialized {@link MediaBrowserViewModel}. It will get its media browser from 151 * the {@link MediaSourceViewModel} provided by {@code viewModelProvider}. It will already 152 * be configured to browse the root of the browser. 153 * 154 * @param mediaSourceVM the {@link MediaSourceViewModel} singleton. 155 * @param viewModelProvider the ViewModelProvider to load ViewModels from. 156 * @return an initialized MediaBrowserViewModel configured to browse the specified browseId. 157 */ 158 @NonNull getInstanceForBrowseRoot( MediaSourceViewModel mediaSourceVM, @NonNull ViewModelProvider viewModelProvider)159 public static MediaBrowserViewModel getInstanceForBrowseRoot( 160 MediaSourceViewModel mediaSourceVM, @NonNull ViewModelProvider viewModelProvider) { 161 RootMediaBrowserViewModel viewModel = 162 viewModelProvider.get(KEY_BROWSER_ROOT, RootMediaBrowserViewModel.class); 163 initMediaBrowser(mediaSourceVM.getConnectedMediaBrowser(), viewModel); 164 return viewModel; 165 } 166 initMediaBrowser( @onNull LiveData<MediaBrowserCompat> connectedMediaBrowser, MediaBrowserViewModelImpl viewModel)167 private static void initMediaBrowser( 168 @NonNull LiveData<MediaBrowserCompat> connectedMediaBrowser, 169 MediaBrowserViewModelImpl viewModel) { 170 if (viewModel.getMediaBrowserSource() != connectedMediaBrowser) { 171 viewModel.setConnectedMediaBrowser(connectedMediaBrowser); 172 } 173 } 174 } 175 } 176