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