1 /* 2 * Copyright (c) 2016, 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 package com.android.car.stream.media; 17 18 import android.app.PendingIntent; 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.graphics.Bitmap; 23 import android.graphics.Canvas; 24 import android.graphics.drawable.VectorDrawable; 25 import android.view.KeyEvent; 26 import android.widget.RemoteViews; 27 import com.android.car.stream.MediaPlaybackExtension; 28 import com.android.car.stream.R; 29 import com.android.car.stream.StreamCard; 30 import com.android.car.stream.StreamConstants; 31 import com.android.car.stream.StreamServiceConstants; 32 33 /** 34 * A converter that creates a {@link StreamCard} for currently playing media. 35 */ 36 public class MediaConverter { 37 private final PendingIntent mGotoMediaFacetAction; 38 private final PendingIntent mPauseAction; 39 private final PendingIntent mSkipToNextAction; 40 private final PendingIntent mSkipToPreviousAction; 41 private final PendingIntent mPlayAction; 42 private final PendingIntent mStopAction; 43 44 private Bitmap mPlayIcon; 45 private Bitmap mPauseIcon; 46 MediaConverter(Context context)47 public MediaConverter(Context context) { 48 String mediaPackage = context.getString(R.string.car_media_component_package); 49 mGotoMediaFacetAction = createGoToMediaFacetIntent(context, mediaPackage); 50 51 mPauseAction = getMediaActionIntent(context, 52 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PAUSE), 53 KeyEvent.KEYCODE_MEDIA_PAUSE /* requestCode */); 54 55 mSkipToNextAction = getMediaActionIntent(context, 56 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD), 57 KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD /* requestCode */); 58 59 mSkipToPreviousAction = getMediaActionIntent(context, 60 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD), 61 KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD /* requestCode */); 62 63 64 mPlayAction = getMediaActionIntent(context, 65 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY), 66 KeyEvent.KEYCODE_MEDIA_PLAY /* requestCode */); 67 68 mStopAction = getMediaActionIntent(context, 69 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP), 70 KeyEvent.KEYCODE_MEDIA_STOP /* requestCode */); 71 72 int iconSize = context.getResources() 73 .getDimensionPixelSize(R.dimen.stream_card_secondary_icon_dimen); 74 mPlayIcon = getBitmap((VectorDrawable) 75 context.getDrawable(R.drawable.ic_play_arrow), iconSize, iconSize); 76 mPauseIcon = getBitmap((VectorDrawable) 77 context.getDrawable(R.drawable.ic_pause), iconSize, iconSize); 78 } 79 convert( String title, String subtitle, Bitmap albumArt, int appAccentColor, String appName, boolean canSkipToNext, boolean canSkipToPrevious, boolean hasPause, boolean isPlaying)80 public StreamCard convert( 81 String title, 82 String subtitle, 83 Bitmap albumArt, 84 int appAccentColor, 85 String appName, 86 boolean canSkipToNext, 87 boolean canSkipToPrevious, 88 boolean hasPause, 89 boolean isPlaying) { 90 91 StreamCard.Builder builder = new StreamCard.Builder(StreamConstants.CARD_TYPE_MEDIA, 92 StreamConstants.MEDIA_CARD_ID, System.currentTimeMillis()); 93 builder.setClickAction(mGotoMediaFacetAction); 94 builder.setPrimaryText(title); 95 builder.setSecondaryText(subtitle); 96 Bitmap icon = isPlaying ? mPlayIcon : mPauseIcon; 97 builder.setPrimaryIcon(icon); 98 99 MediaPlaybackExtension extension = new MediaPlaybackExtension(title, subtitle, albumArt, 100 appAccentColor, canSkipToNext, canSkipToPrevious, hasPause, isPlaying, appName, 101 mStopAction, mPauseAction, mPlayAction, mSkipToNextAction, mSkipToPreviousAction); 102 103 builder.setCardExtension(extension); 104 return builder.build(); 105 } 106 107 /** 108 * Attaches a {@link PendingIntent} to the given {@link RemoteViews}. The PendingIntent will 109 * send the user to the CarMediaApp when touched. Note that this does not resolve to the 110 * application currently in the media card; instead, it just opens the last music app. For 111 * example, if the card is generated by Google Play Music, but the last opened music app 112 * was Spotify, then Spotify will open when the music card is tapped. 113 */ createGoToMediaFacetIntent(Context context, String mediaPackage)114 private PendingIntent createGoToMediaFacetIntent(Context context, String mediaPackage) { 115 Intent intent = context.getPackageManager().getLaunchIntentForPackage(mediaPackage); 116 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); 117 118 return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 119 } 120 getMediaActionIntent(Context context, KeyEvent ke, int requestCode)121 private PendingIntent getMediaActionIntent(Context context, KeyEvent ke, int requestCode) { 122 Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON); 123 i.setPackage(context.getPackageName()); 124 i.putExtra(Intent.EXTRA_KEY_EVENT, ke); 125 126 PendingIntent pendingIntent = 127 PendingIntent.getBroadcast( 128 context, 129 requestCode, 130 i, 131 PendingIntent.FLAG_CANCEL_CURRENT 132 ); 133 return pendingIntent; 134 } 135 getBitmap(VectorDrawable vectorDrawable, int width, int height)136 private static Bitmap getBitmap(VectorDrawable vectorDrawable, int width, int height) { 137 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 138 Canvas canvas = new Canvas(bitmap); 139 vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 140 vectorDrawable.draw(canvas); 141 return bitmap; 142 } 143 } 144