/*
 * 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.bluetooth.avrcpcontroller;

import android.bluetooth.BluetoothAvrcpController;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.browse.MediaBrowser.MediaItem;
import android.media.session.PlaybackState;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;

import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dpsink.A2dpSinkService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;

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

/**
 * Provides Bluetooth AVRCP Controller State Machine responsible for all remote control connections
 * and interactions with a remote controlable device.
 */
class AvrcpControllerStateMachine extends StateMachine {

    // commands from Binder service
    static final int MESSAGE_SEND_PASS_THROUGH_CMD = 1;
    static final int MESSAGE_SEND_GROUP_NAVIGATION_CMD = 3;
    static final int MESSAGE_GET_FOLDER_LIST = 6;
    static final int MESSAGE_FETCH_ATTR_AND_PLAY_ITEM = 9;

    // commands from native layer
    static final int MESSAGE_PROCESS_SET_ABS_VOL_CMD = 103;
    static final int MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION = 104;
    static final int MESSAGE_PROCESS_TRACK_CHANGED = 105;
    static final int MESSAGE_PROCESS_PLAY_POS_CHANGED = 106;
    static final int MESSAGE_PROCESS_PLAY_STATUS_CHANGED = 107;
    static final int MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION = 108;
    static final int MESSAGE_PROCESS_GET_FOLDER_ITEMS = 109;
    static final int MESSAGE_PROCESS_GET_FOLDER_ITEMS_OUT_OF_RANGE = 110;
    static final int MESSAGE_PROCESS_GET_PLAYER_ITEMS = 111;
    static final int MESSAGE_PROCESS_FOLDER_PATH = 112;
    static final int MESSAGE_PROCESS_SET_BROWSED_PLAYER = 113;
    static final int MESSAGE_PROCESS_SET_ADDRESSED_PLAYER = 114;
    static final int MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED = 115;
    static final int MESSAGE_PROCESS_NOW_PLAYING_CONTENTS_CHANGED = 116;

    // commands for connection
    static final int MESSAGE_PROCESS_RC_FEATURES = 301;
    static final int MESSAGE_PROCESS_CONNECTION_CHANGE = 302;
    static final int MESSAGE_PROCESS_BROWSE_CONNECTION_CHANGE = 303;

    // Interal messages
    static final int MESSAGE_INTERNAL_CMD_TIMEOUT = 403;
    static final int MESSAGE_INTERNAL_ABS_VOL_TIMEOUT = 404;

    static final int ABS_VOL_TIMEOUT_MILLIS = 1000; //1s
    static final int CMD_TIMEOUT_MILLIS = 5000; // 5s
    // Fetch only 20 items at a time.
    static final int GET_FOLDER_ITEMS_PAGINATION_SIZE = 20;
    // Fetch no more than 1000 items per directory.
    static final int MAX_FOLDER_ITEMS = 1000;

    /*
     * Base value for absolute volume from JNI
     */
    private static final int ABS_VOL_BASE = 127;

    /*
     * Notification types for Avrcp protocol JNI.
     */
    private static final byte NOTIFICATION_RSP_TYPE_INTERIM = 0x00;
    private static final byte NOTIFICATION_RSP_TYPE_CHANGED = 0x01;


    private static final String TAG = "AvrcpControllerSM";
    private static final boolean DBG = true;
    private static final boolean VDBG = false;

    private final Context mContext;
    private final AudioManager mAudioManager;

    private final State mDisconnected;
    private final State mConnected;
    private final SetAddresedPlayerAndPlayItem mSetAddrPlayer;
    private final GetFolderList mGetFolderList;

    private final Object mLock = new Object();
    private static final MediaMetadata EMPTY_MEDIA_METADATA = new MediaMetadata.Builder().build();

    // APIs exist to access these so they must be thread safe
    private Boolean mIsConnected = false;
    private RemoteDevice mRemoteDevice;
    private AvrcpPlayer mAddressedPlayer;

    // Only accessed from State Machine processMessage
    private int mVolumeChangedNotificationsToIgnore = 0;
    private int mPreviousPercentageVol = -1;
    private int mAddressedPlayerID = -1;
    private SparseArray<AvrcpPlayer> mAvailablePlayerList = new SparseArray<AvrcpPlayer>();

    // Browse tree.
    private BrowseTree mBrowseTree = new BrowseTree();

    AvrcpControllerStateMachine(Context context) {
        super(TAG);
        mContext = context;

        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
        mContext.registerReceiver(mBroadcastReceiver, filter);

        mDisconnected = new Disconnected();
        mConnected = new Connected();

        // Used to change folder path and fetch the new folder listing.
        mSetAddrPlayer = new SetAddresedPlayerAndPlayItem();
        mGetFolderList = new GetFolderList();

        addState(mDisconnected);
        addState(mConnected);

        // Any action that needs blocking other requests to the state machine will be implemented as
        // a separate substate of the mConnected state. Once transtition to the sub-state we should
        // only handle the messages that are relevant to the sub-action. Everything else should be
        // deferred so that once we transition to the mConnected we can process them hence.
        addState(mSetAddrPlayer, mConnected);
        addState(mGetFolderList, mConnected);

        setInitialState(mDisconnected);
    }

    class Disconnected extends State {

        @Override
        public boolean processMessage(Message msg) {
            if (DBG) Log.d(TAG, " HandleMessage: " + dumpMessageString(msg.what));
            switch (msg.what) {
                case MESSAGE_PROCESS_CONNECTION_CHANGE:
                    if (msg.arg1 == BluetoothProfile.STATE_CONNECTED) {
                        mBrowseTree = new BrowseTree();
                        transitionTo(mConnected);
                        BluetoothDevice rtDevice = (BluetoothDevice) msg.obj;
                        synchronized (mLock) {
                            mRemoteDevice = new RemoteDevice(rtDevice);
                            mAddressedPlayer = new AvrcpPlayer();
                            mIsConnected = true;
                        }
                        MetricsLogger.logProfileConnectionEvent(
                                BluetoothMetricsProto.ProfileId.AVRCP_CONTROLLER);
                        Intent intent = new Intent(
                                BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
                        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE,
                                BluetoothProfile.STATE_DISCONNECTED);
                        intent.putExtra(BluetoothProfile.EXTRA_STATE,
                                BluetoothProfile.STATE_CONNECTED);
                        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, rtDevice);
                        mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
                    }
                    break;

                default:
                    Log.w(TAG,
                            "Currently Disconnected not handling " + dumpMessageString(msg.what));
                    return false;
            }
            return true;
        }
    }

    class Connected extends State {
        @Override
        public boolean processMessage(Message msg) {
            if (DBG) Log.d(TAG, " HandleMessage: " + dumpMessageString(msg.what));
            A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService();
            synchronized (mLock) {
                switch (msg.what) {
                    case MESSAGE_SEND_PASS_THROUGH_CMD:
                        BluetoothDevice device = (BluetoothDevice) msg.obj;
                        AvrcpControllerService.sendPassThroughCommandNative(
                                Utils.getByteAddress(device), msg.arg1, msg.arg2);
                        if (a2dpSinkService != null) {
                            if (DBG) Log.d(TAG, " inform AVRCP Commands to A2DP Sink ");
                            a2dpSinkService.informAvrcpPassThroughCmd(device, msg.arg1, msg.arg2);
                        }
                        break;

                    case MESSAGE_SEND_GROUP_NAVIGATION_CMD:
                        AvrcpControllerService.sendGroupNavigationCommandNative(
                                mRemoteDevice.getBluetoothAddress(), msg.arg1, msg.arg2);
                        break;

                    case MESSAGE_GET_FOLDER_LIST:
                        // Whenever we transition we set the information for folder we need to
                        // return result.
                        if (DBG) Log.d(TAG, "Message_GET_FOLDER_LIST" + (String) msg.obj);
                        mGetFolderList.setFolder((String) msg.obj);
                        transitionTo(mGetFolderList);
                        break;

                    case MESSAGE_FETCH_ATTR_AND_PLAY_ITEM: {
                        int scope = msg.arg1;
                        String playItemUid = (String) msg.obj;
                        BrowseTree.BrowseNode currBrPlayer = mBrowseTree.getCurrentBrowsedPlayer();
                        BrowseTree.BrowseNode currAddrPlayer =
                                mBrowseTree.getCurrentAddressedPlayer();
                        BrowseTree.BrowseNode itemToPlay =
                                mBrowseTree.findBrowseNodeByID(playItemUid);
                        if (DBG) {
                            Log.d(TAG, "currBrPlayer " + currBrPlayer + " currAddrPlayer "
                                    + currAddrPlayer);
                        }
                        if (currBrPlayer == null
                                || currBrPlayer.equals(currAddrPlayer)
                                || scope == AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING) {
                            // String is encoded as a Hex String (mostly for display purposes)
                            // hence convert this back to real byte string.
                            // NOTE: It may be possible that sending play while the same item is
                            // playing leads to reset of track.
                            AvrcpControllerService.playItemNative(
                                    mRemoteDevice.getBluetoothAddress(), (byte) scope,
                                    AvrcpControllerService.hexStringToByteUID(playItemUid), 0);
                        } else {
                            // Send out the request for setting addressed player.
                            AvrcpControllerService.setAddressedPlayerNative(
                                    mRemoteDevice.getBluetoothAddress(),
                                    currBrPlayer.getPlayerID());
                            mSetAddrPlayer.setItemAndScope(currBrPlayer.getID(), playItemUid,
                                    scope);
                            transitionTo(mSetAddrPlayer);
                        }
                        break;
                    }

                    case MESSAGE_PROCESS_CONNECTION_CHANGE:
                        if (msg.arg1 == BluetoothProfile.STATE_DISCONNECTED) {
                            synchronized (mLock) {
                                mIsConnected = false;
                                mRemoteDevice = null;
                            }
                            mBrowseTree.clear();
                            transitionTo(mDisconnected);
                            BluetoothDevice rtDevice = (BluetoothDevice) msg.obj;
                            Intent intent = new Intent(
                                    BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
                            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE,
                                    BluetoothProfile.STATE_CONNECTED);
                            intent.putExtra(BluetoothProfile.EXTRA_STATE,
                                    BluetoothProfile.STATE_DISCONNECTED);
                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, rtDevice);
                            mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
                        }
                        break;

                    case MESSAGE_PROCESS_BROWSE_CONNECTION_CHANGE:
                        // Service tells us if the browse is connected or disconnected.
                        // This is useful only for deciding whether to send browse commands rest of
                        // the connection state handling should be done via the message
                        // MESSAGE_PROCESS_CONNECTION_CHANGE.
                        Intent intent = new Intent(
                                AvrcpControllerService.ACTION_BROWSE_CONNECTION_STATE_CHANGED);
                        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, (BluetoothDevice) msg.obj);
                        if (DBG) {
                            Log.d(TAG, "Browse connection state " + msg.arg1);
                        }
                        if (msg.arg1 == 1) {
                            intent.putExtra(BluetoothProfile.EXTRA_STATE,
                                    BluetoothProfile.STATE_CONNECTED);
                        } else if (msg.arg1 == 0) {
                            intent.putExtra(BluetoothProfile.EXTRA_STATE,
                                    BluetoothProfile.STATE_DISCONNECTED);
                        } else {
                            Log.w(TAG, "Incorrect browse state " + msg.arg1);
                        }

                        mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
                        break;

                    case MESSAGE_PROCESS_RC_FEATURES:
                        mRemoteDevice.setRemoteFeatures(msg.arg1);
                        break;

                    case MESSAGE_PROCESS_SET_ABS_VOL_CMD:
                        mVolumeChangedNotificationsToIgnore++;
                        removeMessages(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT);
                        sendMessageDelayed(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT,
                                ABS_VOL_TIMEOUT_MILLIS);
                        setAbsVolume(msg.arg1, msg.arg2);
                        break;

                    case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION: {
                        mRemoteDevice.setNotificationLabel(msg.arg1);
                        mRemoteDevice.setAbsVolNotificationRequested(true);
                        int percentageVol = getVolumePercentage();
                        if (DBG) {
                            Log.d(TAG, " Sending Interim Response = " + percentageVol + " label "
                                    + msg.arg1);
                        }
                        AvrcpControllerService.sendRegisterAbsVolRspNative(
                                mRemoteDevice.getBluetoothAddress(), NOTIFICATION_RSP_TYPE_INTERIM,
                                percentageVol, mRemoteDevice.getNotificationLabel());
                    }
                    break;

                    case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION: {
                        if (mVolumeChangedNotificationsToIgnore > 0) {
                            mVolumeChangedNotificationsToIgnore--;
                            if (mVolumeChangedNotificationsToIgnore == 0) {
                                removeMessages(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT);
                            }
                        } else {
                            if (mRemoteDevice.getAbsVolNotificationRequested()) {
                                int percentageVol = getVolumePercentage();
                                if (percentageVol != mPreviousPercentageVol) {
                                    AvrcpControllerService.sendRegisterAbsVolRspNative(
                                            mRemoteDevice.getBluetoothAddress(),
                                            NOTIFICATION_RSP_TYPE_CHANGED, percentageVol,
                                            mRemoteDevice.getNotificationLabel());
                                    mPreviousPercentageVol = percentageVol;
                                    mRemoteDevice.setAbsVolNotificationRequested(false);
                                }
                            }
                        }
                    }
                    break;

                    case MESSAGE_INTERNAL_ABS_VOL_TIMEOUT:
                        // Volume changed notifications should come back promptly from the
                        // AudioManager, if for some reason some notifications were squashed don't
                        // prevent future notifications.
                        if (DBG) Log.d(TAG, "Timed out on volume changed notification");
                        mVolumeChangedNotificationsToIgnore = 0;
                        break;

                    case MESSAGE_PROCESS_TRACK_CHANGED:
                        // Music start playing automatically and update Metadata
                        boolean updateTrack =
                                mAddressedPlayer.updateCurrentTrack((TrackInfo) msg.obj);
                        if (updateTrack) {
                            broadcastMetaDataChanged(
                                    mAddressedPlayer.getCurrentTrack().getMediaMetaData());
                        }
                        break;

                    case MESSAGE_PROCESS_PLAY_POS_CHANGED:
                        if (msg.arg2 != -1) {
                            mAddressedPlayer.setPlayTime(msg.arg2);
                            broadcastPlayBackStateChanged(getCurrentPlayBackState());
                        }
                        break;

                    case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
                        int status = msg.arg1;
                        mAddressedPlayer.setPlayStatus(status);
                        if (status == PlaybackState.STATE_PLAYING) {
                            a2dpSinkService.informTGStatePlaying(mRemoteDevice.mBTDevice, true);
                        } else if (status == PlaybackState.STATE_PAUSED
                                || status == PlaybackState.STATE_STOPPED) {
                            a2dpSinkService.informTGStatePlaying(mRemoteDevice.mBTDevice, false);
                        }
                        break;

                    case MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED:
                        mAddressedPlayerID = msg.arg1;
                        if (DBG) Log.d(TAG, "AddressedPlayer = " + mAddressedPlayerID);
                        AvrcpPlayer updatedPlayer = mAvailablePlayerList.get(mAddressedPlayerID);
                        if (updatedPlayer != null) {
                            mAddressedPlayer = updatedPlayer;
                            if (DBG) Log.d(TAG, "AddressedPlayer = " + mAddressedPlayer.getName());
                        } else {
                            mBrowseTree.mRootNode.setCached(false);
                        }
                        sendMessage(MESSAGE_PROCESS_SET_ADDRESSED_PLAYER);
                        break;

                    case MESSAGE_PROCESS_NOW_PLAYING_CONTENTS_CHANGED:
                        mBrowseTree.mNowPlayingNode.setCached(false);
                        mGetFolderList.setFolder(mBrowseTree.mNowPlayingNode.getID());
                        transitionTo(mGetFolderList);
                        break;

                    default:
                        Log.d(TAG, "Unhandled message" + msg.what);
                        return false;
                }
            }
            return true;
        }
    }

    // Handle the get folder listing action
    // a) Fetch the listing of folders
    // b) Once completed return the object listing
    class GetFolderList extends CmdState {
        private static final String STATE_TAG = "AVRCPSM.GetFolderList";

        boolean mAbort;
        BrowseTree.BrowseNode mBrowseNode;
        BrowseTree.BrowseNode mNextStep;

        @Override
        public void enter() {
            // Setup the timeouts.
            super.enter();
            mAbort = false;
            if (mBrowseNode == null) {
                transitionTo(mConnected);
            } else {
                navigateToFolderOrRetrieve(mBrowseNode);
            }
        }

        public void setFolder(String id) {
            if (DBG) Log.d(STATE_TAG, "Setting folder to " + id);
            mBrowseNode = mBrowseTree.findBrowseNodeByID(id);
        }

        @Override
        public boolean processMessage(Message msg) {
            Log.d(STATE_TAG, "processMessage " + msg.what);
            switch (msg.what) {
                case MESSAGE_PROCESS_GET_FOLDER_ITEMS:
                    ArrayList<MediaItem> folderList = (ArrayList<MediaItem>) msg.obj;
                    int endIndicator = mBrowseNode.getExpectedChildren() - 1;
                    if (DBG) {
                        Log.d(STATE_TAG,
                                " End " + endIndicator
                                        + " received " + folderList.size());
                    }

                    // Always update the node so that the user does not wait forever
                    // for the list to populate.
                    mBrowseNode.addChildren(folderList);
                    broadcastFolderList(mBrowseNode.getID());

                    if (mBrowseNode.getChildrenCount() >= endIndicator || folderList.size() == 0
                            || mAbort) {
                        // If we have fetched all the elements or if the remotes sends us 0 elements
                        // (which can lead us into a loop since mCurrInd does not proceed) we simply
                        // abort.
                        mBrowseNode.setCached(true);
                        transitionTo(mConnected);
                    } else {
                        // Fetch the next set of items.
                        fetchContents(mBrowseNode);
                        // Reset the timeout message since we are doing a new fetch now.
                        removeMessages(MESSAGE_INTERNAL_CMD_TIMEOUT);
                        sendMessageDelayed(MESSAGE_INTERNAL_CMD_TIMEOUT, CMD_TIMEOUT_MILLIS);
                    }
                    break;
                case MESSAGE_PROCESS_SET_BROWSED_PLAYER:
                    mBrowseTree.setCurrentBrowsedPlayer(mNextStep.getID(), msg.arg1, msg.arg2);
                    removeMessages(MESSAGE_INTERNAL_CMD_TIMEOUT);
                    sendMessageDelayed(MESSAGE_INTERNAL_CMD_TIMEOUT, CMD_TIMEOUT_MILLIS);
                    navigateToFolderOrRetrieve(mBrowseNode);
                    break;

                case MESSAGE_PROCESS_FOLDER_PATH:
                    mBrowseTree.setCurrentBrowsedFolder(mNextStep.getID());
                    mBrowseTree.getCurrentBrowsedFolder().setExpectedChildren(msg.arg1);

                    if (mAbort) {
                        transitionTo(mConnected);
                    } else {
                        removeMessages(MESSAGE_INTERNAL_CMD_TIMEOUT);
                        sendMessageDelayed(MESSAGE_INTERNAL_CMD_TIMEOUT, CMD_TIMEOUT_MILLIS);
                        navigateToFolderOrRetrieve(mBrowseNode);
                    }
                    break;

                case MESSAGE_PROCESS_GET_PLAYER_ITEMS:
                    BrowseTree.BrowseNode rootNode = mBrowseTree.mRootNode;
                    if (!rootNode.isCached()) {
                        List<AvrcpPlayer> playerList = (List<AvrcpPlayer>) msg.obj;
                        mAvailablePlayerList.clear();
                        for (AvrcpPlayer player : playerList) {
                            mAvailablePlayerList.put(player.getId(), player);
                        }
                        rootNode.addChildren(playerList);
                        mBrowseTree.setCurrentBrowsedFolder(BrowseTree.ROOT);
                        rootNode.setExpectedChildren(playerList.size());
                        rootNode.setCached(true);
                        broadcastFolderList(BrowseTree.ROOT);
                    }
                    transitionTo(mConnected);
                    break;


                case MESSAGE_INTERNAL_CMD_TIMEOUT:
                    // We have timed out to execute the request, we should simply send
                    // whatever listing we have gotten until now.
                    broadcastFolderList(mBrowseNode.getID());
                    transitionTo(mConnected);
                    break;

                case MESSAGE_PROCESS_GET_FOLDER_ITEMS_OUT_OF_RANGE:
                    // If we have gotten an error for OUT OF RANGE we have
                    // already sent all the items to the client hence simply
                    // transition to Connected state here.
                    mBrowseNode.setCached(true);
                    broadcastFolderList(mBrowseNode.getID());
                    transitionTo(mConnected);
                    break;

                case MESSAGE_GET_FOLDER_LIST:
                    if (!mBrowseNode.equals((String) msg.obj)) {
                        mAbort = true;
                        deferMessage(msg);
                        Log.d(STATE_TAG, "Go Get Another Directory");
                    } else {
                        Log.d(STATE_TAG, "Get The Same Directory, ignore");
                    }
                    break;

                case MESSAGE_FETCH_ATTR_AND_PLAY_ITEM:
                    // A new request has come in, no need to fetch more.
                    mAbort = true;
                    deferMessage(msg);
                    break;

                case MESSAGE_SEND_PASS_THROUGH_CMD:
                case MESSAGE_SEND_GROUP_NAVIGATION_CMD:
                case MESSAGE_PROCESS_SET_ABS_VOL_CMD:
                case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION:
                case MESSAGE_PROCESS_TRACK_CHANGED:
                case MESSAGE_PROCESS_PLAY_POS_CHANGED:
                case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
                case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION:
                case MESSAGE_PROCESS_CONNECTION_CHANGE:
                case MESSAGE_PROCESS_BROWSE_CONNECTION_CHANGE:
                    // All of these messages should be handled by parent state immediately.
                    return false;

                default:
                    if (DBG) Log.d(STATE_TAG, "deferring message " + msg.what + " to connected!");
                    deferMessage(msg);
            }
            return true;
        }

        private void fetchContents(BrowseTree.BrowseNode target) {
            int start = target.getChildrenCount();
            int end = Math.min(target.getExpectedChildren(), target.getChildrenCount()
                            + GET_FOLDER_ITEMS_PAGINATION_SIZE) - 1;
            switch (target.getScope()) {
                case AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST:
                    AvrcpControllerService.getPlayerListNative(mRemoteDevice.getBluetoothAddress(),
                            start, end);
                    break;
                case AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING:
                    AvrcpControllerService.getNowPlayingListNative(
                            mRemoteDevice.getBluetoothAddress(), start, end);
                    break;
                case AvrcpControllerService.BROWSE_SCOPE_VFS:
                    AvrcpControllerService.getFolderListNative(mRemoteDevice.getBluetoothAddress(),
                            start, end);
                    break;
                default:
                    Log.e(STATE_TAG, "Scope " + target.getScope() + " cannot be handled here.");
            }
        }

        /* One of several things can happen when trying to get a folder list
         *
         *
         * 0: The folder handle is no longer valid
         * 1: The folder contents can be retrieved directly (NowPlaying, Root, Current)
         * 2: The folder is a browsable player
         * 3: The folder is a non browsable player
         * 4: The folder is not a child of the current folder
         * 5: The folder is a child of the current folder
         *
         */
        private void navigateToFolderOrRetrieve(BrowseTree.BrowseNode target) {
            mNextStep = mBrowseTree.getNextStepToFolder(target);
            if (DBG) {
                Log.d(TAG, "NAVIGATING From " + mBrowseTree.getCurrentBrowsedFolder().toString());
                Log.d(TAG, "NAVIGATING Toward " + target.toString());
            }
            if (mNextStep == null) {
                sendMessage(MESSAGE_INTERNAL_CMD_TIMEOUT);
            } else if (target.equals(mBrowseTree.mNowPlayingNode)
                       || target.equals(mBrowseTree.mRootNode)
                       || mNextStep.equals(mBrowseTree.getCurrentBrowsedFolder())) {
                fetchContents(mNextStep);
            } else if (mNextStep.isPlayer()) {
                if (DBG) Log.d(TAG, "NAVIGATING Player " + mNextStep.toString());
                if (mNextStep.isBrowsable()) {
                    AvrcpControllerService.setBrowsedPlayerNative(
                            mRemoteDevice.getBluetoothAddress(), mNextStep.getPlayerID());
                } else {
                    if (DBG) Log.d(TAG, "Player doesn't support browsing");
                    mNextStep.setCached(true);
                    broadcastFolderList(mNextStep.getID());
                    transitionTo(mConnected);
                }
            } else if (mNextStep.equals(mBrowseTree.mNavigateUpNode)) {
                if (DBG) Log.d(TAG, "NAVIGATING UP " + mNextStep.toString());
                mNextStep = mBrowseTree.getCurrentBrowsedFolder().getParent();
                mBrowseTree.getCurrentBrowsedFolder().setCached(false);

                AvrcpControllerService.changeFolderPathNative(
                        mRemoteDevice.getBluetoothAddress(),
                        AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_UP,
                        AvrcpControllerService.hexStringToByteUID(null));

            } else {
                if (DBG) Log.d(TAG, "NAVIGATING DOWN " + mNextStep.toString());
                AvrcpControllerService.changeFolderPathNative(
                        mRemoteDevice.getBluetoothAddress(),
                        AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_DOWN,
                        AvrcpControllerService.hexStringToByteUID(mNextStep.getFolderUID()));
            }
        }

        @Override
        public void exit() {
            mBrowseNode = null;
            super.exit();
        }
    }

    class SetAddresedPlayerAndPlayItem extends CmdState {
        private static final String STATE_TAG = "AVRCPSM.SetAddresedPlayerAndPlayItem";
        int mScope;
        String mPlayItemId;
        String mAddrPlayerId;

        public void setItemAndScope(String addrPlayerId, String playItemId, int scope) {
            mAddrPlayerId = addrPlayerId;
            mPlayItemId = playItemId;
            mScope = scope;
        }

        @Override
        public boolean processMessage(Message msg) {
            if (DBG) Log.d(STATE_TAG, "processMessage " + msg.what);
            switch (msg.what) {
                case MESSAGE_PROCESS_SET_ADDRESSED_PLAYER:
                    // Set the new addressed player.
                    mBrowseTree.setCurrentAddressedPlayer(mAddrPlayerId);

                    // And now play the item.
                    AvrcpControllerService.playItemNative(mRemoteDevice.getBluetoothAddress(),
                            (byte) mScope, AvrcpControllerService.hexStringToByteUID(mPlayItemId),
                            (int) 0);

                    // Transition to connected state here.
                    transitionTo(mConnected);
                    break;

                case MESSAGE_INTERNAL_CMD_TIMEOUT:
                    transitionTo(mConnected);
                    break;

                case MESSAGE_SEND_PASS_THROUGH_CMD:
                case MESSAGE_SEND_GROUP_NAVIGATION_CMD:
                case MESSAGE_PROCESS_SET_ABS_VOL_CMD:
                case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION:
                case MESSAGE_PROCESS_TRACK_CHANGED:
                case MESSAGE_PROCESS_PLAY_POS_CHANGED:
                case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
                case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION:
                case MESSAGE_PROCESS_CONNECTION_CHANGE:
                case MESSAGE_PROCESS_BROWSE_CONNECTION_CHANGE:
                    // All of these messages should be handled by parent state immediately.
                    return false;

                default:
                    if (DBG) Log.d(STATE_TAG, "deferring message " + msg.what + " to connected!");
                    deferMessage(msg);
            }
            return true;
        }
    }

    // Class template for commands. Each state should do the following:
    // (a) In enter() send a timeout message which could be tracked in the
    // processMessage() stage.
    // (b) In exit() remove all the timeouts.
    //
    // Essentially the lifecycle of a timeout should be bounded to a CmdState always.
    abstract class CmdState extends State {
        @Override
        public void enter() {
            sendMessageDelayed(MESSAGE_INTERNAL_CMD_TIMEOUT, CMD_TIMEOUT_MILLIS);
        }

        @Override
        public void exit() {
            removeMessages(MESSAGE_INTERNAL_CMD_TIMEOUT);
        }
    }

    // Interface APIs
    boolean isConnected() {
        synchronized (mLock) {
            return mIsConnected;
        }
    }

    void doQuit() {
        try {
            mContext.unregisterReceiver(mBroadcastReceiver);
        } catch (IllegalArgumentException expected) {
            // If the receiver was never registered unregister will throw an
            // IllegalArgumentException.
        }
        quit();
    }

    void dump(StringBuilder sb) {
        if (mRemoteDevice == null) return;
        BluetoothDevice device = mRemoteDevice.mBTDevice;
        if (device == null) return;
        ProfileService.println(sb, "mCurrentDevice: " + device.getAddress() + "("
                + device.getName() + ") " + this.toString());
    }

    MediaMetadata getCurrentMetaData() {
        synchronized (mLock) {
            if (mAddressedPlayer != null && mAddressedPlayer.getCurrentTrack() != null) {
                MediaMetadata mmd = mAddressedPlayer.getCurrentTrack().getMediaMetaData();
                if (DBG) {
                    Log.d(TAG, "getCurrentMetaData mmd " + mmd);
                }
            }
            return EMPTY_MEDIA_METADATA;
        }
    }

    PlaybackState getCurrentPlayBackState() {
        return getCurrentPlayBackState(true);
    }

    PlaybackState getCurrentPlayBackState(boolean cached) {
        if (cached) {
            synchronized (mLock) {
                if (mAddressedPlayer == null) {
                    return new PlaybackState.Builder().setState(PlaybackState.STATE_ERROR,
                            PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0).build();
                }
                return mAddressedPlayer.getPlaybackState();
            }
        } else {
            // Issue a native request, we return NULL since this is only for PTS.
            AvrcpControllerService.getPlaybackStateNative(mRemoteDevice.getBluetoothAddress());
            return null;
        }
    }

    List<MediaItem> getContents(String uid) {
        BrowseTree.BrowseNode currentNode = mBrowseTree.findBrowseNodeByID(uid);

        if (DBG) Log.d(TAG, "getContents(" + uid + ") currentNode = " + currentNode);
        if (currentNode != null) {
            if (!currentNode.isCached()) {
                sendMessage(AvrcpControllerStateMachine.MESSAGE_GET_FOLDER_LIST, uid);
            }
            return currentNode.getContents();
        }
        return null;
    }

    public void fetchAttrAndPlayItem(String uid) {
        BrowseTree.BrowseNode currItem = mBrowseTree.findBrowseNodeByID(uid);
        BrowseTree.BrowseNode currFolder = mBrowseTree.getCurrentBrowsedFolder();
        if (DBG) Log.d(TAG, "fetchAttrAndPlayItem mediaId=" + uid + " node=" + currItem);
        if (currItem != null) {
            int scope = currItem.getParent().isNowPlaying()
                    ? AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING
                    : AvrcpControllerService.BROWSE_SCOPE_VFS;
            Message msg =
                    obtainMessage(AvrcpControllerStateMachine.MESSAGE_FETCH_ATTR_AND_PLAY_ITEM,
                            scope, 0, currItem.getFolderUID());
            sendMessage(msg);
        }
    }

    private void broadcastMetaDataChanged(MediaMetadata metadata) {
        Intent intent = new Intent(AvrcpControllerService.ACTION_TRACK_EVENT);
        intent.putExtra(AvrcpControllerService.EXTRA_METADATA, metadata);
        if (VDBG) {
            Log.d(TAG, " broadcastMetaDataChanged = " + metadata.getDescription());
        }
        mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);

    }

    private void broadcastFolderList(String id) {
        Intent intent = new Intent(AvrcpControllerService.ACTION_FOLDER_LIST);
        if (VDBG) Log.d(TAG, "broadcastFolderList id " + id);
        intent.putExtra(AvrcpControllerService.EXTRA_FOLDER_ID, id);
        BluetoothMediaBrowserService bluetoothMediaBrowserService =
                BluetoothMediaBrowserService.getBluetoothMediaBrowserService();
        if (bluetoothMediaBrowserService != null) {
            bluetoothMediaBrowserService.processInternalEvent(intent);
        }
    }

    private void broadcastPlayBackStateChanged(PlaybackState state) {
        Intent intent = new Intent(AvrcpControllerService.ACTION_TRACK_EVENT);
        intent.putExtra(AvrcpControllerService.EXTRA_PLAYBACK, state);
        if (DBG) {
            Log.d(TAG, " broadcastPlayBackStateChanged = " + state.toString());
        }
        mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
    }

    private void setAbsVolume(int absVol, int label) {
        int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        int currIndex = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        // Ignore first volume command since phone may not know difference between stream volume
        // and amplifier volume.
        if (mRemoteDevice.getFirstAbsVolCmdRecvd()) {
            int newIndex = (maxVolume * absVol) / ABS_VOL_BASE;
            if (DBG) {
                Log.d(TAG, " setAbsVolume =" + absVol + " maxVol = " + maxVolume
                        + " cur = " + currIndex + " new = " + newIndex);
            }
            /*
             * In some cases change in percentage is not sufficient enough to warrant
             * change in index values which are in range of 0-15. For such cases
             * no action is required
             */
            if (newIndex != currIndex) {
                mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, newIndex,
                        AudioManager.FLAG_SHOW_UI);
            }
        } else {
            mRemoteDevice.setFirstAbsVolCmdRecvd();
            absVol = (currIndex * ABS_VOL_BASE) / maxVolume;
            if (DBG) Log.d(TAG, " SetAbsVol recvd for first time, respond with " + absVol);
        }
        AvrcpControllerService.sendAbsVolRspNative(mRemoteDevice.getBluetoothAddress(), absVol,
                label);
    }

    private int getVolumePercentage() {
        int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        int currIndex = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        int percentageVol = ((currIndex * ABS_VOL_BASE) / maxVolume);
        return percentageVol;
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                if (streamType == AudioManager.STREAM_MUSIC) {
                    sendMessage(MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION);
                }
            }
        }
    };

    public static String dumpMessageString(int message) {
        String str = "UNKNOWN";
        switch (message) {
            case MESSAGE_SEND_PASS_THROUGH_CMD:
                str = "REQ_PASS_THROUGH_CMD";
                break;
            case MESSAGE_SEND_GROUP_NAVIGATION_CMD:
                str = "REQ_GRP_NAV_CMD";
                break;
            case MESSAGE_PROCESS_SET_ABS_VOL_CMD:
                str = "CB_SET_ABS_VOL_CMD";
                break;
            case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION:
                str = "CB_REGISTER_ABS_VOL";
                break;
            case MESSAGE_PROCESS_TRACK_CHANGED:
                str = "CB_TRACK_CHANGED";
                break;
            case MESSAGE_PROCESS_PLAY_POS_CHANGED:
                str = "CB_PLAY_POS_CHANGED";
                break;
            case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
                str = "CB_PLAY_STATUS_CHANGED";
                break;
            case MESSAGE_PROCESS_RC_FEATURES:
                str = "CB_RC_FEATURES";
                break;
            case MESSAGE_PROCESS_CONNECTION_CHANGE:
                str = "CB_CONN_CHANGED";
                break;
            default:
                str = Integer.toString(message);
                break;
        }
        return str;
    }
}
