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 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 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 */ 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 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 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