10eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan/*
20eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * Copyright (C) 2017 The Android Open Source Project
30eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan *
40eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * Licensed under the Apache License, Version 2.0 (the "License");
50eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * you may not use this file except in compliance with the License.
60eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * You may obtain a copy of the License at
70eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan *
80eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan *      http://www.apache.org/licenses/LICENSE-2.0
90eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan *
100eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * Unless required by applicable law or agreed to in writing, software
110eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * distributed under the License is distributed on an "AS IS" BASIS,
120eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * See the License for the specific language governing permissions and
140eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * limitations under the License.
150eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan */
160eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
170eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanpackage com.android.pmc;
180eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
190eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.app.AlarmManager;
200eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.app.PendingIntent;
210eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.bluetooth.BluetoothA2dp;
220eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.bluetooth.BluetoothAdapter;
230eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.bluetooth.BluetoothCodecConfig;
240eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.bluetooth.BluetoothCodecStatus;
250eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.bluetooth.BluetoothDevice;
260eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.bluetooth.BluetoothProfile;
270eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.content.BroadcastReceiver;
280eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.content.Context;
290eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.content.Intent;
300eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.content.IntentFilter;
310eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.media.MediaPlayer;
320eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.net.Uri;
330eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.os.Bundle;
340eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.os.SystemClock;
350eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport android.util.Log;
360eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
370eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanimport java.util.ArrayList;
383aad68c052667ec9b4c833f44432906359530da1Jim Tanimport java.util.Set;
390eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
400eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan/**
410eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan * Bluetooth A2DP Receiver functions for codec power testing.
420eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan */
430eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tanpublic class A2dpReceiver extends BroadcastReceiver {
440eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public static final String TAG = "A2DPPOWER";
450eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public static final String A2DP_INTENT = "com.android.pmc.A2DP";
460eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public static final String A2DP_ALARM = "com.android.pmc.A2DP.Alarm";
470eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public static final int THOUSAND = 1000;
480eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public static final int WAIT_SECONDS = 10;
493aad68c052667ec9b4c833f44432906359530da1Jim Tan    public static final int ALARM_MESSAGE = 1;
500eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
51ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan    public static final float NORMAL_VOLUME = 0.3f;
520eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public static final float ZERO_VOLUME = 0.0f;
530eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
540eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private final Context mContext;
550eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private final AlarmManager mAlarmManager;
563aad68c052667ec9b4c833f44432906359530da1Jim Tan    private final BluetoothAdapter mBluetoothAdapter;
570eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
580eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private MediaPlayer mPlayer;
590eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private BluetoothA2dp mBluetoothA2dp;
603aad68c052667ec9b4c833f44432906359530da1Jim Tan
613aad68c052667ec9b4c833f44432906359530da1Jim Tan    private PMCStatusLogger mPMCStatusLogger;
620eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
630eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
640eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * BroadcastReceiver() to get status after calling setCodecConfigPreference()
650eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
660eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
670eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private BroadcastReceiver mBluetoothA2dpReceiver = new BroadcastReceiver() {
680eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        @Override
690eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        public void onReceive(Context context, Intent intent) {
700eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "mBluetoothA2dpReceiver.onReceive() intent=" + intent);
710eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            String action = intent.getAction();
720eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
730eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            if (BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED.equals(action)) {
740eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                getCodecValue(true);
750eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
760eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
770eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    };
780eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
790eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
800eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * ServiceListener for A2DP connection/disconnection event
810eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
820eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
830eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private BluetoothProfile.ServiceListener mBluetoothA2dpServiceListener =
840eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            new BluetoothProfile.ServiceListener() {
850eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            public void onServiceConnected(int profile,
860eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                                           BluetoothProfile proxy) {
870eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                Log.d(TAG, "BluetoothA2dpServiceListener.onServiceConnected");
880eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                mBluetoothA2dp = (BluetoothA2dp) proxy;
890eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                getCodecValue(true);
900eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
910eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
920eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            public void onServiceDisconnected(int profile) {
930eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                Log.d(TAG, "BluetoothA2dpServiceListener.onServiceDisconnected");
940eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                mBluetoothA2dp = null;
950eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
960eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        };
970eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
980eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
990eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * Constructor to be called by PMC
1000eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
1010eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param context - PMC will provide a context
1020eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param alarmManager - PMC will provide alarmManager
1030eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
1040eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public A2dpReceiver(Context context, AlarmManager alarmManager) {
1050eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        // Prepare for setting alarm service
1060eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        mContext = context;
1070eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        mAlarmManager = alarmManager;
1083aad68c052667ec9b4c833f44432906359530da1Jim Tan
1090eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
1100eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (mBluetoothAdapter == null) {
1110eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.e(TAG, "BluetoothAdapter is Null");
1120eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return;
1130eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        } else {
1140eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            if (!mBluetoothAdapter.isEnabled()) {
1150eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                Log.d(TAG, "BluetoothAdapter is NOT enabled, enable now");
1160eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                mBluetoothAdapter.enable();
1170eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                if (!mBluetoothAdapter.isEnabled()) {
1180eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                    Log.e(TAG, "Can't enable Bluetooth");
1190eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                    return;
1200eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                }
1210eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
1220eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
1230eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        // Setup BroadcastReceiver for ACTION_CODEC_CONFIG_CHANGED
1240eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        IntentFilter filter = new IntentFilter();
1250eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (mBluetoothAdapter != null) {
1263aad68c052667ec9b4c833f44432906359530da1Jim Tan            mBluetoothAdapter.getProfileProxy(mContext,
1270eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                                    mBluetoothA2dpServiceListener,
1280eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                                    BluetoothProfile.A2DP);
1293aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "After getProfileProxy()");
1300eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
1310eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        filter = new IntentFilter();
1320eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        filter.addAction(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED);
1333aad68c052667ec9b4c833f44432906359530da1Jim Tan        mContext.registerReceiver(mBluetoothA2dpReceiver, filter);
1343aad68c052667ec9b4c833f44432906359530da1Jim Tan
1353aad68c052667ec9b4c833f44432906359530da1Jim Tan        Log.d(TAG, "A2dpReceiver()");
1363aad68c052667ec9b4c833f44432906359530da1Jim Tan    }
1373aad68c052667ec9b4c833f44432906359530da1Jim Tan
1383aad68c052667ec9b4c833f44432906359530da1Jim Tan    /**
1393aad68c052667ec9b4c833f44432906359530da1Jim Tan     * initialize() to setup Bluetooth adapters and check if Bluetooth device is connected
1403aad68c052667ec9b4c833f44432906359530da1Jim Tan     *              it is called when PMC command is received to start streaming
1413aad68c052667ec9b4c833f44432906359530da1Jim Tan     */
1423aad68c052667ec9b4c833f44432906359530da1Jim Tan    private boolean initialize() {
1433aad68c052667ec9b4c833f44432906359530da1Jim Tan        Log.d(TAG, "Start initialize()");
1443aad68c052667ec9b4c833f44432906359530da1Jim Tan
1453aad68c052667ec9b4c833f44432906359530da1Jim Tan        // Check if any Bluetooth devices are connected
1463aad68c052667ec9b4c833f44432906359530da1Jim Tan        ArrayList<BluetoothDevice> results = new ArrayList<BluetoothDevice>();
1473aad68c052667ec9b4c833f44432906359530da1Jim Tan        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
1483aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (bondedDevices == null) {
1493aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.e(TAG, "Bonded devices list is null");
1503aad68c052667ec9b4c833f44432906359530da1Jim Tan            return false;
1513aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
1523aad68c052667ec9b4c833f44432906359530da1Jim Tan        for (BluetoothDevice bd : bondedDevices) {
1533aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (bd.isConnected()) {
1543aad68c052667ec9b4c833f44432906359530da1Jim Tan                results.add(bd);
1553aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
1563aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
1573aad68c052667ec9b4c833f44432906359530da1Jim Tan
1583aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (results.isEmpty()) {
1593aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.e(TAG, "No device is connected");
1603aad68c052667ec9b4c833f44432906359530da1Jim Tan            return false;
1613aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
1623aad68c052667ec9b4c833f44432906359530da1Jim Tan
1633aad68c052667ec9b4c833f44432906359530da1Jim Tan        Log.d(TAG, "Finish initialize()");
1643aad68c052667ec9b4c833f44432906359530da1Jim Tan
1653aad68c052667ec9b4c833f44432906359530da1Jim Tan        return true;
1660eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
1670eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
1680eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
1690eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * Method to receive the broadcast from Python client or AlarmManager
1700eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
1710eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param context - system will provide a context to this function
1720eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param intent - system will provide an intent to this function
1730eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
1740eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    @Override
1750eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    public void onReceive(Context context, Intent intent) {
1760eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (!intent.getAction().equals(A2DP_INTENT)) return;
1770eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        boolean alarm = intent.hasExtra(A2DP_ALARM);
1780eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (alarm) {
1793aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.v(TAG, "Alarm Message to Stop playing");
1803aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPMCStatusLogger.logStatus("SUCCEED");
1813aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPlayer.stop();
1823aad68c052667ec9b4c833f44432906359530da1Jim Tan            // Release the Media Player
1833aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPlayer.release();
1840eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        } else {
1850eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "Received PMC command message");
1860eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            processParameters(intent);
1870eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
1880eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
1890eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
1900eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
1910eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * Method to process parameters from Python client
1920eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
1930eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param intent - system will provide an intent to this function
1940eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
1950eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private void processParameters(Intent intent) {
1960eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        int codecType = BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
1970eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        int sampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
1980eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        int bitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
1990eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        int channelMode = BluetoothCodecConfig.CHANNEL_MODE_STEREO;
2000eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        // codecSpecific1 is for LDAC quality so far
2010eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        // Other code specific values are not used now
2020eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        long codecSpecific1 = 0, codecSpecific2 = 0, codecSpecific3 = 0,
2030eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                codecSpecific4 = 0;
2043aad68c052667ec9b4c833f44432906359530da1Jim Tan        int playTime = 0;
2050eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        String musicUrl;
2060eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        String tmpStr;
2073aad68c052667ec9b4c833f44432906359530da1Jim Tan
208dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        // Create the logger object
209dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        mPMCStatusLogger = new PMCStatusLogger(TAG + ".log", TAG);
210dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti
2113aad68c052667ec9b4c833f44432906359530da1Jim Tan        // For a baseline case when Blueooth is off but music is playing with speaker is muted
2123aad68c052667ec9b4c833f44432906359530da1Jim Tan        boolean bt_off_mute = false;
2130eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2140eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Bundle extras = intent.getExtras();
2150eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2160eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (extras == null) {
2170eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.e(TAG, "No parameters specified");
2180eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return;
2190eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
220dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti
221dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        if (extras.containsKey("BT_OFF_Mute")) {
222dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti            Log.v(TAG, "Mute is specified for Bluetooth off baseline case");
223dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti            bt_off_mute = true;
224dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        }
225dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti
226dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        // initialize() if we are testing over Bluetooth, we do NOT test
227dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        // over bluetooth for the play music with Bluetooth off test case.
228dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        if (!bt_off_mute) {
229dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti            if (!initialize()) {
230dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti                mPMCStatusLogger.logStatus("initialize() Failed");
231dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti                return;
232dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti            }
2330eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
2343aad68c052667ec9b4c833f44432906359530da1Jim Tan        // Check if it is baseline Bluetooth is on but not stream
2353aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (extras.containsKey("BT_ON_NotPlay")) {
2363aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.v(TAG, "NotPlay is specified for baseline case that only Bluetooth is on");
2373aad68c052667ec9b4c833f44432906359530da1Jim Tan            // Do nothing further
2383aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPMCStatusLogger.logStatus("READY");
2393aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPMCStatusLogger.logStatus("SUCCEED");
2400eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return;
2410eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
2420eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2430eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (!extras.containsKey("PlayTime")) {
2440eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.e(TAG, "No Play Time specified");
2450eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return;
2460eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
2470eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        tmpStr = extras.getString("PlayTime");
2480eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Log.d(TAG, "Play Time = " + tmpStr);
2490eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        playTime = Integer.valueOf(tmpStr);
2500eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2510eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (!extras.containsKey("MusicURL")) {
2520eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.e(TAG, "No Music URL specified");
2530eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return;
2540eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
2550eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        musicUrl = extras.getString("MusicURL");
2560eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Log.d(TAG, "Music URL = " + musicUrl);
2570eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2583aad68c052667ec9b4c833f44432906359530da1Jim Tan        // playTime and musicUrl are necessary
2593aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (playTime == 0 || musicUrl.isEmpty() || musicUrl == null) {
2600eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "Invalid paramters");
2610eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return;
2620eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
2633aad68c052667ec9b4c833f44432906359530da1Jim Tan        // Check if it is the baseline that Bluetooth is off but streaming with speakers muted
264dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti        if (!bt_off_mute) {
2653aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (!extras.containsKey("CodecType")) {
2663aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.e(TAG, "No Codec Type specified");
2673aad68c052667ec9b4c833f44432906359530da1Jim Tan                return;
2683aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
2693aad68c052667ec9b4c833f44432906359530da1Jim Tan            tmpStr = extras.getString("CodecType");
2703aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "Codec Type= " + tmpStr);
2713aad68c052667ec9b4c833f44432906359530da1Jim Tan            codecType = Integer.valueOf(tmpStr);
2720eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2733aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (!extras.containsKey("SampleRate")) {
2743aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.e(TAG, "No Sample Rate specified");
2753aad68c052667ec9b4c833f44432906359530da1Jim Tan                return;
2763aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
2773aad68c052667ec9b4c833f44432906359530da1Jim Tan            tmpStr = extras.getString("SampleRate");
2783aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "Sample Rate = " + tmpStr);
2793aad68c052667ec9b4c833f44432906359530da1Jim Tan            sampleRate = Integer.valueOf(tmpStr);
2800eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2813aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (!extras.containsKey("BitsPerSample")) {
2823aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.e(TAG, "No BitsPerSample specified");
2833aad68c052667ec9b4c833f44432906359530da1Jim Tan                return;
2843aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
2853aad68c052667ec9b4c833f44432906359530da1Jim Tan            tmpStr = extras.getString("BitsPerSample");
2863aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "BitsPerSample = " + tmpStr);
2873aad68c052667ec9b4c833f44432906359530da1Jim Tan            bitsPerSample = Integer.valueOf(tmpStr);
2883aad68c052667ec9b4c833f44432906359530da1Jim Tan
2893aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (extras.containsKey("ChannelMode")) {
2903aad68c052667ec9b4c833f44432906359530da1Jim Tan                tmpStr = extras.getString("ChannelMode");
2913aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "ChannelMode = " + tmpStr);
2923aad68c052667ec9b4c833f44432906359530da1Jim Tan                channelMode = Integer.valueOf(tmpStr);
2933aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
2940eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
2953aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (extras.containsKey("LdacPlaybackQuality")) {
2963aad68c052667ec9b4c833f44432906359530da1Jim Tan                tmpStr = extras.getString("LdacPlaybackQuality");
2973aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "LdacPlaybackQuality = " + tmpStr);
2983aad68c052667ec9b4c833f44432906359530da1Jim Tan                codecSpecific1 = Integer.valueOf(tmpStr);
2993aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
3000eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3013aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (extras.containsKey("CodecSpecific2")) {
3023aad68c052667ec9b4c833f44432906359530da1Jim Tan                tmpStr = extras.getString("CodecSpecific2");
3033aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "CodecSpecific2 = " + tmpStr);
3043aad68c052667ec9b4c833f44432906359530da1Jim Tan                codecSpecific1 = Integer.valueOf(tmpStr);
305ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan            }
3060eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3073aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (extras.containsKey("CodecSpecific3")) {
3083aad68c052667ec9b4c833f44432906359530da1Jim Tan                tmpStr = extras.getString("CodecSpecific3");
3093aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "CodecSpecific3 = " + tmpStr);
3103aad68c052667ec9b4c833f44432906359530da1Jim Tan                codecSpecific1 = Integer.valueOf(tmpStr);
3113aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
3120eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3133aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (extras.containsKey("CodecSpecific4")) {
3143aad68c052667ec9b4c833f44432906359530da1Jim Tan                tmpStr = extras.getString("CodecSpecific4");
3153aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "CodecSpecific4 = " + tmpStr);
3163aad68c052667ec9b4c833f44432906359530da1Jim Tan                codecSpecific1 = Integer.valueOf(tmpStr);
3173aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
3180eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3193aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (codecType == BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID
3203aad68c052667ec9b4c833f44432906359530da1Jim Tan                    || sampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE
3213aad68c052667ec9b4c833f44432906359530da1Jim Tan                    || bitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
322dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti                Log.d(TAG, "Invalid parameters");
3233aad68c052667ec9b4c833f44432906359530da1Jim Tan                return;
3243aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
3253aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
3260eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3273aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (playMusic(musicUrl, bt_off_mute)) {
3283aad68c052667ec9b4c833f44432906359530da1Jim Tan            // Set the requested Codecs on the device for normal codec cases
3293aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (!bt_off_mute) {
3303aad68c052667ec9b4c833f44432906359530da1Jim Tan                if (!setCodecValue(codecType, sampleRate, bitsPerSample, channelMode,
3313aad68c052667ec9b4c833f44432906359530da1Jim Tan                        codecSpecific1, codecSpecific2, codecSpecific3, codecSpecific4)) {
3323aad68c052667ec9b4c833f44432906359530da1Jim Tan                    mPMCStatusLogger.logStatus("setCodecValue() Failed");
3333aad68c052667ec9b4c833f44432906359530da1Jim Tan                }
3343aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
3353aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPMCStatusLogger.logStatus("READY");
3363aad68c052667ec9b4c833f44432906359530da1Jim Tan            startAlarm(playTime);
3370eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        } else {
3383aad68c052667ec9b4c833f44432906359530da1Jim Tan            mPMCStatusLogger.logStatus("playMusic() Failed");
3390eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
3400eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
3410eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3423aad68c052667ec9b4c833f44432906359530da1Jim Tan
3430eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
3443aad68c052667ec9b4c833f44432906359530da1Jim Tan     * Function to setup MediaPlayer and play music
3450eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
3460eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param musicURL - Music URL
347dcf6ecc947983a92f6a4b1e5028c33780b58307cAndi Janti     * @param btOffMute - true is to mute speakers
3480eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
3490eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
3503aad68c052667ec9b4c833f44432906359530da1Jim Tan    private boolean playMusic(String musicURL, boolean btOffMute) {
3510eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3520eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        mPlayer = MediaPlayer.create(mContext, Uri.parse(musicURL));
3530eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (mPlayer == null) {
3540eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.e(TAG, "Failed to create Media Player");
3550eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            return false;
3560eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
3570eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Log.d(TAG, "Media Player created: " + musicURL);
3580eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3593aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (btOffMute) {
3603aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.v(TAG, "Mute Speakers for Bluetooth off baseline case");
3610eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            mPlayer.setVolume(ZERO_VOLUME, ZERO_VOLUME);
3620eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        } else {
3630eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "Set Normal Volume for speakers");
3640eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            mPlayer.setVolume(NORMAL_VOLUME, NORMAL_VOLUME);
3650eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
3663aad68c052667ec9b4c833f44432906359530da1Jim Tan        // Play Music now and setup looping
3673aad68c052667ec9b4c833f44432906359530da1Jim Tan        mPlayer.start();
3683aad68c052667ec9b4c833f44432906359530da1Jim Tan        mPlayer.setLooping(true);
3693aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (!mPlayer.isPlaying()) {
3703aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.e(TAG, "Media Player is not playing");
3713aad68c052667ec9b4c833f44432906359530da1Jim Tan            return false;
3723aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
3733aad68c052667ec9b4c833f44432906359530da1Jim Tan
3740eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        return true;
3750eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
3760eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3770eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
3780eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * Function to be called to start alarm
3790eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
3800eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param alarmStartTime - time when the music needs to be started or stopped
3810eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
3823aad68c052667ec9b4c833f44432906359530da1Jim Tan    private void startAlarm(int alarmStartTime) {
3830eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3840eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Intent alarmIntent = new Intent(A2DP_INTENT);
3850eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        alarmIntent.putExtra(A2DP_ALARM, ALARM_MESSAGE);
3860eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3870eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        long triggerTime = SystemClock.elapsedRealtime()
3880eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                               + alarmStartTime * THOUSAND;
3890eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        mAlarmManager.setExactAndAllowWhileIdle(
3900eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                          AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime,
3910eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                          PendingIntent.getBroadcast(mContext, 0,
3920eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                                        alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT));
3930eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
3940eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
3950eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
3960eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * Function to get current codec config
3970eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param printCapabilities - Flag to indicate if to print local and selectable capabilities
3980eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
3990eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    private BluetoothCodecConfig getCodecValue(boolean printCapabilities) {
4000eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        BluetoothCodecStatus codecStatus = null;
4010eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        BluetoothCodecConfig codecConfig = null;
4020eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        BluetoothCodecConfig[] codecsLocalCapabilities = null;
4030eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        BluetoothCodecConfig[] codecsSelectableCapabilities = null;
4040eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
4050eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (mBluetoothA2dp != null) {
4060eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            codecStatus = mBluetoothA2dp.getCodecStatus();
4070eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            if (codecStatus != null) {
4080eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                codecConfig = codecStatus.getCodecConfig();
4090eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                codecsLocalCapabilities = codecStatus.getCodecsLocalCapabilities();
4100eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                codecsSelectableCapabilities = codecStatus.getCodecsSelectableCapabilities();
4110eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
4120eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
4130eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (codecConfig == null) return null;
4140eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
4150eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Log.d(TAG, "GetCodecValue: " + codecConfig.toString());
4160eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
4170eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (printCapabilities) {
4180eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "Local Codec Capabilities ");
4190eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            for (BluetoothCodecConfig config : codecsLocalCapabilities) {
4200eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                Log.d(TAG, config.toString());
4210eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
4220eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "Codec Selectable Capabilities: ");
4230eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            for (BluetoothCodecConfig config : codecsSelectableCapabilities) {
4240eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                Log.d(TAG, config.toString());
4250eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            }
4260eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
4270eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        return codecConfig;
4280eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
4290eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
4300eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    /**
4310eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * Function to set new codec config
4320eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     *
4330eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param codecType - Codec Type
4340eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param sampleRate - Sample Rate
4350eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param bitsPerSample - Bit Per Sample
4360eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param codecSpecific1 - LDAC playback quality
4370eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param codecSpecific2 - codecSpecific2
4380eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param codecSpecific3 - codecSpecific3
4390eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     * @param codecSpecific4 - codecSpecific4
4400eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan     */
4413aad68c052667ec9b4c833f44432906359530da1Jim Tan    private boolean setCodecValue(int codecType, int sampleRate, int bitsPerSample,
4420eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                int channelMode, long codecSpecific1, long codecSpecific2,
4430eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                long codecSpecific3, long codecSpecific4) {
4440eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        Log.d(TAG, "SetCodecValue: Codec Type: " + codecType + " sampleRate: " + sampleRate
4450eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                + " bitsPerSample: " + bitsPerSample + " Channel Mode: " + channelMode
4460eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                + " LDAC quality: " + codecSpecific1);
4470eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
4480eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        BluetoothCodecConfig codecConfig =
4490eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                new BluetoothCodecConfig(codecType, BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
4500eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                sampleRate, bitsPerSample, channelMode,
4510eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan                codecSpecific1, codecSpecific2, codecSpecific3, codecSpecific4);
4520eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan
4533aad68c052667ec9b4c833f44432906359530da1Jim Tan        // Wait here to see if mBluetoothA2dp is set
4543aad68c052667ec9b4c833f44432906359530da1Jim Tan        for (int i = 0; i < WAIT_SECONDS; i++) {
4553aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "Wait for BluetoothA2dp");
4563aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (mBluetoothA2dp != null) {
4573aad68c052667ec9b4c833f44432906359530da1Jim Tan                break;
4583aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
4593aad68c052667ec9b4c833f44432906359530da1Jim Tan
4603aad68c052667ec9b4c833f44432906359530da1Jim Tan            try {
4613aad68c052667ec9b4c833f44432906359530da1Jim Tan                Thread.sleep(THOUSAND);
4623aad68c052667ec9b4c833f44432906359530da1Jim Tan            } catch (InterruptedException e) {
4633aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "Sleep is interrupted");
4643aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
4653aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
4663aad68c052667ec9b4c833f44432906359530da1Jim Tan
4670eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        if (mBluetoothA2dp != null) {
4680eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.d(TAG, "setCodecConfigPreference()");
4690eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            mBluetoothA2dp.setCodecConfigPreference(codecConfig);
4700eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        } else {
4710eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan            Log.e(TAG, "mBluetoothA2dp is null. Codec is not set");
4723aad68c052667ec9b4c833f44432906359530da1Jim Tan            return false;
4733aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
4743aad68c052667ec9b4c833f44432906359530da1Jim Tan        // Wait here to see if the codec is changed to new value
4753aad68c052667ec9b4c833f44432906359530da1Jim Tan        for (int i = 0; i < WAIT_SECONDS; i++) {
4763aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (verifyCodeConfig(codecType, sampleRate,
4773aad68c052667ec9b4c833f44432906359530da1Jim Tan                    bitsPerSample, channelMode, codecSpecific1))  {
4783aad68c052667ec9b4c833f44432906359530da1Jim Tan                break;
4793aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
4803aad68c052667ec9b4c833f44432906359530da1Jim Tan            try {
4813aad68c052667ec9b4c833f44432906359530da1Jim Tan                Thread.sleep(THOUSAND);
4823aad68c052667ec9b4c833f44432906359530da1Jim Tan            } catch (InterruptedException e) {
4833aad68c052667ec9b4c833f44432906359530da1Jim Tan                Log.d(TAG, "Sleep is interrupted");
4843aad68c052667ec9b4c833f44432906359530da1Jim Tan            }
4853aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
4863aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (!verifyCodeConfig(codecType, sampleRate,
4873aad68c052667ec9b4c833f44432906359530da1Jim Tan                bitsPerSample, channelMode, codecSpecific1)) {
4883aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.e(TAG, "Codec config is NOT set correctly");
4893aad68c052667ec9b4c833f44432906359530da1Jim Tan            return false;
4900eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan        }
4913aad68c052667ec9b4c833f44432906359530da1Jim Tan        return true;
4920eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan    }
4933aad68c052667ec9b4c833f44432906359530da1Jim Tan
4943aad68c052667ec9b4c833f44432906359530da1Jim Tan    /**
4953aad68c052667ec9b4c833f44432906359530da1Jim Tan     * Method to verify if the codec config values are changed
4963aad68c052667ec9b4c833f44432906359530da1Jim Tan     *
4973aad68c052667ec9b4c833f44432906359530da1Jim Tan     * @param codecType - Codec Type
4983aad68c052667ec9b4c833f44432906359530da1Jim Tan     * @param sampleRate - Sample Rate
4993aad68c052667ec9b4c833f44432906359530da1Jim Tan     * @param bitsPerSample - Bit Per Sample
5003aad68c052667ec9b4c833f44432906359530da1Jim Tan     * @param codecSpecific1 - LDAC playback quality
5013aad68c052667ec9b4c833f44432906359530da1Jim Tan     */
5023aad68c052667ec9b4c833f44432906359530da1Jim Tan    private boolean verifyCodeConfig(int codecType, int sampleRate, int bitsPerSample,
5033aad68c052667ec9b4c833f44432906359530da1Jim Tan                                     int channelMode, long codecSpecific1) {
5043aad68c052667ec9b4c833f44432906359530da1Jim Tan        BluetoothCodecConfig codecConfig = null;
5053aad68c052667ec9b4c833f44432906359530da1Jim Tan        codecConfig = getCodecValue(false);
5063aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (codecConfig == null) return false;
5073aad68c052667ec9b4c833f44432906359530da1Jim Tan
5083aad68c052667ec9b4c833f44432906359530da1Jim Tan        if (codecType == BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC) {
5093aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (codecConfig.getCodecType() == codecType
5103aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getSampleRate() == sampleRate
5113aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getBitsPerSample() == bitsPerSample
5123aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getChannelMode() == channelMode
5133aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getCodecSpecific1() == codecSpecific1) return true;
5143aad68c052667ec9b4c833f44432906359530da1Jim Tan        } else {
5153aad68c052667ec9b4c833f44432906359530da1Jim Tan            if (codecConfig.getCodecType() == codecType
5163aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getSampleRate() == sampleRate
5173aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getBitsPerSample() == bitsPerSample
5183aad68c052667ec9b4c833f44432906359530da1Jim Tan                    && codecConfig.getChannelMode() == channelMode) return true;
5193aad68c052667ec9b4c833f44432906359530da1Jim Tan        }
5203aad68c052667ec9b4c833f44432906359530da1Jim Tan
5213aad68c052667ec9b4c833f44432906359530da1Jim Tan        return false;
5223aad68c052667ec9b4c833f44432906359530da1Jim Tan    }
5233aad68c052667ec9b4c833f44432906359530da1Jim Tan
5240eef78fec19807c7f0223f90ca235e10e6f5ea61Jim Tan}
525