/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.car.radio;

import android.app.Service;
import android.car.hardware.radio.CarRadioManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioMetadata;
import android.hardware.radio.RadioTuner;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.support.annotation.Nullable;
import android.support.car.Car;
import android.support.car.CarNotConnectedException;
import android.support.car.CarConnectionCallback;
import android.support.car.media.CarAudioManager;
import android.text.TextUtils;
import android.util.Log;
import com.android.car.radio.demo.RadioDemo;
import com.android.car.radio.service.IRadioCallback;
import com.android.car.radio.service.IRadioManager;
import com.android.car.radio.service.RadioRds;
import com.android.car.radio.service.RadioStation;

import java.util.ArrayList;
import java.util.List;

/**
 * A persistent {@link Service} that is responsible for opening and closing a {@link RadioTuner}.
 * All radio operations should be delegated to this class. To be notified of any changes in radio
 * metadata, register as a {@link android.hardware.radio.RadioTuner.Callback} on this Service.
 *
 * <p>Utilize the {@link RadioBinder} to perform radio operations.
 */
public class RadioService extends Service implements AudioManager.OnAudioFocusChangeListener {
    private static String TAG = "Em.RadioService";

    /**
     * The amount of time to wait before re-trying to open the {@link #mRadioTuner}.
     */
    private static final int RADIO_TUNER_REOPEN_DELAY_MS = 5000;

    private int mReOpenRadioTunerCount = 0;
    private final Handler mHandler = new Handler();

    private Car mCarApi;
    private RadioTuner mRadioTuner;

    private boolean mRadioSuccessfullyInitialized;
    private int mCurrentRadioBand = RadioManager.BAND_FM;
    private int mCurrentRadioChannel = RadioStorage.INVALID_RADIO_CHANNEL;

    private String mCurrentChannelInfo;
    private String mCurrentArtist;
    private String mCurrentSongTitle;

    private RadioManager mRadioManager;
    private RadioBackgroundScanner mBackgroundScanner;
    private RadioManager.FmBandDescriptor mFmDescriptor;
    private RadioManager.AmBandDescriptor mAmDescriptor;

    private RadioManager.FmBandConfig mFmConfig;
    private RadioManager.AmBandConfig mAmConfig;

    private final List<RadioManager.ModuleProperties> mModules = new ArrayList<>();

    private CarAudioManager mCarAudioManager;
    private AudioAttributes mRadioAudioAttributes;

    /**
     * Whether or not this {@link RadioService} currently has audio focus, meaning it is the
     * primary driver of media. Usually, interaction with the radio will be prefaced with an
     * explicit request for audio focus. However, this is not ideal when muting the radio, so this
     * state needs to be tracked.
     */
    private boolean mHasAudioFocus;

    /**
     * An internal {@link android.hardware.radio.RadioTuner.Callback} that will listen for
     * changes in radio metadata and pass these method calls through to
     * {@link #mRadioTunerCallbacks}.
     */
    private RadioTuner.Callback mInternalRadioTunerCallback = new InternalRadioCallback();
    private List<IRadioCallback> mRadioTunerCallbacks = new ArrayList<>();

    @Override
    public IBinder onBind(Intent intent) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onBind(); Intent: " + intent);
        }
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onCreate()");
        }

        // Connection to car services does not work for non-automotive yet, so this call needs to
        // be guarded.
        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
            mCarApi = Car.createCar(this /* context */, mCarConnectionCallback);
            mCarApi.connect();
        }

        if (SystemProperties.getBoolean(RadioDemo.DEMO_MODE_PROPERTY, false)) {
            initializeDemo();
        } else {
            initialze();
        }
    }

    /**
     * Initializes this service to use a demo {@link IRadioManager}.
     *
     * @see {@link RadioDemo}
     */
    private void initializeDemo() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "initializeDemo()");
        }

        mBinder = RadioDemo.getInstance(this /* context */).createDemoManager();
    }

    /**
     * Connects to the {@link RadioManager}.
     */
    private void initialze() {
        mRadioManager = (RadioManager) getSystemService(Context.RADIO_SERVICE);

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "initialze(); mRadioManager: " + mRadioManager);
        }

        if (mRadioManager == null) {
            Log.w(TAG, "RadioManager could not be loaded.");
            return;
        }

        int status = mRadioManager.listModules(mModules);
        if (status != RadioManager.STATUS_OK) {
            Log.w(TAG, "Load modules failed with status: " + status);
            return;
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "initialze(); listModules complete: " + mModules);
        }

        if (mModules.size() == 0) {
            Log.w(TAG, "No radio modules on device.");
            return;
        }

        boolean isDebugLoggable = Log.isLoggable(TAG, Log.DEBUG);

        // Load the possible radio bands. For now, just accept FM and AM bands.
        for (RadioManager.BandDescriptor band : mModules.get(0).getBands()) {
            if (isDebugLoggable) {
                Log.d(TAG, "loading band: " + band.toString());
            }

            if (mFmDescriptor == null && band.getType() == RadioManager.BAND_FM) {
                mFmDescriptor = (RadioManager.FmBandDescriptor) band;
            }

            if (mAmDescriptor == null && band.getType() == RadioManager.BAND_AM) {
                mAmDescriptor = (RadioManager.AmBandDescriptor) band;
            }
        }

        if (mFmDescriptor == null && mAmDescriptor == null) {
            Log.w(TAG, "No AM and FM radio bands could be loaded.");
            return;
        }

        // TODO: Make stereo configurable depending on device.
        mFmConfig = new RadioManager.FmBandConfig.Builder(mFmDescriptor)
                .setStereo(true)
                .build();
        mAmConfig = new RadioManager.AmBandConfig.Builder(mAmDescriptor)
                .setStereo(true)
                .build();

        // If there is a second tuner on the device, then set it up as the background scanner.
        if (mModules.size() >= 2) {
            if (isDebugLoggable) {
                Log.d(TAG, "Second tuner detected on device; setting up background scanner");
            }

            mBackgroundScanner = new RadioBackgroundScanner(this /* context */, mRadioManager,
                    mAmConfig, mFmConfig, mModules.get(1));
        }

        mRadioSuccessfullyInitialized = true;
    }

    @Override
    public void onDestroy() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDestroy()");
        }

        close();

        if (mCarApi != null) {
            mCarApi.disconnect();
        }

        super.onDestroy();
    }

    /**
     * Opens the current radio band. Currently, this only supports FM and AM bands.
     *
     * @param radioBand One of {@link RadioManager#BAND_FM}, {@link RadioManager#BAND_AM},
     *                  {@link RadioManager#BAND_FM_HD} or {@link RadioManager#BAND_AM_HD}.
     * @return {@link RadioManager#STATUS_OK} if successful; otherwise,
     * {@link RadioManager#STATUS_ERROR}.
     */
    private int openRadioBandInternal(int radioBand) {
        if (requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            Log.e(TAG, "openRadioBandInternal() audio focus request fail");
            return RadioManager.STATUS_ERROR;
        }

        mCurrentRadioBand = radioBand;
        RadioManager.BandConfig config = getRadioConfig(radioBand);

        if (config == null) {
            Log.w(TAG, "Cannot create config for radio band: " + radioBand);
            return RadioManager.STATUS_ERROR;
        }

        if (mRadioTuner != null) {
            mRadioTuner.setConfiguration(config);
        } else {
            mRadioTuner = mRadioManager.openTuner(mModules.get(0).getId(), config, true,
                    mInternalRadioTunerCallback, null /* handler */);
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "openRadioBandInternal() STATUS_OK");
        }

        if (mBackgroundScanner != null) {
            mBackgroundScanner.onRadioBandChanged(radioBand);
        }

        // Reset the counter for exponential backoff each time the radio tuner has been successfully
        // opened.
        mReOpenRadioTunerCount = 0;

        return RadioManager.STATUS_OK;
    }

    /**
     * Returns a {@link RadioRds} object that holds all the current radio metadata. If all the
     * metadata is empty, then {@code null} is returned.
     */
    @Nullable
    private RadioRds createCurrentRadioRds() {
        if (TextUtils.isEmpty(mCurrentChannelInfo) && TextUtils.isEmpty(mCurrentArtist)
                && TextUtils.isEmpty(mCurrentSongTitle)) {
            return null;
        }

        return new RadioRds(mCurrentChannelInfo, mCurrentArtist, mCurrentSongTitle);
    }

    /**
     * Creates a {@link RadioStation} that encapsulates all the information about the current
     * radio station.
     */
    private RadioStation createCurrentRadioStation() {
        // mCurrentRadioChannel can possibly be invalid if this class never receives a callback
        // for onProgramInfoChanged(). As a result, manually retrieve the information for the
        // current station from RadioTuner if this is the case.
        if (mCurrentRadioChannel == RadioStorage.INVALID_RADIO_CHANNEL && mRadioTuner != null) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "createCurrentRadioStation(); invalid current radio channel. "
                        + "Calling getProgramInformation for valid station");
            }

            // getProgramInformation() expects an array of size 1.
            RadioManager.ProgramInfo[] info = new RadioManager.ProgramInfo[1];
            int status = mRadioTuner.getProgramInformation(info);

            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "getProgramInformation() status: " + status + "; info: " + info[0]);
            }

            if (status == RadioManager.STATUS_OK && info[0] != null) {
                mCurrentRadioChannel = info[0].getChannel();

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "program info channel: " + mCurrentRadioChannel);
                }
            }
        }

        return new RadioStation(mCurrentRadioChannel, 0 /* subChannelNumber */,
                mCurrentRadioBand, createCurrentRadioRds());
    }

    /**
     * Returns the proper {@link android.hardware.radio.RadioManager.BandConfig} for the given
     * radio band. {@code null} is returned if the band is not suppored.
     */
    @Nullable
    private RadioManager.BandConfig getRadioConfig(int selectedRadioBand) {
        switch (selectedRadioBand) {
            case RadioManager.BAND_AM:
                return mAmConfig;
            case RadioManager.BAND_FM:
                return mFmConfig;

            // TODO: Support BAND_FM_HD and BAND_AM_HD.

            default:
                return null;
        }
    }

    private int requestAudioFocus() {
        int status = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        try {
            status = mCarAudioManager.requestAudioFocus(this, mRadioAudioAttributes,
                    AudioManager.AUDIOFOCUS_GAIN, 0);
        } catch (CarNotConnectedException e) {
            Log.e(TAG, "requestAudioFocus() failed", e);
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "requestAudioFocus status: " + status);
        }

        if (status == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            mHasAudioFocus = true;

            // Receiving audio focus means that the radio is un-muted.
            for (IRadioCallback callback : mRadioTunerCallbacks) {
                try {
                    callback.onRadioMuteChanged(false);
                } catch (RemoteException e) {
                    Log.e(TAG, "requestAudioFocus(); onRadioMuteChanged() notify failed: "
                            + e.getMessage());
                }
            }
        }

        return status;
    }

    private void abandonAudioFocus() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "abandonAudioFocus()");
        }

        if (mCarAudioManager == null) {
            return;
        }

        mCarAudioManager.abandonAudioFocus(this, mRadioAudioAttributes);
        mHasAudioFocus = false;

        for (IRadioCallback callback : mRadioTunerCallbacks) {
            try {
                callback.onRadioMuteChanged(true);
            } catch (RemoteException e) {
                Log.e(TAG, "abandonAudioFocus(); onRadioMutechanged() notify failed: "
                        + e.getMessage());
            }
        }
    }

    /**
     * Closes any active {@link RadioTuner}s and releases audio focus.
     */
    private void close() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "close()");
        }

        abandonAudioFocus();

        if (mRadioTuner != null) {
            mRadioTuner.close();
            mRadioTuner = null;
        }
    }

    @Override
    public void onAudioFocusChange(int focusChange) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "focus change: " + focusChange);
        }

        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                mHasAudioFocus = true;
                openRadioBandInternal(mCurrentRadioBand);
                break;

            // For a transient loss, just allow the focus to be released. The radio will stop
            // itself automatically. There is no need for an explicit abandon audio focus call
            // because this removes the AudioFocusChangeListener.
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                mHasAudioFocus = false;
                break;

            case AudioManager.AUDIOFOCUS_LOSS:
                close();
                break;

            default:
                // Do nothing for all other cases.
        }
    }

    /**
     * {@link CarConnectionCallback} that retrieves the {@link CarRadioManager}.
     */
    private final CarConnectionCallback mCarConnectionCallback =
            new CarConnectionCallback() {
                @Override
                public void onConnected(Car car) {
                    if (Log.isLoggable(TAG, Log.DEBUG)) {
                        Log.d(TAG, "Car service connected.");
                    }
                    try {
                        // The CarAudioManager only needs to be retrieved once.
                        if (mCarAudioManager == null) {
                            mCarAudioManager = (CarAudioManager) mCarApi.getCarManager(
                                    android.car.Car.AUDIO_SERVICE);

                            mRadioAudioAttributes = mCarAudioManager.getAudioAttributesForCarUsage(
                                    CarAudioManager.CAR_AUDIO_USAGE_RADIO);
                        }
                    } catch (CarNotConnectedException e) {
                        //TODO finish
                        Log.e(TAG, "Car not connected");
                    }
                }

                @Override
                public void onDisconnected(Car car) {
                    if (Log.isLoggable(TAG, Log.DEBUG)) {
                        Log.d(TAG, "Car service disconnected.");
                    }
                }
            };

    private IRadioManager.Stub mBinder = new IRadioManager.Stub() {
        /**
         * Tunes the radio to the given frequency. To be notified of a successful tune, register
         * as a {@link android.hardware.radio.RadioTuner.Callback}.
         */
        @Override
        public void tune(RadioStation radioStation) {
            if (mRadioManager == null || radioStation == null
                    || requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
                return;
            }

            if (mRadioTuner == null || radioStation.getRadioBand() != mCurrentRadioBand) {
                int radioStatus = openRadioBandInternal(radioStation.getRadioBand());
                if (radioStatus == RadioManager.STATUS_ERROR) {
                    return;
                }
            }

            int status = mRadioTuner.tune(radioStation.getChannelNumber(), 0 /* subChannel */);

            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Tuning to station: " + radioStation + "\n\tstatus: " + status);
            }
        }

        /**
         * Seeks the radio forward. To be notified of a successful tune, register as a
         * {@link android.hardware.radio.RadioTuner.Callback}.
         */
        @Override
        public void seekForward() {
            if (mRadioManager == null
                    || requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
                return;
            }

            if (mRadioTuner == null) {
                int radioStatus = openRadioBandInternal(mCurrentRadioBand);
                if (radioStatus == RadioManager.STATUS_ERROR) {
                    return;
                }
            }

            mRadioTuner.scan(RadioTuner.DIRECTION_UP, true);
        }

        /**
         * Seeks the radio backwards. To be notified of a successful tune, register as a
         * {@link android.hardware.radio.RadioTuner.Callback}.
         */
        @Override
        public void seekBackward() {
            if (mRadioManager == null
                    || requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
                return;
            }

            if (mRadioTuner == null) {
                int radioStatus = openRadioBandInternal(mCurrentRadioBand);
                if (radioStatus == RadioManager.STATUS_ERROR) {
                    return;
                }
            }

            mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, true);
        }

        /**
         * Mutes the radio.
         *
         * @return {@code true} if the mute was successful.
         */
        @Override
        public boolean mute() {
            if (mRadioManager == null) {
                return false;
            }

            if (mCarAudioManager == null) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "mute() called, but not connected to CarAudioManager");
                }
                return false;
            }

            // If the radio does not currently have focus, then no need to do anything because the
            // radio won't be playing any sound.
            if (!mHasAudioFocus) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "mute() called, but radio does not currently have audio focus; "
                            + "ignoring.");
                }
                return false;
            }

            boolean muteSuccessful = false;

            try {
                muteSuccessful = mCarAudioManager.setMediaMute(true);

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "setMediaMute(true) status: " + muteSuccessful);
                }
            } catch (CarNotConnectedException e) {
                Log.e(TAG, "mute() failed: " + e.getMessage());
                e.printStackTrace();
            }

            if (muteSuccessful && mRadioTunerCallbacks.size() > 0) {
                for (IRadioCallback callback : mRadioTunerCallbacks) {
                    try {
                        callback.onRadioMuteChanged(true);
                    } catch (RemoteException e) {
                        Log.e(TAG, "mute() notify failed: " + e.getMessage());
                    }
                }
            }

            return muteSuccessful;
        }

        /**
         * Un-mutes the radio and causes audio to play.
         *
         * @return {@code true} if the un-mute was successful.
         */
        @Override
        public boolean unMute() {
            if (mRadioManager == null) {
                return false;
            }

            if (mCarAudioManager == null) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "toggleMute() called, but not connected to CarAudioManager");
                }
                return false;
            }

            // Requesting audio focus will automatically un-mute the radio if it had been muted.
            return requestAudioFocus() == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
        }

        /**
         * Returns {@code true} if the radio is currently muted.
         */
        @Override
        public boolean isMuted() {
            if (!mHasAudioFocus) {
                return true;
            }

            if (mRadioManager == null) {
                return true;
            }

            if (mCarAudioManager == null) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "isMuted() called, but not connected to CarAudioManager");
                }
                return true;
            }

            boolean isMuted = false;

            try {
                isMuted = mCarAudioManager.isMediaMuted();
            } catch (CarNotConnectedException e) {
                Log.e(TAG, "isMuted() failed: " + e.getMessage());
                e.printStackTrace();
            }

            return isMuted;
        }

        /**
         * Opens the radio for the given band.
         *
         * @param radioBand One of {@link RadioManager#BAND_FM}, {@link RadioManager#BAND_AM},
         *                  {@link RadioManager#BAND_FM_HD} or {@link RadioManager#BAND_AM_HD}.
         * @return {@link RadioManager#STATUS_OK} if successful; otherwise,
         * {@link RadioManager#STATUS_ERROR}.
         */
        @Override
        public int openRadioBand(int radioBand) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "openRadioBand() for band: " + radioBand);
            }

            if (mRadioManager == null) {
                return RadioManager.STATUS_ERROR;
            }

            return openRadioBandInternal(radioBand);
        }

        /**
         * Adds the given {@link android.hardware.radio.RadioTuner.Callback} to be notified
         * of any radio metadata changes.
         */
        @Override
        public void addRadioTunerCallback(IRadioCallback callback) {
            if (callback == null) {
                return;
            }

            mRadioTunerCallbacks.add(callback);
        }

        /**
         * Removes the given {@link android.hardware.radio.RadioTuner.Callback} from receiving
         * any radio metadata chagnes.
         */
        @Override
        public void removeRadioTunerCallback(IRadioCallback callback) {
            if (callback == null) {
                return;
            }

            mRadioTunerCallbacks.remove(callback);
        }

        /**
         * Returns a {@link RadioStation} that encapsulates the information about the current
         * station the radio is tuned to.
         */
        @Override
        public RadioStation getCurrentRadioStation() {
            return createCurrentRadioStation();
        }

        /**
         * Returns {@code true} if the radio was able to successfully initialize. A value of
         * {@code false} here could mean that the {@code RadioService} was not able to connect to
         * the {@link RadioManager} or there were no radio modules on the current device.
         */
        @Override
        public boolean isInitialized() {
            return mRadioSuccessfullyInitialized;
        }

        /**
         * Returns {@code true} if the radio currently has focus and is therefore the application
         * that is supplying music.
         */
        @Override
        public boolean hasFocus() {
            return mHasAudioFocus;
        }

        /**
         * Returns {@code true} if the current radio module has dual tuners, meaning that a tuner
         * is available to scan for stations in the background.
         */
        @Override
        public boolean hasDualTuners() {
            return mModules.size() >= 2;
        }
    };

    /**
     * A extension of {@link android.hardware.radio.RadioTuner.Callback} that delegates to a
     * callback registered on this service.
     */
    private class InternalRadioCallback extends RadioTuner.Callback {
        @Override
        public void onProgramInfoChanged(RadioManager.ProgramInfo info) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onProgramInfoChanged(); info: " + info);
            }

            clearMetadata();

            if (info != null) {
                mCurrentRadioChannel = info.getChannel();

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "onProgramInfoChanged(); info channel: " + mCurrentRadioChannel);
                }
            }

            RadioStation station = createCurrentRadioStation();

            try {
                for (IRadioCallback callback : mRadioTunerCallbacks) {
                    callback.onRadioStationChanged(station);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "onProgramInfoChanged(); "
                        + "Failed to notify IRadioCallbacks: " + e.getMessage());
            }
        }

        @Override
        public void onMetadataChanged(RadioMetadata metadata) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onMetadataChanged(); metadata: " + metadata);
            }

            clearMetadata();
            updateMetadata(metadata);

            RadioRds radioRds = createCurrentRadioRds();

            try {
                for (IRadioCallback callback : mRadioTunerCallbacks) {
                    callback.onRadioMetadataChanged(radioRds);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "onMetadataChanged(); "
                        + "Failed to notify IRadioCallbacks: " + e.getMessage());
            }
        }

        @Override
        public void onConfigurationChanged(RadioManager.BandConfig config) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onConfigurationChanged(): config: " + config);
            }

            clearMetadata();

            if (config != null) {
                mCurrentRadioBand = config.getType();

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "onConfigurationChanged(): config type: " + mCurrentRadioBand);
                }

            }

            try {
                for (IRadioCallback callback : mRadioTunerCallbacks) {
                    callback.onRadioBandChanged(mCurrentRadioBand);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "onConfigurationChanged(); "
                        + "Failed to notify IRadioCallbacks: " + e.getMessage());
            }
        }

        @Override
        public void onError(int status) {
            Log.e(TAG, "onError(); status: " + status);

            // If there is a hardware failure or the radio service died, then this requires a
            // re-opening of the radio tuner.
            if (status == RadioTuner.ERROR_HARDWARE_FAILURE
                    || status == RadioTuner.ERROR_SERVER_DIED) {
                if (mRadioTuner != null) {
                    mRadioTuner.close();
                    mRadioTuner = null;
                }

                // Attempt to re-open the RadioTuner. Each time the radio tuner fails to open, the
                // mReOpenRadioTunerCount will be incremented.
                mHandler.removeCallbacks(mOpenRadioTunerRunnable);
                mHandler.postDelayed(mOpenRadioTunerRunnable,
                        mReOpenRadioTunerCount * RADIO_TUNER_REOPEN_DELAY_MS);

                mReOpenRadioTunerCount++;
            }

            try {
                for (IRadioCallback callback : mRadioTunerCallbacks) {
                    callback.onError(status);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "onError(); Failed to notify IRadioCallbacks: " + e.getMessage());
            }
        }

        @Override
        public void onControlChanged(boolean control) {
            // If the radio loses control of the RadioTuner, then close it and allow it to be
            // re-opened when control has been gained.
            if (!control) {
                close();
                return;
            }

            if (mRadioTuner == null) {
                openRadioBandInternal(mCurrentRadioBand);
            }
        }

        /**
         * Sets all metadata fields to {@code null}.
         */
        private void clearMetadata() {
            mCurrentChannelInfo = null;
            mCurrentArtist = null;
            mCurrentSongTitle = null;
        }

        /**
         * Retrieves the relevant information off the given {@link RadioMetadata} object and
         * sets them correspondingly on {@link #mCurrentChannelInfo}, {@link #mCurrentArtist}
         * and {@link #mCurrentSongTitle}.
         */
        private void updateMetadata(RadioMetadata metadata) {
            if (metadata != null) {
                mCurrentChannelInfo = metadata.getString(RadioMetadata.METADATA_KEY_RDS_PS);
                mCurrentArtist = metadata.getString(RadioMetadata.METADATA_KEY_ARTIST);
                mCurrentSongTitle = metadata.getString(RadioMetadata.METADATA_KEY_TITLE);

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, String.format("updateMetadata(): [channel info: %s, artist: %s, "
                            + "song title: %s]", mCurrentChannelInfo, mCurrentArtist,
                            mCurrentSongTitle));
                }
            }
        }
    }

    private final Runnable mOpenRadioTunerRunnable = () -> openRadioBandInternal(mCurrentRadioBand);
}
