blob: 7e5f858f050be1224989ec7dcb22369b6861041e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.bluetooth;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.server.BluetoothA2dpService;
22import android.content.Context;
23import android.os.ServiceManager;
24import android.os.RemoteException;
25import android.os.IBinder;
26import android.util.Log;
27
Nick Pellybd022f42009-08-14 18:33:38 -070028import java.util.Arrays;
29import java.util.Collections;
30import java.util.Set;
31import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
33/**
34 * Public API for controlling the Bluetooth A2DP Profile Service.
35 *
36 * BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
37 * Service via IPC.
38 *
39 * Creating a BluetoothA2dp object will initiate a binding with the
40 * BluetoothHeadset service. Users of this object should call close() when they
41 * are finished, so that this proxy object can unbind from the service.
42 *
43 * Currently the BluetoothA2dp service runs in the system server and this
44 * proxy object will be immediately bound to the service on construction.
Jaikumar Ganesh721361f2009-11-20 15:21:47 -080045 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 * Currently this class provides methods to connect to A2DP audio sinks.
47 *
48 * @hide
49 */
Nick Pellybd022f42009-08-14 18:33:38 -070050public final class BluetoothA2dp {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 private static final String TAG = "BluetoothA2dp";
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080052 private static final boolean DBG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053
Nick Pelly005b2282009-09-10 10:21:56 -070054 /** int extra for ACTION_SINK_STATE_CHANGED */
55 public static final String EXTRA_SINK_STATE =
56 "android.bluetooth.a2dp.extra.SINK_STATE";
57 /** int extra for ACTION_SINK_STATE_CHANGED */
58 public static final String EXTRA_PREVIOUS_SINK_STATE =
59 "android.bluetooth.a2dp.extra.PREVIOUS_SINK_STATE";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
61 /** Indicates the state of an A2DP audio sink has changed.
Nick Pelly005b2282009-09-10 10:21:56 -070062 * This intent will always contain EXTRA_SINK_STATE,
63 * EXTRA_PREVIOUS_SINK_STATE and BluetoothDevice.EXTRA_DEVICE
64 * extras.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 */
66 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Nick Pelly005b2282009-09-10 10:21:56 -070067 public static final String ACTION_SINK_STATE_CHANGED =
68 "android.bluetooth.a2dp.action.SINK_STATE_CHANGED";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
70 public static final int STATE_DISCONNECTED = 0;
71 public static final int STATE_CONNECTING = 1;
72 public static final int STATE_CONNECTED = 2;
73 public static final int STATE_DISCONNECTING = 3;
74 /** Playing implies connected */
75 public static final int STATE_PLAYING = 4;
76
Jaikumar Ganesh721361f2009-11-20 15:21:47 -080077 /** Default priority for a2dp devices that we try to auto-connect
78 * and allow incoming connections */
79 public static final int PRIORITY_AUTO_CONNECT = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 /** Default priority for a2dp devices that should allow incoming
81 * connections */
Jaikumar Ganesh721361f2009-11-20 15:21:47 -080082 public static final int PRIORITY_ON = 100;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 /** Default priority for a2dp devices that should not allow incoming
84 * connections */
85 public static final int PRIORITY_OFF = 0;
Jaikumar Ganesh551ed722009-12-11 12:00:31 -080086 /** Default priority when not set or when the device is unpaired */
87 public static final int PRIORITY_UNDEFINED = -1;
Nick Pellybd022f42009-08-14 18:33:38 -070088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 private final IBluetoothA2dp mService;
90 private final Context mContext;
91
92 /**
93 * Create a BluetoothA2dp proxy object for interacting with the local
94 * Bluetooth A2DP service.
95 * @param c Context
96 */
97 public BluetoothA2dp(Context c) {
98 mContext = c;
Nick Pellybd022f42009-08-14 18:33:38 -070099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
Michael Chan081f58a2009-09-30 17:59:40 -0700101 if (b != null) {
102 mService = IBluetoothA2dp.Stub.asInterface(b);
103 } else {
104 Log.w(TAG, "Bluetooth A2DP service not available!");
105
106 // Instead of throwing an exception which prevents people from going
107 // into Wireless settings in the emulator. Let it crash later when it is actually used.
108 mService = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 }
111
112 /** Initiate a connection to an A2DP sink.
113 * Listen for SINK_STATE_CHANGED_ACTION to find out when the
114 * connection is completed.
Nick Pellybd022f42009-08-14 18:33:38 -0700115 * @param device Remote BT device.
Nick Pellyb24e11b2009-09-08 17:40:43 -0700116 * @return false on immediate error, true otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 * @hide
118 */
Nick Pellyb24e11b2009-09-08 17:40:43 -0700119 public boolean connectSink(BluetoothDevice device) {
Nick Pellybd022f42009-08-14 18:33:38 -0700120 if (DBG) log("connectSink(" + device + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 try {
Nick Pellybd022f42009-08-14 18:33:38 -0700122 return mService.connectSink(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 } catch (RemoteException e) {
Nick Pellyb24e11b2009-09-08 17:40:43 -0700124 Log.e(TAG, "", e);
125 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 }
127 }
128
129 /** Initiate disconnect from an A2DP sink.
130 * Listen for SINK_STATE_CHANGED_ACTION to find out when
131 * disconnect is completed.
Nick Pellybd022f42009-08-14 18:33:38 -0700132 * @param device Remote BT device.
Nick Pellyb24e11b2009-09-08 17:40:43 -0700133 * @return false on immediate error, true otherwise
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 * @hide
135 */
Nick Pellyb24e11b2009-09-08 17:40:43 -0700136 public boolean disconnectSink(BluetoothDevice device) {
Nick Pellybd022f42009-08-14 18:33:38 -0700137 if (DBG) log("disconnectSink(" + device + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 try {
Nick Pellybd022f42009-08-14 18:33:38 -0700139 return mService.disconnectSink(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 } catch (RemoteException e) {
Nick Pellyb24e11b2009-09-08 17:40:43 -0700141 Log.e(TAG, "", e);
142 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 }
144 }
145
Zhu Lanf9bbe1e2009-06-24 10:51:57 +0800146 /** Initiate suspend from an A2DP sink.
147 * Listen for SINK_STATE_CHANGED_ACTION to find out when
148 * suspend is completed.
149 * @param device Remote BT device.
150 * @return false on immediate error, true otherwise
151 * @hide
152 */
Nick Pellye766eae2009-09-30 12:06:28 -0700153 public boolean suspendSink(BluetoothDevice device) {
Zhu Lanf9bbe1e2009-06-24 10:51:57 +0800154 try {
155 return mService.suspendSink(device);
156 } catch (RemoteException e) {
157 Log.e(TAG, "", e);
158 return false;
159 }
160 }
161
162 /** Initiate resume from an suspended A2DP sink.
163 * Listen for SINK_STATE_CHANGED_ACTION to find out when
164 * resume is completed.
165 * @param device Remote BT device.
166 * @return false on immediate error, true otherwise
167 * @hide
168 */
Nick Pellye766eae2009-09-30 12:06:28 -0700169 public boolean resumeSink(BluetoothDevice device) {
Zhu Lanf9bbe1e2009-06-24 10:51:57 +0800170 try {
171 return mService.resumeSink(device);
172 } catch (RemoteException e) {
173 Log.e(TAG, "", e);
174 return false;
175 }
176 }
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 /** Check if a specified A2DP sink is connected.
Nick Pellybd022f42009-08-14 18:33:38 -0700179 * @param device Remote BT device.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 * @return True if connected (or playing), false otherwise and on error.
181 * @hide
182 */
Nick Pellybd022f42009-08-14 18:33:38 -0700183 public boolean isSinkConnected(BluetoothDevice device) {
184 if (DBG) log("isSinkConnected(" + device + ")");
185 int state = getSinkState(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 return state == STATE_CONNECTED || state == STATE_PLAYING;
187 }
188
189 /** Check if any A2DP sink is connected.
Nick Pellybd022f42009-08-14 18:33:38 -0700190 * @return a unmodifiable set of connected A2DP sinks, or null on error.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 * @hide
192 */
Nick Pellybd022f42009-08-14 18:33:38 -0700193 public Set<BluetoothDevice> getConnectedSinks() {
194 if (DBG) log("getConnectedSinks()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 try {
Nick Pellybd022f42009-08-14 18:33:38 -0700196 return Collections.unmodifiableSet(
197 new HashSet<BluetoothDevice>(Arrays.asList(mService.getConnectedSinks())));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 } catch (RemoteException e) {
Nick Pellyb24e11b2009-09-08 17:40:43 -0700199 Log.e(TAG, "", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 return null;
201 }
202 }
203
Jaikumar Ganeshb16c4f72009-12-04 15:10:54 -0800204 /** Check if any A2DP sink is in Non Disconnected state
205 * i.e playing, connected, connecting, disconnecting.
206 * @return a unmodifiable set of connected A2DP sinks, or null on error.
207 * @hide
208 */
209 public Set<BluetoothDevice> getNonDisconnectedSinks() {
210 if (DBG) log("getNonDisconnectedSinks()");
211 try {
212 return Collections.unmodifiableSet(
213 new HashSet<BluetoothDevice>(Arrays.asList(mService.getNonDisconnectedSinks())));
214 } catch (RemoteException e) {
215 Log.e(TAG, "", e);
216 return null;
217 }
218 }
219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 /** Get the state of an A2DP sink
Nick Pellybd022f42009-08-14 18:33:38 -0700221 * @param device Remote BT device.
Nick Pellyb24e11b2009-09-08 17:40:43 -0700222 * @return State code, one of STATE_
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 * @hide
224 */
Nick Pellybd022f42009-08-14 18:33:38 -0700225 public int getSinkState(BluetoothDevice device) {
226 if (DBG) log("getSinkState(" + device + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 try {
Nick Pellybd022f42009-08-14 18:33:38 -0700228 return mService.getSinkState(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 } catch (RemoteException e) {
Nick Pellyb24e11b2009-09-08 17:40:43 -0700230 Log.e(TAG, "", e);
231 return BluetoothA2dp.STATE_DISCONNECTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 }
233 }
234
235 /**
236 * Set priority of a2dp sink.
237 * Priority is a non-negative integer. By default paired sinks will have
238 * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0).
239 * Sinks with priority greater than zero will accept incoming connections
240 * (if no sink is currently connected).
241 * Priority for unpaired sink must be PRIORITY_NONE.
Nick Pellybd022f42009-08-14 18:33:38 -0700242 * @param device Paired sink
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 * @param priority Integer priority, for example PRIORITY_AUTO or
244 * PRIORITY_NONE
Nick Pellyb24e11b2009-09-08 17:40:43 -0700245 * @return true if priority is set, false on error
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 */
Nick Pellyb24e11b2009-09-08 17:40:43 -0700247 public boolean setSinkPriority(BluetoothDevice device, int priority) {
Nick Pellybd022f42009-08-14 18:33:38 -0700248 if (DBG) log("setSinkPriority(" + device + ", " + priority + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 try {
Nick Pellybd022f42009-08-14 18:33:38 -0700250 return mService.setSinkPriority(device, priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 } catch (RemoteException e) {
Nick Pellyb24e11b2009-09-08 17:40:43 -0700252 Log.e(TAG, "", e);
253 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 }
255 }
256
257 /**
258 * Get priority of a2dp sink.
Nick Pellybd022f42009-08-14 18:33:38 -0700259 * @param device Sink
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 * @return non-negative priority, or negative error code on error.
261 */
Nick Pellybd022f42009-08-14 18:33:38 -0700262 public int getSinkPriority(BluetoothDevice device) {
263 if (DBG) log("getSinkPriority(" + device + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 try {
Nick Pellybd022f42009-08-14 18:33:38 -0700265 return mService.getSinkPriority(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 } catch (RemoteException e) {
Nick Pellyb24e11b2009-09-08 17:40:43 -0700267 Log.e(TAG, "", e);
268 return PRIORITY_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 }
270 }
271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 /** Helper for converting a state to a string.
273 * For debug use only - strings are not internationalized.
274 * @hide
275 */
276 public static String stateToString(int state) {
277 switch (state) {
278 case STATE_DISCONNECTED:
279 return "disconnected";
280 case STATE_CONNECTING:
281 return "connecting";
282 case STATE_CONNECTED:
283 return "connected";
284 case STATE_DISCONNECTING:
285 return "disconnecting";
286 case STATE_PLAYING:
287 return "playing";
288 default:
289 return "<unknown state " + state + ">";
290 }
291 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -0800292
293 private static void log(String msg) {
294 Log.d(TAG, msg);
295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296}