BluetoothA2dpSink.java revision 1bec6a5b0d67f120b7013572f6b1a4f1e1b3c584
12263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood/*
22263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * Copyright (C) 2014 The Android Open Source Project
32263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *
42263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
52263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * you may not use this file except in compliance with the License.
62263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * You may obtain a copy of the License at
72263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *
82263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
92263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *
102263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * Unless required by applicable law or agreed to in writing, software
112263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
122263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * See the License for the specific language governing permissions and
142263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * limitations under the License.
152263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood */
162263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
172263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodpackage android.bluetooth;
182263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
192263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.content.ComponentName;
202263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.content.Context;
212263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.content.Intent;
222263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.content.ServiceConnection;
232263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.os.IBinder;
242263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.os.RemoteException;
252263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport android.util.Log;
262263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
272263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport java.util.ArrayList;
282263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodimport java.util.List;
292263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
302263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood/**
312263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * This class provides the public APIs to control the Bluetooth A2DP Sink
322263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * profile.
332263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *
342263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *<p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink
352263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
362263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * the BluetoothA2dpSink proxy object.
372263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood *
382263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood * @hide
392263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood */
402263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwoodpublic final class BluetoothA2dpSink implements BluetoothProfile {
412263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private static final String TAG = "BluetoothA2dpSink";
422263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private static final boolean DBG = true;
432263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private static final boolean VDBG = false;
442263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
452263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
462263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Intent used to broadcast the change in connection state of the A2DP Sink
472263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * profile.
482263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
492263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>This intent will have 3 extras:
502263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <ul>
512263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
522263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
532263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
542263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * </ul>
552263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
562263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
572263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
582263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
592263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
602263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
612263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * receive.
622263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
632263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static final String ACTION_CONNECTION_STATE_CHANGED =
642263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
652263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
662263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
672263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Intent used to broadcast the change in the Playing state of the A2DP Sink
682263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * profile.
692263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
702263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>This intent will have 3 extras:
712263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <ul>
722263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
732263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
742263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
752263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * </ul>
762263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
772263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
782263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
792263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
802263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
812263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * receive.
822263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
832263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static final String ACTION_PLAYING_STATE_CHANGED =
842263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED";
852263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
862263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
872263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * A2DP sink device is streaming music. This state can be one of
882263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
892263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
902263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
912263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static final int STATE_PLAYING   =  10;
922263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
932263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
942263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * A2DP sink device is NOT streaming music. This state can be one of
952263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
962263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
972263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
982263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static final int STATE_NOT_PLAYING   =  11;
992263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1002263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
1012263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Intent used to broadcast the change in the Playing state of the A2DP Sink
1022263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * profile.
1032263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
1042263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>This intent will have 3 extras:
1052263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <ul>
1062263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link #EXTRA_AUDIO_CONFIG} - The audio configuration for the remote device. </li>
1072263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
1082263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * </ul>
1092263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
1102263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
1112263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * receive.
1122263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
1132263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static final String ACTION_AUDIO_CONFIG_CHANGED =
1142263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED";
1152263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1162263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
1172263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Extra for the {@link #ACTION_AUDIO_CONFIG_CHANGED} intent.
1182263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
1192263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * This extra represents the current audio configuration of the A2DP source device.
1202263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@see BluetoothAudioConfig}
1212263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
1222263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static final String EXTRA_AUDIO_CONFIG
1232263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            = "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
1242263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1252263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private Context mContext;
1262263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private ServiceListener mServiceListener;
1272263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private IBluetoothA2dpSink mService;
1282263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private BluetoothAdapter mAdapter;
1292263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1302263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
1312263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            new IBluetoothStateChangeCallback.Stub() {
1322263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                public void onBluetoothStateChange(boolean up) {
1332263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
1342263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    if (!up) {
1352263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                        if (VDBG) Log.d(TAG,"Unbinding service...");
1362263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                        synchronized (mConnection) {
1372263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                            try {
1382263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                mService = null;
1392263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                mContext.unbindService(mConnection);
1402263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                            } catch (Exception re) {
1412263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                Log.e(TAG,"",re);
1422263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                            }
1432263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                        }
1442263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    } else {
1452263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                        synchronized (mConnection) {
1462263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                            try {
1472263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                if (mService == null) {
1482263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                    if (VDBG) Log.d(TAG,"Binding service...");
1492263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                    doBind();
1502263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                }
1512263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                            } catch (Exception re) {
1522263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                                Log.e(TAG,"",re);
1532263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                            }
1542263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                        }
1552263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    }
1562263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                }
1572263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        };
1582263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
1592263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Create a BluetoothA2dp proxy object for interacting with the local
1602263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Bluetooth A2DP service.
1612263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
1622263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
1632263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) {
1642263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        mContext = context;
1652263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        mServiceListener = l;
1662263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        mAdapter = BluetoothAdapter.getDefaultAdapter();
1672263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1682263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mgr != null) {
1692263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
1702263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
1712263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
1722263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG,"",e);
1732263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
1742263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
1752263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1762263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        doBind();
1772263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
1782263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1792263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    boolean doBind() {
1802263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        Intent intent = new Intent(IBluetoothA2dpSink.class.getName());
1812263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
1822263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        intent.setComponent(comp);
1832263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
1842263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                android.os.Process.myUserHandle())) {
1852263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
1862263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return false;
1872263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
1882263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return true;
1892263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
1902263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
1912263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /*package*/ void close() {
1922263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        mServiceListener = null;
1932263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1942263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mgr != null) {
1952263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
1962263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
1972263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (Exception e) {
1982263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG,"",e);
1992263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
2002263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
2012263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
2022263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        synchronized (mConnection) {
2032263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            if (mService != null) {
2042263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                try {
2052263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    mService = null;
2062263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    mContext.unbindService(mConnection);
2072263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                } catch (Exception re) {
2082263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                    Log.e(TAG,"",re);
2092263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                }
2102263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
2112263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
2122263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
2132263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
2142263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public void finalize() {
2152263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        close();
2162263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
2172263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
2182263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Initiate connection to a profile of the remote bluetooth device.
2192263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2202263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p> Currently, the system supports only 1 connection to the
2212263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * A2DP profile. The API will automatically disconnect connected
2222263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * devices before connecting.
2232263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2242263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p> This API returns false in scenarios like the profile on the
2252263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * device is already connected or Bluetooth is not turned on.
2262263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * When this API returns true, it is guaranteed that
2272263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * connection state intent for the profile will be broadcasted with
2282263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * the state. Users can get the connection state of the profile
2292263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * from this intent.
2302263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2312263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2322263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * permission.
2332263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2342263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @param device Remote Bluetooth Device
2352263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @return false on immediate error,
2362263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *               true otherwise
2372263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @hide
2382263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
2392263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public boolean connect(BluetoothDevice device) {
2402263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (DBG) log("connect(" + device + ")");
2412263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService != null && isEnabled() &&
2422263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            isValidDevice(device)) {
2432263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
2442263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return mService.connect(device);
2452263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
2462263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2472263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return false;
2482263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
2492263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
2502263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2512263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return false;
2522263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
2532263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
2542263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
2552263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Initiate disconnection from a profile
2562263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2572263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p> This API will return false in scenarios like the profile on the
2582263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Bluetooth device is not in connected state etc. When this API returns,
2592263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * true, it is guaranteed that the connection state change
2602263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * intent will be broadcasted with the state. Users can get the
2612263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * disconnection state of the profile from this intent.
2622263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2632263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p> If the disconnection is initiated by a remote device, the state
2642263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * will transition from {@link #STATE_CONNECTED} to
2652263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
2662263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * host (local) device the state will transition from
2672263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
2682263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * state {@link #STATE_DISCONNECTED}. The transition to
2692263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
2702263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * two scenarios.
2712263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2722263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2732263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * permission.
2742263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
2752263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @param device Remote Bluetooth Device
2762263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @return false on immediate error,
2772263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *               true otherwise
2782263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @hide
2792263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
2802263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public boolean disconnect(BluetoothDevice device) {
2812263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (DBG) log("disconnect(" + device + ")");
2822263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService != null && isEnabled() &&
2832263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            isValidDevice(device)) {
2842263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
2852263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return mService.disconnect(device);
2862263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
2872263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2882263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return false;
2892263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
2902263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
2912263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2922263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return false;
2932263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
2942263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
2952263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
2962263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@inheritDoc}
2972263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
2982263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public List<BluetoothDevice> getConnectedDevices() {
2992263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (VDBG) log("getConnectedDevices()");
3002263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService != null && isEnabled()) {
3012263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
3022263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return mService.getConnectedDevices();
3032263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
3042263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3052263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return new ArrayList<BluetoothDevice>();
3062263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
3072263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
3082263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3092263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return new ArrayList<BluetoothDevice>();
3102263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
3112263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
3122263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
3132263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@inheritDoc}
3142263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
3152263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
3162263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (VDBG) log("getDevicesMatchingStates()");
3172263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService != null && isEnabled()) {
3182263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
3192263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return mService.getDevicesMatchingConnectionStates(states);
3202263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
3212263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3222263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return new ArrayList<BluetoothDevice>();
3232263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
3242263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
3252263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3262263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return new ArrayList<BluetoothDevice>();
3272263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
3282263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
3292263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
3302263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@inheritDoc}
3312263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
3322263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public int getConnectionState(BluetoothDevice device) {
3332263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (VDBG) log("getState(" + device + ")");
3342263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService != null && isEnabled()
3352263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            && isValidDevice(device)) {
3362263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
3372263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return mService.getConnectionState(device);
3382263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
3392263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3402263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return BluetoothProfile.STATE_DISCONNECTED;
3412263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
3422263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
3432263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3442263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return BluetoothProfile.STATE_DISCONNECTED;
3452263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
3462263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
3472263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
3482263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Get the current audio configuration for the A2DP source device,
3492263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * or null if the device has no audio configuration
3502263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
3512263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
3522263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
3532263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @param device Remote bluetooth device.
3542263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @return audio configuration for the device, or null
3552263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
3562263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * {@see BluetoothAudioConfig}
3572263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
3582263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood          public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
3592263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (VDBG) log("getAudioConfig(" + device + ")");
3602263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService != null && isEnabled()
3612263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            && isValidDevice(device)) {
3622263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            try {
3632263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return mService.getAudioConfig(device);
3642263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            } catch (RemoteException e) {
3652263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3662263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                return null;
3672263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
3682263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
3692263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3702263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        return null;
3712263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
3722263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
3732263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    /**
3741bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * Set priority of the profile
3751bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
3761bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * <p> The device should already be paired.
3771bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *  Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
3781bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * {@link #PRIORITY_OFF},
3791bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
3801bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
3811bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * permission.
3821bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
3831bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @param device Paired bluetooth device
3841bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @param priority
3851bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @return true if priority is set, false on error
3861bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @hide
3871bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     */
3881bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    public boolean setPriority(BluetoothDevice device, int priority) {
3891bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (DBG) log("setPriority(" + device + ", " + priority + ")");
3901bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (mService != null && isEnabled()
3911bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            && isValidDevice(device)) {
3921bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            if (priority != BluetoothProfile.PRIORITY_OFF &&
3931bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                priority != BluetoothProfile.PRIORITY_ON){
3941bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                return false;
3951bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            }
3961bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            try {
3971bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                return mService.setPriority(device, priority);
3981bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            } catch (RemoteException e) {
3991bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                   Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
4001bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                   return false;
4011bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            }
4021bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        }
4031bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4041bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            return false;
4051bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    }
4061bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal
4071bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    /**
4081bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * Get the priority of the profile.
4091bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
4101bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * <p> The priority can be any of:
4111bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
4121bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
4131bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
4141bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
4151bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
4161bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @param device Bluetooth device
4171bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @return priority of the device
4181bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @hide
4191bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     */
4201bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    public int getPriority(BluetoothDevice device) {
4211bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (VDBG) log("getPriority(" + device + ")");
4221bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (mService != null && isEnabled()
4231bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            && isValidDevice(device)) {
4241bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            try {
4251bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                return mService.getPriority(device);
4261bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            } catch (RemoteException e) {
4271bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
4281bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                return BluetoothProfile.PRIORITY_OFF;
4291bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            }
4301bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        }
4311bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4321bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        return BluetoothProfile.PRIORITY_OFF;
4331bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    }
4341bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal
4351bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    /**
4361bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * Check if A2DP profile is streaming music.
4371bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
4381bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
4391bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     *
4401bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     * @param device BluetoothDevice device
4411bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal     */
4421bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    public boolean isA2dpPlaying(BluetoothDevice device) {
4431bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (mService != null && isEnabled()
4441bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            && isValidDevice(device)) {
4451bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            try {
4461bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                return mService.isA2dpPlaying(device);
4471bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            } catch (RemoteException e) {
4481bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
4491bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal                return false;
4501bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal            }
4511bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        }
4521bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4531bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal        return false;
4541bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    }
4551bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal
4561bec6a5b0d67f120b7013572f6b1a4f1e1b3c584Sanket Agarwal    /**
4572263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * Helper for converting a state to a string.
4582263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     *
4592263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * For debug use only - strings are not internationalized.
4602263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     * @hide
4612263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood     */
4622263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    public static String stateToString(int state) {
4632263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        switch (state) {
4642263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        case STATE_DISCONNECTED:
4652263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return "disconnected";
4662263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        case STATE_CONNECTING:
4672263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return "connecting";
4682263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        case STATE_CONNECTED:
4692263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return "connected";
4702263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        case STATE_DISCONNECTING:
4712263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return "disconnecting";
4722263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        case STATE_PLAYING:
4732263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return "playing";
4742263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        case STATE_NOT_PLAYING:
4752263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood          return "not playing";
4762263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        default:
4772263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            return "<unknown state " + state + ">";
4782263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
4792263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
4802263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
4812263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private final ServiceConnection mConnection = new ServiceConnection() {
4822263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        public void onServiceConnected(ComponentName className, IBinder service) {
4832263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            if (DBG) Log.d(TAG, "Proxy object connected");
4842263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            mService = IBluetoothA2dpSink.Stub.asInterface(service);
4852263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
4862263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            if (mServiceListener != null) {
4872263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
4882263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                        BluetoothA2dpSink.this);
4892263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
4902263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
4912263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        public void onServiceDisconnected(ComponentName className) {
4922263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            if (DBG) Log.d(TAG, "Proxy object disconnected");
4932263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            mService = null;
4942263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            if (mServiceListener != null) {
4952263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK);
4962263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood            }
4972263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood        }
4982263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    };
4992263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
5002263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private boolean isEnabled() {
5012263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
5022263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood       return false;
5032263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
5042263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
5052263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private boolean isValidDevice(BluetoothDevice device) {
5062263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood       if (device == null) return false;
5072263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
5082263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
5092263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood       return false;
5102263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
5112263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood
5122263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    private static void log(String msg) {
5132263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood      Log.d(TAG, msg);
5142263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood    }
5152263dd1ddd1a8ac828c25d34000c85165cad21efMike Lockwood}
516