release-request-051da47e-713f-4e09-8f6c-698fb4d4e92e-for-git_oc-dr1-release-3997165 snap-temp-L04400000062809322

Change-Id: I3a7d57f769a4752f56555b441731f5e5f2ed9dbe
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ca7ad2a..e7d0c10 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -18,8 +18,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.car.radio">
     <uses-sdk
-        android:minSdkVersion="23"
-        android:targetSdkVersion="23" />
+        android:minSdkVersion="25"
+        android:targetSdkVersion="25" />
 
     <!-- This permission is required to allow the radio to be muted. -->
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
diff --git a/src/com/android/car/radio/CarRadioActivity.java b/src/com/android/car/radio/CarRadioActivity.java
index 4aa4261..c278bbc 100644
--- a/src/com/android/car/radio/CarRadioActivity.java
+++ b/src/com/android/car/radio/CarRadioActivity.java
@@ -19,7 +19,9 @@
 import android.content.Intent;
 import android.hardware.radio.RadioManager;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
 import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
 import android.util.Log;
 
 import com.android.car.app.CarDrawerActivity;
@@ -39,7 +41,8 @@
         MainRadioFragment.RadioPresetListClickListener,
         ManualTunerFragment.ManualTunerCompletionListener {
     private static final String TAG = "Em.RadioActivity";
-    private static final String MANUAL_TUNER_BACKSTACK = "ManualTunerBackstack";
+    private static final String MANUAL_TUNER_BACKSTACK = "MANUAL_TUNER_BACKSTACK";
+    private static final String CONTENT_FRAGMENT_TAG = "CONTENT_FRAGMENT_TAG";
 
     private static final int[] SUPPORTED_RADIO_BANDS = new int[] {
         RadioManager.BAND_AM, RadioManager.BAND_FM };
@@ -56,21 +59,26 @@
     private static final String EXTRA_RADIO_APP_FOREGROUND
             = "android.intent.action.RADIO_APP_STATE";
 
-    private RadioController mRadioController;
-    private MainRadioFragment mMainFragment;
-    private boolean mTunerOpened;
+    /**
+     * Whether or not it is safe to make transactions on the
+     * {@link android.support.v4.app.FragmentManager}. This variable prevents a possible exception
+     * when calling commit() on the FragmentManager.
+     *
+     * <p>The default value is {@code true} because it is only after
+     * {@link #onSaveInstanceState(Bundle)} has been called that fragment commits are not allowed.
+     */
+    private boolean mAllowFragmentCommits = true;
 
-    private FragmentWithFade mCurrentFragment;
+    private RadioController mRadioController;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         mRadioController = new RadioController(this);
-        mMainFragment = MainRadioFragment.newInstance(mRadioController);
-        mMainFragment.setPresetListClickListener(this);
-        setContentFragment(mMainFragment);
-        mCurrentFragment = mMainFragment;
+        setContentFragment(
+                MainRadioFragment.newInstance(mRadioController, this /* clickListener */));
+
     }
 
     @Override
@@ -80,56 +88,50 @@
 
     @Override
     public void onPresetListClicked() {
-        mMainFragment.setPresetListClickListener(null);
-
-        RadioPresetsFragment fragment =
-                RadioPresetsFragment.newInstance(mRadioController);
-        fragment.setPresetListExitListener(this);
-
-        setContentFragment(fragment);
-        mCurrentFragment = fragment;
+        setContentFragment(
+                RadioPresetsFragment.newInstance(mRadioController, this /* existListener */));
     }
 
     @Override
     public void OnPresetListExit() {
-        mMainFragment.setPresetListClickListener(this);
-        setContentFragment(mMainFragment);
-        mCurrentFragment = mMainFragment;
+        setContentFragment(
+                MainRadioFragment.newInstance(mRadioController, this /* clickListener */));
     }
 
-    public void startManualTuner() {
-        if (mTunerOpened) {
+    private void startManualTuner() {
+        if (!mAllowFragmentCommits || getSupportFragmentManager().getBackStackEntryCount() > 0) {
             return;
         }
 
-        mCurrentFragment.fadeOutContent();
+        Fragment currentFragment = getCurrentFragment();
+        if (currentFragment instanceof FragmentWithFade) {
+            ((FragmentWithFade) currentFragment).fadeOutContent();
+        }
 
-        ManualTunerFragment fragment =
+        ManualTunerFragment tunerFragment =
                 ManualTunerFragment.newInstance(mRadioController.getCurrentRadioBand());
-        fragment.setManualTunerCompletionListener(this);
+        tunerFragment.setManualTunerCompletionListener(this);
 
         getSupportFragmentManager().beginTransaction()
                 .setCustomAnimations(R.anim.slide_up, R.anim.slide_down,
                         R.anim.slide_up, R.anim.slide_down)
-                .add(getContentContainerId(), fragment)
+                .add(getContentContainerId(), tunerFragment)
                 .addToBackStack(MANUAL_TUNER_BACKSTACK)
-                .commitAllowingStateLoss();
-
-        mTunerOpened = true;
+                .commit();
     }
 
     @Override
     public void onStationSelected(RadioStation station) {
-        // A station can only be selected if the manual tuner fragment has been shown; so, remove
-        // that here.
-        getSupportFragmentManager().popBackStack();
-        mCurrentFragment.fadeInContent();
+        maybeDismissManualTuner();
+
+        Fragment fragment = getCurrentFragment();
+        if (fragment instanceof FragmentWithFade) {
+            ((FragmentWithFade) fragment).fadeInContent();
+        }
 
         if (station != null) {
             mRadioController.tuneToRadioChannel(station);
         }
-
-        mTunerOpened = false;
     }
 
     @Override
@@ -140,6 +142,10 @@
             Log.d(TAG, "onStart");
         }
 
+        // Fragment commits are not allowed once the Activity's state has been saved. Once
+        // onStart() has been called, the FragmentManager should now allow commits.
+        mAllowFragmentCommits = true;
+
         mRadioController.start();
 
         Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE);
@@ -171,12 +177,50 @@
         mRadioController.shutdown();
     }
 
-    private void setContentFragment(Fragment fragment) {
-        getSupportFragmentManager().beginTransaction()
-                .replace(getContentContainerId(), fragment)
-                .commit();
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        // A transaction can only be committed with this method prior to its containing activity
+        // saving its state.
+        mAllowFragmentCommits = false;
+        super.onSaveInstanceState(outState);
     }
 
+    /**
+     * Checks if the manual tuner is currently being displayed. If it is, then dismiss it.
+     */
+    private void maybeDismissManualTuner() {
+        FragmentManager fragmentManager = getSupportFragmentManager();
+        if (fragmentManager.getBackStackEntryCount() > 0) {
+            // A station can only be selected if the manual tuner fragment has been shown; so, remove
+            // that here.
+            getSupportFragmentManager().popBackStack();
+        }
+    }
+
+    private void setContentFragment(Fragment fragment) {
+        if (!mAllowFragmentCommits) {
+            return;
+        }
+
+        getSupportFragmentManager().beginTransaction()
+                .replace(getContentContainerId(), fragment, CONTENT_FRAGMENT_TAG)
+                .commitNow();
+    }
+
+    /**
+     * Returns the fragment that is currently being displayed as the content view. Note that this
+     * is not necessarily the fragment that is visible. The manual tuner fragment can be displayed
+     * on top of this content fragment.
+     */
+    @Nullable
+    private Fragment getCurrentFragment() {
+        return getSupportFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
+    }
+
+    /**
+     * An adapter that is responsible for populating the Radio drawer with the available bands to
+     * select, as well as the option for opening the manual tuner.
+     */
     private class RadioDrawerAdapter extends CarDrawerAdapter {
         private final List<String> mDrawerOptions =
                 new ArrayList<>(SUPPORTED_RADIO_BANDS.length + 1);
diff --git a/src/com/android/car/radio/CarouselView.java b/src/com/android/car/radio/CarouselView.java
index 0c74c29..2fc5ec0 100644
--- a/src/com/android/car/radio/CarouselView.java
+++ b/src/com/android/car/radio/CarouselView.java
@@ -47,12 +47,6 @@
      */
     private static final float DEFAULT_VIEW_ALPHA = 0.24f;
 
-    /**
-     * The number of additional views to bind other than the ones that fit on the screen. These
-     * additional views will allow for a smooth animation when the carousel is shifted.
-     */
-    private static final int EXTRA_VIEWS_TO_BIND = 2;
-
     private CarouselView.Adapter mAdapter;
     private int mTopOffset;
     private int mItemMargin;
@@ -138,14 +132,6 @@
     }
 
     /**
-     * Sets the position within the data set of this carousel's adapter that will be displayed as
-     * the first item in the carousel.
-     */
-    public void setStartPosition(int position) {
-        mStartPosition = position;
-    }
-
-    /**
      * Sets the amount by which the first view in the carousel will be offset from the top of the
      * carousel. The last item and second item will sandwich this first view and expand upwards
      * and downwards respectively as space permits.
diff --git a/src/com/android/car/radio/MainRadioFragment.java b/src/com/android/car/radio/MainRadioFragment.java
index ae2decd..109d425 100644
--- a/src/com/android/car/radio/MainRadioFragment.java
+++ b/src/com/android/car/radio/MainRadioFragment.java
@@ -51,22 +51,6 @@
         void onPresetListClicked();
     }
 
-    /**
-     * Sets the {@link RadioController} that is responsible for updating the UI of this fragment
-     * with the information of the current radio station.
-     */
-    private void setRadioController(RadioController radioController) {
-        mRadioController = radioController;
-    }
-
-    /**
-     * Sets the listener that will be notified when the button to start the display of the user's
-     * presets has been clicked.
-     */
-    public void setPresetListClickListener(RadioPresetListClickListener starter) {
-        mPresetListListener = starter;
-    }
-
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
@@ -130,9 +114,11 @@
      * @param radioController The {@link RadioController} that is responsible for updating the UI
      *                        of the returned fragment.
      */
-    public static MainRadioFragment newInstance(RadioController radioController) {
+    static MainRadioFragment newInstance(RadioController radioController,
+            RadioPresetListClickListener clickListener) {
         MainRadioFragment fragment = new MainRadioFragment();
-        fragment.setRadioController(radioController);
+        fragment.mRadioController = radioController;
+        fragment.mPresetListListener = clickListener;
 
         return fragment;
     }
diff --git a/src/com/android/car/radio/ManualTunerController.java b/src/com/android/car/radio/ManualTunerController.java
index 79f7c6d..8f15428 100644
--- a/src/com/android/car/radio/ManualTunerController.java
+++ b/src/com/android/car/radio/ManualTunerController.java
@@ -21,6 +21,7 @@
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
+
 import com.android.car.radio.service.RadioStation;
 
 import java.util.ArrayList;
@@ -36,12 +37,9 @@
      */
     private static final int NUM_OF_MANUAL_TUNER_BUTTONS = 10;
 
-    private final StringBuffer mCurrentChannel = new StringBuffer();
+    private final StringBuilder mCurrentChannel = new StringBuilder();
 
-    private final Context mContext;
     private final TextView mChannelView;
-    private final RadioBandButton mAmBandButton;
-    private final RadioBandButton mFmBandButton;
 
     private int mCurrentRadioBand;
 
@@ -66,7 +64,7 @@
     private final int mEnabledButtonColor;
     private final int mDisabledButtonColor;
 
-    private final View mDoneButton;
+    private View mDoneButton;
     private ManualTunerClickListener mManualTunerClickListener;
 
     /**
@@ -114,9 +112,8 @@
         void onDone(RadioStation station);
     }
 
-    public ManualTunerController(Context context, View container, int currentRadioBand) {
-        mContext = context;
-        mChannelView = (TextView) container.findViewById(R.id.manual_tuner_channel);
+    ManualTunerController(Context context, View container, int currentRadioBand) {
+        mChannelView = container.findViewById(R.id.manual_tuner_channel);
 
         // Default to FM band.
         if (currentRadioBand != RadioManager.BAND_FM && currentRadioBand != RadioManager.BAND_AM) {
@@ -129,21 +126,8 @@
                 ? mAmChannelValidator
                 : mFmChannelValidator;
 
-        mEnabledButtonColor = mContext.getColor(R.color.manual_tuner_button_text);
-        mDisabledButtonColor = mContext.getColor(R.color.car_radio_control_button_disabled);
-
-        View backButton = container.findViewById(R.id.exit_manual_tuner_button);
-        backButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                if (mManualTunerClickListener != null) {
-                    mManualTunerClickListener.onBack();
-                }
-            }
-        });
-
-        mDoneButton = container.findViewById(R.id.manual_tuner_done_button);
-        mDoneButton.setOnClickListener(mDoneButtonClickListener);
+        mEnabledButtonColor = context.getColor(R.color.manual_tuner_button_text);
+        mDisabledButtonColor = context.getColor(R.color.car_radio_control_button_disabled);
 
         mNumberZero = context.getString(R.string.manual_tuner_0);
         mNumberOne = context.getString(R.string.manual_tuner_1);
@@ -157,84 +141,126 @@
         mNumberNine = context.getString(R.string.manual_tuner_9);
         mPeriod = context.getString(R.string.manual_tuner_period);
 
+        initializeChannelButtons(container);
         initializeManualTunerButtons(container);
 
-        mAmBandButton = (RadioBandButton) container.findViewById(R.id.manual_tuner_am_band);
-        mAmBandButton.setOnClickListener(mBandSwitcherListener);
-        mFmBandButton = (RadioBandButton) container.findViewById(R.id.manual_tuner_fm_band);
-        mFmBandButton.setOnClickListener(mBandSwitcherListener);
+        updateButtonState();
+    }
+
+    /**
+     * Initializes the buttons responsible for adjusting the channel to be entered by the manual
+     * tuner.
+     */
+    private void initializeChannelButtons(View container) {
+        RadioBandButton amBandButton = container.findViewById(R.id.manual_tuner_am_band);
+        RadioBandButton fmBandButton = container.findViewById(R.id.manual_tuner_fm_band);
+        mDoneButton = container.findViewById(R.id.manual_tuner_done_button);
+
+        View backButton = container.findViewById(R.id.exit_manual_tuner_button);
+        backButton.setOnClickListener(v -> {
+            if (mManualTunerClickListener != null) {
+                mManualTunerClickListener.onBack();
+            }
+        });
+
+        amBandButton.setOnClickListener(v -> {
+            mCurrentRadioBand = RadioManager.BAND_AM;
+            mChannelValidator = mAmChannelValidator;
+            amBandButton.setIsBandSelected(true);
+            fmBandButton.setIsBandSelected(false);
+            resetChannel();
+        });
+
+        fmBandButton.setOnClickListener(v -> {
+            mCurrentRadioBand = RadioManager.BAND_FM;
+            mChannelValidator = mFmChannelValidator;
+            amBandButton.setIsBandSelected(false);
+            fmBandButton.setIsBandSelected(true);
+            resetChannel();
+        });
+
+        mDoneButton.setOnClickListener(v -> {
+            if (mManualTunerClickListener == null) {
+                return;
+            }
+
+            int channelFrequency = mChannelValidator.convertToHz(mCurrentChannel.toString());
+            RadioStation station = new RadioStation(channelFrequency, 0 /* subChannelNumber */,
+                    mCurrentRadioBand, null /* rds */);
+
+            mManualTunerClickListener.onDone(station);
+        });
 
         if (mCurrentRadioBand == RadioManager.BAND_AM) {
-            mAmBandButton.setIsBandSelected(true);
+            amBandButton.setIsBandSelected(true);
         } else {
-            mFmBandButton.setIsBandSelected(true);
+            fmBandButton.setIsBandSelected(true);
         }
-
-        updateButtonState();
     }
 
     /**
      * Sets up the click listeners and tags for the manual tuner buttons.
      */
     private void initializeManualTunerButtons(View container) {
-        Button numberZero = (Button) container.findViewById(R.id.manual_tuner_0);
+        Button numberZero = container.findViewById(R.id.manual_tuner_0);
         numberZero.setOnClickListener(new TuneButtonClickListener(mNumberZero));
         numberZero.setTag(R.id.manual_tuner_button_value, mNumberZero);
         mManualTunerButtons.add(numberZero);
 
-        Button numberOne = (Button) container.findViewById(R.id.manual_tuner_1);
+        Button numberOne = container.findViewById(R.id.manual_tuner_1);
         numberOne.setOnClickListener(new TuneButtonClickListener(mNumberOne));
         numberOne.setTag(R.id.manual_tuner_button_value, mNumberOne);
         mManualTunerButtons.add(numberOne);
 
-        Button numberTwo = (Button) container.findViewById(R.id.manual_tuner_2);
+        Button numberTwo = container.findViewById(R.id.manual_tuner_2);
         numberTwo.setOnClickListener(new TuneButtonClickListener(mNumberTwo));
         numberTwo.setTag(R.id.manual_tuner_button_value, mNumberTwo);
         mManualTunerButtons.add(numberTwo);
 
-        Button numberThree = (Button) container.findViewById(R.id.manual_tuner_3);
+        Button numberThree = container.findViewById(R.id.manual_tuner_3);
         numberThree.setOnClickListener(new TuneButtonClickListener(mNumberThree));
         numberThree.setTag(R.id.manual_tuner_button_value, mNumberThree);
         mManualTunerButtons.add(numberThree);
 
-        Button numberFour = (Button) container.findViewById(R.id.manual_tuner_4);
+        Button numberFour = container.findViewById(R.id.manual_tuner_4);
         numberFour.setOnClickListener(new TuneButtonClickListener(mNumberFour));
         numberFour.setTag(R.id.manual_tuner_button_value, mNumberFour);
         mManualTunerButtons.add(numberFour);
 
-        Button numberFive = (Button) container.findViewById(R.id.manual_tuner_5);
+        Button numberFive = container.findViewById(R.id.manual_tuner_5);
         numberFive.setOnClickListener(new TuneButtonClickListener(mNumberFive));
         numberFive.setTag(R.id.manual_tuner_button_value, mNumberFive);
         mManualTunerButtons.add(numberFive);
 
-        Button numberSix = (Button) container.findViewById(R.id.manual_tuner_6);
+        Button numberSix = container.findViewById(R.id.manual_tuner_6);
         numberSix.setOnClickListener(new TuneButtonClickListener(mNumberSix));
         numberSix.setTag(R.id.manual_tuner_button_value, mNumberSix);
         mManualTunerButtons.add(numberSix);
 
-        Button numberSeven = (Button) container.findViewById(R.id.manual_tuner_7);
+        Button numberSeven = container.findViewById(R.id.manual_tuner_7);
         numberSeven.setOnClickListener(new TuneButtonClickListener(mNumberSeven));
         numberSeven.setTag(R.id.manual_tuner_button_value, mNumberSeven);
         mManualTunerButtons.add(numberSeven);
 
-        Button numberEight = (Button) container.findViewById(R.id.manual_tuner_8);
+        Button numberEight = container.findViewById(R.id.manual_tuner_8);
         numberEight.setOnClickListener(new TuneButtonClickListener(mNumberEight));
         numberEight.setTag(R.id.manual_tuner_button_value, mNumberEight);
         mManualTunerButtons.add(numberEight);
 
-        Button numberNine = (Button) container.findViewById(R.id.manual_tuner_9);
+        Button numberNine = container.findViewById(R.id.manual_tuner_9);
         numberNine.setOnClickListener(new TuneButtonClickListener(mNumberNine));
         numberNine.setTag(R.id.manual_tuner_button_value, mNumberNine);
         mManualTunerButtons.add(numberNine);
 
-        container.findViewById(R.id.manual_tuner_backspace).setOnClickListener(mBackspaceListener);
+        container.findViewById(R.id.manual_tuner_backspace)
+                .setOnClickListener(new BackSpaceListener());
     }
 
     /**
      * Sets the given {@link ManualTunerClickListener} to be notified when the done button of the manual
      * tuner has been clicked.
      */
-    public void setDoneButtonListener(ManualTunerClickListener listener) {
+    void setDoneButtonListener(ManualTunerClickListener listener) {
         mManualTunerClickListener = listener;
     }
 
@@ -281,11 +307,7 @@
                     return charValue >= 5 || charValue == 1;
                 case 1:
                     // Ensure that the number is above the lower AM limit of 530.
-                    if (number.equals(mNumberFive)) {
-                        return charValue >= 3;
-                    }
-
-                    return true;
+                    return !number.equals(mNumberFive) || charValue >= 3;
                 case 2:
                     // Any number is allowed to be appended if the current AM station being entered
                     // is a number in the 1000s.
@@ -481,48 +503,25 @@
         mChannelView.setText(mCurrentChannel.toString());
     }
 
-    private final View.OnClickListener mDoneButtonClickListener = new View.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            if (mManualTunerClickListener == null) {
-                return;
-            }
+    /**
+     * Resets any radio station that may have been entered and updates the button states
+     * accordingly.
+     */
+    private void resetChannel() {
+        mChannelView.setText(null);
 
-            int channelFrequency = mChannelValidator.convertToHz(mCurrentChannel.toString());
-            RadioStation station = new RadioStation(channelFrequency, 0 /* subChannelNumber */,
-                    mCurrentRadioBand, null /* rds */);
+        // Clear the string buffer by setting the length to zero rather than allocating a new
+        // one.
+        mCurrentChannel.setLength(0);
 
-            mManualTunerClickListener.onDone(station);
-        }
-    };
+        updateButtonState();
+    }
 
-    private final View.OnClickListener mBandSwitcherListener = new View.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            // Currently only AM and FM bands are supported.
-            if (v == mAmBandButton) {
-                mCurrentRadioBand = RadioManager.BAND_AM;
-                mChannelValidator = mAmChannelValidator;
-                mAmBandButton.setIsBandSelected(true);
-                mFmBandButton.setIsBandSelected(false);
-            } else {
-                mCurrentRadioBand = RadioManager.BAND_FM;
-                mChannelValidator = mFmChannelValidator;
-                mAmBandButton.setIsBandSelected(false);
-                mFmBandButton.setIsBandSelected(true);
-            }
-
-            mChannelView.setText(null);
-
-            // Clear the string buffer by setting the length to zero rather than allocating a new
-            // one.
-            mCurrentChannel.setLength(0);
-
-            updateButtonState();
-        }
-    };
-
-    private final View.OnClickListener mBackspaceListener = new View.OnClickListener() {
+    /**
+     * A {@link android.view.View.OnClickListener} that handles back space clicks. It is responsible
+     * for removing characters from the {@link #mChannelView} TextView.
+     */
+    private class BackSpaceListener implements View.OnClickListener {
         @Override
         public void onClick(View v) {
             if (mCurrentChannel.length() == 0) {
@@ -553,7 +552,7 @@
                 mCurrentChannel.deleteCharAt(lastIndex);
             }
         }
-    };
+    }
 
     /**
      * A {@link android.view.View.OnClickListener} for each of the manual tuner buttons that
@@ -562,7 +561,7 @@
     private class TuneButtonClickListener implements View.OnClickListener {
         private final String mValue;
 
-        public TuneButtonClickListener(String value) {
+        TuneButtonClickListener(String value) {
             mValue = value;
         }
 
diff --git a/src/com/android/car/radio/ManualTunerFragment.java b/src/com/android/car/radio/ManualTunerFragment.java
index d05127d..3ccf7a3 100644
--- a/src/com/android/car/radio/ManualTunerFragment.java
+++ b/src/com/android/car/radio/ManualTunerFragment.java
@@ -22,10 +22,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.car.radio.service.RadioStation;
 
 /**
- * A fragment that allows the user to manuall input a radio station to tune to.
+ * A fragment that allows the user to manually input a radio station to tune to.
  */
 public class ManualTunerFragment extends Fragment implements
         ManualTunerController.ManualTunerClickListener {
diff --git a/src/com/android/car/radio/PlayPauseButton.java b/src/com/android/car/radio/PlayPauseButton.java
index 5a2f33c..878322d 100644
--- a/src/com/android/car/radio/PlayPauseButton.java
+++ b/src/com/android/car/radio/PlayPauseButton.java
@@ -21,6 +21,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.widget.ImageView;
+
 import com.android.car.apps.common.FabDrawable;
 
 /**
diff --git a/src/com/android/car/radio/PrescannedRadioStationAdapter.java b/src/com/android/car/radio/PrescannedRadioStationAdapter.java
index 6453756..13a3e21 100644
--- a/src/com/android/car/radio/PrescannedRadioStationAdapter.java
+++ b/src/com/android/car/radio/PrescannedRadioStationAdapter.java
@@ -22,6 +22,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
+
 import com.android.car.radio.service.RadioStation;
 
 import java.util.List;
@@ -157,8 +158,8 @@
             return;
         }
 
-        TextView radioChannel = (TextView) view.findViewById(R.id.radio_list_station_channel);
-        TextView radioBandView = (TextView) view.findViewById(R.id.radio_list_station_band);
+        TextView radioChannel = view.findViewById(R.id.radio_list_station_channel);
+        TextView radioBandView = view.findViewById(R.id.radio_list_station_band);
 
         RadioStation station = mStations.get(position);
 
diff --git a/src/com/android/car/radio/PresetListScrollListener.java b/src/com/android/car/radio/PresetListScrollListener.java
index f938f36..3ec9f36 100644
--- a/src/com/android/car/radio/PresetListScrollListener.java
+++ b/src/com/android/car/radio/PresetListScrollListener.java
@@ -47,7 +47,8 @@
         mRemoveElevationAnimator = ValueAnimator.ofFloat(mContainerElevation, 0.f);
         mRemoveElevationAnimator
                 .setDuration(ANIMATION_DURATION_MS)
-                .addUpdateListener(mElevationUpdateListener);
+                .addUpdateListener(animation -> mCurrentRadioCardContainer.setElevation(
+                        (float) animation.getAnimatedValue()));
     }
 
     @Override
@@ -66,15 +67,4 @@
             mCurrentRadioCard.setTranslationZ(mContainerElevation);
         }
     }
-
-    /**
-     * {@link android.animation.ValueAnimator.AnimatorUpdateListener} that updates the elevation
-     * of the {@link #mCurrentRadioCardContainer}.
-     */
-    private final ValueAnimator.AnimatorUpdateListener mElevationUpdateListener =
-            new ValueAnimator.AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    mCurrentRadioCardContainer.setElevation((float) animation.getAnimatedValue());
-                }
-            };
 }
diff --git a/src/com/android/car/radio/PresetsViewHolder.java b/src/com/android/car/radio/PresetsViewHolder.java
index f4c6ad8..84e738b 100644
--- a/src/com/android/car/radio/PresetsViewHolder.java
+++ b/src/com/android/car/radio/PresetsViewHolder.java
@@ -71,10 +71,8 @@
         mColorMapper = RadioChannelColorMapper.getInstance(mContext);
         mPresetClickListener = listener;
 
-        mPresetItemChannel =
-                (TextView) presetsView.findViewById(R.id.preset_station_channel);
-        mPresetItemMetadata =
-                (TextView) presetsView.findViewById(R.id.preset_item_metadata);
+        mPresetItemChannel = presetsView.findViewById(R.id.preset_station_channel);
+        mPresetItemMetadata = presetsView.findViewById(R.id.preset_item_metadata);
         mEqualizer = presetsView.findViewById(R.id.preset_equalizer);
 
         mPresetItemChannelBg = (GradientDrawable) mPresetItemChannel.getBackground();
diff --git a/src/com/android/car/radio/RadioAnimationManager.java b/src/com/android/car/radio/RadioAnimationManager.java
index 55ad1f6..bf6b1ca 100644
--- a/src/com/android/car/radio/RadioAnimationManager.java
+++ b/src/com/android/car/radio/RadioAnimationManager.java
@@ -31,6 +31,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
+
 import com.android.car.stream.ui.ColumnCalculator;
 
 /**
@@ -98,7 +99,7 @@
         mPresetFabSize = res.getDimensionPixelSize(R.dimen.car_presets_play_button_size);
         mPresetContainerHeight = res.getDimensionPixelSize(R.dimen.car_preset_container_height);
 
-        mRadioCard = (CardView) container.findViewById(R.id.current_radio_station_card);
+        mRadioCard = container.findViewById(R.id.current_radio_station_card);
         mRadioCardContainer = container.findViewById(R.id.preset_current_card_container);
         mFab = container.findViewById(R.id.radio_play_button);
         mPresetFab = container.findViewById(R.id.preset_radio_play_button);
diff --git a/src/com/android/car/radio/RadioBandButton.java b/src/com/android/car/radio/RadioBandButton.java
index 24142b1..0a5769a 100644
--- a/src/com/android/car/radio/RadioBandButton.java
+++ b/src/com/android/car/radio/RadioBandButton.java
@@ -33,8 +33,6 @@
     @ColorInt private int mSelectedColor;
     @ColorInt private int mNormalColor;
 
-    public boolean mIsBandSelected;
-
     public RadioBandButton(Context context) {
         super(context);
         init(context, null);
@@ -80,9 +78,7 @@
      * {@link #setSelected(boolean)}.
      */
     public void setIsBandSelected(boolean selected) {
-        mIsBandSelected = selected;
-
-        if (mIsBandSelected) {
+        if (selected) {
             setTextColor(mSelectedColor);
             setBackground(mSelectedBackground);
         } else {
diff --git a/src/com/android/car/radio/RadioChannelColorMapper.java b/src/com/android/car/radio/RadioChannelColorMapper.java
index 44f36f5..d83f127 100644
--- a/src/com/android/car/radio/RadioChannelColorMapper.java
+++ b/src/com/android/car/radio/RadioChannelColorMapper.java
@@ -70,7 +70,7 @@
     /**
      * Convenience method for returning a color based on a {@link RadioStation}.
      *
-     * @see {@link #getColorForStation(int, int)}
+     * @see #getColorForStation(int, int)
      */
     @ColorInt
     public int getColorForStation(@NonNull RadioStation radioStation) {
diff --git a/src/com/android/car/radio/RadioController.java b/src/com/android/car/radio/RadioController.java
index 1b0c979..bf03fa2 100644
--- a/src/com/android/car/radio/RadioController.java
+++ b/src/com/android/car/radio/RadioController.java
@@ -37,6 +37,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
+
 import com.android.car.radio.service.IRadioCallback;
 import com.android.car.radio.service.IRadioManager;
 import com.android.car.radio.service.RadioRds;
@@ -59,7 +60,7 @@
      * The percentage by which to darken the color that should be set on the status bar.
      * This darkening gives the status bar the illusion that it is transparent.
      *
-     * @see {@link RadioController#setShouldColorStatusBar(boolean)}
+     * @see RadioController#setShouldColorStatusBar(boolean)
      */
     private static final float STATUS_BAR_DARKEN_PERCENTAGE = 0.4f;
 
@@ -69,7 +70,7 @@
     private static final int BACKGROUND_CHANGE_ANIM_TIME_MS = 450;
     private static final int INVALID_BACKGROUND_COLOR = 0;
 
-    private final int CHANNEL_CHANGE_DURATION_MS = 200;
+    private static final int CHANNEL_CHANGE_DURATION_MS = 200;
 
     private int mCurrentChannelNumber = RadioStorage.INVALID_RADIO_CHANNEL;
 
@@ -646,7 +647,7 @@
             Log.d(TAG, "onLoadFinished(); number of pre-scanned stations: " + size);
         }
 
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+        if (Log.isLoggable(TAG, Log.VERBOSE) && preScannedStations != null) {
             for (RadioStation station : preScannedStations) {
                 Log.v(TAG, "station: " + station.toString());
             }
@@ -981,11 +982,8 @@
     };
 
     private final ValueAnimator.AnimatorUpdateListener mBackgroundColorUpdater =
-            new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animator) {
-                    int backgroundColor = (int) animator.getAnimatedValue();
-                    setBackgroundColor(backgroundColor);
-                }
+            animator -> {
+                int backgroundColor = (int) animator.getAnimatedValue();
+                setBackgroundColor(backgroundColor);
             };
 }
diff --git a/src/com/android/car/radio/RadioDatabase.java b/src/com/android/car/radio/RadioDatabase.java
index 5ad186f..a6dae76 100644
--- a/src/com/android/car/radio/RadioDatabase.java
+++ b/src/com/android/car/radio/RadioDatabase.java
@@ -211,7 +211,7 @@
         }
 
         SQLiteDatabase db = getWritableDatabase();
-        long status = -1;
+        long status;
 
         db.beginTransaction();
         try {
@@ -237,7 +237,7 @@
         assertNotMainThread();
 
         SQLiteDatabase db = getWritableDatabase();
-        long rowsDeleted = 0;
+        long rowsDeleted;
 
         db.beginTransaction();
         try {
diff --git a/src/com/android/car/radio/RadioDisplayController.java b/src/com/android/car/radio/RadioDisplayController.java
index bff8db8..8bb9577 100644
--- a/src/com/android/car/radio/RadioDisplayController.java
+++ b/src/com/android/car/radio/RadioDisplayController.java
@@ -55,21 +55,20 @@
     public void initialize(View container) {
         // Note that the band and channel number can exist without the stub
         // single_channel_view_stub. Refer to setSingleChannelDisplay() for more information.
-        mChannelBand = (TextView) container.findViewById(R.id.radio_station_band);
-        mChannelNumber = (TextView) container.findViewById(R.id.radio_station_channel);
+        mChannelBand = container.findViewById(R.id.radio_station_band);
+        mChannelNumber = container.findViewById(R.id.radio_station_channel);
 
-        mCurrentSongTitle = (TextView) container.findViewById(R.id.radio_station_song);
-        mCurrentSongArtistOrStation =
-                (TextView) container.findViewById(R.id.radio_station_artist_or_station);
+        mCurrentSongTitle = container.findViewById(R.id.radio_station_song);
+        mCurrentSongArtistOrStation = container.findViewById(R.id.radio_station_artist_or_station);
 
-        mBackwardSeekButton = (ImageView) container.findViewById(R.id.radio_back_button);
-        mForwardSeekButton = (ImageView) container.findViewById(R.id.radio_forward_button);
+        mBackwardSeekButton = container.findViewById(R.id.radio_back_button);
+        mForwardSeekButton = container.findViewById(R.id.radio_forward_button);
 
-        mPlayButton = (PlayPauseButton) container.findViewById(R.id.radio_play_button);
-        mPresetPlayButton = (PlayPauseButton) container.findViewById(R.id.preset_radio_play_button);
+        mPlayButton = container.findViewById(R.id.radio_play_button);
+        mPresetPlayButton = container.findViewById(R.id.preset_radio_play_button);
 
-        mPresetsListButton = (ImageView) container.findViewById(R.id.radio_presets_list);
-        mAddPresetsButton = (ImageView) container.findViewById(R.id.radio_add_presets_button);
+        mPresetsListButton = container.findViewById(R.id.radio_presets_list);
+        mAddPresetsButton = container.findViewById(R.id.radio_add_presets_button);
     }
 
     /**
@@ -77,15 +76,15 @@
      * station.
      */
     public void setSingleChannelDisplay(View container) {
-        ViewStub stub = (ViewStub) container.findViewById(R.id.single_channel_view_stub);
+        ViewStub stub = container.findViewById(R.id.single_channel_view_stub);
 
         if (stub != null) {
             container = stub.inflate();
         }
 
         // Update references to the band and channel number.
-        mChannelBand = (TextView) container.findViewById(R.id.radio_station_band);
-        mChannelNumber = (TextView) container.findViewById(R.id.radio_station_channel);
+        mChannelBand = container.findViewById(R.id.radio_station_band);
+        mChannelNumber = container.findViewById(R.id.radio_station_channel);
     }
 
     /**
@@ -93,7 +92,7 @@
      * well as pre-scanned stations for the current band.
      */
     public void setChannelListDisplay(View container, PrescannedRadioStationAdapter adapter) {
-        ViewStub stub = (ViewStub) container.findViewById(R.id.channel_list_view_stub);
+        ViewStub stub = container.findViewById(R.id.channel_list_view_stub);
 
         if (stub == null) {
             return;
@@ -121,13 +120,6 @@
     }
 
     /**
-     * Returns the View that is responsible for rendering the play/pause state.
-     */
-    public View getPlayButton() {
-        return mPlayButton;
-    }
-
-    /**
      * Set whether or not the buttons controlled by this controller are enabled. If {@code false}
      * is passed to this method, then no {@link View.OnClickListener}s will be
      * triggered when the buttons are pressed. In addition, the look of the button wil be updated
diff --git a/src/com/android/car/radio/RadioPresetsFragment.java b/src/com/android/car/radio/RadioPresetsFragment.java
index 73473a3..455e7c5 100644
--- a/src/com/android/car/radio/RadioPresetsFragment.java
+++ b/src/com/android/car/radio/RadioPresetsFragment.java
@@ -29,8 +29,9 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import com.android.car.view.PagedListView;
+
 import com.android.car.radio.service.RadioStation;
+import com.android.car.view.PagedListView;
 
 import java.util.List;
 
@@ -78,13 +79,6 @@
         mRadioController = radioController;
     }
 
-    /**
-     * Sets the lsitener that will be notified when the preset list should be closed.
-     */
-    public void setPresetListExitListener(PresetListExitListener listener) {
-        mPresetListExitListener = listener;
-    }
-
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
@@ -104,7 +98,7 @@
             mAnimManager.playExitAnimation(RadioPresetsFragment.this /* listener */);
         });
 
-        mPresetsList = (PagedListView) mRootView.findViewById(R.id.presets_list);
+        mPresetsList = mRootView.findViewById(R.id.presets_list);
         mPresetsList.setLightMode();
         mPresetsList.setDefaultItemDecoration(new ItemSpacingDecoration(context));
         mPresetsList.setAdapter(mPresetsAdapter);
@@ -320,9 +314,11 @@
      * @param radioController The {@link RadioController} that is responsible for updating the UI
      *                        of the returned fragment.
      */
-    public static RadioPresetsFragment newInstance(RadioController radioController) {
+    public static RadioPresetsFragment newInstance(RadioController radioController,
+            PresetListExitListener existListener) {
         RadioPresetsFragment fragment = new RadioPresetsFragment();
         fragment.setRadioController(radioController);
+        fragment.mPresetListExitListener = existListener;
 
         return fragment;
     }
diff --git a/src/com/android/car/radio/RadioService.java b/src/com/android/car/radio/RadioService.java
index 876c9d4..90a12b6 100644
--- a/src/com/android/car/radio/RadioService.java
+++ b/src/com/android/car/radio/RadioService.java
@@ -137,7 +137,7 @@
     /**
      * Initializes this service to use a demo {@link IRadioManager}.
      *
-     * @see {@link RadioDemo}
+     * @see RadioDemo
      */
     private void initializeDemo() {
         if (Log.isLoggable(TAG, Log.DEBUG)) {
diff --git a/src/com/android/car/radio/RadioStorage.java b/src/com/android/car/radio/RadioStorage.java
index 35210a2..3ce8297 100644
--- a/src/com/android/car/radio/RadioStorage.java
+++ b/src/com/android/car/radio/RadioStorage.java
@@ -29,6 +29,7 @@
 import com.android.car.radio.demo.RadioDemo;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -169,7 +170,7 @@
      * Convenience method for checking if a specific channel is a preset. This method will assume
      * the subchannel is 0.
      *
-     * @see {@link #isPreset(RadioStation)}
+     * @see #isPreset(RadioStation)
      * @return {@code true} if the channel is a user saved preset.
      */
     public boolean isPreset(int channel, int radioBand) {
@@ -202,7 +203,7 @@
      * <p>Upon a successful store, the presets list will be refreshed via a call to
      * {@link #refreshPresets()}.
      *
-     * @see {@link #refreshPresets()}
+     * @see #refreshPresets()
      */
     public void storePreset(RadioStation preset) {
         if (preset == null) {
@@ -218,7 +219,7 @@
      * <p>Upon a successful removal, the presets list will be refreshed via a call to
      * {@link #refreshPresets()}.
      *
-     * @see {@link #refreshPresets()}
+     * @see #refreshPresets()
      */
     public void removePreset(RadioStation preset) {
         if (preset == null) {
@@ -313,7 +314,10 @@
             return;
         }
 
-        new StorePreScannedAsyncTask(radioBand).execute(stations);
+        // Converting to an array rather than passing a List to the execute to avoid any potential
+        // heap pollution via AsyncTask's varargs.
+        new StorePreScannedAsyncTask(radioBand).execute(
+                stations.toArray(new RadioStation[stations.size()]));
     }
 
     /**
@@ -452,7 +456,7 @@
      * {@link AsyncTask} that will store a list of pre-scanned {@link RadioStation}s that is passed
      * to its {@link AsyncTask#execute(Object[])}.
      */
-    private class StorePreScannedAsyncTask extends AsyncTask<List<RadioStation>, Void, Boolean> {
+    private class StorePreScannedAsyncTask extends AsyncTask<RadioStation, Void, Boolean> {
         private static final String TAG = "Em.StorePreScannedAT";
         private final int mRadioBand;
 
@@ -461,10 +465,9 @@
         }
 
         @Override
-        protected Boolean doInBackground(List<RadioStation> ... stationsList) {
-            List<RadioStation> stations = stationsList[0];
-
-            boolean result = sRadioDatabase.insertPreScannedStations(mRadioBand, stations);
+        protected Boolean doInBackground(RadioStation... radioStations) {
+            boolean result = sRadioDatabase.insertPreScannedStations(mRadioBand,
+                    Arrays.asList(radioStations));
 
             if (Log.isLoggable(TAG, Log.DEBUG)) {
                 Log.d(TAG, "Store pre-scanned stations success: " + result);