AdapterService.java revision f848f42a0ec33519a8143f01a1acfe835e2cd1bc
1/* 2 * Copyright (C) 2012 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 17/** 18 * @hide 19 */ 20 21package com.android.bluetooth.btservice; 22 23import android.app.AlarmManager; 24import android.app.Application; 25import android.app.PendingIntent; 26import android.app.Service; 27import android.bluetooth.BluetoothAdapter; 28import android.bluetooth.BluetoothDevice; 29import android.bluetooth.BluetoothProfile; 30import android.bluetooth.BluetoothUuid; 31import android.bluetooth.IBluetooth; 32import android.bluetooth.IBluetoothCallback; 33import android.bluetooth.IBluetoothManager; 34import android.bluetooth.IBluetoothManagerCallback; 35import android.bluetooth.BluetoothActivityEnergyInfo; 36import android.bluetooth.OobData; 37import android.bluetooth.UidTraffic; 38import android.content.BroadcastReceiver; 39import android.content.ContentResolver; 40import android.content.Context; 41import android.content.Intent; 42import android.content.IntentFilter; 43import android.content.SharedPreferences; 44import android.os.BatteryStats; 45import android.os.Binder; 46import android.os.Bundle; 47import android.os.Handler; 48import android.os.IBinder; 49import android.os.Message; 50import android.os.ParcelFileDescriptor; 51import android.os.ParcelUuid; 52import android.os.PowerManager; 53import android.os.Process; 54import android.os.RemoteCallbackList; 55import android.os.RemoteException; 56import android.os.SystemClock; 57import android.provider.Settings; 58import android.text.TextUtils; 59import android.util.Base64; 60import android.util.EventLog; 61import android.util.Log; 62import android.util.Pair; 63 64import android.util.SparseArray; 65import com.android.bluetooth.a2dp.A2dpService; 66import com.android.bluetooth.a2dp.A2dpSinkService; 67import com.android.bluetooth.hid.HidService; 68import com.android.bluetooth.hfp.HeadsetService; 69import com.android.bluetooth.hfpclient.HeadsetClientService; 70import com.android.bluetooth.hdp.HealthService; 71import com.android.bluetooth.pan.PanService; 72import com.android.bluetooth.sdp.SdpManager; 73import com.android.internal.R; 74import com.android.bluetooth.Utils; 75import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 76 77import java.io.FileDescriptor; 78import java.io.FileOutputStream; 79import java.io.FileWriter; 80import java.io.IOException; 81import java.io.PrintWriter; 82import java.nio.charset.StandardCharsets; 83import java.util.ArrayList; 84import java.util.Arrays; 85import java.util.HashMap; 86import java.util.Set; 87import java.util.Map; 88import java.util.Iterator; 89import java.util.Map.Entry; 90import java.util.List; 91 92import android.content.pm.PackageManager; 93import android.os.ServiceManager; 94import com.android.internal.app.IBatteryStats; 95 96public class AdapterService extends Service { 97 private static final String TAG = "BluetoothAdapterService"; 98 private static final boolean DBG = false; 99 private static final boolean TRACE_REF = false; 100 private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; 101 private static final int MIN_OFFLOADED_FILTERS = 10; 102 private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; 103 //For Debugging only 104 private static int sRefCount=0; 105 106 private final Object mEnergyInfoLock = new Object(); 107 private int mStackReportedState; 108 private int mTxTimeTotalMs; 109 private int mRxTimeTotalMs; 110 private int mIdleTimeTotalMs; 111 private int mEnergyUsedTotalVoltAmpSecMicro; 112 private SparseArray<UidTraffic> mUidTraffic = new SparseArray<>(); 113 114 private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>(); 115 116 public static final String ACTION_LOAD_ADAPTER_PROPERTIES = 117 "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 118 public static final String ACTION_SERVICE_STATE_CHANGED = 119 "com.android.bluetooth.btservice.action.STATE_CHANGED"; 120 public static final String EXTRA_ACTION="action"; 121 public static final int PROFILE_CONN_CONNECTED = 1; 122 public static final int PROFILE_CONN_REJECTED = 2; 123 124 private static final String ACTION_ALARM_WAKEUP = 125 "com.android.bluetooth.btservice.action.ALARM_WAKEUP"; 126 127 public static final String BLUETOOTH_ADMIN_PERM = 128 android.Manifest.permission.BLUETOOTH_ADMIN; 129 public static final String BLUETOOTH_PRIVILEGED = 130 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 131 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 132 static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; 133 134 private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = 135 "phonebook_access_permission"; 136 private static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = 137 "message_access_permission"; 138 private static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = 139 "sim_access_permission"; 140 141 private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY; 142 143 private static final String[] DEVICE_TYPE_NAMES = new String[] { 144 "???", 145 "BR/EDR", 146 "LE", 147 "DUAL" 148 }; 149 150 static { 151 classInitNative(); 152 } 153 154 private static AdapterService sAdapterService; 155 public static synchronized AdapterService getAdapterService(){ 156 if (sAdapterService != null && !sAdapterService.mCleaningUp) { 157 Log.d(TAG, "getAdapterService() - returning " + sAdapterService); 158 return sAdapterService; 159 } 160 if (DBG) { 161 if (sAdapterService == null) { 162 Log.d(TAG, "getAdapterService() - Service not available"); 163 } else if (sAdapterService.mCleaningUp) { 164 Log.d(TAG,"getAdapterService() - Service is cleaning up"); 165 } 166 } 167 return null; 168 } 169 170 private static synchronized void setAdapterService(AdapterService instance) { 171 if (instance != null && !instance.mCleaningUp) { 172 if (DBG) Log.d(TAG, "setAdapterService() - set to: " + sAdapterService); 173 sAdapterService = instance; 174 } else { 175 if (DBG) { 176 if (sAdapterService == null) { 177 Log.d(TAG, "setAdapterService() - Service not available"); 178 } else if (sAdapterService.mCleaningUp) { 179 Log.d(TAG,"setAdapterService() - Service is cleaning up"); 180 } 181 } 182 } 183 } 184 185 private static synchronized void clearAdapterService() { 186 sAdapterService = null; 187 } 188 189 private AdapterProperties mAdapterProperties; 190 private AdapterState mAdapterStateMachine; 191 private BondStateMachine mBondStateMachine; 192 private JniCallbacks mJniCallbacks; 193 private RemoteDevices mRemoteDevices; 194 195 /* TODO: Consider to remove the search API from this class, if changed to use call-back */ 196 private SdpManager mSdpManager = null; 197 198 private boolean mProfilesStarted; 199 private boolean mNativeAvailable; 200 private boolean mCleaningUp; 201 private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>(); 202 //Only BluetoothManagerService should be registered 203 private RemoteCallbackList<IBluetoothCallback> mCallbacks; 204 private int mCurrentRequestId; 205 private boolean mQuietmode = false; 206 207 private AlarmManager mAlarmManager; 208 private PendingIntent mPendingAlarm; 209 private IBatteryStats mBatteryStats; 210 private PowerManager mPowerManager; 211 private PowerManager.WakeLock mWakeLock; 212 private String mWakeLockName; 213 214 private ProfileObserver mProfileObserver; 215 216 public AdapterService() { 217 super(); 218 if (TRACE_REF) { 219 synchronized (AdapterService.class) { 220 sRefCount++; 221 debugLog("AdapterService() - REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount); 222 } 223 } 224 225 // This is initialized at the beginning in order to prevent 226 // NullPointerException from happening if AdapterService 227 // functions are called before BLE is turned on due to 228 // |mRemoteDevices| being null. 229 mRemoteDevices = new RemoteDevices(this); 230 } 231 232 public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 233 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED); 234 m.obj = device; 235 m.arg1 = profileId; 236 m.arg2 = newState; 237 Bundle b = new Bundle(1); 238 b.putInt("prevState", prevState); 239 m.setData(b); 240 mHandler.sendMessage(m); 241 } 242 243 public void initProfilePriorities(BluetoothDevice device, ParcelUuid[] mUuids) { 244 if(mUuids == null) return; 245 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES); 246 m.obj = device; 247 m.arg1 = mUuids.length; 248 Bundle b = new Bundle(1); 249 for(int i=0; i<mUuids.length; i++) { 250 b.putParcelable("uuids" + i, mUuids[i]); 251 } 252 m.setData(b); 253 mHandler.sendMessage(m); 254 } 255 256 private void processInitProfilePriorities (BluetoothDevice device, ParcelUuid[] uuids){ 257 HidService hidService = HidService.getHidService(); 258 A2dpService a2dpService = A2dpService.getA2dpService(); 259 A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService(); 260 HeadsetService headsetService = HeadsetService.getHeadsetService(); 261 HeadsetClientService headsetClientService = HeadsetClientService.getHeadsetClientService(); 262 263 // Set profile priorities only for the profiles discovered on the remote device. 264 // This avoids needless auto-connect attempts to profiles non-existent on the remote device 265 if ((hidService != null) && 266 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) || 267 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) && 268 (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){ 269 hidService.setPriority(device,BluetoothProfile.PRIORITY_ON); 270 } 271 272 // If we do not have a stored priority for HFP/A2DP (all roles) then default to on. 273 if ((headsetService != null) && 274 ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP) || 275 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) && 276 (headsetService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) { 277 headsetService.setPriority(device,BluetoothProfile.PRIORITY_ON); 278 } 279 280 if ((a2dpService != null) && 281 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink) || 282 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AdvAudioDist)) && 283 (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){ 284 a2dpService.setPriority(device,BluetoothProfile.PRIORITY_ON); 285 } 286 287 if ((headsetClientService != null) && 288 ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) || 289 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) && 290 (headsetClientService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) { 291 headsetClientService.setPriority(device, BluetoothProfile.PRIORITY_ON); 292 } 293 294 if ((a2dpSinkService != null) && 295 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource) && 296 (a2dpSinkService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) { 297 a2dpSinkService.setPriority(device, BluetoothProfile.PRIORITY_ON); 298 } 299 300 } 301 302 private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 303 // Profiles relevant to phones. 304 if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET)) && 305 (newState == BluetoothProfile.STATE_CONNECTED)){ 306 debugLog( "Profile connected. Schedule missing profile connection if any"); 307 connectOtherProfile(device, PROFILE_CONN_CONNECTED); 308 setProfileAutoConnectionPriority(device, profileId); 309 } 310 311 // Profiles relevant to Car Kitts. 312 if (((profileId == BluetoothProfile.A2DP_SINK) || 313 (profileId == BluetoothProfile.HEADSET_CLIENT)) && 314 (newState == BluetoothProfile.STATE_CONNECTED)) { 315 debugLog( "Profile connected. Schedule missing profile connection if any"); 316 connectOtherProfile(device, PROFILE_CONN_CONNECTED); 317 setProfileAutoConnectionPriority(device, profileId); 318 } 319 320 IBluetooth.Stub binder = mBinder; 321 if (binder != null) { 322 try { 323 binder.sendConnectionStateChange(device, profileId, newState,prevState); 324 } catch (RemoteException re) { 325 errorLog("" + re); 326 } 327 } 328 } 329 330 public void addProfile(ProfileService profile) { 331 synchronized (mProfiles) { 332 mProfiles.add(profile); 333 } 334 } 335 336 public void removeProfile(ProfileService profile) { 337 synchronized (mProfiles) { 338 mProfiles.remove(profile); 339 } 340 } 341 342 public void onProfileServiceStateChanged(String serviceName, int state) { 343 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 344 m.obj=serviceName; 345 m.arg1 = state; 346 mHandler.sendMessage(m); 347 } 348 349 private void processProfileServiceStateChanged(String serviceName, int state) { 350 boolean doUpdate=false; 351 boolean isBleTurningOn; 352 boolean isBleTurningOff; 353 boolean isTurningOn; 354 boolean isTurningOff; 355 356 synchronized (mProfileServicesState) { 357 Integer prevState = mProfileServicesState.get(serviceName); 358 if (prevState != null && prevState != state) { 359 mProfileServicesState.put(serviceName,state); 360 doUpdate=true; 361 } 362 } 363 debugLog("processProfileServiceStateChanged() serviceName=" + serviceName 364 + ", state=" + state +", doUpdate=" + doUpdate); 365 366 if (!doUpdate) { 367 return; 368 } 369 370 synchronized (mAdapterStateMachine) { 371 isTurningOff = mAdapterStateMachine.isTurningOff(); 372 isTurningOn = mAdapterStateMachine.isTurningOn(); 373 isBleTurningOn = mAdapterStateMachine.isBleTurningOn(); 374 isBleTurningOff = mAdapterStateMachine.isBleTurningOff(); 375 } 376 377 debugLog("processProfileServiceStateChanged() - serviceName=" + serviceName + 378 " isTurningOn=" + isTurningOn + " isTurningOff=" + isTurningOff + 379 " isBleTurningOn=" + isBleTurningOn + " isBleTurningOff=" + isBleTurningOff); 380 381 if (isBleTurningOn) { 382 if (serviceName.equals("com.android.bluetooth.gatt.GattService")) { 383 debugLog("GattService is started"); 384 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED)); 385 return; 386 } 387 388 } else if(isBleTurningOff) { 389 if (serviceName.equals("com.android.bluetooth.gatt.GattService")) { 390 debugLog("GattService stopped"); 391 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STOPPED)); 392 return; 393 } 394 395 } else if (isTurningOff) { 396 //On to BLE_ON 397 //Process stop or disable pending 398 //Check if all services are stopped if so, do cleanup 399 synchronized (mProfileServicesState) { 400 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 401 while (i.hasNext()) { 402 Map.Entry<String,Integer> entry = i.next(); 403 debugLog("Service: " + entry.getKey()); 404 if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) { 405 debugLog("Skip GATT service - already started before"); 406 continue; 407 } 408 if (BluetoothAdapter.STATE_OFF != entry.getValue()) { 409 debugLog("onProfileServiceStateChange() - Profile still running: " 410 + entry.getKey()); 411 return; 412 } 413 } 414 } 415 debugLog("onProfileServiceStateChange() - All profile services stopped..."); 416 //Send message to state machine 417 mProfilesStarted=false; 418 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED)); 419 420 } else if (isTurningOn) { 421 updateInteropDatabase(); 422 423 //Process start pending 424 //Check if all services are started if so, update state 425 synchronized (mProfileServicesState) { 426 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 427 while (i.hasNext()) { 428 Map.Entry<String,Integer> entry = i.next(); 429 debugLog("Service: " + entry.getKey()); 430 if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) { 431 debugLog("Skip GATT service - already started before"); 432 continue; 433 } 434 if (BluetoothAdapter.STATE_ON != entry.getValue()) { 435 debugLog("onProfileServiceStateChange() - Profile still not running:" 436 + entry.getKey()); 437 return; 438 } 439 } 440 } 441 debugLog("onProfileServiceStateChange() - All profile services started."); 442 mProfilesStarted=true; 443 //Send message to state machine 444 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 445 } 446 } 447 448 private void updateInteropDatabase() { 449 interopDatabaseClearNative(); 450 451 String interop_string = Settings.Global.getString(getContentResolver(), 452 Settings.Global.BLUETOOTH_INTEROPERABILITY_LIST); 453 if (interop_string == null) return; 454 Log.d(TAG, "updateInteropDatabase: [" + interop_string + "]"); 455 456 String[] entries = interop_string.split(";"); 457 for (String entry : entries) { 458 String[] tokens = entry.split(","); 459 if (tokens.length != 2) continue; 460 461 // Get feature 462 int feature = 0; 463 try { 464 feature = Integer.parseInt(tokens[1]); 465 } catch (NumberFormatException e) { 466 Log.e(TAG, "updateInteropDatabase: Invalid feature '" + tokens[1] + "'"); 467 continue; 468 } 469 470 // Get address bytes and length 471 int length = (tokens[0].length() + 1) / 3; 472 if (length < 1 || length > 6) { 473 Log.e(TAG, "updateInteropDatabase: Malformed address string '" + tokens[0] + "'"); 474 continue; 475 } 476 477 byte[] addr = new byte[6]; 478 int offset = 0; 479 for (int i = 0; i < tokens[0].length(); ) { 480 if (tokens[0].charAt(i) == ':') { 481 i += 1; 482 } else { 483 try { 484 addr[offset++] = (byte) Integer.parseInt(tokens[0].substring(i, i + 2), 16); 485 } catch (NumberFormatException e) { 486 offset = 0; 487 break; 488 } 489 i += 2; 490 } 491 } 492 493 // Check if address was parsed ok, otherwise, move on... 494 if (offset == 0) continue; 495 496 // Add entry 497 interopDatabaseAddNative(feature, addr, length); 498 } 499 } 500 501 @Override 502 public void onCreate() { 503 super.onCreate(); 504 debugLog("onCreate()"); 505 mBinder = new AdapterServiceBinder(this); 506 mAdapterProperties = new AdapterProperties(this); 507 mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); 508 mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); 509 initNative(); 510 mNativeAvailable=true; 511 mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); 512 //Load the name and address 513 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 514 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 515 mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 516 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 517 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 518 BatteryStats.SERVICE_NAME)); 519 520 mSdpManager = SdpManager.init(this); 521 registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); 522 mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler()); 523 mProfileObserver.start(); 524 } 525 526 @Override 527 public IBinder onBind(Intent intent) { 528 debugLog("onBind()"); 529 return mBinder; 530 } 531 public boolean onUnbind(Intent intent) { 532 debugLog("onUnbind() - calling cleanup"); 533 cleanup(); 534 return super.onUnbind(intent); 535 } 536 537 public void onDestroy() { 538 debugLog("onDestroy()"); 539 mProfileObserver.stop(); 540 } 541 542 void BleOnProcessStart() { 543 debugLog("BleOnProcessStart()"); 544 545 if (getApplicationContext().getResources().getBoolean( 546 R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 547 Config.init(getApplicationContext()); 548 } 549 550 Class[] supportedProfileServices = Config.getSupportedProfiles(); 551 //Initialize data objects 552 for (int i=0; i < supportedProfileServices.length;i++) { 553 mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); 554 } 555 556 // Reset |mRemoteDevices| whenever BLE is turned off then on 557 // This is to replace the fact that |mRemoteDevices| was 558 // reinitialized in previous code. 559 // 560 // TODO(apanicke): The reason is unclear but 561 // I believe it is to clear the variable every time BLE was 562 // turned off then on. The same effect can be achieved by 563 // calling cleanup but this may not be necessary at all 564 // We should figure out why this is needed later 565 mRemoteDevices.cleanup(); 566 mAdapterProperties.init(mRemoteDevices); 567 568 debugLog("BleOnProcessStart() - Make Bond State Machine"); 569 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 570 571 mJniCallbacks.init(mBondStateMachine,mRemoteDevices); 572 573 try { 574 mBatteryStats.noteResetBleScan(); 575 } catch (RemoteException e) { 576 // Ignore. 577 } 578 579 //FIXME: Set static instance here??? 580 setAdapterService(this); 581 582 //Start Gatt service 583 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 584 } 585 586 void startCoreServices() 587 { 588 debugLog("startCoreServices()"); 589 Class[] supportedProfileServices = Config.getSupportedProfiles(); 590 591 //Start profile services 592 if (!mProfilesStarted && supportedProfileServices.length >0) { 593 //Startup all profile services 594 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 595 }else { 596 debugLog("startCoreProfiles(): Profile Services alreay started"); 597 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 598 } 599 } 600 601 void startBluetoothDisable() { 602 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE)); 603 } 604 605 boolean stopProfileServices() { 606 Class[] supportedProfileServices = Config.getSupportedProfiles(); 607 if (mProfilesStarted && supportedProfileServices.length>0) { 608 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 609 return true; 610 } 611 debugLog("stopProfileServices() - No profiles services to stop or already stopped."); 612 return false; 613 } 614 615 boolean stopGattProfileService() { 616 //TODO: can optimize this instead of looping around all supported profiles 617 debugLog("stopGattProfileService()"); 618 Class[] supportedProfileServices = Config.getSupportedProfiles(); 619 620 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 621 return true; 622 } 623 624 625 void updateAdapterState(int prevState, int newState){ 626 if (mCallbacks !=null) { 627 int n=mCallbacks.beginBroadcast(); 628 debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 629 for (int i=0; i <n;i++) { 630 try { 631 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); 632 } catch (RemoteException e) { 633 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 634 } 635 } 636 mCallbacks.finishBroadcast(); 637 } 638 } 639 640 void cleanup () { 641 debugLog("cleanup()"); 642 if (mCleaningUp) { 643 errorLog("cleanup() - Service already starting to cleanup, ignoring request..."); 644 return; 645 } 646 647 mCleaningUp = true; 648 649 unregisterReceiver(mAlarmBroadcastReceiver); 650 651 if (mPendingAlarm != null) { 652 mAlarmManager.cancel(mPendingAlarm); 653 mPendingAlarm = null; 654 } 655 656 // This wake lock release may also be called concurrently by 657 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 658 synchronized (this) { 659 if (mWakeLock != null) { 660 mWakeLock.release(); 661 mWakeLock = null; 662 } 663 } 664 665 if (mAdapterStateMachine != null) { 666 mAdapterStateMachine.doQuit(); 667 mAdapterStateMachine.cleanup(); 668 } 669 670 if (mBondStateMachine != null) { 671 mBondStateMachine.doQuit(); 672 mBondStateMachine.cleanup(); 673 } 674 675 if (mRemoteDevices != null) { 676 mRemoteDevices.cleanup(); 677 } 678 679 if(mSdpManager != null) { 680 mSdpManager.cleanup(); 681 mSdpManager = null; 682 } 683 684 if (mNativeAvailable) { 685 debugLog("cleanup() - Cleaning up adapter native"); 686 cleanupNative(); 687 mNativeAvailable=false; 688 } 689 690 if (mAdapterProperties != null) { 691 mAdapterProperties.cleanup(); 692 } 693 694 if (mJniCallbacks != null) { 695 mJniCallbacks.cleanup(); 696 } 697 698 if (mProfileServicesState != null) { 699 mProfileServicesState.clear(); 700 } 701 702 clearAdapterService(); 703 704 if (mBinder != null) { 705 mBinder.cleanup(); 706 mBinder = null; //Do not remove. Otherwise Binder leak! 707 } 708 709 if (mCallbacks !=null) { 710 mCallbacks.kill(); 711 } 712 713 System.exit(0); 714 } 715 716 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 717 private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20; 718 private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30; 719 private static final int MESSAGE_PROFILE_INIT_PRIORITIES=40; 720 private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000; 721 722 private final Handler mHandler = new Handler() { 723 @Override 724 public void handleMessage(Message msg) { 725 debugLog("handleMessage() - Message: " + msg.what); 726 727 switch (msg.what) { 728 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 729 debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 730 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 731 } 732 break; 733 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: { 734 debugLog( "handleMessage() - MESSAGE_PROFILE_CONNECTION_STATE_CHANGED"); 735 processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR)); 736 } 737 break; 738 case MESSAGE_PROFILE_INIT_PRIORITIES: { 739 debugLog( "handleMessage() - MESSAGE_PROFILE_INIT_PRIORITIES"); 740 ParcelUuid[] mUuids = new ParcelUuid[msg.arg1]; 741 for(int i=0; i<mUuids.length; i++) { 742 mUuids[i] = msg.getData().getParcelable("uuids" + i); 743 } 744 processInitProfilePriorities((BluetoothDevice) msg.obj, mUuids); 745 } 746 break; 747 case MESSAGE_CONNECT_OTHER_PROFILES: { 748 debugLog( "handleMessage() - MESSAGE_CONNECT_OTHER_PROFILES"); 749 processConnectOtherProfiles((BluetoothDevice) msg.obj,msg.arg1); 750 } 751 break; 752 } 753 } 754 }; 755 756 @SuppressWarnings("rawtypes") 757 private void setGattProfileServiceState(Class[] services, int state) { 758 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 759 Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving..."); 760 return; 761 } 762 763 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 764 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 765 766 if (state == BluetoothAdapter.STATE_OFF) { 767 expectedCurrentState= BluetoothAdapter.STATE_ON; 768 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 769 } 770 771 for (int i=0; i <services.length;i++) { 772 String serviceName = services[i].getName(); 773 String simpleName = services[i].getSimpleName(); 774 775 if (simpleName.equals("GattService")) { 776 Integer serviceState = mProfileServicesState.get(serviceName); 777 778 if(serviceState != null && serviceState != expectedCurrentState) { 779 debugLog("setProfileServiceState() - Unable to " 780 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 781 + " service " + serviceName 782 + ". Invalid state: " + serviceState); 783 continue; 784 } 785 debugLog("setProfileServiceState() - " 786 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 787 + " service " + serviceName); 788 789 mProfileServicesState.put(serviceName,pendingState); 790 Intent intent = new Intent(this,services[i]); 791 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 792 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 793 startService(intent); 794 return; 795 } 796 } 797 } 798 799 800 @SuppressWarnings("rawtypes") 801 private void setProfileServiceState(Class[] services, int state) { 802 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 803 debugLog("setProfileServiceState() - Invalid state, leaving..."); 804 return; 805 } 806 807 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 808 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 809 if (state == BluetoothAdapter.STATE_OFF) { 810 expectedCurrentState= BluetoothAdapter.STATE_ON; 811 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 812 } 813 814 for (int i=0; i <services.length;i++) { 815 String serviceName = services[i].getName(); 816 String simpleName = services[i].getSimpleName(); 817 818 if (simpleName.equals("GattService")) continue; 819 820 Integer serviceState = mProfileServicesState.get(serviceName); 821 if(serviceState != null && serviceState != expectedCurrentState) { 822 debugLog("setProfileServiceState() - Unable to " 823 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 824 + " service " + serviceName 825 + ". Invalid state: " + serviceState); 826 continue; 827 } 828 829 debugLog("setProfileServiceState() - " 830 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 831 + " service " + serviceName); 832 833 mProfileServicesState.put(serviceName,pendingState); 834 Intent intent = new Intent(this,services[i]); 835 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 836 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 837 startService(intent); 838 } 839 } 840 841 private boolean isAvailable() { 842 return !mCleaningUp; 843 } 844 845 /** 846 * Handlers for incoming service calls 847 */ 848 private AdapterServiceBinder mBinder; 849 850 /** 851 * The Binder implementation must be declared to be a static class, with 852 * the AdapterService instance passed in the constructor. Furthermore, 853 * when the AdapterService shuts down, the reference to the AdapterService 854 * must be explicitly removed. 855 * 856 * Otherwise, a memory leak can occur from repeated starting/stopping the 857 * service...Please refer to android.os.Binder for further details on 858 * why an inner instance class should be avoided. 859 * 860 */ 861 private static class AdapterServiceBinder extends IBluetooth.Stub { 862 private AdapterService mService; 863 864 public AdapterServiceBinder(AdapterService svc) { 865 mService = svc; 866 } 867 public boolean cleanup() { 868 mService = null; 869 return true; 870 } 871 872 public AdapterService getService() { 873 if (mService != null && mService.isAvailable()) { 874 return mService; 875 } 876 return null; 877 } 878 public boolean isEnabled() { 879 // don't check caller, may be called from system UI 880 AdapterService service = getService(); 881 if (service == null) return false; 882 return service.isEnabled(); 883 } 884 885 public int getState() { 886 // don't check caller, may be called from system UI 887 AdapterService service = getService(); 888 if (service == null) return BluetoothAdapter.STATE_OFF; 889 return service.getState(); 890 } 891 892 public boolean enable() { 893 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 894 (!Utils.checkCaller())) { 895 Log.w(TAG, "enable() - Not allowed for non-active user and non system user"); 896 return false; 897 } 898 AdapterService service = getService(); 899 if (service == null) return false; 900 return service.enable(); 901 } 902 903 public boolean enableNoAutoConnect() { 904 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 905 (!Utils.checkCaller())) { 906 Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user"); 907 return false; 908 } 909 910 AdapterService service = getService(); 911 if (service == null) return false; 912 return service.enableNoAutoConnect(); 913 } 914 915 public boolean disable() { 916 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 917 (!Utils.checkCaller())) { 918 Log.w(TAG, "disable() - Not allowed for non-active user and non system user"); 919 return false; 920 } 921 922 AdapterService service = getService(); 923 if (service == null) return false; 924 return service.disable(); 925 } 926 927 public String getAddress() { 928 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 929 (!Utils.checkCallerAllowManagedProfiles(mService))) { 930 Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user"); 931 return null; 932 } 933 934 AdapterService service = getService(); 935 if (service == null) return null; 936 return service.getAddress(); 937 } 938 939 public ParcelUuid[] getUuids() { 940 if (!Utils.checkCaller()) { 941 Log.w(TAG, "getUuids() - Not allowed for non-active user"); 942 return new ParcelUuid[0]; 943 } 944 945 AdapterService service = getService(); 946 if (service == null) return new ParcelUuid[0]; 947 return service.getUuids(); 948 } 949 950 public String getName() { 951 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 952 (!Utils.checkCaller())) { 953 Log.w(TAG, "getName() - Not allowed for non-active user and non system user"); 954 return null; 955 } 956 957 AdapterService service = getService(); 958 if (service == null) return null; 959 return service.getName(); 960 } 961 962 public boolean setName(String name) { 963 if (!Utils.checkCaller()) { 964 Log.w(TAG, "setName() - Not allowed for non-active user"); 965 return false; 966 } 967 968 AdapterService service = getService(); 969 if (service == null) return false; 970 return service.setName(name); 971 } 972 973 public int getScanMode() { 974 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 975 Log.w(TAG, "getScanMode() - Not allowed for non-active user"); 976 return BluetoothAdapter.SCAN_MODE_NONE; 977 } 978 979 AdapterService service = getService(); 980 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 981 return service.getScanMode(); 982 } 983 984 public boolean setScanMode(int mode, int duration) { 985 if (!Utils.checkCaller()) { 986 Log.w(TAG, "setScanMode() - Not allowed for non-active user"); 987 return false; 988 } 989 990 AdapterService service = getService(); 991 if (service == null) return false; 992 return service.setScanMode(mode,duration); 993 } 994 995 public int getDiscoverableTimeout() { 996 if (!Utils.checkCaller()) { 997 Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user"); 998 return 0; 999 } 1000 1001 AdapterService service = getService(); 1002 if (service == null) return 0; 1003 return service.getDiscoverableTimeout(); 1004 } 1005 1006 public boolean setDiscoverableTimeout(int timeout) { 1007 if (!Utils.checkCaller()) { 1008 Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user"); 1009 return false; 1010 } 1011 1012 AdapterService service = getService(); 1013 if (service == null) return false; 1014 return service.setDiscoverableTimeout(timeout); 1015 } 1016 1017 public boolean startDiscovery() { 1018 if (!Utils.checkCaller()) { 1019 Log.w(TAG, "startDiscovery() - Not allowed for non-active user"); 1020 return false; 1021 } 1022 1023 AdapterService service = getService(); 1024 if (service == null) return false; 1025 return service.startDiscovery(); 1026 } 1027 1028 public boolean cancelDiscovery() { 1029 if (!Utils.checkCaller()) { 1030 Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user"); 1031 return false; 1032 } 1033 1034 AdapterService service = getService(); 1035 if (service == null) return false; 1036 return service.cancelDiscovery(); 1037 } 1038 public boolean isDiscovering() { 1039 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1040 Log.w(TAG, "isDiscovering() - Not allowed for non-active user"); 1041 return false; 1042 } 1043 1044 AdapterService service = getService(); 1045 if (service == null) return false; 1046 return service.isDiscovering(); 1047 } 1048 1049 public BluetoothDevice[] getBondedDevices() { 1050 // don't check caller, may be called from system UI 1051 AdapterService service = getService(); 1052 if (service == null) return new BluetoothDevice[0]; 1053 return service.getBondedDevices(); 1054 } 1055 1056 public int getAdapterConnectionState() { 1057 // don't check caller, may be called from system UI 1058 AdapterService service = getService(); 1059 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 1060 return service.getAdapterConnectionState(); 1061 } 1062 1063 public int getProfileConnectionState(int profile) { 1064 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1065 Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user"); 1066 return BluetoothProfile.STATE_DISCONNECTED; 1067 } 1068 1069 AdapterService service = getService(); 1070 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 1071 return service.getProfileConnectionState(profile); 1072 } 1073 1074 public boolean createBond(BluetoothDevice device, int transport) { 1075 if (!Utils.checkCaller()) { 1076 Log.w(TAG, "createBond() - Not allowed for non-active user"); 1077 return false; 1078 } 1079 1080 AdapterService service = getService(); 1081 if (service == null) return false; 1082 return service.createBond(device, transport, null); 1083 } 1084 1085 public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) { 1086 if (!Utils.checkCaller()) { 1087 Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user"); 1088 return false; 1089 } 1090 1091 AdapterService service = getService(); 1092 if (service == null) return false; 1093 return service.createBond(device, transport, oobData); 1094 } 1095 1096 public boolean cancelBondProcess(BluetoothDevice device) { 1097 if (!Utils.checkCaller()) { 1098 Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user"); 1099 return false; 1100 } 1101 1102 AdapterService service = getService(); 1103 if (service == null) return false; 1104 return service.cancelBondProcess(device); 1105 } 1106 1107 public boolean removeBond(BluetoothDevice device) { 1108 if (!Utils.checkCaller()) { 1109 Log.w(TAG, "removeBond() - Not allowed for non-active user"); 1110 return false; 1111 } 1112 1113 AdapterService service = getService(); 1114 if (service == null) return false; 1115 return service.removeBond(device); 1116 } 1117 1118 public int getBondState(BluetoothDevice device) { 1119 // don't check caller, may be called from system UI 1120 AdapterService service = getService(); 1121 if (service == null) return BluetoothDevice.BOND_NONE; 1122 return service.getBondState(device); 1123 } 1124 1125 public int getConnectionState(BluetoothDevice device) { 1126 AdapterService service = getService(); 1127 if (service == null) return 0; 1128 return service.getConnectionState(device); 1129 } 1130 1131 public String getRemoteName(BluetoothDevice device) { 1132 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1133 Log.w(TAG, "getRemoteName() - Not allowed for non-active user"); 1134 return null; 1135 } 1136 1137 AdapterService service = getService(); 1138 if (service == null) return null; 1139 return service.getRemoteName(device); 1140 } 1141 1142 public int getRemoteType(BluetoothDevice device) { 1143 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1144 Log.w(TAG, "getRemoteType() - Not allowed for non-active user"); 1145 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1146 } 1147 1148 AdapterService service = getService(); 1149 if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1150 return service.getRemoteType(device); 1151 } 1152 1153 public String getRemoteAlias(BluetoothDevice device) { 1154 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1155 Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user"); 1156 return null; 1157 } 1158 1159 AdapterService service = getService(); 1160 if (service == null) return null; 1161 return service.getRemoteAlias(device); 1162 } 1163 1164 public boolean setRemoteAlias(BluetoothDevice device, String name) { 1165 if (!Utils.checkCaller()) { 1166 Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user"); 1167 return false; 1168 } 1169 1170 AdapterService service = getService(); 1171 if (service == null) return false; 1172 return service.setRemoteAlias(device, name); 1173 } 1174 1175 public int getRemoteClass(BluetoothDevice device) { 1176 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1177 Log.w(TAG, "getRemoteClass() - Not allowed for non-active user"); 1178 return 0; 1179 } 1180 1181 AdapterService service = getService(); 1182 if (service == null) return 0; 1183 return service.getRemoteClass(device); 1184 } 1185 1186 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1187 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1188 Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user"); 1189 return new ParcelUuid[0]; 1190 } 1191 1192 AdapterService service = getService(); 1193 if (service == null) return new ParcelUuid[0]; 1194 return service.getRemoteUuids(device); 1195 } 1196 1197 public boolean fetchRemoteUuids(BluetoothDevice device) { 1198 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1199 Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user"); 1200 return false; 1201 } 1202 1203 AdapterService service = getService(); 1204 if (service == null) return false; 1205 return service.fetchRemoteUuids(device); 1206 } 1207 1208 1209 1210 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1211 if (!Utils.checkCaller()) { 1212 Log.w(TAG, "setPin() - Not allowed for non-active user"); 1213 return false; 1214 } 1215 1216 AdapterService service = getService(); 1217 if (service == null) return false; 1218 return service.setPin(device, accept, len, pinCode); 1219 } 1220 1221 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1222 if (!Utils.checkCaller()) { 1223 Log.w(TAG, "setPasskey() - Not allowed for non-active user"); 1224 return false; 1225 } 1226 1227 AdapterService service = getService(); 1228 if (service == null) return false; 1229 return service.setPasskey(device, accept, len, passkey); 1230 } 1231 1232 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1233 if (!Utils.checkCaller()) { 1234 Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user"); 1235 return false; 1236 } 1237 1238 AdapterService service = getService(); 1239 if (service == null) return false; 1240 return service.setPairingConfirmation(device, accept); 1241 } 1242 1243 public int getPhonebookAccessPermission(BluetoothDevice device) { 1244 if (!Utils.checkCaller()) { 1245 Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user"); 1246 return BluetoothDevice.ACCESS_UNKNOWN; 1247 } 1248 1249 AdapterService service = getService(); 1250 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1251 return service.getPhonebookAccessPermission(device); 1252 } 1253 1254 public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1255 if (!Utils.checkCaller()) { 1256 Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user"); 1257 return false; 1258 } 1259 1260 AdapterService service = getService(); 1261 if (service == null) return false; 1262 return service.setPhonebookAccessPermission(device, value); 1263 } 1264 1265 public int getMessageAccessPermission(BluetoothDevice device) { 1266 if (!Utils.checkCaller()) { 1267 Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user"); 1268 return BluetoothDevice.ACCESS_UNKNOWN; 1269 } 1270 1271 AdapterService service = getService(); 1272 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1273 return service.getMessageAccessPermission(device); 1274 } 1275 1276 public boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1277 if (!Utils.checkCaller()) { 1278 Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user"); 1279 return false; 1280 } 1281 1282 AdapterService service = getService(); 1283 if (service == null) return false; 1284 return service.setMessageAccessPermission(device, value); 1285 } 1286 1287 public int getSimAccessPermission(BluetoothDevice device) { 1288 if (!Utils.checkCaller()) { 1289 Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user"); 1290 return BluetoothDevice.ACCESS_UNKNOWN; 1291 } 1292 1293 AdapterService service = getService(); 1294 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1295 return service.getSimAccessPermission(device); 1296 } 1297 1298 public boolean setSimAccessPermission(BluetoothDevice device, int value) { 1299 if (!Utils.checkCaller()) { 1300 Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user"); 1301 return false; 1302 } 1303 1304 AdapterService service = getService(); 1305 if (service == null) return false; 1306 return service.setSimAccessPermission(device, value); 1307 } 1308 1309 public void sendConnectionStateChange(BluetoothDevice 1310 device, int profile, int state, int prevState) { 1311 AdapterService service = getService(); 1312 if (service == null) return; 1313 service.sendConnectionStateChange(device, profile, state, prevState); 1314 } 1315 1316 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1317 ParcelUuid uuid, int port, int flag) { 1318 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1319 Log.w(TAG, "connectSocket() - Not allowed for non-active user"); 1320 return null; 1321 } 1322 1323 AdapterService service = getService(); 1324 if (service == null) return null; 1325 return service.connectSocket(device, type, uuid, port, flag); 1326 } 1327 1328 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1329 ParcelUuid uuid, int port, int flag) { 1330 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1331 Log.w(TAG, "createSocketChannel() - Not allowed for non-active user"); 1332 return null; 1333 } 1334 1335 AdapterService service = getService(); 1336 if (service == null) return null; 1337 return service.createSocketChannel(type, serviceName, uuid, port, flag); 1338 } 1339 public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { 1340 if (!Utils.checkCaller()) { 1341 Log.w(TAG,"sdpSea(): not allowed for non-active user"); 1342 return false; 1343 } 1344 1345 AdapterService service = getService(); 1346 if (service == null) return false; 1347 return service.sdpSearch(device,uuid); 1348 } 1349 1350 public boolean configHciSnoopLog(boolean enable) { 1351 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 1352 EventLog.writeEvent(0x534e4554 /* SNET */, "Bluetooth", Binder.getCallingUid(), 1353 "configHciSnoopLog() - Not allowed for non-active user b/18643224"); 1354 return false; 1355 } 1356 1357 AdapterService service = getService(); 1358 if (service == null) return false; 1359 return service.configHciSnoopLog(enable); 1360 } 1361 1362 public boolean factoryReset() { 1363 AdapterService service = getService(); 1364 if (service == null) return false; 1365 service.disable(); 1366 return service.factoryReset(); 1367 1368 } 1369 1370 public void registerCallback(IBluetoothCallback cb) { 1371 AdapterService service = getService(); 1372 if (service == null) return ; 1373 service.registerCallback(cb); 1374 } 1375 1376 public void unregisterCallback(IBluetoothCallback cb) { 1377 AdapterService service = getService(); 1378 if (service == null) return ; 1379 service.unregisterCallback(cb); 1380 } 1381 1382 public boolean isMultiAdvertisementSupported() { 1383 AdapterService service = getService(); 1384 if (service == null) return false; 1385 return service.isMultiAdvertisementSupported(); 1386 } 1387 1388 public boolean isPeripheralModeSupported() { 1389 AdapterService service = getService(); 1390 if (service == null) return false; 1391 return service.isPeripheralModeSupported(); 1392 } 1393 1394 public boolean isOffloadedFilteringSupported() { 1395 AdapterService service = getService(); 1396 if (service == null) return false; 1397 int val = service.getNumOfOffloadedScanFilterSupported(); 1398 return (val >= MIN_OFFLOADED_FILTERS); 1399 } 1400 1401 public boolean isOffloadedScanBatchingSupported() { 1402 AdapterService service = getService(); 1403 if (service == null) return false; 1404 int val = service.getOffloadedScanResultStorage(); 1405 return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES); 1406 } 1407 1408 public boolean isActivityAndEnergyReportingSupported() { 1409 AdapterService service = getService(); 1410 if (service == null) return false; 1411 return service.isActivityAndEnergyReportingSupported(); 1412 } 1413 1414 public void getActivityEnergyInfoFromController() { 1415 AdapterService service = getService(); 1416 if (service == null) return; 1417 service.getActivityEnergyInfoFromController(); 1418 } 1419 1420 public BluetoothActivityEnergyInfo reportActivityInfo() { 1421 AdapterService service = getService(); 1422 if (service == null) return null; 1423 return service.reportActivityInfo(); 1424 } 1425 1426 public void onLeServiceUp(){ 1427 AdapterService service = getService(); 1428 if (service == null) return; 1429 service.onLeServiceUp(); 1430 } 1431 1432 public void onBrEdrDown(){ 1433 AdapterService service = getService(); 1434 if (service == null) return; 1435 service.onBrEdrDown(); 1436 } 1437 1438 public void dump(FileDescriptor fd, String[] args) { 1439 PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); 1440 AdapterService service = getService(); 1441 if (service == null) return; 1442 service.dump(fd, writer, args); 1443 } 1444 }; 1445 1446 // ----API Methods-------- 1447 1448 boolean isEnabled() { 1449 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1450 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 1451 } 1452 1453 int getState() { 1454 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1455 if (mAdapterProperties != null) return mAdapterProperties.getState(); 1456 return BluetoothAdapter.STATE_OFF; 1457 } 1458 1459 boolean enable() { 1460 return enable (false); 1461 } 1462 1463 public boolean enableNoAutoConnect() { 1464 return enable (true); 1465 } 1466 1467 public synchronized boolean enable(boolean quietMode) { 1468 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1469 1470 debugLog("enable() - Enable called with quiet mode status = " + mQuietmode); 1471 mQuietmode = quietMode; 1472 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON); 1473 mAdapterStateMachine.sendMessage(m); 1474 return true; 1475 } 1476 1477 boolean disable() { 1478 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1479 1480 debugLog("disable() called..."); 1481 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF); 1482 mAdapterStateMachine.sendMessage(m); 1483 return true; 1484 } 1485 1486 String getAddress() { 1487 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1488 1489 String addrString = null; 1490 byte[] address = mAdapterProperties.getAddress(); 1491 return Utils.getAddressStringFromByte(address); 1492 } 1493 1494 ParcelUuid[] getUuids() { 1495 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1496 1497 return mAdapterProperties.getUuids(); 1498 } 1499 1500 String getName() { 1501 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1502 "Need BLUETOOTH permission"); 1503 1504 try { 1505 return mAdapterProperties.getName(); 1506 } catch (Throwable t) { 1507 debugLog("getName() - Unexpected exception (" + t + ")"); 1508 } 1509 return null; 1510 } 1511 1512 boolean setName(String name) { 1513 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1514 "Need BLUETOOTH ADMIN permission"); 1515 1516 return mAdapterProperties.setName(name); 1517 } 1518 1519 int getScanMode() { 1520 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1521 1522 return mAdapterProperties.getScanMode(); 1523 } 1524 1525 boolean setScanMode(int mode, int duration) { 1526 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1527 1528 setDiscoverableTimeout(duration); 1529 1530 int newMode = convertScanModeToHal(mode); 1531 return mAdapterProperties.setScanMode(newMode); 1532 } 1533 1534 int getDiscoverableTimeout() { 1535 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1536 1537 return mAdapterProperties.getDiscoverableTimeout(); 1538 } 1539 1540 boolean setDiscoverableTimeout(int timeout) { 1541 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1542 1543 return mAdapterProperties.setDiscoverableTimeout(timeout); 1544 } 1545 1546 boolean startDiscovery() { 1547 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1548 "Need BLUETOOTH ADMIN permission"); 1549 1550 return startDiscoveryNative(); 1551 } 1552 1553 boolean cancelDiscovery() { 1554 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1555 "Need BLUETOOTH ADMIN permission"); 1556 1557 return cancelDiscoveryNative(); 1558 } 1559 1560 boolean isDiscovering() { 1561 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1562 1563 return mAdapterProperties.isDiscovering(); 1564 } 1565 1566 BluetoothDevice[] getBondedDevices() { 1567 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1568 return mAdapterProperties.getBondedDevices(); 1569 } 1570 1571 int getAdapterConnectionState() { 1572 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1573 return mAdapterProperties.getConnectionState(); 1574 } 1575 1576 int getProfileConnectionState(int profile) { 1577 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1578 1579 return mAdapterProperties.getProfileConnectionState(profile); 1580 } 1581 boolean sdpSearch(BluetoothDevice device,ParcelUuid uuid) { 1582 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1583 if(mSdpManager != null) { 1584 mSdpManager.sdpSearch(device,uuid); 1585 return true; 1586 } else { 1587 return false; 1588 } 1589 } 1590 1591 boolean createBond(BluetoothDevice device, int transport, OobData oobData) { 1592 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1593 "Need BLUETOOTH ADMIN permission"); 1594 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1595 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 1596 return false; 1597 } 1598 1599 // Pairing is unreliable while scanning, so cancel discovery 1600 // Note, remove this when native stack improves 1601 cancelDiscoveryNative(); 1602 1603 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 1604 msg.obj = device; 1605 msg.arg1 = transport; 1606 1607 if (oobData != null) { 1608 Bundle oobDataBundle = new Bundle(); 1609 oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData); 1610 msg.setData(oobDataBundle); 1611 } 1612 mBondStateMachine.sendMessage(msg); 1613 return true; 1614 } 1615 1616 public boolean isQuietModeEnabled() { 1617 debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode); 1618 return mQuietmode; 1619 } 1620 1621 public void autoConnect(){ 1622 if (getState() != BluetoothAdapter.STATE_ON){ 1623 errorLog("autoConnect() - BT is not ON. Exiting autoConnect"); 1624 return; 1625 } 1626 if (isQuietModeEnabled() == false) { 1627 debugLog( "autoConnect() - Initiate auto connection on BT on..."); 1628 // Phone profiles. 1629 autoConnectHeadset(); 1630 autoConnectA2dp(); 1631 1632 // Car Kitt profiles. 1633 autoConnectHeadsetClient(); 1634 autoConnectA2dpSink(); 1635 } 1636 else { 1637 debugLog( "autoConnect() - BT is in quiet mode. Not initiating auto connections"); 1638 } 1639 } 1640 1641 private void autoConnectHeadset(){ 1642 HeadsetService hsService = HeadsetService.getHeadsetService(); 1643 1644 BluetoothDevice bondedDevices[] = getBondedDevices(); 1645 if ((bondedDevices == null) ||(hsService == null)) { 1646 return; 1647 } 1648 for (BluetoothDevice device : bondedDevices) { 1649 if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1650 debugLog("autoConnectHeadset() - Connecting HFP with " + device.toString()); 1651 hsService.connect(device); 1652 } 1653 } 1654 } 1655 1656 private void autoConnectA2dp(){ 1657 A2dpService a2dpSservice = A2dpService.getA2dpService(); 1658 BluetoothDevice bondedDevices[] = getBondedDevices(); 1659 if ((bondedDevices == null) ||(a2dpSservice == null)) { 1660 return; 1661 } 1662 for (BluetoothDevice device : bondedDevices) { 1663 if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1664 debugLog("autoConnectA2dp() - Connecting A2DP with " + device.toString()); 1665 a2dpSservice.connect(device); 1666 } 1667 } 1668 } 1669 1670 private void autoConnectHeadsetClient() { 1671 HeadsetClientService headsetClientService = HeadsetClientService.getHeadsetClientService(); 1672 BluetoothDevice bondedDevices[] = getBondedDevices(); 1673 if ((bondedDevices == null) || (headsetClientService == null)) { 1674 return; 1675 } 1676 1677 for (BluetoothDevice device : bondedDevices) { 1678 debugLog("autoConnectHeadsetClient() - Connecting Headset Client with " + 1679 device.toString()); 1680 headsetClientService.connect(device); 1681 } 1682 } 1683 1684 private void autoConnectA2dpSink() { 1685 A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService(); 1686 BluetoothDevice bondedDevices[] = getBondedDevices(); 1687 if ((bondedDevices == null) || (a2dpSinkService == null)) { 1688 return; 1689 } 1690 1691 for (BluetoothDevice device : bondedDevices) { 1692 debugLog("autoConnectA2dpSink() - Connecting A2DP Sink with " + device.toString()); 1693 a2dpSinkService.connect(device); 1694 } 1695 } 1696 1697 public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){ 1698 if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) && 1699 (isQuietModeEnabled()== false)){ 1700 Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES); 1701 m.obj = device; 1702 m.arg1 = (int)firstProfileStatus; 1703 mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT); 1704 } 1705 } 1706 1707 private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){ 1708 if (getState()!= BluetoothAdapter.STATE_ON){ 1709 return; 1710 } 1711 HeadsetService hsService = HeadsetService.getHeadsetService(); 1712 A2dpService a2dpService = A2dpService.getA2dpService(); 1713 1714 // if any of the profile service is null, second profile connection not required 1715 if ((hsService == null) ||(a2dpService == null )){ 1716 return; 1717 } 1718 List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices(); 1719 List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices(); 1720 // Check if the device is in disconnected state and if so return 1721 // We ned to connect other profile only if one of the profile is still in connected state 1722 // This is required to avoide a race condition in which profiles would 1723 // automaticlly connect if the disconnection is initiated within 6 seconds of connection 1724 //First profile connection being rejected is an exception 1725 if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&& 1726 (PROFILE_CONN_CONNECTED == firstProfileStatus)){ 1727 return; 1728 } 1729 if((hfConnDevList.isEmpty()) && 1730 (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1731 hsService.connect(device); 1732 } 1733 else if((a2dpConnDevList.isEmpty()) && 1734 (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1735 a2dpService.connect(device); 1736 } 1737 } 1738 1739 private void adjustOtherHeadsetPriorities(HeadsetService hsService, 1740 List<BluetoothDevice> connectedDeviceList) { 1741 for (BluetoothDevice device : getBondedDevices()) { 1742 if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1743 !connectedDeviceList.contains(device)) { 1744 hsService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1745 } 1746 } 1747 } 1748 1749 private void adjustOtherSinkPriorities(A2dpService a2dpService, 1750 BluetoothDevice connectedDevice) { 1751 for (BluetoothDevice device : getBondedDevices()) { 1752 if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1753 !device.equals(connectedDevice)) { 1754 a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1755 } 1756 } 1757 } 1758 1759 void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){ 1760 if (profileId == BluetoothProfile.HEADSET) { 1761 HeadsetService hsService = HeadsetService.getHeadsetService(); 1762 List<BluetoothDevice> deviceList = hsService.getConnectedDevices(); 1763 if ((hsService != null) && 1764 (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){ 1765 adjustOtherHeadsetPriorities(hsService, deviceList); 1766 hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1767 } 1768 } 1769 } 1770 1771 boolean cancelBondProcess(BluetoothDevice device) { 1772 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1773 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1774 return cancelBondNative(addr); 1775 } 1776 1777 boolean removeBond(BluetoothDevice device) { 1778 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1779 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1780 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 1781 return false; 1782 } 1783 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 1784 msg.obj = device; 1785 mBondStateMachine.sendMessage(msg); 1786 return true; 1787 } 1788 1789 int getBondState(BluetoothDevice device) { 1790 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1791 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1792 if (deviceProp == null) { 1793 return BluetoothDevice.BOND_NONE; 1794 } 1795 return deviceProp.getBondState(); 1796 } 1797 1798 int getConnectionState(BluetoothDevice device) { 1799 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1800 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1801 return getConnectionStateNative(addr); 1802 } 1803 1804 String getRemoteName(BluetoothDevice device) { 1805 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1806 if (mRemoteDevices == null) return null; 1807 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1808 if (deviceProp == null) return null; 1809 return deviceProp.getName(); 1810 } 1811 1812 int getRemoteType(BluetoothDevice device) { 1813 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1814 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1815 if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1816 return deviceProp.getDeviceType(); 1817 } 1818 1819 String getRemoteAlias(BluetoothDevice device) { 1820 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1821 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1822 if (deviceProp == null) return null; 1823 return deviceProp.getAlias(); 1824 } 1825 1826 boolean setRemoteAlias(BluetoothDevice device, String name) { 1827 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1828 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1829 if (deviceProp == null) return false; 1830 deviceProp.setAlias(device, name); 1831 return true; 1832 } 1833 1834 int getRemoteClass(BluetoothDevice device) { 1835 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1836 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1837 if (deviceProp == null) return 0; 1838 1839 return deviceProp.getBluetoothClass(); 1840 } 1841 1842 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1843 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1844 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1845 if (deviceProp == null) return null; 1846 return deviceProp.getUuids(); 1847 } 1848 1849 boolean fetchRemoteUuids(BluetoothDevice device) { 1850 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1851 mRemoteDevices.fetchUuids(device); 1852 return true; 1853 } 1854 1855 1856 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1857 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1858 "Need BLUETOOTH ADMIN permission"); 1859 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1860 // Only allow setting a pin in bonding state, or bonded state in case of security upgrade. 1861 if (deviceProp == null || 1862 (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING && 1863 deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) { 1864 return false; 1865 } 1866 1867 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1868 return pinReplyNative(addr, accept, len, pinCode); 1869 } 1870 1871 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1872 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1873 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1874 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1875 return false; 1876 } 1877 1878 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1879 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 1880 Utils.byteArrayToInt(passkey)); 1881 } 1882 1883 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1884 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1885 "Need BLUETOOTH ADMIN permission"); 1886 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1887 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1888 return false; 1889 } 1890 1891 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1892 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 1893 accept, 0); 1894 } 1895 1896 int getPhonebookAccessPermission(BluetoothDevice device) { 1897 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1898 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1899 Context.MODE_PRIVATE); 1900 if (!pref.contains(device.getAddress())) { 1901 return BluetoothDevice.ACCESS_UNKNOWN; 1902 } 1903 return pref.getBoolean(device.getAddress(), false) 1904 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1905 } 1906 1907 boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1908 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1909 "Need BLUETOOTH PRIVILEGED permission"); 1910 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1911 Context.MODE_PRIVATE); 1912 SharedPreferences.Editor editor = pref.edit(); 1913 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1914 editor.remove(device.getAddress()); 1915 } else { 1916 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1917 } 1918 return editor.commit(); 1919 } 1920 1921 int getMessageAccessPermission(BluetoothDevice device) { 1922 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1923 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1924 Context.MODE_PRIVATE); 1925 if (!pref.contains(device.getAddress())) { 1926 return BluetoothDevice.ACCESS_UNKNOWN; 1927 } 1928 return pref.getBoolean(device.getAddress(), false) 1929 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1930 } 1931 1932 boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1933 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1934 "Need BLUETOOTH PRIVILEGED permission"); 1935 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1936 Context.MODE_PRIVATE); 1937 SharedPreferences.Editor editor = pref.edit(); 1938 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1939 editor.remove(device.getAddress()); 1940 } else { 1941 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1942 } 1943 return editor.commit(); 1944 } 1945 1946 int getSimAccessPermission(BluetoothDevice device) { 1947 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1948 SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, 1949 Context.MODE_PRIVATE); 1950 if (!pref.contains(device.getAddress())) { 1951 return BluetoothDevice.ACCESS_UNKNOWN; 1952 } 1953 return pref.getBoolean(device.getAddress(), false) 1954 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1955 } 1956 1957 boolean setSimAccessPermission(BluetoothDevice device, int value) { 1958 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1959 "Need BLUETOOTH PRIVILEGED permission"); 1960 SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, 1961 Context.MODE_PRIVATE); 1962 SharedPreferences.Editor editor = pref.edit(); 1963 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1964 editor.remove(device.getAddress()); 1965 } else { 1966 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1967 } 1968 return editor.commit(); 1969 } 1970 1971 void sendConnectionStateChange(BluetoothDevice 1972 device, int profile, int state, int prevState) { 1973 // TODO(BT) permission check? 1974 // Since this is a binder call check if Bluetooth is on still 1975 if (getState() == BluetoothAdapter.STATE_OFF) return; 1976 1977 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 1978 1979 } 1980 1981 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1982 ParcelUuid uuid, int port, int flag) { 1983 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1984 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 1985 type, Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid()); 1986 if (fd < 0) { 1987 errorLog("Failed to connect socket"); 1988 return null; 1989 } 1990 return ParcelFileDescriptor.adoptFd(fd); 1991 } 1992 1993 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1994 ParcelUuid uuid, int port, int flag) { 1995 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1996 int fd = createSocketChannelNative(type, serviceName, 1997 Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid()); 1998 if (fd < 0) { 1999 errorLog("Failed to create socket channel"); 2000 return null; 2001 } 2002 return ParcelFileDescriptor.adoptFd(fd); 2003 } 2004 2005 boolean configHciSnoopLog(boolean enable) { 2006 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2007 return configHciSnoopLogNative(enable); 2008 } 2009 2010 boolean factoryReset() { 2011 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2012 return factoryResetNative(); 2013 } 2014 2015 void registerCallback(IBluetoothCallback cb) { 2016 mCallbacks.register(cb); 2017 } 2018 2019 void unregisterCallback(IBluetoothCallback cb) { 2020 mCallbacks.unregister(cb); 2021 } 2022 2023 public int getNumOfAdvertisementInstancesSupported() { 2024 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2025 return mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 2026 } 2027 2028 public boolean isMultiAdvertisementSupported() { 2029 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2030 return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA; 2031 } 2032 2033 public boolean isRpaOffloadSupported() { 2034 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2035 return mAdapterProperties.isRpaOffloadSupported(); 2036 } 2037 2038 public int getNumOfOffloadedIrkSupported() { 2039 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2040 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 2041 } 2042 2043 public int getNumOfOffloadedScanFilterSupported() { 2044 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2045 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 2046 } 2047 2048 public boolean isPeripheralModeSupported() { 2049 return getResources().getBoolean(R.bool.config_bluetooth_le_peripheral_mode_supported); 2050 } 2051 2052 public int getOffloadedScanResultStorage() { 2053 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2054 return mAdapterProperties.getOffloadedScanResultStorage(); 2055 } 2056 2057 private boolean isActivityAndEnergyReportingSupported() { 2058 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2059 return mAdapterProperties.isActivityAndEnergyReportingSupported(); 2060 } 2061 2062 private void getActivityEnergyInfoFromController() { 2063 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2064 if (isActivityAndEnergyReportingSupported()) { 2065 readEnergyInfo(); 2066 } 2067 } 2068 2069 private BluetoothActivityEnergyInfo reportActivityInfo() { 2070 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2071 synchronized (mEnergyInfoLock) { 2072 final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo( 2073 SystemClock.elapsedRealtime(), 2074 mStackReportedState, 2075 mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs, 2076 mEnergyUsedTotalVoltAmpSecMicro); 2077 2078 // Count the number of entries that have byte counts > 0 2079 int arrayLen = 0; 2080 for (int i = 0; i < mUidTraffic.size(); i++) { 2081 final UidTraffic traffic = mUidTraffic.valueAt(i); 2082 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 2083 arrayLen++; 2084 } 2085 } 2086 2087 // Copy the traffic objects whose byte counts are > 0 and reset the originals. 2088 final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null; 2089 int putIdx = 0; 2090 for (int i = 0; i < mUidTraffic.size(); i++) { 2091 final UidTraffic traffic = mUidTraffic.valueAt(i); 2092 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 2093 result[putIdx++] = traffic.clone(); 2094 traffic.setRxBytes(0); 2095 traffic.setTxBytes(0); 2096 } 2097 } 2098 2099 info.setUidTraffic(result); 2100 2101 // Read on clear values; a record of data is created with 2102 // timstamp and new samples are collected until read again 2103 mStackReportedState = 0; 2104 mTxTimeTotalMs = 0; 2105 mRxTimeTotalMs = 0; 2106 mIdleTimeTotalMs = 0; 2107 mEnergyUsedTotalVoltAmpSecMicro = 0; 2108 return info; 2109 } 2110 } 2111 2112 public int getTotalNumOfTrackableAdvertisements() { 2113 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2114 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 2115 } 2116 2117 public void onLeServiceUp() { 2118 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 2119 mAdapterStateMachine.sendMessage(m); 2120 } 2121 2122 public void onBrEdrDown() { 2123 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 2124 mAdapterStateMachine.sendMessage(m); 2125 } 2126 2127 private static int convertScanModeToHal(int mode) { 2128 switch (mode) { 2129 case BluetoothAdapter.SCAN_MODE_NONE: 2130 return AbstractionLayer.BT_SCAN_MODE_NONE; 2131 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 2132 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 2133 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 2134 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2135 } 2136 // errorLog("Incorrect scan mode in convertScanModeToHal"); 2137 return -1; 2138 } 2139 2140 static int convertScanModeFromHal(int mode) { 2141 switch (mode) { 2142 case AbstractionLayer.BT_SCAN_MODE_NONE: 2143 return BluetoothAdapter.SCAN_MODE_NONE; 2144 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 2145 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 2146 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 2147 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2148 } 2149 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 2150 return -1; 2151 } 2152 2153 // This function is called from JNI. It allows native code to set a single wake 2154 // alarm. If an alarm is already pending and a new request comes in, the alarm 2155 // will be rescheduled (i.e. the previously set alarm will be cancelled). 2156 private boolean setWakeAlarm(long delayMillis, boolean shouldWake) { 2157 synchronized (this) { 2158 if (mPendingAlarm != null) { 2159 mAlarmManager.cancel(mPendingAlarm); 2160 } 2161 2162 long wakeupTime = SystemClock.elapsedRealtime() + delayMillis; 2163 int type = shouldWake 2164 ? AlarmManager.ELAPSED_REALTIME_WAKEUP 2165 : AlarmManager.ELAPSED_REALTIME; 2166 2167 Intent intent = new Intent(ACTION_ALARM_WAKEUP); 2168 mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); 2169 mAlarmManager.setExact(type, wakeupTime, mPendingAlarm); 2170 return true; 2171 } 2172 } 2173 2174 // This function is called from JNI. It allows native code to acquire a single wake lock. 2175 // If the wake lock is already held, this function returns success. Although this function 2176 // only supports acquiring a single wake lock at a time right now, it will eventually be 2177 // extended to allow acquiring an arbitrary number of wake locks. The current interface 2178 // takes |lockName| as a parameter in anticipation of that implementation. 2179 private boolean acquireWakeLock(String lockName) { 2180 if (mWakeLock != null) { 2181 if (!lockName.equals(mWakeLockName)) { 2182 errorLog("Multiple wake lock acquisition attempted; aborting: " + lockName); 2183 return false; 2184 } 2185 2186 // We're already holding the desired wake lock so return success. 2187 if (mWakeLock.isHeld()) { 2188 return true; 2189 } 2190 } 2191 2192 mWakeLockName = lockName; 2193 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 2194 mWakeLock.acquire(); 2195 return true; 2196 } 2197 2198 // This function is called from JNI. It allows native code to release a wake lock acquired 2199 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 2200 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 2201 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. 2202 private boolean releaseWakeLock(String lockName) { 2203 synchronized (this) { 2204 if (mWakeLock == null) { 2205 errorLog("Repeated wake lock release; aborting release: " + lockName); 2206 return false; 2207 } 2208 2209 mWakeLock.release(); 2210 mWakeLock = null; 2211 mWakeLockName = null; 2212 } 2213 return true; 2214 } 2215 2216 private void energyInfoCallback(int status, int ctrl_state, long tx_time, long rx_time, 2217 long idle_time, long energy_used, UidTraffic[] data) 2218 throws RemoteException { 2219 if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID && 2220 ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 2221 // Energy is product of mA, V and ms. If the chipset doesn't 2222 // report it, we have to compute it from time 2223 if (energy_used == 0) { 2224 energy_used = (long)((tx_time * getTxCurrentMa() 2225 + rx_time * getRxCurrentMa() 2226 + idle_time * getIdleCurrentMa()) * getOperatingVolt()); 2227 } 2228 2229 synchronized (mEnergyInfoLock) { 2230 mStackReportedState = ctrl_state; 2231 mTxTimeTotalMs += tx_time; 2232 mRxTimeTotalMs += rx_time; 2233 mIdleTimeTotalMs += idle_time; 2234 mEnergyUsedTotalVoltAmpSecMicro += energy_used; 2235 2236 for (UidTraffic traffic : data) { 2237 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid()); 2238 if (existingTraffic == null) { 2239 mUidTraffic.put(traffic.getUid(), traffic); 2240 } else { 2241 existingTraffic.addRxBytes(traffic.getRxBytes()); 2242 existingTraffic.addTxBytes(traffic.getTxBytes()); 2243 } 2244 } 2245 } 2246 } 2247 2248 debugLog("energyInfoCallback() status = " + status + 2249 "tx_time = " + tx_time + "rx_time = " + rx_time + 2250 "idle_time = " + idle_time + "energy_used = " + energy_used + 2251 "ctrl_state = " + ctrl_state + 2252 "traffic = " + Arrays.toString(data)); 2253 } 2254 2255 private int getIdleCurrentMa() { 2256 return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma); 2257 } 2258 2259 private int getTxCurrentMa() { 2260 return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma); 2261 } 2262 2263 private int getRxCurrentMa() { 2264 return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma); 2265 } 2266 2267 private double getOperatingVolt() { 2268 return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0; 2269 } 2270 2271 @Override 2272 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 2273 enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 2274 2275 if (args.length > 0) { 2276 debugLog("dumpsys arguments, check for protobuf output: " + 2277 TextUtils.join(" ", args)); 2278 if (args[0].startsWith("--proto")) { 2279 if (args[0].equals("--proto-java-bin")) { 2280 dumpJava(fd); 2281 } else { 2282 dumpNative(fd, args); 2283 } 2284 return; 2285 } 2286 } 2287 2288 writer.println("Bluetooth Status"); 2289 writer.println(" enabled: " + isEnabled()); 2290 writer.println(" state: " + getState()); 2291 writer.println(" address: " + getAddress()); 2292 writer.println(" name: " + getName() + "\n"); 2293 2294 writer.println("Bonded devices:"); 2295 for (BluetoothDevice device : getBondedDevices()) { 2296 writer.println(" " + device.getAddress() + 2297 " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " + 2298 device.getName()); 2299 } 2300 2301 // Dump profile information 2302 StringBuilder sb = new StringBuilder(); 2303 synchronized (mProfiles) { 2304 for (ProfileService profile : mProfiles) { 2305 profile.dump(sb); 2306 } 2307 } 2308 2309 writer.write(sb.toString()); 2310 writer.flush(); 2311 2312 dumpNative(fd, args); 2313 } 2314 2315 private void dumpJava(FileDescriptor fd) { 2316 BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog(); 2317 2318 for (ProfileService profile : mProfiles) { 2319 profile.dumpProto(log); 2320 } 2321 2322 try { 2323 FileOutputStream protoOut = new FileOutputStream(fd); 2324 String protoOutString = 2325 Base64.encodeToString(log.toByteArray(), Base64.DEFAULT); 2326 protoOut.write(protoOutString.getBytes(StandardCharsets.UTF_8)); 2327 protoOut.close(); 2328 } catch (IOException e) { 2329 errorLog("Unable to write Java protobuf to file descriptor."); 2330 } 2331 } 2332 2333 private void debugLog(String msg) { 2334 if (DBG) Log.d(TAG, msg); 2335 } 2336 2337 private void errorLog(String msg) { 2338 Log.e(TAG, msg); 2339 } 2340 2341 private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() { 2342 @Override 2343 public void onReceive(Context context, Intent intent) { 2344 synchronized (AdapterService.this) { 2345 mPendingAlarm = null; 2346 alarmFiredNative(); 2347 } 2348 } 2349 }; 2350 2351 private native static void classInitNative(); 2352 private native boolean initNative(); 2353 private native void cleanupNative(); 2354 /*package*/ native boolean enableNative(); 2355 /*package*/ native boolean disableNative(); 2356 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 2357 /*package*/ native boolean getAdapterPropertiesNative(); 2358 /*package*/ native boolean getAdapterPropertyNative(int type); 2359 /*package*/ native boolean setAdapterPropertyNative(int type); 2360 /*package*/ native boolean 2361 setDevicePropertyNative(byte[] address, int type, byte[] val); 2362 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 2363 2364 /*package*/ native boolean createBondNative(byte[] address, int transport); 2365 /*package*/ native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData); 2366 /*package*/ native boolean removeBondNative(byte[] address); 2367 /*package*/ native boolean cancelBondNative(byte[] address); 2368 /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid); 2369 2370 /*package*/ native int getConnectionStateNative(byte[] address); 2371 2372 private native boolean startDiscoveryNative(); 2373 private native boolean cancelDiscoveryNative(); 2374 2375 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 2376 private native boolean sspReplyNative(byte[] address, int type, boolean 2377 accept, int passkey); 2378 2379 /*package*/ native boolean getRemoteServicesNative(byte[] address); 2380 /*package*/ native boolean getRemoteMasInstancesNative(byte[] address); 2381 2382 private native int readEnergyInfo(); 2383 // TODO(BT) move this to ../btsock dir 2384 private native int connectSocketNative(byte[] address, int type, 2385 byte[] uuid, int port, int flag, int callingUid); 2386 private native int createSocketChannelNative(int type, String serviceName, 2387 byte[] uuid, int port, int flag, int callingUid); 2388 2389 /*package*/ native boolean configHciSnoopLogNative(boolean enable); 2390 /*package*/ native boolean factoryResetNative(); 2391 2392 private native void alarmFiredNative(); 2393 private native void dumpNative(FileDescriptor fd, String[] arguments); 2394 2395 private native void interopDatabaseClearNative(); 2396 private native void interopDatabaseAddNative(int feature, byte[] address, int length); 2397 2398 protected void finalize() { 2399 cleanup(); 2400 if (TRACE_REF) { 2401 synchronized (AdapterService.class) { 2402 sRefCount--; 2403 debugLog("finalize() - REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 2404 } 2405 } 2406 } 2407} 2408