• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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.bluetooth.audio_util;
18 
19 import android.content.Context;
20 import android.content.pm.PackageManager;
21 import android.media.MediaDescription;
22 import android.media.MediaMetadata;
23 import android.media.browse.MediaBrowser.MediaItem;
24 import android.media.session.MediaSession;
25 import android.os.Bundle;
26 import android.util.Log;
27 
28 import com.android.bluetooth.R;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 class Util {
34     public static String TAG = "audio_util.Util";
35     public static boolean DEBUG = false;
36 
37     private static final String GPM_KEY = "com.google.android.music.mediasession.music_metadata";
38 
39     // TODO (apanicke): Remove this prefix later, for now it makes debugging easier.
40     public static final String NOW_PLAYING_PREFIX = "NowPlayingId";
41 
42     /**
43      * Get an empty set of Metadata
44      */
empty_data()45     public static final Metadata empty_data() {
46         Metadata ret = new Metadata();
47         ret.mediaId = "Not Provided";
48         ret.title = "Not Provided";
49         ret.artist = "";
50         ret.album = "";
51         ret.genre = "";
52         ret.trackNum = "1";
53         ret.numTracks = "1";
54         ret.duration = "0";
55         ret.image = null;
56         return ret;
57     }
58 
59     /**
60      * Get whether or not Bluetooth is configured to support URI images or not.
61      *
62      * Note that creating URI images will dramatically increase memory usage.
63      */
areUriImagesSupported(Context context)64     public static boolean areUriImagesSupported(Context context) {
65         if (context == null) return false;
66         return context.getResources().getBoolean(R.bool.avrcp_target_cover_art_uri_images);
67     }
68 
69     /**
70      * Translate a bundle of MediaMetadata keys to audio_util's Metadata
71      */
toMetadata(Context context, Bundle bundle)72     public static Metadata toMetadata(Context context, Bundle bundle) {
73         Metadata.Builder builder = new Metadata.Builder();
74         return builder.useContext(context).useDefaults().fromBundle(bundle).build();
75     }
76 
77     /**
78      * Translate a MediaDescription to audio_util's Metadata
79      */
toMetadata(Context context, MediaDescription desc)80     public static Metadata toMetadata(Context context, MediaDescription desc) {
81         // Find GPM_KEY data if it exists
82         MediaMetadata data = null;
83         Bundle extras = (desc != null ? desc.getExtras() : null);
84         if (extras != null && extras.containsKey(GPM_KEY)) {
85             data = (MediaMetadata) extras.get(GPM_KEY);
86         }
87 
88         Metadata.Builder builder = new Metadata.Builder();
89         return builder.useContext(context).useDefaults().fromMediaDescription(desc)
90                 .fromMediaMetadata(data).build();
91     }
92 
93     /**
94      * Translate a MediaItem to audio_util's Metadata
95      */
toMetadata(Context context, MediaItem item)96     public static Metadata toMetadata(Context context, MediaItem item) {
97         Metadata.Builder builder = new Metadata.Builder();
98         return builder.useContext(context).useDefaults().fromMediaItem(item).build();
99     }
100 
101     /**
102      * Translate a MediaSession.QueueItem to audio_util's Metadata
103      */
toMetadata(Context context, MediaSession.QueueItem item)104     public static Metadata toMetadata(Context context, MediaSession.QueueItem item) {
105         Metadata.Builder builder = new Metadata.Builder().useDefaults().fromQueueItem(item);
106         // For Queue Items, the Media Id will always be just its Queue ID
107         // We don't need to use its actual ID since we don't promise UIDS being valid
108         // between a file system and it's now playing list.
109         if (item != null) builder.setMediaId(NOW_PLAYING_PREFIX + item.getQueueId());
110         return builder.build();
111     }
112 
113     /**
114      * Translate a MediaMetadata to audio_util's Metadata
115      */
toMetadata(Context context, MediaMetadata data)116     public static Metadata toMetadata(Context context, MediaMetadata data) {
117         Metadata.Builder builder = new Metadata.Builder();
118         // This will always be currsong. The AVRCP service will overwrite the mediaId if it needs to
119         // TODO (apanicke): Remove when the service is ready, right now it makes debugging much more
120         // convenient
121         return builder.useContext(context).useDefaults().fromMediaMetadata(data)
122                 .setMediaId("currsong").build();
123     }
124 
125     /**
126      * Translate a list of MediaSession.QueueItem to a list of audio_util's Metadata
127      */
toMetadataList(Context context, List<MediaSession.QueueItem> items)128     public static List<Metadata> toMetadataList(Context context,
129             List<MediaSession.QueueItem> items) {
130         ArrayList<Metadata> list = new ArrayList<Metadata>();
131 
132         if (items == null) return list;
133 
134         for (int i = 0; i < items.size(); i++) {
135             Metadata data = toMetadata(context, items.get(i));
136             data.trackNum = "" + (i + 1);
137             data.numTracks = "" + items.size();
138             list.add(data);
139         }
140 
141         return list;
142     }
143 
144     // Helper method to close a list of ListItems so that if the callee wants
145     // to mutate the list they can do it without affecting any internally cached info
cloneList(List<ListItem> list)146     public static List<ListItem> cloneList(List<ListItem> list) {
147         List<ListItem> clone = new ArrayList<ListItem>(list.size());
148         for (ListItem item : list) clone.add(item.clone());
149         return clone;
150     }
151 
getDisplayName(Context context, String packageName)152     public static String getDisplayName(Context context, String packageName) {
153         try {
154             PackageManager manager = context.getPackageManager();
155             return manager.getApplicationLabel(manager.getApplicationInfo(packageName, 0))
156                     .toString();
157         } catch (Exception e) {
158             Log.w(TAG, "Name Not Found using package name: " + packageName);
159             return packageName;
160         }
161     }
162 }
163