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.os.Bundle; 20 import android.support.v4.media.MediaBrowserCompat; 21 22 import androidx.annotation.NonNull; 23 import androidx.annotation.Nullable; 24 25 import com.android.car.media.common.MediaConstants; 26 import com.android.car.media.common.MediaItemMetadata; 27 28 import java.util.ArrayList; 29 import java.util.Collection; 30 import java.util.Collections; 31 import java.util.HashSet; 32 import java.util.List; 33 import java.util.function.Predicate; 34 import java.util.stream.Collectors; 35 36 /** 37 * TODO: rename to MediaBrowserUtils. 38 * Provides utility methods for {@link MediaBrowserCompat}. 39 */ 40 public class MediaBrowserViewModelImpl { 41 MediaBrowserViewModelImpl()42 private MediaBrowserViewModelImpl() { 43 } 44 45 /** 46 * Filters the items that are valid for the root (tabs) or the current node. Returns null when 47 * the given list is null to preserve its error signal. 48 */ 49 @Nullable filterItems(boolean forRoot, @Nullable List<MediaItemMetadata> items)50 public static List<MediaItemMetadata> filterItems(boolean forRoot, 51 @Nullable List<MediaItemMetadata> items) { 52 if (items == null) return null; 53 Predicate<MediaItemMetadata> predicate = forRoot ? MediaItemMetadata::isBrowsable 54 : item -> (item.isPlayable() || item.isBrowsable()); 55 return items.stream().filter(predicate).collect(Collectors.toList()); 56 } 57 58 /** Returns only the browse-able items from the given list. */ 59 @Nullable selectBrowseableItems( @ullable List<MediaItemMetadata> items)60 public static List<MediaItemMetadata> selectBrowseableItems( 61 @Nullable List<MediaItemMetadata> items) { 62 if (items == null) return null; 63 Predicate<MediaItemMetadata> predicate = MediaItemMetadata::isBrowsable; 64 return items.stream().filter(predicate).collect(Collectors.toList()); 65 } 66 67 68 @SuppressWarnings("deprecation") getSupportsSearch(@ullable MediaBrowserCompat mediaBrowserCompat)69 public static boolean getSupportsSearch(@Nullable MediaBrowserCompat mediaBrowserCompat) { 70 if (mediaBrowserCompat == null) { 71 return false; 72 } 73 Bundle extras = mediaBrowserCompat.getExtras(); 74 if (extras == null) { 75 return false; 76 } 77 if (extras.containsKey(MediaConstants.MEDIA_SEARCH_SUPPORTED)) { 78 return extras.getBoolean(MediaConstants.MEDIA_SEARCH_SUPPORTED); 79 } 80 if (extras.containsKey(MediaConstants.MEDIA_SEARCH_SUPPORTED_PRERELEASE)) { 81 return extras.getBoolean(MediaConstants.MEDIA_SEARCH_SUPPORTED_PRERELEASE); 82 } 83 return false; 84 } 85 86 @SuppressWarnings("deprecation") getRootBrowsableHint(@ullable MediaBrowserCompat mediaBrowserCompat)87 public static int getRootBrowsableHint(@Nullable MediaBrowserCompat mediaBrowserCompat) { 88 if (mediaBrowserCompat == null) { 89 return 0; 90 } 91 Bundle extras = mediaBrowserCompat.getExtras(); 92 if (extras == null) { 93 return 0; 94 } 95 if (extras.containsKey(MediaConstants.CONTENT_STYLE_BROWSABLE_HINT)) { 96 return extras.getInt(MediaConstants.CONTENT_STYLE_BROWSABLE_HINT, 0); 97 } 98 if (extras.containsKey(MediaConstants.CONTENT_STYLE_BROWSABLE_HINT_PRERELEASE)) { 99 return extras.getInt(MediaConstants.CONTENT_STYLE_BROWSABLE_HINT_PRERELEASE, 0); 100 } 101 return 0; 102 } 103 104 @SuppressWarnings("deprecation") getRootPlayableHint(@ullable MediaBrowserCompat mediaBrowserCompat)105 public static int getRootPlayableHint(@Nullable MediaBrowserCompat mediaBrowserCompat) { 106 if (mediaBrowserCompat == null) { 107 return 0; 108 } 109 Bundle extras = mediaBrowserCompat.getExtras(); 110 if (extras == null) { 111 return 0; 112 } 113 if (extras.containsKey(MediaConstants.CONTENT_STYLE_PLAYABLE_HINT)) { 114 return extras.getInt(MediaConstants.CONTENT_STYLE_PLAYABLE_HINT, 0); 115 } 116 if (extras.containsKey(MediaConstants.CONTENT_STYLE_PLAYABLE_HINT_PRERELEASE)) { 117 return extras.getInt(MediaConstants.CONTENT_STYLE_PLAYABLE_HINT_PRERELEASE, 0); 118 } 119 return 0; 120 } 121 122 /** Returns the elements of oldList that do NOT appear in newList. */ computeRemovedItems( @ullable List<MediaItemMetadata> oldList, @Nullable List<MediaItemMetadata> newList)123 public static @NonNull Collection<MediaItemMetadata> computeRemovedItems( 124 @Nullable List<MediaItemMetadata> oldList, @Nullable List<MediaItemMetadata> newList) { 125 if (oldList == null || oldList.isEmpty()) { 126 // Nothing was removed 127 return Collections.emptyList(); 128 } 129 130 if (newList == null || newList.isEmpty()) { 131 // Everything was removed 132 return new ArrayList<>(oldList); 133 } 134 135 HashSet<MediaItemMetadata> itemsById = new HashSet<>(oldList); 136 itemsById.removeAll(newList); 137 return itemsById; 138 } 139 } 140