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 17 package com.android.car.stream.radio; 18 19 import android.app.PendingIntent; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.graphics.Bitmap; 24 import android.graphics.Canvas; 25 import android.graphics.drawable.VectorDrawable; 26 import android.support.annotation.ColorInt; 27 import com.android.car.radio.service.RadioStation; 28 import com.android.car.stream.MediaPlaybackExtension; 29 import com.android.car.stream.R; 30 import com.android.car.stream.StreamCard; 31 import com.android.car.stream.StreamConstants; 32 import com.android.car.stream.StreamServiceConstants; 33 34 /** 35 * A converter that is responsible for transforming a {@link RadioStation} into a 36 * {@link StreamCard}. 37 */ 38 public class RadioConverter { 39 /** 40 * The separator between the radio channel and band (e.g. between 99.7 and FM). 41 */ 42 private static final String CHANNEL_AND_BAND_SEPARATOR = " "; 43 44 private final Context mContext; 45 46 private final PendingIntent mGoToRadioAction; 47 private final PendingIntent mPauseAction; 48 private final PendingIntent mForwardSeekAction; 49 private final PendingIntent mBackwardSeekAction; 50 private final PendingIntent mPlayAction; 51 private final PendingIntent mStopAction; 52 53 @ColorInt 54 private final int mAccentColor; 55 56 private final Bitmap mPlayIcon; 57 private final Bitmap mPauseIcon; 58 RadioConverter(Context context)59 public RadioConverter(Context context) { 60 mContext = context; 61 62 mGoToRadioAction = createGoToRadioIntent(); 63 mPauseAction = createRadioActionIntent(RadioStreamProducer.ACTION_PAUSE); 64 mPlayAction = createRadioActionIntent(RadioStreamProducer.ACTION_PLAY); 65 mStopAction = createRadioActionIntent(RadioStreamProducer.ACTION_STOP); 66 mForwardSeekAction = createRadioActionIntent(RadioStreamProducer.ACTION_SEEK_FORWARD); 67 mBackwardSeekAction = createRadioActionIntent(RadioStreamProducer.ACTION_SEEK_BACKWARD); 68 69 mAccentColor = mContext.getColor(R.color.car_radio_accent_color); 70 71 int iconSize = context.getResources() 72 .getDimensionPixelSize(R.dimen.stream_card_secondary_icon_dimen); 73 mPlayIcon = getBitmap((VectorDrawable) 74 mContext.getDrawable(R.drawable.ic_play_arrow), iconSize, iconSize); 75 mPauseIcon = getBitmap((VectorDrawable) 76 mContext.getDrawable(R.drawable.ic_pause), iconSize, iconSize); 77 } 78 79 /** 80 * Converts the given {@link RadioStation} and play status into a {@link StreamCard} that can 81 * be used to display a radio card. 82 */ convert(RadioStation station, boolean isPlaying)83 public StreamCard convert(RadioStation station, boolean isPlaying) { 84 StreamCard.Builder builder = new StreamCard.Builder(StreamConstants.CARD_TYPE_MEDIA, 85 StreamConstants.RADIO_CARD_ID, System.currentTimeMillis()); 86 87 builder.setClickAction(mGoToRadioAction); 88 89 String title = createTitleText(station); 90 builder.setPrimaryText(title); 91 92 String subtitle = null; 93 if (station.getRds() != null) { 94 subtitle = station.getRds().getProgramService(); 95 builder.setSecondaryText(subtitle); 96 } 97 98 Bitmap icon = isPlaying ? mPlayIcon : mPauseIcon; 99 builder.setPrimaryIcon(icon); 100 101 MediaPlaybackExtension extension = new MediaPlaybackExtension(title, subtitle, 102 null /* albumArt */, mAccentColor, true /* canSkipToNext */, 103 true /* canSkipToPrevious */, true /* hasPause */, isPlaying, 104 mContext.getString(R.string.radio_app_name), mStopAction, mPauseAction, mPlayAction, 105 mForwardSeekAction, mBackwardSeekAction); 106 107 builder.setCardExtension(extension); 108 return builder.build(); 109 } 110 111 /** 112 * Returns the String that represents the title text of the radio card. The title should be 113 * a combination of the current channel number and radio band. 114 */ createTitleText(RadioStation station)115 private String createTitleText(RadioStation station) { 116 int radioBand = station.getRadioBand(); 117 String channel = RadioFormatter.formatRadioChannel(radioBand, 118 station.getChannelNumber()); 119 String band = RadioFormatter.formatRadioBand(mContext, radioBand); 120 121 return channel + CHANNEL_AND_BAND_SEPARATOR + band; 122 } 123 124 /** 125 * Returns an {@link Intent} that will take the user to the radio application. 126 */ createGoToRadioIntent()127 private PendingIntent createGoToRadioIntent() { 128 ComponentName radioComponent = new ComponentName( 129 mContext.getString(R.string.car_radio_component_package), 130 mContext.getString(R.string.car_radio_component_activity)); 131 132 Intent intent = new Intent(); 133 intent.setComponent(radioComponent); 134 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); 135 136 return PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 137 } 138 139 /** 140 * Returns an {@link Intent} that will perform the given action. 141 * 142 * @param action One of the action values in {@link RadioStreamProducer}. e.g. 143 * {@link RadioStreamProducer#ACTION_PAUSE}. 144 */ createRadioActionIntent(int action)145 private PendingIntent createRadioActionIntent(int action) { 146 Intent intent = new Intent(RadioStreamProducer.RADIO_INTENT_ACTION); 147 intent.setPackage(mContext.getPackageName()); 148 intent.putExtra(RadioStreamProducer.RADIO_ACTION_EXTRA, action); 149 150 return PendingIntent.getBroadcast(mContext, action /* requestCode */, 151 intent, PendingIntent.FLAG_CANCEL_CURRENT); 152 } 153 154 /** 155 * Returns a {@link Bitmap} that corresponds to the given {@link VectorDrawable}. 156 */ getBitmap(VectorDrawable vectorDrawable, int width, int height)157 private static Bitmap getBitmap(VectorDrawable vectorDrawable, int width, int height) { 158 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 159 Canvas canvas = new Canvas(bitmap); 160 vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 161 vectorDrawable.draw(canvas); 162 return bitmap; 163 } 164 } 165