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.radio; 18 19 import android.content.Intent; 20 import android.hardware.radio.RadioManager; 21 import android.os.Bundle; 22 import android.support.v4.app.Fragment; 23 import android.util.Log; 24 25 import com.android.car.app.CarDrawerActivity; 26 import com.android.car.app.CarDrawerAdapter; 27 import com.android.car.app.DrawerItemViewHolder; 28 import com.android.car.radio.service.RadioStation; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * The main activity for the radio. This activity initializes the radio controls and listener for 35 * radio changes. 36 */ 37 public class CarRadioActivity extends CarDrawerActivity implements 38 RadioPresetsFragment.PresetListExitListener, 39 MainRadioFragment.RadioPresetListClickListener, 40 ManualTunerFragment.ManualTunerCompletionListener { 41 private static final String TAG = "Em.RadioActivity"; 42 private static final String MANUAL_TUNER_BACKSTACK = "ManualTunerBackstack"; 43 44 private static final int[] SUPPORTED_RADIO_BANDS = new int[] { 45 RadioManager.BAND_AM, RadioManager.BAND_FM }; 46 47 /** 48 * Intent action for notifying that the radio state has changed. 49 */ 50 private static final String ACTION_RADIO_APP_STATE_CHANGE 51 = "android.intent.action.RADIO_APP_STATE_CHANGE"; 52 53 /** 54 * Boolean Intent extra indicating if the radio is the currently in the foreground. 55 */ 56 private static final String EXTRA_RADIO_APP_FOREGROUND 57 = "android.intent.action.RADIO_APP_STATE"; 58 59 private RadioController mRadioController; 60 private MainRadioFragment mMainFragment; 61 private boolean mTunerOpened; 62 63 private FragmentWithFade mCurrentFragment; 64 65 @Override onCreate(Bundle savedInstanceState)66 protected void onCreate(Bundle savedInstanceState) { 67 super.onCreate(savedInstanceState); 68 69 mRadioController = new RadioController(this); 70 mMainFragment = MainRadioFragment.newInstance(mRadioController); 71 mMainFragment.setPresetListClickListener(this); 72 setContentFragment(mMainFragment); 73 mCurrentFragment = mMainFragment; 74 } 75 76 @Override getRootAdapter()77 protected CarDrawerAdapter getRootAdapter() { 78 return new RadioDrawerAdapter(); 79 } 80 81 @Override onPresetListClicked()82 public void onPresetListClicked() { 83 mMainFragment.setPresetListClickListener(null); 84 85 RadioPresetsFragment fragment = 86 RadioPresetsFragment.newInstance(mRadioController); 87 fragment.setPresetListExitListener(this); 88 89 setContentFragment(fragment); 90 mCurrentFragment = fragment; 91 } 92 93 @Override OnPresetListExit()94 public void OnPresetListExit() { 95 mMainFragment.setPresetListClickListener(this); 96 setContentFragment(mMainFragment); 97 mCurrentFragment = mMainFragment; 98 } 99 startManualTuner()100 public void startManualTuner() { 101 if (mTunerOpened) { 102 return; 103 } 104 105 mCurrentFragment.fadeOutContent(); 106 107 ManualTunerFragment fragment = 108 ManualTunerFragment.newInstance(mRadioController.getCurrentRadioBand()); 109 fragment.setManualTunerCompletionListener(this); 110 111 getSupportFragmentManager().beginTransaction() 112 .setCustomAnimations(R.anim.slide_up, R.anim.slide_down, 113 R.anim.slide_up, R.anim.slide_down) 114 .add(getContentContainerId(), fragment) 115 .addToBackStack(MANUAL_TUNER_BACKSTACK) 116 .commitAllowingStateLoss(); 117 118 mTunerOpened = true; 119 } 120 121 @Override onStationSelected(RadioStation station)122 public void onStationSelected(RadioStation station) { 123 // A station can only be selected if the manual tuner fragment has been shown; so, remove 124 // that here. 125 getSupportFragmentManager().popBackStack(); 126 mCurrentFragment.fadeInContent(); 127 128 if (station != null) { 129 mRadioController.tuneToRadioChannel(station); 130 } 131 132 mTunerOpened = false; 133 } 134 135 @Override onStart()136 protected void onStart() { 137 super.onStart(); 138 139 if (Log.isLoggable(TAG, Log.DEBUG)) { 140 Log.d(TAG, "onStart"); 141 } 142 143 mRadioController.start(); 144 145 Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE); 146 broadcast.putExtra(EXTRA_RADIO_APP_FOREGROUND, true); 147 sendBroadcast(broadcast); 148 } 149 150 @Override onStop()151 protected void onStop() { 152 super.onStop(); 153 154 if (Log.isLoggable(TAG, Log.DEBUG)) { 155 Log.d(TAG, "onStop"); 156 } 157 158 Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE); 159 broadcast.putExtra(EXTRA_RADIO_APP_FOREGROUND, false); 160 sendBroadcast(broadcast); 161 } 162 163 @Override onDestroy()164 protected void onDestroy() { 165 super.onDestroy(); 166 167 if (Log.isLoggable(TAG, Log.DEBUG)) { 168 Log.d(TAG, "onDestroy"); 169 } 170 171 mRadioController.shutdown(); 172 } 173 setContentFragment(Fragment fragment)174 private void setContentFragment(Fragment fragment) { 175 getSupportFragmentManager().beginTransaction() 176 .replace(getContentContainerId(), fragment) 177 .commit(); 178 } 179 180 private class RadioDrawerAdapter extends CarDrawerAdapter { 181 private final List<String> mDrawerOptions = 182 new ArrayList<>(SUPPORTED_RADIO_BANDS.length + 1); 183 RadioDrawerAdapter()184 RadioDrawerAdapter() { 185 super(CarRadioActivity.this, 186 false /* showDisabledListOnEmpty */, 187 true /* useSmallLayout */ ); 188 setTitle(getString(R.string.app_name)); 189 // The ordering of options is hardcoded. The click handler below depends on it. 190 for (int band : SUPPORTED_RADIO_BANDS) { 191 String bandText = 192 RadioChannelFormatter.formatRadioBand(CarRadioActivity.this, band); 193 mDrawerOptions.add(bandText); 194 } 195 mDrawerOptions.add(getString(R.string.manual_tuner_drawer_entry)); 196 } 197 198 @Override getActualItemCount()199 protected int getActualItemCount() { 200 return mDrawerOptions.size(); 201 } 202 203 @Override populateViewHolder(DrawerItemViewHolder holder, int position)204 public void populateViewHolder(DrawerItemViewHolder holder, int position) { 205 holder.getTitle().setText(mDrawerOptions.get(position)); 206 } 207 208 @Override onItemClick(int position)209 public void onItemClick(int position) { 210 closeDrawer(); 211 if (position < SUPPORTED_RADIO_BANDS.length) { 212 mRadioController.openRadioBand(SUPPORTED_RADIO_BANDS[position]); 213 } else if (position == SUPPORTED_RADIO_BANDS.length) { 214 startManualTuner(); 215 } else { 216 Log.w(TAG, "Unexpected position: " + position); 217 } 218 } 219 } 220 } 221