19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.bluetooth;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pellyimport android.annotation.SdkConstant;
20005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pellyimport android.annotation.SdkConstant.SdkConstantType;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ServiceConnection;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
2603cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport android.os.RemoteException;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2903cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.ArrayList;
3003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.List;
3162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Public API for controlling the Bluetooth Headset Service. This includes both
3462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Bluetooth Headset and Handsfree (v1.5) profiles.
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>BluetoothHeadset is a proxy object for controlling the Bluetooth Headset
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Service via IPC.
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Use {@link BluetoothAdapter#getProfileProxy} to get
4062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * the BluetoothHeadset proxy object. Use
4162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Android only supports one connected Bluetooth Headset at a time.
4462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Each method is protected with its appropriate permission.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshpublic final class BluetoothHeadset implements BluetoothProfile {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "BluetoothHeadset";
480f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final boolean DBG = true;
49563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean VDBG = false;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
5262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the Headset
5362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
5462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
5562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
56c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
57c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
58c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
59c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
60c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
610706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
6262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
6362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
6462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
65c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
66c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * receive.
6762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
68005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
6962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
7062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
7162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
72005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    /**
7362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in the Audio Connection state of the
7462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP profile.
7562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
7662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
77c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
78c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
79c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
80c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
81c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
820706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
8362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED},
8462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
85c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission
86c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * to receive.
87005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly     */
88005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
89005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    public static final String ACTION_AUDIO_STATE_CHANGED =
9062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
9162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
92c24dbdb57b30f9e8fa6b0c5b48372017b5ae46b0Jaikumar Ganesh
93005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly    /**
94e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * Intent used to broadcast that the headset has posted a
95e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * vendor-specific event.
96e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     *
97e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * <p>This intent will have 4 extras and 1 category.
98c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
99c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *  <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device
100c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *       </li>
101c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *  <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor
102c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *       specific command </li>
103c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *  <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT
104c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *       command type which can be one of  {@link #AT_CMD_TYPE_READ},
105c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *       {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET},
1060706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     *       {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li>
107c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *  <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command
108c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *       arguments. </li>
109c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
110e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     *
1110706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     *<p> The category is the Company ID of the vendor defining the
112e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * vendor-specific command. {@link BluetoothAssignedNumbers}
113e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     *
114e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * For example, for Plantronics specific events
115e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * Category will be {@link #VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY}.55
116e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     *
117e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * <p> For example, an AT+XEVENT=foo,3 will get translated into
118c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
119c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li>
120c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li>
1210706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     *   <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li>
122c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
123c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission
124c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * to receive.
125a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     */
126a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
127a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT =
128a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek            "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
129a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek
130a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    /**
131a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     * A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
132a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     * intents that contains the name of the vendor-specific command.
133a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     */
134a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD =
135a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek            "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
136a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek
137a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    /**
138a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     * An int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
139e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * intents that contains the AT command type of the vendor-specific command.
140e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     */
141e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE =
142e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh            "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
143e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh
144e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    /**
145e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * AT command type READ used with
146e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
147e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * For example, AT+VGM?. There are no arguments for this command type.
148e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     */
149e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final int AT_CMD_TYPE_READ = 0;
150e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh
151e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    /**
152e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * AT command type TEST used with
153e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
154e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * For example, AT+VGM=?. There are no arguments for this command type.
155e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     */
156e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final int AT_CMD_TYPE_TEST = 1;
157e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh
158e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    /**
159e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * AT command type SET used with
160e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
161e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * For example, AT+VGM=<args>.
162e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     */
163e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final int AT_CMD_TYPE_SET = 2;
164e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh
165e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    /**
166e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * AT command type BASIC used with
167e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
168e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * For example, ATD. Single character commands and everything following the
169e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * character are arguments.
170e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     */
171e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final int AT_CMD_TYPE_BASIC = 3;
172e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh
173e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    /**
174e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * AT command type ACTION used with
175e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
176e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * For example, AT+CHUP. There are no arguments for action commands.
177a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     */
178e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final int AT_CMD_TYPE_ACTION = 4;
179a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek
180a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    /**
181a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     * A Parcelable String array extra field in
182a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     * {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains
183a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     * the arguments to the vendor-specific command.
184a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek     */
185a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek    public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS =
186a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek            "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
187a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek
188e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    /**
189e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * The intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
190e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     * for the companyId
191e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh     */
192e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY  =
193e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh            "android.bluetooth.headset.intent.category.companyid";
194e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh
19530d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh    /**
196c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * Headset state when SCO audio is not connected.
19762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * This state can be one of
19862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
19962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
200005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly     */
201b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh    public static final int STATE_AUDIO_DISCONNECTED = 10;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
204c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * Headset state when SCO audio is connecting.
20562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * This state can be one of
20662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
20762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
209b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh    public static final int STATE_AUDIO_CONNECTING = 11;
21062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
21130d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh    /**
212c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * Headset state when SCO audio is connected.
21330d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     * This state can be one of
21430d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
21530d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
21630d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     */
217b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh    public static final int STATE_AUDIO_CONNECTED = 12;
218b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh
21962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
22062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private Context mContext;
22162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private ServiceListener mServiceListener;
22262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private IBluetoothHeadset mService;
223bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private BluetoothAdapter mAdapter;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2250f42037eb7b5118015c2caca635538324ccf0ccffredc    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
2260f42037eb7b5118015c2caca635538324ccf0ccffredc            new IBluetoothStateChangeCallback.Stub() {
2270f42037eb7b5118015c2caca635538324ccf0ccffredc                public void onBluetoothStateChange(boolean up) {
2280f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
2290f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (!up) {
230563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                        if (VDBG) Log.d(TAG,"Unbinding service...");
2310f42037eb7b5118015c2caca635538324ccf0ccffredc                        synchronized (mConnection) {
2320f42037eb7b5118015c2caca635538324ccf0ccffredc                            try {
2330f42037eb7b5118015c2caca635538324ccf0ccffredc                                mService = null;
2340f42037eb7b5118015c2caca635538324ccf0ccffredc                                mContext.unbindService(mConnection);
2350f42037eb7b5118015c2caca635538324ccf0ccffredc                            } catch (Exception re) {
2360f42037eb7b5118015c2caca635538324ccf0ccffredc                                Log.e(TAG,"",re);
2370f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
2380f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
2390f42037eb7b5118015c2caca635538324ccf0ccffredc                    } else {
2400f42037eb7b5118015c2caca635538324ccf0ccffredc                        synchronized (mConnection) {
2410f42037eb7b5118015c2caca635538324ccf0ccffredc                            try {
2420f42037eb7b5118015c2caca635538324ccf0ccffredc                                if (mService == null) {
243563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                                    if (VDBG) Log.d(TAG,"Binding service...");
2440f42037eb7b5118015c2caca635538324ccf0ccffredc                                    if (!mContext.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
2450f42037eb7b5118015c2caca635538324ccf0ccffredc                                        Log.e(TAG, "Could not bind to Bluetooth Headset Service");
2460f42037eb7b5118015c2caca635538324ccf0ccffredc                                    }
2470f42037eb7b5118015c2caca635538324ccf0ccffredc                                }
2480f42037eb7b5118015c2caca635538324ccf0ccffredc                            } catch (Exception re) {
2490f42037eb7b5118015c2caca635538324ccf0ccffredc                                Log.e(TAG,"",re);
2500f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
2510f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
2520f42037eb7b5118015c2caca635538324ccf0ccffredc                    }
2530f42037eb7b5118015c2caca635538324ccf0ccffredc                }
2540f42037eb7b5118015c2caca635538324ccf0ccffredc        };
2550f42037eb7b5118015c2caca635538324ccf0ccffredc
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a BluetoothHeadset proxy object.
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
25962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /*package*/ BluetoothHeadset(Context context, ServiceListener l) {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceListener = l;
26262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
2630f42037eb7b5118015c2caca635538324ccf0ccffredc
2640f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
2650f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
2660f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
2670f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
2680f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (RemoteException e) {
2690f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
2700f42037eb7b5118015c2caca635538324ccf0ccffredc            }
2710f42037eb7b5118015c2caca635538324ccf0ccffredc        }
2720f42037eb7b5118015c2caca635538324ccf0ccffredc
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!context.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Could not bind to Bluetooth Headset Service");
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Close the connection to the backing service.
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Other public functions of BluetoothHeadset will return default error
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * results once close() has been called. Multiple invocations of close()
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are ok.
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
28413450df2b9264ef2220418f308037c19cec739a9Matthew Xie    /*package*/ void close() {
285563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("close()");
2860f42037eb7b5118015c2caca635538324ccf0ccffredc
2870f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
2880f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
2890f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
2900f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
2910f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (Exception e) {
2920f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
2930f42037eb7b5118015c2caca635538324ccf0ccffredc            }
2940f42037eb7b5118015c2caca635538324ccf0ccffredc        }
2950f42037eb7b5118015c2caca635538324ccf0ccffredc
2960f42037eb7b5118015c2caca635538324ccf0ccffredc        synchronized (mConnection) {
2970f42037eb7b5118015c2caca635538324ccf0ccffredc            if (mService != null) {
2980f42037eb7b5118015c2caca635538324ccf0ccffredc                try {
2990f42037eb7b5118015c2caca635538324ccf0ccffredc                    mService = null;
3000f42037eb7b5118015c2caca635538324ccf0ccffredc                    mContext.unbindService(mConnection);
3010f42037eb7b5118015c2caca635538324ccf0ccffredc                } catch (Exception re) {
3020f42037eb7b5118015c2caca635538324ccf0ccffredc                    Log.e(TAG,"",re);
3030f42037eb7b5118015c2caca635538324ccf0ccffredc                }
3040f42037eb7b5118015c2caca635538324ccf0ccffredc            }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3069bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
310f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate connection to a profile of the remote bluetooth device.
311f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
312f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> Currently, the system supports only 1 connection to the
313f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * headset/handsfree profile. The API will automatically disconnect connected
314f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * devices before connecting.
315f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
316f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API returns false in scenarios like the profile on the
317f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * device is already connected or Bluetooth is not turned on.
318f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * When this API returns true, it is guaranteed that
319f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * connection state intent for the profile will be broadcasted with
320f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * the state. Users can get the connection state of the profile
321f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * from this intent.
322f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
323f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
324f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
325f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
326f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
327f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
328f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
32962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
33162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean connect(BluetoothDevice device) {
33262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("connect(" + device + ")");
33362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
33462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
33662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.connect(device);
33762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
33862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, Log.getStackTraceString(new Throwable()));
33962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
34062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
34262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
34362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
347f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate disconnection from a profile
348f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
349f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API will return false in scenarios like the profile on the
350f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Bluetooth device is not in connected state etc. When this API returns,
351f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * true, it is guaranteed that the connection state change
352f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
353f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * disconnection state of the profile from this intent.
354f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
355f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> If the disconnection is initiated by a remote device, the state
356f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * will transition from {@link #STATE_CONNECTED} to
357f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
358f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * host (local) device the state will transition from
359f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
360f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * state {@link #STATE_DISCONNECTED}. The transition to
361f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
362f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * two scenarios.
363f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
364f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
365f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
366f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
367f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
368f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
369f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
37062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
37262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
37362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
37462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
37562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
37762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.disconnect(device);
37862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
37962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              Log.e(TAG, Log.getStackTraceString(new Throwable()));
38062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              return false;
38162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
38362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
38462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
38862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
39003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh    public List<BluetoothDevice> getConnectedDevices() {
391563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getConnectedDevices()");
39262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
39403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return mService.getConnectedDevices();
39562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
39662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, Log.getStackTraceString(new Throwable()));
39703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
39862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
40062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
40103cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
40562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
40703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
408563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getDevicesMatchingStates()");
40962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
41103cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return mService.getDevicesMatchingConnectionStates(states);
41262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
41362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, Log.getStackTraceString(new Throwable()));
41403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
41562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
41762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
41803cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
42262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
42462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
425563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getConnectionState(" + device + ")");
42662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
42762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
42962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getConnectionState(device);
43062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
43162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, Log.getStackTraceString(new Throwable()));
43262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return BluetoothProfile.STATE_DISCONNECTED;
43362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
43562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
43662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return BluetoothProfile.STATE_DISCONNECTED;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
440f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Set priority of the profile
441f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
442f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The device should already be paired.
443f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *  Priority can be one of {@link #PRIORITY_ON} or
444f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_OFF},
445f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
446f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
447f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
448f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
449f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Paired bluetooth device
450f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param priority
451f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return true if priority is set, false on error
45262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
45462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
45562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
45662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
45762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
45862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            if (priority != BluetoothProfile.PRIORITY_OFF &&
4596f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                priority != BluetoothProfile.PRIORITY_ON) {
46062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              return false;
46162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
46362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.setPriority(device, priority);
46462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
46562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, Log.getStackTraceString(new Throwable()));
46662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
46762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
46962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
474f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Get the priority of the profile.
475f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
476f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The priority can be any of:
477f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
478f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
479f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
480f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
481f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
482f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Bluetooth device
483f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return priority of the device
48462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
48662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
487563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getPriority(" + device + ")");
48862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
48962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
49162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getPriority(device);
49262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
49362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, Log.getStackTraceString(new Throwable()));
49462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return PRIORITY_OFF;
49562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
49762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
49862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return PRIORITY_OFF;
49962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
50062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
50162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
50262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Start Bluetooth voice recognition. This methods sends the voice
50362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * recognition AT command to the headset and establishes the
50462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * audio connection.
50562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
50662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
507b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * If this function returns true, this intent will be broadcasted with
508b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
509b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     *
510b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * <p> {@link #EXTRA_STATE} will transition from
511b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
512b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
513b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * in case of failure to establish the audio connection.
51462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
515b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
51662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
51762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device Bluetooth headset
51862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @return false if there is no headset connected of if the
51962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *               connected headset doesn't support voice recognition
52062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *               or on error, true otherwise
52162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
52262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean startVoiceRecognition(BluetoothDevice device) {
52362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("startVoiceRecognition()");
52462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
52562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
52662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
52762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.startVoiceRecognition(device);
52862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
52962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG,  Log.getStackTraceString(new Throwable()));
53062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
53162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        }
53262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
53762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Stop Bluetooth Voice Recognition mode, and shut down the
53862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Bluetooth audio path.
53962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
540c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
54162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
54262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device Bluetooth headset
54362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @return false if there is no headset connected
54462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *               or on error, true otherwise
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
54662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean stopVoiceRecognition(BluetoothDevice device) {
54762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("stopVoiceRecognition()");
54862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
54962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
55162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.stopVoiceRecognition(device);
55262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
55362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG,  Log.getStackTraceString(new Throwable()));
55462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
55662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
56162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Check if Bluetooth SCO audio is connected.
56262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
563c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
56462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
56562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device Bluetooth headset
56662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @return true if SCO is connected,
56762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *         false otherwise or on error
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
56962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean isAudioConnected(BluetoothDevice device) {
570563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("isAudioConnected()");
57162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
57262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
57462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              return mService.isAudioConnected(device);
57562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
57662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              Log.e(TAG,  Log.getStackTraceString(new Throwable()));
57762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
5786c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly        }
57962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
58062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
5816c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly    }
5826c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly
5836c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly    /**
5846c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * Get battery usage hint for Bluetooth Headset service.
5856c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * This is a monotonically increasing integer. Wraps to 0 at
5866c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * Integer.MAX_INT, and at boot.
5876c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * Current implementation returns the number of AT commands handled since
5886c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * boot. This is a good indicator for spammy headset/handsfree units that
5896c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * can keep the device awake by polling for cellular status updates. As a
5906c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * rule of thumb, each AT command prevents the CPU from sleeping for 500 ms
59162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
59262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device the bluetooth headset.
5936c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * @return monotonically increasing battery usage hint, or a negative error
5946c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     *         code on error
5956c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     * @hide
5966c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly     */
59762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getBatteryUsageHint(BluetoothDevice device) {
598563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getBatteryUsageHint()");
59962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
60062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
6016c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly            try {
60262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getBatteryUsageHint(device);
60362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
60462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG,  Log.getStackTraceString(new Throwable()));
60562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
60762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
61062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
611d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent    /**
612d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent     * Indicates if current platform supports voice dialing over bluetooth SCO.
61362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
614d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent     * @return true if voice dialing over bluetooth is supported, false otherwise.
615d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent     * @hide
616d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent     */
617d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent    public static boolean isBluetoothVoiceDialingEnabled(Context context) {
618d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent        return context.getResources().getBoolean(
619d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent                com.android.internal.R.bool.config_bluetooth_sco_off_call);
620d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent    }
621d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent
6229b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    /**
6239b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     * Accept the incoming connection.
62462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Note: This is an internal function and shouldn't be exposed
62562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6269b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     * @hide
6279b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     */
6289b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    public boolean acceptIncomingConnect(BluetoothDevice device) {
6299b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        if (DBG) log("acceptIncomingConnect");
63062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
6319b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            try {
6329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh                return mService.acceptIncomingConnect(device);
6339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            } catch (RemoteException e) {Log.e(TAG, e.toString());}
6349b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        } else {
6359b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            Log.w(TAG, "Proxy not attached to service");
6369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
6379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
6389b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
6399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
6409b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
6419b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    /**
642a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie     * Reject the incoming connection.
643a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie     * @hide
644a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie     */
645a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    public boolean rejectIncomingConnect(BluetoothDevice device) {
646a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (DBG) log("rejectIncomingConnect");
647a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        if (mService != null) {
648a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            try {
649a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie                return mService.rejectIncomingConnect(device);
650a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            } catch (RemoteException e) {Log.e(TAG, e.toString());}
651a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        } else {
652a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            Log.w(TAG, "Proxy not attached to service");
653a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
654a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        }
655a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie        return false;
656a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    }
657a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie
658a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /**
6593e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Get the current audio state of the Headset.
6609b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     * Note: This is an internal function and shouldn't be exposed
66162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6629b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     * @hide
6639b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     */
6643e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public int getAudioState(BluetoothDevice device) {
665563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getAudioState");
6663e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && !isDisabled()) {
6679b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            try {
6683e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                return mService.getAudioState(device);
6699b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            } catch (RemoteException e) {Log.e(TAG, e.toString());}
6709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        } else {
6719b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            Log.w(TAG, "Proxy not attached to service");
6729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
6739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
6743e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
6759b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
6769b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh
6779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    /**
6783e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Check if Bluetooth SCO audio is connected.
6793e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *
6803e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
68162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6823e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * @return true if SCO is connected,
6833e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *         false otherwise or on error
6849b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     * @hide
6859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh     */
6863e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public boolean isAudioOn() {
687563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("isAudioOn()");
6883e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && isEnabled()) {
6899b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh            try {
6903e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie              return mService.isAudioOn();
6913e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            } catch (RemoteException e) {
6923e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie              Log.e(TAG,  Log.getStackTraceString(new Throwable()));
6933e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
6949b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        }
6953e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService == null) Log.w(TAG, "Proxy not attached to service");
6969b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh        return false;
6973e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
6989b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh    }
69962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
70062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
7013e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Initiates a connection of headset audio.
7023e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * It setup SCO channel with remote connected headset device.
70362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
7043e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * @return true if successful
7053e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *         false if there was some error such as
7063e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *               there is no connected headset
70762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
70862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
7093e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public boolean connectAudio() {
7103e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && isEnabled()) {
71162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
7123e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                return mService.connectAudio();
7133e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            } catch (RemoteException e) {
7143e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                Log.e(TAG, e.toString());
7153e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
71662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        } else {
71762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            Log.w(TAG, "Proxy not attached to service");
71862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
71962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        }
72062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
72162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
72262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
72330d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh    /**
7243e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Initiates a disconnection of headset audio.
7253e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * It tears down the SCO channel from remote headset device.
72630d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     *
7273e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * @return true if successful
7283e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *         false if there was some error such as
7293e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *               there is no connected SCO channel
73030d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     * @hide
73130d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh     */
7323e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public boolean disconnectAudio() {
7333e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && isEnabled()) {
73430d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh            try {
7353e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                return mService.disconnectAudio();
7363e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            } catch (RemoteException e) {
7373e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                Log.e(TAG, e.toString());
7383e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
73930d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh        } else {
74030d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh            Log.w(TAG, "Proxy not attached to service");
74130d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
74230d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh        }
7433e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        return false;
74430d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh    }
74530d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh
746f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh    /**
747dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * Initiates a SCO channel connection with the headset (if connected).
748dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * Also initiates a virtual voice call for Handsfree devices as many devices
749dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * do not accept SCO audio without a call.
750dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * This API allows the handsfree device to be used for routing non-cellular
751dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * call audio.
752f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     *
753f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     * @param device Remote Bluetooth Device
754f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     * @return true if successful, false if there was some error.
755f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     * @hide
756f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     */
757dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh    public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
758dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh        if (DBG) log("startScoUsingVirtualVoiceCall()");
759f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        if (mService != null && isEnabled() && isValidDevice(device)) {
760f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            try {
761dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh                return mService.startScoUsingVirtualVoiceCall(device);
762f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            } catch (RemoteException e) {
763f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh                Log.e(TAG, e.toString());
764f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            }
765f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        } else {
766f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            Log.w(TAG, "Proxy not attached to service");
767f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
768f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        }
769f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        return false;
770f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh    }
771f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh
772f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh    /**
773dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * Terminates an ongoing SCO connection and the associated virtual
774dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh     * call.
775f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     *
776f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     * @param device Remote Bluetooth Device
777f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     * @return true if successful, false if there was some error.
778f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     * @hide
779f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh     */
780dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh    public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
781dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh        if (DBG) log("stopScoUsingVirtualVoiceCall()");
782f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        if (mService != null && isEnabled() && isValidDevice(device)) {
783f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            try {
784dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh                return mService.stopScoUsingVirtualVoiceCall(device);
785f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            } catch (RemoteException e) {
786f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh                Log.e(TAG, e.toString());
787f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            }
788f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        } else {
789f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            Log.w(TAG, "Proxy not attached to service");
790f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
791f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        }
792f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh        return false;
793f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh    }
794f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh
7953e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    /**
7963e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Notify Headset of phone state change.
7973e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * This is a backdoor for phone app to call BluetoothHeadset since
7983e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * there is currently not a good way to get precise call state change outside
7993e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * of phone app.
8003e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *
8013e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * @hide
8023e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     */
8033e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
8043e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                                  int type) {
8053e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && isEnabled()) {
8063e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            try {
8073e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mService.phoneStateChanged(numActive, numHeld, callState, number, type);
8083e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            } catch (RemoteException e) {
8093e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                Log.e(TAG, e.toString());
8103e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
8113e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        } else {
8123e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            Log.w(TAG, "Proxy not attached to service");
8133e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
8143e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
8153e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    }
8163e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
8173e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    /**
8183e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Notify Headset of phone roam state change.
8193e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * This is a backdoor for phone app to call BluetoothHeadset since
8203e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * there is currently not a good way to get roaming state change outside
8213e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * of phone app.
8223e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *
8233e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * @hide
8243e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     */
8253e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public void roamChanged(boolean roaming) {
8263e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && isEnabled()) {
8273e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            try {
8283e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mService.roamChanged(roaming);
8293e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            } catch (RemoteException e) {
8303e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                Log.e(TAG, e.toString());
8313e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
8323e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        } else {
8333e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            Log.w(TAG, "Proxy not attached to service");
8343e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
8353e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
8363e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    }
8373e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
8383e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    /**
8393e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * Send Headset of CLCC response
8403e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     *
8413e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     * @hide
8423e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie     */
8433e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
8443e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                             String number, int type) {
8453e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        if (mService != null && isEnabled()) {
8463e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            try {
8473e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mService.clccResponse(index, direction, status, mode, mpty, number, type);
8483e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            } catch (RemoteException e) {
8493e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                Log.e(TAG, e.toString());
8503e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
8513e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        } else {
8523e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            Log.w(TAG, "Proxy not attached to service");
8533e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
8543e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
8553e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    }
8563e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ServiceConnection mConnection = new ServiceConnection() {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onServiceConnected(ComponentName className, IBinder service) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DBG) Log.d(TAG, "Proxy object connected");
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService = IBluetoothHeadset.Stub.asInterface(service);
86162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mServiceListener != null) {
86362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, BluetoothHeadset.this);
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onServiceDisconnected(ComponentName className) {
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DBG) Log.d(TAG, "Proxy object disconnected");
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService = null;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mServiceListener != null) {
87062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
874f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project
87562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isEnabled() {
87662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
87762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
87862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
87962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
8806f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh    private boolean isDisabled() {
8816f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true;
8826f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh       return false;
8836f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh    }
8846f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh
88562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
88662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (device == null) return false;
88762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
88862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
88962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
89062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
89162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
892f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    private static void log(String msg) {
893f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project        Log.d(TAG, msg);
894f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    }
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
896