blob: 6610d0e96052b371db281ec409d770f4198bf7f5 [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.server;
18
19import android.bluetooth.BluetoothA2dp;
20import android.bluetooth.BluetoothClass;
Nick Pellybd022f42009-08-14 18:33:38 -070021import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.bluetooth.BluetoothDevice;
23import android.bluetooth.BluetoothError;
24import android.bluetooth.BluetoothIntent;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070025import android.bluetooth.BluetoothUuid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Context;
27import android.content.Intent;
28import android.os.Handler;
29import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.util.Log;
31
32import java.util.HashMap;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070033import java.util.UUID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
35/**
36 * TODO: Move this to
37 * java/services/com/android/server/BluetoothEventLoop.java
38 * and make the contructor package private again.
39 *
40 * @hide
41 */
42class BluetoothEventLoop {
43 private static final String TAG = "BluetoothEventLoop";
44 private static final boolean DBG = false;
45
46 private int mNativeData;
47 private Thread mThread;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070048 private boolean mStarted;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 private boolean mInterrupted;
Nick Pellybd022f42009-08-14 18:33:38 -070050
The Android Open Source Project10592532009-03-18 17:39:46 -070051 private final HashMap<String, Integer> mPasskeyAgentRequestData;
Nick Pellybd022f42009-08-14 18:33:38 -070052 private final BluetoothService mBluetoothService;
53 private final BluetoothAdapter mAdapter;
The Android Open Source Project10592532009-03-18 17:39:46 -070054 private final Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56 private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -070057 private static final int EVENT_RESTART_BLUETOOTH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 // The time (in millisecs) to delay the pairing attempt after the first
60 // auto pairing attempt fails. We use an exponential delay with
61 // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
62 // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
63 private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
64 private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
65
66 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
67 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
68
69 private final Handler mHandler = new Handler() {
70 @Override
71 public void handleMessage(Message msg) {
72 switch (msg.what) {
73 case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
74 String address = (String)msg.obj;
75 if (address != null) {
76 mBluetoothService.createBond(address);
77 return;
78 }
79 break;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -070080 case EVENT_RESTART_BLUETOOTH:
Nick Pelly37b5a102009-03-24 20:46:18 -070081 mBluetoothService.restart();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -070082 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 }
84 }
85 };
86
87 static { classInitNative(); }
88 private static native void classInitNative();
89
Nick Pellybd022f42009-08-14 18:33:38 -070090 /* pacakge */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
91 BluetoothService bluetoothService) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 mBluetoothService = bluetoothService;
93 mContext = context;
94 mPasskeyAgentRequestData = new HashMap();
Nick Pellybd022f42009-08-14 18:33:38 -070095 mAdapter = adapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 initializeNativeDataNative();
97 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098
99 protected void finalize() throws Throwable {
100 try {
101 cleanupNativeDataNative();
102 } finally {
103 super.finalize();
104 }
105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700107 /* package */ HashMap<String, Integer> getPasskeyAgentRequestData() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 return mPasskeyAgentRequestData;
109 }
110
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700111 /* package */ void start() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700113 if (!isEventLoopRunningNative()) {
114 if (DBG) log("Starting Event Loop thread");
115 startEventLoopNative();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 }
117 }
118
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700119 public void stop() {
120 if (isEventLoopRunningNative()) {
121 if (DBG) log("Stopping Event Loop thread");
122 stopEventLoopNative();
123 }
124 }
125
126 public boolean isEventLoopRunning() {
127 return isEventLoopRunningNative();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 }
129
Jaikumar Ganesh9488cbd2009-08-03 17:17:37 -0700130 private void addDevice(String address, String[] properties) {
131 mBluetoothService.addRemoteDeviceProperties(address, properties);
132 String rssi = mBluetoothService.getRemoteDeviceProperty(address, "RSSI");
133 String classValue = mBluetoothService.getRemoteDeviceProperty(address, "Class");
134 String name = mBluetoothService.getRemoteDeviceProperty(address, "Name");
135 short rssiValue;
136 // For incoming connections, we don't get the RSSI value. Use a default of MIN_VALUE.
137 // If we accept the pairing, we will automatically show it at the top of the list.
138 if (rssi != null) {
139 rssiValue = (short)Integer.valueOf(rssi).intValue();
140 } else {
141 rssiValue = Short.MIN_VALUE;
142 }
143 if (classValue != null) {
144 Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700145 intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
Jaikumar Ganesh9488cbd2009-08-03 17:17:37 -0700146 intent.putExtra(BluetoothIntent.CLASS, Integer.valueOf(classValue));
147 intent.putExtra(BluetoothIntent.RSSI, rssiValue);
148 intent.putExtra(BluetoothIntent.NAME, name);
149
150 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
151 } else {
152 log ("ClassValue: " + classValue + " for remote device: " + address + " is null");
153 }
154 }
155
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700156 private void onDeviceFound(String address, String[] properties) {
157 if (properties == null) {
158 Log.e(TAG, "ERROR: Remote device properties are null");
159 return;
160 }
Jaikumar Ganesh9488cbd2009-08-03 17:17:37 -0700161 addDevice(address, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 }
163
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700164 private void onDeviceDisappeared(String address) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700166 intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700170 private void onCreatePairedDeviceResult(String address, int result) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 address = address.toUpperCase();
172 if (result == BluetoothError.SUCCESS) {
173 mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
174 if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
175 mBluetoothService.getBondState().clearPinAttempts(address);
176 }
177 } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
178 mBluetoothService.getBondState().getAttempt(address) == 1) {
179 mBluetoothService.getBondState().addAutoPairingFailure(address);
180 pairingAttempt(address, result);
181 } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
182 mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
183 pairingAttempt(address, result);
184 } else {
185 mBluetoothService.getBondState().setBondState(address,
186 BluetoothDevice.BOND_NOT_BONDED, result);
187 if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
188 mBluetoothService.getBondState().clearPinAttempts(address);
189 }
190 }
191 }
192
193 private void pairingAttempt(String address, int result) {
194 // This happens when our initial guess of "0000" as the pass key
195 // fails. Try to create the bond again and display the pin dialog
196 // to the user. Use back-off while posting the delayed
197 // message. The initial value is
198 // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
199 // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
200 // reached, display an error to the user.
201 int attempt = mBluetoothService.getBondState().getAttempt(address);
202 if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
203 MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
204 mBluetoothService.getBondState().clearPinAttempts(address);
205 mBluetoothService.getBondState().setBondState(address,
206 BluetoothDevice.BOND_NOT_BONDED, result);
207 return;
208 }
209
210 Message message = mHandler.obtainMessage(EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
211 message.obj = address;
212 boolean postResult = mHandler.sendMessageDelayed(message,
213 attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
214 if (!postResult) {
215 mBluetoothService.getBondState().clearPinAttempts(address);
216 mBluetoothService.getBondState().setBondState(address,
217 BluetoothDevice.BOND_NOT_BONDED, result);
218 return;
219 }
220 mBluetoothService.getBondState().attempt(address);
221 }
222
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700223 private void onDeviceCreated(String deviceObjectPath) {
Jaikumar Ganesh9488cbd2009-08-03 17:17:37 -0700224 String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
225 if (!mBluetoothService.isRemoteDeviceInCache(address)) {
226 // Incoming connection, we haven't seen this device, add to cache.
227 String[] properties = mBluetoothService.getRemoteDeviceProperties(address);
228 if (properties != null) {
229 addDevice(address, properties);
230 }
231 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700232 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 }
234
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700235 private void onDeviceRemoved(String deviceObjectPath) {
236 String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
237 if (address != null)
238 mBluetoothService.getBondState().setBondState(address.toUpperCase(),
239 BluetoothDevice.BOND_NOT_BONDED, BluetoothDevice.UNBOND_REASON_REMOVED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 }
241
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700242 /*package*/ void onPropertyChanged(String[] propValues) {
243 String name = propValues[0];
244 if (name.equals("Name")) {
245 Intent intent = new Intent(BluetoothIntent.NAME_CHANGED_ACTION);
246 intent.putExtra(BluetoothIntent.NAME, propValues[1]);
247 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
248 mBluetoothService.setProperty(name, propValues[1]);
249 } else if (name.equals("Pairable") || name.equals("Discoverable")) {
250 String pairable = name.equals("Pairable") ? propValues[1] :
251 mBluetoothService.getProperty("Pairable");
252 String discoverable = name.equals("Discoverable") ? propValues[1] :
253 mBluetoothService.getProperty("Discoverable");
254
255 // This shouldn't happen, unless Adapter Properties are null.
256 if (pairable == null || discoverable == null)
257 return;
258
Nick Pellybd022f42009-08-14 18:33:38 -0700259 int mode = BluetoothService.bluezStringToScanMode(
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700260 pairable.equals("true"),
261 discoverable.equals("true"));
262 if (mode >= 0) {
263 Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
264 intent.putExtra(BluetoothIntent.SCAN_MODE, mode);
265 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
266 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
267 }
268 mBluetoothService.setProperty(name, propValues[1]);
269 } else if (name.equals("Discovering")) {
270 Intent intent;
271 if (propValues[1].equals("true")) {
272 mBluetoothService.setIsDiscovering(true);
273 intent = new Intent(BluetoothIntent.DISCOVERY_STARTED_ACTION);
274 } else {
275 // Stop the discovery.
276 mBluetoothService.cancelDiscovery();
277 mBluetoothService.setIsDiscovering(false);
278 intent = new Intent(BluetoothIntent.DISCOVERY_COMPLETED_ACTION);
279 }
280 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
281 mBluetoothService.setProperty(name, propValues[1]);
282 } else if (name.equals("Devices")) {
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700283 String value = null;
284 int len = Integer.valueOf(propValues[1]);
285 if (len > 0) {
286 value = "";
287 for (int i = 2; i < propValues.length; i++) {
288 value = value + propValues[i] + ',';
289 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700290 }
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700291 mBluetoothService.setProperty(name, value);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700292 } else if (name.equals("Powered")) {
293 // bluetoothd has restarted, re-read all our properties.
294 // Note: bluez only sends this property change when it restarts.
295 if (propValues[1].equals("true"))
296 onRestartRequired();
297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 }
299
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700300 private void onDevicePropertyChanged(String deviceObjectPath, String[] propValues) {
301 String name = propValues[0];
302 String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
303 if (address == null) {
304 Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null");
305 return;
306 }
Nick Pellybd022f42009-08-14 18:33:38 -0700307 BluetoothDevice device = mAdapter.getRemoteDevice(address);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700308 if (name.equals("Name")) {
309 Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700310 intent.putExtra(BluetoothIntent.DEVICE, device);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700311 intent.putExtra(BluetoothIntent.NAME, propValues[1]);
312 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
313 mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
314 } else if (name.equals("Class")) {
315 Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700316 intent.putExtra(BluetoothIntent.DEVICE, device);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700317 intent.putExtra(BluetoothIntent.CLASS, propValues[1]);
318 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
319 mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
320 } else if (name.equals("Connected")) {
321 Intent intent = null;
322 if (propValues[1].equals("true")) {
323 intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION);
324 } else {
325 intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION);
326 }
Nick Pellybd022f42009-08-14 18:33:38 -0700327 intent.putExtra(BluetoothIntent.DEVICE, device);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700328 mContext.sendBroadcast(intent, BLUETOOTH_PERM);
329 mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
330 } else if (name.equals("UUIDs")) {
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700331 String uuid = null;
332 int len = Integer.valueOf(propValues[1]);
333 if (len > 0) {
334 uuid = "";
335 for (int i = 2; i < propValues.length; i++) {
336 uuid = uuid + propValues[i] + ",";
337 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700338 }
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700339 mBluetoothService.setRemoteDeviceProperty(address, name, uuid);
Jaikumar Ganesh9488cbd2009-08-03 17:17:37 -0700340 } else if (name.equals("Paired")) {
341 if (propValues[1].equals("true")) {
342 mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
343 } else {
344 mBluetoothService.getBondState().setBondState(address,
345 BluetoothDevice.BOND_NOT_BONDED);
346 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700347 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700348 }
349
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700350 private String checkPairingRequestAndGetAddress(String objectPath, int nativeData) {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700351 String address = mBluetoothService.getAddressFromObjectPath(objectPath);
352 if (address == null) {
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700353 Log.e(TAG, "Unable to get device address in checkPairingRequestAndGetAddress, " +
354 "returning null");
355 return null;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 address = address.toUpperCase();
358 mPasskeyAgentRequestData.put(address, new Integer(nativeData));
359
Nick Pellybd022f42009-08-14 18:33:38 -0700360 if (mBluetoothService.getBluetoothState() == BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700361 // shutdown path
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700362 mBluetoothService.cancelPairingUserInput(address);
363 return null;
The Android Open Source Project10592532009-03-18 17:39:46 -0700364 }
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700365 return address;
366 }
367
368 private void onRequestConfirmation(String objectPath, int passkey, int nativeData) {
369 String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
370 if (address == null) return;
371
372 Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700373 intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700374 intent.putExtra(BluetoothIntent.PASSKEY, passkey);
375 intent.putExtra(BluetoothIntent.PAIRING_VARIANT,
376 BluetoothDevice.PAIRING_VARIANT_CONFIRMATION);
377 mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
378 return;
379 }
380
381 private void onRequestPasskey(String objectPath, int nativeData) {
382 String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
383 if (address == null) return;
384
385 Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700386 intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700387 intent.putExtra(BluetoothIntent.PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PASSKEY);
388 mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
389 return;
390 }
391
392 private void onRequestPinCode(String objectPath, int nativeData) {
393 String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
394 if (address == null) return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 if (mBluetoothService.getBondState().getBondState(address) ==
397 BluetoothDevice.BOND_BONDING) {
398 // we initiated the bonding
399 int btClass = mBluetoothService.getRemoteClass(address);
400
401 // try 0000 once if the device looks dumb
402 switch (BluetoothClass.Device.getDevice(btClass)) {
403 case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
404 case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
405 case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
406 case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
407 case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
408 case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
409 if (!mBluetoothService.getBondState().hasAutoPairingFailed(address) &&
410 !mBluetoothService.getBondState().isAutoPairingBlacklisted(address)) {
411 mBluetoothService.getBondState().attempt(address);
412 mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
413 return;
414 }
415 }
416 }
417 Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
Nick Pellybd022f42009-08-14 18:33:38 -0700418 intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700419 intent.putExtra(BluetoothIntent.PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PIN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700421 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 }
423
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700424 private boolean onAgentAuthorize(String objectPath, String deviceUuid) {
425 String address = mBluetoothService.getAddressFromObjectPath(objectPath);
426 if (address == null) {
427 Log.e(TAG, "Unable to get device address in onAuthAgentAuthorize");
428 return false;
429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 boolean authorized = false;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700432 UUID uuid = UUID.fromString(deviceUuid);
Jaikumar Ganeshade40522009-07-30 13:32:25 -0700433 if (mBluetoothService.isEnabled() &&
Jaikumar Ganesh9488cbd2009-08-03 17:17:37 -0700434 (BluetoothUuid.isAudioSink(uuid) || BluetoothUuid.isAvrcpController(uuid)
435 || BluetoothUuid.isAdvAudioDist(uuid))) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
Nick Pellybd022f42009-08-14 18:33:38 -0700437 BluetoothDevice device = mAdapter.getRemoteDevice(address);
438 authorized = a2dp.getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 if (authorized) {
Jaikumar Ganeshade40522009-07-30 13:32:25 -0700440 Log.i(TAG, "Allowing incoming A2DP / AVRCP connection from " + address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 } else {
Jaikumar Ganeshade40522009-07-30 13:32:25 -0700442 Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 }
444 } else {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700445 Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 }
447 return authorized;
448 }
449
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700450 private void onAgentCancel() {
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700451 Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION);
452 mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
453 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 }
455
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700456 private void onRestartRequired() {
457 if (mBluetoothService.isEnabled()) {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700458 Log.e(TAG, "*** A serious error occured (did bluetoothd crash?) - " +
459 "restarting Bluetooth ***");
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700460 mHandler.sendEmptyMessage(EVENT_RESTART_BLUETOOTH);
461 }
462 }
463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 private static void log(String msg) {
465 Log.d(TAG, msg);
466 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700467
468 private native void initializeNativeDataNative();
469 private native void startEventLoopNative();
470 private native void stopEventLoopNative();
471 private native boolean isEventLoopRunningNative();
472 private native void cleanupNativeDataNative();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473}