• 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.Application;
24 import android.app.Service;
25 import android.bluetooth.BluetoothAdapter;
26 import android.bluetooth.BluetoothDevice;
27 import android.bluetooth.BluetoothProfile;
28 import android.bluetooth.IBluetooth;
29 import android.bluetooth.IBluetoothCallback;
30 import android.bluetooth.IBluetoothManager;
31 import android.bluetooth.IBluetoothManagerCallback;
32 import android.content.BroadcastReceiver;
33 import android.content.ContentResolver;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.os.Binder;
38 import android.os.Bundle;
39 import android.os.Handler;
40 import android.os.IBinder;
41 import android.os.Message;
42 import android.os.ParcelFileDescriptor;
43 import android.os.ParcelUuid;
44 import android.os.Process;
45 import android.os.RemoteCallbackList;
46 import android.os.RemoteException;
47 import android.provider.Settings;
48 import android.util.Log;
49 import android.util.Pair;
50 import com.android.bluetooth.a2dp.A2dpService;
51 import com.android.bluetooth.hid.HidService;
52 import com.android.bluetooth.hfp.HeadsetService;
53 import com.android.bluetooth.hdp.HealthService;
54 import com.android.bluetooth.pan.PanService;
55 import com.android.bluetooth.R;
56 import com.android.bluetooth.Utils;
57 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
58 import java.io.FileDescriptor;
59 import java.io.IOException;
60 import java.util.ArrayList;
61 import java.util.HashMap;
62 import java.util.Set;
63 import java.util.Map;
64 import java.util.Iterator;
65 import java.util.Map.Entry;
66 import java.util.List;
67 import android.content.pm.PackageManager;
68 import android.os.ServiceManager;
69 
70 public class AdapterService extends Service {
71     private static final String TAG = "BluetoothAdapterService";
72     private static final boolean DBG = false;
73     private static final boolean TRACE_REF = true;
74     //For Debugging only
75     private static int sRefCount=0;
76 
77     public static final String ACTION_LOAD_ADAPTER_PROPERTIES="com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES";
78     public static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
79     public static final String EXTRA_ACTION="action";
80     public static final int PROFILE_CONN_CONNECTED  = 1;
81     public static final int PROFILE_CONN_REJECTED  = 2;
82 
83     static final String BLUETOOTH_ADMIN_PERM =
84         android.Manifest.permission.BLUETOOTH_ADMIN;
85     static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
86 
87     private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY;
88 
89     static {
classInitNative()90         classInitNative();
91     }
92 
93     private static AdapterService sAdapterService;
getAdapterService()94     public static synchronized AdapterService getAdapterService(){
95         if (sAdapterService != null && !sAdapterService.mCleaningUp) {
96             if (DBG) Log.d(TAG, "getAdapterService(): returning " + sAdapterService);
97             return sAdapterService;
98         }
99         if (DBG)  {
100             if (sAdapterService == null) {
101                 Log.d(TAG, "getAdapterService(): service not available");
102             } else if (sAdapterService.mCleaningUp) {
103                 Log.d(TAG,"getAdapterService(): service is cleaning up");
104             }
105         }
106         return null;
107     }
108 
setAdapterService(AdapterService instance)109     private static synchronized void setAdapterService(AdapterService instance) {
110         if (instance != null && !instance.mCleaningUp) {
111             if (DBG) Log.d(TAG, "setAdapterService(): set to: " + sAdapterService);
112             sAdapterService = instance;
113         } else {
114             if (DBG)  {
115                 if (sAdapterService == null) {
116                     Log.d(TAG, "setAdapterService(): service not available");
117                 } else if (sAdapterService.mCleaningUp) {
118                     Log.d(TAG,"setAdapterService(): service is cleaning up");
119                 }
120             }
121         }
122     }
123 
clearAdapterService()124     private static synchronized void clearAdapterService() {
125         sAdapterService = null;
126     }
127 
128     private AdapterProperties mAdapterProperties;
129     private AdapterState mAdapterStateMachine;
130     private BondStateMachine mBondStateMachine;
131     private JniCallbacks mJniCallbacks;
132     private RemoteDevices mRemoteDevices;
133     private boolean mProfilesStarted;
134     private boolean mNativeAvailable;
135     private boolean mCleaningUp;
136     private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>();
137     private RemoteCallbackList<IBluetoothCallback> mCallbacks;//Only BluetoothManagerService should be registered
138     private int mCurrentRequestId;
139     private boolean mQuietmode = false;
140 
AdapterService()141     public AdapterService() {
142         super();
143         if (TRACE_REF) {
144             synchronized (AdapterService.class) {
145                 sRefCount++;
146                 Log.d(TAG, "REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount);
147             }
148         }
149     }
150 
onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState)151     public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
152         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED);
153         m.obj = device;
154         m.arg1 = profileId;
155         m.arg2 = newState;
156         Bundle b = new Bundle(1);
157         b.putInt("prevState", prevState);
158         m.setData(b);
159         mHandler.sendMessage(m);
160     }
161 
processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState)162     private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
163         if (((profileId == BluetoothProfile.A2DP) ||(profileId == BluetoothProfile.HEADSET)) &&
164             (newState == BluetoothProfile.STATE_CONNECTED)){
165             if (DBG) debugLog( "Profile connected. Schedule missing profile connection if any");
166             connectOtherProfile(device, PROFILE_CONN_CONNECTED);
167             setProfileAutoConnectionPriority(device, profileId);
168         }
169         IBluetooth.Stub binder = mBinder;
170         if (binder != null) {
171             try {
172                 binder.sendConnectionStateChange(device, profileId, newState,prevState);
173             } catch (RemoteException re) {
174                 Log.e(TAG, "",re);
175             }
176         }
177     }
178 
onProfileServiceStateChanged(String serviceName, int state)179     public void onProfileServiceStateChanged(String serviceName, int state) {
180         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
181         m.obj=serviceName;
182         m.arg1 = state;
183         mHandler.sendMessage(m);
184     }
185 
processProfileServiceStateChanged(String serviceName, int state)186     private void processProfileServiceStateChanged(String serviceName, int state) {
187         boolean doUpdate=false;
188         boolean isTurningOn;
189         boolean isTurningOff;
190 
191         synchronized (mProfileServicesState) {
192             Integer prevState = mProfileServicesState.get(serviceName);
193             if (prevState != null && prevState != state) {
194                 mProfileServicesState.put(serviceName,state);
195                 doUpdate=true;
196             }
197         }
198         if (DBG) Log.d(TAG,"onProfileServiceStateChange: serviceName=" + serviceName + ", state = " + state +", doUpdate = " + doUpdate);
199 
200         if (!doUpdate) {
201             return;
202         }
203 
204         synchronized (mAdapterStateMachine) {
205             isTurningOff = mAdapterStateMachine.isTurningOff();
206             isTurningOn = mAdapterStateMachine.isTurningOn();
207         }
208 
209         if (isTurningOff) {
210             //Process stop or disable pending
211             //Check if all services are stopped if so, do cleanup
212             //if (DBG) Log.d(TAG,"Checking if all profiles are stopped...");
213             synchronized (mProfileServicesState) {
214                 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
215                 while (i.hasNext()) {
216                     Map.Entry<String,Integer> entry = i.next();
217                     if (BluetoothAdapter.STATE_OFF != entry.getValue()) {
218                         Log.d(TAG, "Profile still running: " + entry.getKey());
219                         return;
220                     }
221                 }
222             }
223             if (DBG) Log.d(TAG, "All profile services stopped...");
224             //Send message to state machine
225             mProfilesStarted=false;
226             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STOPPED));
227         } else if (isTurningOn) {
228             //Process start pending
229             //Check if all services are started if so, update state
230             //if (DBG) Log.d(TAG,"Checking if all profiles are running...");
231             synchronized (mProfileServicesState) {
232                 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
233                 while (i.hasNext()) {
234                     Map.Entry<String,Integer> entry = i.next();
235                     if (BluetoothAdapter.STATE_ON != entry.getValue()) {
236                         Log.d(TAG, "Profile still not running:" + entry.getKey());
237                         return;
238                     }
239                 }
240             }
241             if (DBG) Log.d(TAG, "All profile services started.");
242             mProfilesStarted=true;
243             //Send message to state machine
244             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
245         }
246     }
247 
248     @Override
onCreate()249     public void onCreate() {
250         super.onCreate();
251         if (DBG) debugLog("onCreate");
252         mBinder = new AdapterServiceBinder(this);
253         mAdapterProperties = new AdapterProperties(this);
254         mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);
255         mJniCallbacks =  new JniCallbacks(mAdapterStateMachine, mAdapterProperties);
256         initNative();
257         mNativeAvailable=true;
258         mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
259         //Load the name and address
260         getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
261         getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
262 
263     }
264 
265     @Override
onBind(Intent intent)266     public IBinder onBind(Intent intent) {
267         if (DBG) debugLog("onBind");
268         return mBinder;
269     }
onUnbind(Intent intent)270     public boolean onUnbind(Intent intent) {
271         if (DBG) debugLog("onUnbind, calling cleanup");
272         cleanup();
273         return super.onUnbind(intent);
274     }
275 
onDestroy()276     public void onDestroy() {
277         debugLog("****onDestroy()********");
278     }
279 
processStart()280     void processStart() {
281         if (DBG) debugLog("processStart()");
282         Class[] supportedProfileServices = Config.getSupportedProfiles();
283         //Initialize data objects
284         for (int i=0; i < supportedProfileServices.length;i++) {
285             mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
286         }
287         mRemoteDevices = new RemoteDevices(this);
288         mAdapterProperties.init(mRemoteDevices);
289 
290         if (DBG) {debugLog("processStart(): Make Bond State Machine");}
291         mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
292 
293         mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
294 
295         //FIXME: Set static instance here???
296         setAdapterService(this);
297 
298         //Start profile services
299         if (!mProfilesStarted && supportedProfileServices.length >0) {
300             //Startup all profile services
301             setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
302         }else {
303             if (DBG) {debugLog("processStart(): Profile Services alreay started");}
304             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
305         }
306     }
307 
startBluetoothDisable()308     void startBluetoothDisable() {
309         mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE));
310     }
311 
stopProfileServices()312     boolean stopProfileServices() {
313         Class[] supportedProfileServices = Config.getSupportedProfiles();
314         if (mProfilesStarted && supportedProfileServices.length>0) {
315             setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
316             return true;
317         } else {
318             if (DBG) {debugLog("stopProfileServices(): No profiles services to stop or already stopped.");}
319             return false;
320         }
321     }
322 
updateAdapterState(int prevState, int newState)323      void updateAdapterState(int prevState, int newState){
324         if (mCallbacks !=null) {
325             int n=mCallbacks.beginBroadcast();
326             Log.d(TAG,"Broadcasting updateAdapterState() to " + n + " receivers.");
327             for (int i=0; i <n;i++) {
328                 try {
329                     mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);
330                 }  catch (RemoteException e) {
331                     Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
332                 }
333             }
334             mCallbacks.finishBroadcast();
335         }
336     }
337 
cleanup()338     void cleanup () {
339         if (DBG)debugLog("cleanup()");
340         if (mCleaningUp) {
341             Log.w(TAG,"*************service already starting to cleanup... Ignoring cleanup request.........");
342             return;
343         }
344 
345         mCleaningUp = true;
346 
347         if (mAdapterStateMachine != null) {
348             mAdapterStateMachine.doQuit();
349             mAdapterStateMachine.cleanup();
350         }
351 
352         if (mBondStateMachine != null) {
353             mBondStateMachine.doQuit();
354             mBondStateMachine.cleanup();
355         }
356 
357         if (mRemoteDevices != null) {
358             mRemoteDevices.cleanup();
359         }
360 
361         if (mNativeAvailable) {
362             Log.d(TAG, "Cleaning up adapter native....");
363             cleanupNative();
364             Log.d(TAG, "Done cleaning up adapter native....");
365             mNativeAvailable=false;
366         }
367 
368         if (mAdapterProperties != null) {
369             mAdapterProperties.cleanup();
370         }
371 
372         if (mJniCallbacks != null) {
373             mJniCallbacks.cleanup();
374         }
375 
376         if (mProfileServicesState != null) {
377             mProfileServicesState.clear();
378         }
379 
380         clearAdapterService();
381 
382         if (mBinder != null) {
383             mBinder.cleanup();
384             mBinder = null;  //Do not remove. Otherwise Binder leak!
385         }
386 
387         if (mCallbacks !=null) {
388             mCallbacks.kill();
389         }
390 
391         if (DBG)debugLog("cleanup() done");
392     }
393 
394     private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1;
395     private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20;
396     private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30;
397     private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000;
398 
399     private final Handler mHandler = new Handler() {
400         @Override
401         public void handleMessage(Message msg) {
402             if (DBG) debugLog("Message: " + msg.what);
403 
404             switch (msg.what) {
405                 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: {
406                     if(DBG) debugLog("MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
407                     processProfileServiceStateChanged((String) msg.obj, msg.arg1);
408                 }
409                     break;
410                 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: {
411                     if (DBG) debugLog( "MESSAGE_PROFILE_CONNECTION_STATE_CHANGED");
412                     processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR));
413                 }
414                     break;
415                 case MESSAGE_CONNECT_OTHER_PROFILES: {
416                     if (DBG) debugLog( "MESSAGE_CONNECT_OTHER_PROFILES");
417                     processConnectOtherProfiles((BluetoothDevice) msg.obj,msg.arg1);
418                 }
419                     break;
420             }
421         }
422     };
423 
424     @SuppressWarnings("rawtypes")
setProfileServiceState(Class[] services, int state)425     private void setProfileServiceState(Class[] services, int state) {
426         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
427             Log.w(TAG,"setProfileServiceState(): invalid state...Leaving...");
428             return;
429         }
430 
431         int expectedCurrentState= BluetoothAdapter.STATE_OFF;
432         int pendingState = BluetoothAdapter.STATE_TURNING_ON;
433         if (state == BluetoothAdapter.STATE_OFF) {
434             expectedCurrentState= BluetoothAdapter.STATE_ON;
435             pendingState = BluetoothAdapter.STATE_TURNING_OFF;
436         }
437 
438         for (int i=0; i <services.length;i++) {
439             String serviceName = services[i].getName();
440             Integer serviceState = mProfileServicesState.get(serviceName);
441             if(serviceState != null && serviceState != expectedCurrentState) {
442                 Log.w(TAG, "Unable to " + (state == BluetoothAdapter.STATE_OFF? "start" : "stop" ) +" service " +
443                         serviceName+". Invalid state: " + serviceState);
444                 continue;
445             }
446 
447             if (DBG) {
448                 Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " +
449                         serviceName);
450             }
451 
452             mProfileServicesState.put(serviceName,pendingState);
453             Intent intent = new Intent(this,services[i]);
454             intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
455             intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
456             startService(intent);
457         }
458     }
459 
isAvailable()460     private boolean isAvailable() {
461         return !mCleaningUp;
462     }
463 
464     /**
465      * Handlers for incoming service calls
466      */
467     private AdapterServiceBinder mBinder;
468 
469     /**
470      * The Binder implementation must be declared to be a static class, with
471      * the AdapterService instance passed in the constructor. Furthermore,
472      * when the AdapterService shuts down, the reference to the AdapterService
473      * must be explicitly removed.
474      *
475      * Otherwise, a memory leak can occur from repeated starting/stopping the
476      * service...Please refer to android.os.Binder for further details on
477      * why an inner instance class should be avoided.
478      *
479      */
480     private static class AdapterServiceBinder extends IBluetooth.Stub {
481         private AdapterService mService;
482 
AdapterServiceBinder(AdapterService svc)483         public AdapterServiceBinder(AdapterService svc) {
484             mService = svc;
485         }
cleanup()486         public boolean cleanup() {
487             mService = null;
488             return true;
489         }
490 
getService()491         public AdapterService getService() {
492             if (mService  != null && mService.isAvailable()) {
493                 return mService;
494             }
495             return null;
496         }
isEnabled()497         public boolean isEnabled() {
498             // don't check caller, may be called from system UI
499             AdapterService service = getService();
500             if (service == null) return false;
501             return service.isEnabled();
502         }
503 
getState()504         public int getState() {
505             // don't check caller, may be called from system UI
506             AdapterService service = getService();
507             if (service == null) return  BluetoothAdapter.STATE_OFF;
508             return service.getState();
509         }
510 
enable()511         public boolean enable() {
512             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
513                 (!Utils.checkCaller())) {
514                 Log.w(TAG,"enable(): not allowed for non-active user and non system user");
515                 return false;
516 	    }
517 
518             AdapterService service = getService();
519             if (service == null) return false;
520             return service.enable();
521         }
522 
enableNoAutoConnect()523         public boolean enableNoAutoConnect() {
524             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
525                 (!Utils.checkCaller())) {
526                 Log.w(TAG,"enableNoAuto(): not allowed for non-active user and non system user");
527                 return false;
528 	    }
529 
530             AdapterService service = getService();
531             if (service == null) return false;
532             return service.enableNoAutoConnect();
533         }
534 
disable()535         public boolean disable() {
536             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
537                 (!Utils.checkCaller())) {
538                 Log.w(TAG,"disable(): not allowed for non-active user and non system user");
539                 return false;
540 	    }
541 
542             AdapterService service = getService();
543             if (service == null) return false;
544             return service.disable();
545         }
546 
getAddress()547         public String getAddress() {
548             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
549                 (!Utils.checkCaller())) {
550                 Log.w(TAG,"getAddress(): not allowed for non-active user and non system user");
551                 return null;
552 	    }
553 
554             AdapterService service = getService();
555             if (service == null) return null;
556             return service.getAddress();
557         }
558 
getUuids()559         public ParcelUuid[] getUuids() {
560             if (!Utils.checkCaller()) {
561                 Log.w(TAG,"getUuids(): not allowed for non-active user");
562                 return new ParcelUuid[0];
563             }
564 
565             AdapterService service = getService();
566             if (service == null) return new ParcelUuid[0];
567             return service.getUuids();
568         }
569 
getName()570         public String getName() {
571             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
572                 (!Utils.checkCaller())) {
573                 Log.w(TAG,"getName(): not allowed for non-active user and non system user");
574                 return null;
575 	    }
576 
577             AdapterService service = getService();
578             if (service == null) return null;
579             return service.getName();
580         }
581 
setName(String name)582         public boolean setName(String name) {
583             if (!Utils.checkCaller()) {
584                 Log.w(TAG,"setName(): not allowed for non-active user");
585                 return false;
586             }
587 
588             AdapterService service = getService();
589             if (service == null) return false;
590             return service.setName(name);
591         }
592 
getScanMode()593         public int getScanMode() {
594             if (!Utils.checkCaller()) {
595                 Log.w(TAG,"getScanMode(): not allowed for non-active user");
596                 return BluetoothAdapter.SCAN_MODE_NONE;
597             }
598 
599             AdapterService service = getService();
600             if (service == null) return BluetoothAdapter.SCAN_MODE_NONE;
601             return service.getScanMode();
602         }
603 
setScanMode(int mode, int duration)604         public boolean setScanMode(int mode, int duration) {
605             if (!Utils.checkCaller()) {
606                 Log.w(TAG,"setScanMode(): not allowed for non-active user");
607                 return false;
608             }
609 
610             AdapterService service = getService();
611             if (service == null) return false;
612             return service.setScanMode(mode,duration);
613         }
614 
getDiscoverableTimeout()615         public int getDiscoverableTimeout() {
616             if (!Utils.checkCaller()) {
617                 Log.w(TAG,"getDiscoverableTimeout(): not allowed for non-active user");
618                 return 0;
619             }
620 
621             AdapterService service = getService();
622             if (service == null) return 0;
623             return service.getDiscoverableTimeout();
624         }
625 
setDiscoverableTimeout(int timeout)626         public boolean setDiscoverableTimeout(int timeout) {
627             if (!Utils.checkCaller()) {
628                 Log.w(TAG,"setDiscoverableTimeout(): not allowed for non-active user");
629                 return false;
630             }
631 
632             AdapterService service = getService();
633             if (service == null) return false;
634             return service.setDiscoverableTimeout(timeout);
635         }
636 
startDiscovery()637         public boolean startDiscovery() {
638             if (!Utils.checkCaller()) {
639                 Log.w(TAG,"startDiscovery(): not allowed for non-active user");
640                 return false;
641             }
642 
643             AdapterService service = getService();
644             if (service == null) return false;
645             return service.startDiscovery();
646         }
647 
cancelDiscovery()648         public boolean cancelDiscovery() {
649             if (!Utils.checkCaller()) {
650                 Log.w(TAG,"cancelDiscovery(): not allowed for non-active user");
651                 return false;
652             }
653 
654             AdapterService service = getService();
655             if (service == null) return false;
656             return service.cancelDiscovery();
657         }
isDiscovering()658         public boolean isDiscovering() {
659             if (!Utils.checkCaller()) {
660                 Log.w(TAG,"isDiscovering(): not allowed for non-active user");
661                 return false;
662             }
663 
664             AdapterService service = getService();
665             if (service == null) return false;
666             return service.isDiscovering();
667         }
668 
getBondedDevices()669         public BluetoothDevice[] getBondedDevices() {
670             // don't check caller, may be called from system UI
671             AdapterService service = getService();
672             if (service == null) return new BluetoothDevice[0];
673             return service.getBondedDevices();
674         }
675 
getAdapterConnectionState()676         public int getAdapterConnectionState() {
677             // don't check caller, may be called from system UI
678             AdapterService service = getService();
679             if (service == null) return BluetoothAdapter.STATE_DISCONNECTED;
680             return service.getAdapterConnectionState();
681         }
682 
getProfileConnectionState(int profile)683         public int getProfileConnectionState(int profile) {
684             if (!Utils.checkCaller()) {
685                 Log.w(TAG,"getProfileConnectionState: not allowed for non-active user");
686                 return BluetoothProfile.STATE_DISCONNECTED;
687             }
688 
689             AdapterService service = getService();
690             if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
691             return service.getProfileConnectionState(profile);
692         }
693 
createBond(BluetoothDevice device)694         public boolean createBond(BluetoothDevice device) {
695             if (!Utils.checkCaller()) {
696                 Log.w(TAG,"createBond(): not allowed for non-active user");
697                 return false;
698             }
699 
700             AdapterService service = getService();
701             if (service == null) return false;
702             return service.createBond(device);
703         }
704 
cancelBondProcess(BluetoothDevice device)705         public boolean cancelBondProcess(BluetoothDevice device) {
706             if (!Utils.checkCaller()) {
707                 Log.w(TAG,"cancelBondProcess(): not allowed for non-active user");
708                 return false;
709             }
710 
711             AdapterService service = getService();
712             if (service == null) return false;
713             return service.cancelBondProcess(device);
714         }
715 
removeBond(BluetoothDevice device)716         public boolean removeBond(BluetoothDevice device) {
717             if (!Utils.checkCaller()) {
718                 Log.w(TAG,"removeBond(): not allowed for non-active user");
719                 return false;
720             }
721 
722             AdapterService service = getService();
723             if (service == null) return false;
724             return service.removeBond(device);
725         }
726 
getBondState(BluetoothDevice device)727         public int getBondState(BluetoothDevice device) {
728             // don't check caller, may be called from system UI
729             AdapterService service = getService();
730             if (service == null) return BluetoothDevice.BOND_NONE;
731             return service.getBondState(device);
732         }
733 
getRemoteName(BluetoothDevice device)734         public String getRemoteName(BluetoothDevice device) {
735             if (!Utils.checkCaller()) {
736                 Log.w(TAG,"getRemoteName(): not allowed for non-active user");
737                 return null;
738             }
739 
740             AdapterService service = getService();
741             if (service == null) return null;
742             return service.getRemoteName(device);
743         }
744 
getRemoteAlias(BluetoothDevice device)745         public String getRemoteAlias(BluetoothDevice device) {
746             if (!Utils.checkCaller()) {
747                 Log.w(TAG,"getRemoteAlias(): not allowed for non-active user");
748                 return null;
749             }
750 
751             AdapterService service = getService();
752             if (service == null) return null;
753             return service.getRemoteAlias(device);
754         }
755 
setRemoteAlias(BluetoothDevice device, String name)756         public boolean setRemoteAlias(BluetoothDevice device, String name) {
757             if (!Utils.checkCaller()) {
758                 Log.w(TAG,"setRemoteAlias(): not allowed for non-active user");
759                 return false;
760             }
761 
762             AdapterService service = getService();
763             if (service == null) return false;
764             return service.setRemoteAlias(device, name);
765         }
766 
getRemoteClass(BluetoothDevice device)767         public int getRemoteClass(BluetoothDevice device) {
768             if (!Utils.checkCaller()) {
769                 Log.w(TAG,"getRemoteClass(): not allowed for non-active user");
770                 return 0;
771             }
772 
773             AdapterService service = getService();
774             if (service == null) return 0;
775             return service.getRemoteClass(device);
776         }
777 
getRemoteUuids(BluetoothDevice device)778         public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
779             if (!Utils.checkCaller()) {
780                 Log.w(TAG,"getRemoteUuids(): not allowed for non-active user");
781                 return new ParcelUuid[0];
782             }
783 
784             AdapterService service = getService();
785             if (service == null) return new ParcelUuid[0];
786             return service.getRemoteUuids(device);
787         }
788 
fetchRemoteUuids(BluetoothDevice device)789         public boolean fetchRemoteUuids(BluetoothDevice device) {
790             if (!Utils.checkCaller()) {
791                 Log.w(TAG,"fetchRemoteUuids(): not allowed for non-active user");
792                 return false;
793             }
794 
795             AdapterService service = getService();
796             if (service == null) return false;
797             return service.fetchRemoteUuids(device);
798         }
799 
setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode)800         public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
801             if (!Utils.checkCaller()) {
802                 Log.w(TAG,"setPin(): not allowed for non-active user");
803                 return false;
804             }
805 
806             AdapterService service = getService();
807             if (service == null) return false;
808             return service.setPin(device, accept, len, pinCode);
809         }
810 
setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey)811         public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
812             if (!Utils.checkCaller()) {
813                 Log.w(TAG,"setPasskey(): not allowed for non-active user");
814                 return false;
815             }
816 
817             AdapterService service = getService();
818             if (service == null) return false;
819             return service.setPasskey(device, accept, len, passkey);
820         }
821 
setPairingConfirmation(BluetoothDevice device, boolean accept)822         public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
823             if (!Utils.checkCaller()) {
824                 Log.w(TAG,"setPairingConfirmation(): not allowed for non-active user");
825                 return false;
826             }
827 
828             AdapterService service = getService();
829             if (service == null) return false;
830             return service.setPairingConfirmation(device, accept);
831         }
832 
sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)833         public void sendConnectionStateChange(BluetoothDevice
834                 device, int profile, int state, int prevState) {
835             AdapterService service = getService();
836             if (service == null) return;
837             service.sendConnectionStateChange(device, profile, state, prevState);
838         }
839 
connectSocket(BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag)840         public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
841                                                   ParcelUuid uuid, int port, int flag) {
842             if (!Utils.checkCaller()) {
843                 Log.w(TAG,"connectSocket(): not allowed for non-active user");
844                 return null;
845             }
846 
847             AdapterService service = getService();
848             if (service == null) return null;
849             return service.connectSocket(device, type, uuid, port, flag);
850         }
851 
createSocketChannel(int type, String serviceName, ParcelUuid uuid, int port, int flag)852         public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
853                                                         ParcelUuid uuid, int port, int flag) {
854             if (!Utils.checkCaller()) {
855                 Log.w(TAG,"createSocketChannel(): not allowed for non-active user");
856                 return null;
857             }
858 
859             AdapterService service = getService();
860             if (service == null) return null;
861             return service.createSocketChannel(type, serviceName, uuid, port, flag);
862         }
863 
registerCallback(IBluetoothCallback cb)864         public void registerCallback(IBluetoothCallback cb) {
865             AdapterService service = getService();
866             if (service == null) return ;
867             service.registerCallback(cb);
868          }
869 
unregisterCallback(IBluetoothCallback cb)870          public void unregisterCallback(IBluetoothCallback cb) {
871              AdapterService service = getService();
872              if (service == null) return ;
873              service.unregisterCallback(cb);
874          }
875     };
876 
877 
878     //----API Methods--------
isEnabled()879      boolean isEnabled() {
880         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
881 
882         return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
883     }
884 
getState()885      int getState() {
886         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
887 
888         if (mAdapterProperties == null){
889             return  BluetoothAdapter.STATE_OFF;
890         }
891         else {
892             debugLog("getState(): mAdapterProperties: " + mAdapterProperties);
893             return mAdapterProperties.getState();
894         }
895     }
896 
enable()897      boolean enable() {
898         return enable (false);
899     }
900 
enableNoAutoConnect()901       public boolean enableNoAutoConnect() {
902          return enable (true);
903      }
904 
enable(boolean quietMode)905      public synchronized boolean enable(boolean quietMode) {
906          enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
907                  "Need BLUETOOTH ADMIN permission");
908          if (DBG)debugLog("Enable called with quiet mode status =  " + mQuietmode);
909          mQuietmode  = quietMode;
910          Message m =
911                  mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
912          mAdapterStateMachine.sendMessage(m);
913          return true;
914      }
915 
disable()916      boolean disable() {
917         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
918                 "Need BLUETOOTH ADMIN permission");
919 
920         if (DBG) debugLog("disable() called...");
921         Message m =
922                 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
923         mAdapterStateMachine.sendMessage(m);
924         return true;
925     }
926 
getAddress()927      String getAddress() {
928         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
929 
930         String addrString = null;
931         byte[] address = mAdapterProperties.getAddress();
932         return Utils.getAddressStringFromByte(address);
933     }
934 
getUuids()935      ParcelUuid[] getUuids() {
936         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
937 
938         return mAdapterProperties.getUuids();
939     }
940 
getName()941      String getName() {
942         enforceCallingOrSelfPermission(BLUETOOTH_PERM,
943                 "Need BLUETOOTH permission");
944 
945         try {
946             return mAdapterProperties.getName();
947         } catch (Throwable t) {
948             Log.d(TAG, "Unexpected exception while calling getName()",t);
949         }
950         return null;
951     }
952 
setName(String name)953      boolean setName(String name) {
954         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
955                 "Need BLUETOOTH ADMIN permission");
956 
957         return mAdapterProperties.setName(name);
958     }
959 
getScanMode()960      int getScanMode() {
961         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
962 
963         return mAdapterProperties.getScanMode();
964     }
965 
setScanMode(int mode, int duration)966      boolean setScanMode(int mode, int duration) {
967         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
968 
969         setDiscoverableTimeout(duration);
970 
971         int newMode = convertScanModeToHal(mode);
972         return mAdapterProperties.setScanMode(newMode);
973     }
974 
getDiscoverableTimeout()975      int getDiscoverableTimeout() {
976         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
977 
978         return mAdapterProperties.getDiscoverableTimeout();
979     }
980 
setDiscoverableTimeout(int timeout)981      boolean setDiscoverableTimeout(int timeout) {
982         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
983 
984         return mAdapterProperties.setDiscoverableTimeout(timeout);
985     }
986 
startDiscovery()987      boolean startDiscovery() {
988         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
989                 "Need BLUETOOTH ADMIN permission");
990 
991         return startDiscoveryNative();
992     }
993 
cancelDiscovery()994      boolean cancelDiscovery() {
995         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
996                 "Need BLUETOOTH ADMIN permission");
997 
998         return cancelDiscoveryNative();
999     }
1000 
isDiscovering()1001      boolean isDiscovering() {
1002         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1003 
1004         return mAdapterProperties.isDiscovering();
1005     }
1006 
getBondedDevices()1007      BluetoothDevice[] getBondedDevices() {
1008         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1009         debugLog("Get Bonded Devices being called");
1010         return mAdapterProperties.getBondedDevices();
1011     }
1012 
getAdapterConnectionState()1013      int getAdapterConnectionState() {
1014         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1015 
1016         return mAdapterProperties.getConnectionState();
1017     }
1018 
getProfileConnectionState(int profile)1019      int getProfileConnectionState(int profile) {
1020         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1021 
1022         return mAdapterProperties.getProfileConnectionState(profile);
1023     }
1024 
createBond(BluetoothDevice device)1025      boolean createBond(BluetoothDevice device) {
1026         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1027             "Need BLUETOOTH ADMIN permission");
1028         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1029         if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
1030             return false;
1031         }
1032 
1033         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
1034         msg.obj = device;
1035         mBondStateMachine.sendMessage(msg);
1036         return true;
1037     }
1038 
isQuietModeEnabled()1039       public boolean isQuietModeEnabled() {
1040           if (DBG) debugLog("Quiet mode Enabled = " + mQuietmode);
1041           return mQuietmode;
1042      }
1043 
autoConnect()1044      public void autoConnect(){
1045         if (getState() != BluetoothAdapter.STATE_ON){
1046              errorLog("BT is not ON. Exiting autoConnect");
1047              return;
1048          }
1049          if (isQuietModeEnabled() == false) {
1050             if (DBG) debugLog( "Initiate auto connection on BT on...");
1051              autoConnectHeadset();
1052              autoConnectA2dp();
1053          }
1054          else {
1055              if (DBG) debugLog( "BT is in Quiet mode. Not initiating  auto connections");
1056          }
1057     }
1058 
autoConnectHeadset()1059      private void autoConnectHeadset(){
1060         HeadsetService  hsService = HeadsetService.getHeadsetService();
1061 
1062         BluetoothDevice bondedDevices[] = getBondedDevices();
1063         if ((bondedDevices == null) ||(hsService == null)) {
1064             return;
1065         }
1066         for (BluetoothDevice device : bondedDevices) {
1067             if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){
1068                 Log.d(TAG,"Auto Connecting Headset Profile with device " + device.toString());
1069                 hsService.connect(device);
1070                 }
1071         }
1072     }
1073 
autoConnectA2dp()1074      private void autoConnectA2dp(){
1075         A2dpService a2dpSservice = A2dpService.getA2dpService();
1076         BluetoothDevice bondedDevices[] = getBondedDevices();
1077         if ((bondedDevices == null) ||(a2dpSservice == null)) {
1078             return;
1079         }
1080         for (BluetoothDevice device : bondedDevices) {
1081             if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){
1082                 Log.d(TAG,"Auto Connecting A2DP Profile with device " + device.toString());
1083                 a2dpSservice.connect(device);
1084                 }
1085         }
1086     }
1087 
connectOtherProfile(BluetoothDevice device, int firstProfileStatus)1088      public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){
1089         if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) &&
1090             (isQuietModeEnabled()== false)){
1091             Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES);
1092             m.obj = device;
1093             m.arg1 = (int)firstProfileStatus;
1094             mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT);
1095         }
1096     }
1097 
processConnectOtherProfiles(BluetoothDevice device, int firstProfileStatus)1098      private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){
1099         if (getState()!= BluetoothAdapter.STATE_ON){
1100             return;
1101         }
1102         HeadsetService  hsService = HeadsetService.getHeadsetService();
1103         A2dpService a2dpService = A2dpService.getA2dpService();
1104         // if any of the profile service is  null, second profile connection not required
1105         if ((hsService == null) ||(a2dpService == null )){
1106             return;
1107         }
1108         List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices();
1109         List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices();
1110         // Check if the device is in disconnected state and if so return
1111         // We ned to connect other profile only if one of the profile is still in connected state
1112         // This is required to avoide a race condition in which profiles would
1113         // automaticlly connect if the disconnection is initiated within 6 seconds of connection
1114         //First profile connection being rejected is an exception
1115         if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&&
1116             (PROFILE_CONN_CONNECTED  == firstProfileStatus)){
1117             return;
1118         }
1119         if((hfConnDevList.isEmpty()) &&
1120             (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){
1121             hsService.connect(device);
1122         }
1123         else if((a2dpConnDevList.isEmpty()) &&
1124             (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){
1125             a2dpService.connect(device);
1126         }
1127     }
1128 
adjustOtherHeadsetPriorities(HeadsetService hsService, BluetoothDevice connectedDevice)1129      private void adjustOtherHeadsetPriorities(HeadsetService  hsService,
1130                                                     BluetoothDevice connectedDevice) {
1131         for (BluetoothDevice device : getBondedDevices()) {
1132            if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
1133                !device.equals(connectedDevice)) {
1134                hsService.setPriority(device, BluetoothProfile.PRIORITY_ON);
1135            }
1136         }
1137      }
1138 
adjustOtherSinkPriorities(A2dpService a2dpService, BluetoothDevice connectedDevice)1139      private void adjustOtherSinkPriorities(A2dpService a2dpService,
1140                                                 BluetoothDevice connectedDevice) {
1141          for (BluetoothDevice device : getBondedDevices()) {
1142              if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
1143                  !device.equals(connectedDevice)) {
1144                  a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
1145              }
1146          }
1147      }
1148 
setProfileAutoConnectionPriority(BluetoothDevice device, int profileId)1149      void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){
1150          if (profileId == BluetoothProfile.HEADSET) {
1151              HeadsetService  hsService = HeadsetService.getHeadsetService();
1152              if ((hsService != null) &&
1153                 (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){
1154                  adjustOtherHeadsetPriorities(hsService, device);
1155                  hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
1156              }
1157          }
1158          else if (profileId ==  BluetoothProfile.A2DP) {
1159              A2dpService a2dpService = A2dpService.getA2dpService();
1160              if ((a2dpService != null) &&
1161                 (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))){
1162                  adjustOtherSinkPriorities(a2dpService, device);
1163                  a2dpService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
1164              }
1165          }
1166     }
1167 
cancelBondProcess(BluetoothDevice device)1168      boolean cancelBondProcess(BluetoothDevice device) {
1169         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1170         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1171         return cancelBondNative(addr);
1172     }
1173 
removeBond(BluetoothDevice device)1174      boolean removeBond(BluetoothDevice device) {
1175         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1176         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1177         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
1178             return false;
1179         }
1180         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
1181         msg.obj = device;
1182         mBondStateMachine.sendMessage(msg);
1183         return true;
1184     }
1185 
getBondState(BluetoothDevice device)1186      int getBondState(BluetoothDevice device) {
1187         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1188         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1189         if (deviceProp == null) {
1190             return BluetoothDevice.BOND_NONE;
1191         }
1192         return deviceProp.getBondState();
1193     }
1194 
getRemoteName(BluetoothDevice device)1195      String getRemoteName(BluetoothDevice device) {
1196         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1197         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1198         if (deviceProp == null) return null;
1199         return deviceProp.getName();
1200     }
1201 
getRemoteAlias(BluetoothDevice device)1202      String getRemoteAlias(BluetoothDevice device) {
1203         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1204         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1205         if (deviceProp == null) return null;
1206         return deviceProp.getAlias();
1207     }
1208 
setRemoteAlias(BluetoothDevice device, String name)1209      boolean setRemoteAlias(BluetoothDevice device, String name) {
1210         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1211         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1212         if (deviceProp == null) return false;
1213         deviceProp.setAlias(name);
1214         return true;
1215     }
1216 
getRemoteClass(BluetoothDevice device)1217      int getRemoteClass(BluetoothDevice device) {
1218         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1219         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1220         if (deviceProp == null) return 0;
1221 
1222         return deviceProp.getBluetoothClass();
1223     }
1224 
getRemoteUuids(BluetoothDevice device)1225      ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
1226         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1227         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1228         if (deviceProp == null) return null;
1229         return deviceProp.getUuids();
1230     }
1231 
fetchRemoteUuids(BluetoothDevice device)1232      boolean fetchRemoteUuids(BluetoothDevice device) {
1233         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1234         mRemoteDevices.fetchUuids(device);
1235         return true;
1236     }
1237 
setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode)1238      boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
1239         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1240         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1241         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1242             return false;
1243         }
1244 
1245         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1246         return pinReplyNative(addr, accept, len, pinCode);
1247     }
1248 
setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey)1249      boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
1250         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1251         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1252         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1253             return false;
1254         }
1255 
1256         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1257         return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
1258                 Utils.byteArrayToInt(passkey));
1259     }
1260 
setPairingConfirmation(BluetoothDevice device, boolean accept)1261      boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
1262         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1263         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1264         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1265             return false;
1266         }
1267 
1268         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1269         return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
1270                 accept, 0);
1271     }
1272 
sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)1273      void sendConnectionStateChange(BluetoothDevice
1274             device, int profile, int state, int prevState) {
1275         // TODO(BT) permission check?
1276         // Since this is a binder call check if Bluetooth is on still
1277         if (getState() == BluetoothAdapter.STATE_OFF) return;
1278 
1279         mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
1280 
1281     }
1282 
connectSocket(BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag)1283      ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
1284                                               ParcelUuid uuid, int port, int flag) {
1285         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1286         int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()),
1287                    type, Utils.uuidToByteArray(uuid), port, flag);
1288         if (fd < 0) {
1289             errorLog("Failed to connect socket");
1290             return null;
1291         }
1292         return ParcelFileDescriptor.adoptFd(fd);
1293     }
1294 
createSocketChannel(int type, String serviceName, ParcelUuid uuid, int port, int flag)1295      ParcelFileDescriptor createSocketChannel(int type, String serviceName,
1296                                                     ParcelUuid uuid, int port, int flag) {
1297         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1298         int fd =  createSocketChannelNative(type, serviceName,
1299                                  Utils.uuidToByteArray(uuid), port, flag);
1300         if (fd < 0) {
1301             errorLog("Failed to create socket channel");
1302             return null;
1303         }
1304         return ParcelFileDescriptor.adoptFd(fd);
1305     }
1306 
registerCallback(IBluetoothCallback cb)1307      void registerCallback(IBluetoothCallback cb) {
1308          mCallbacks.register(cb);
1309       }
1310 
unregisterCallback(IBluetoothCallback cb)1311       void unregisterCallback(IBluetoothCallback cb) {
1312          mCallbacks.unregister(cb);
1313       }
1314 
convertScanModeToHal(int mode)1315     private static int convertScanModeToHal(int mode) {
1316         switch (mode) {
1317             case BluetoothAdapter.SCAN_MODE_NONE:
1318                 return AbstractionLayer.BT_SCAN_MODE_NONE;
1319             case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
1320                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
1321             case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1322                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1323         }
1324        // errorLog("Incorrect scan mode in convertScanModeToHal");
1325         return -1;
1326     }
1327 
convertScanModeFromHal(int mode)1328     static int convertScanModeFromHal(int mode) {
1329         switch (mode) {
1330             case AbstractionLayer.BT_SCAN_MODE_NONE:
1331                 return BluetoothAdapter.SCAN_MODE_NONE;
1332             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
1333                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
1334             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1335                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1336         }
1337         //errorLog("Incorrect scan mode in convertScanModeFromHal");
1338         return -1;
1339     }
1340 
debugLog(String msg)1341     private void debugLog(String msg) {
1342         Log.d(TAG +"(" +hashCode()+")", msg);
1343     }
1344 
errorLog(String msg)1345     private void errorLog(String msg) {
1346         Log.e(TAG +"(" +hashCode()+")", msg);
1347     }
1348 
classInitNative()1349     private native static void classInitNative();
initNative()1350     private native boolean initNative();
cleanupNative()1351     private native void cleanupNative();
enableNative()1352     /*package*/ native boolean enableNative();
disableNative()1353     /*package*/ native boolean disableNative();
setAdapterPropertyNative(int type, byte[] val)1354     /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val);
getAdapterPropertiesNative()1355     /*package*/ native boolean getAdapterPropertiesNative();
getAdapterPropertyNative(int type)1356     /*package*/ native boolean getAdapterPropertyNative(int type);
setAdapterPropertyNative(int type)1357     /*package*/ native boolean setAdapterPropertyNative(int type);
1358     /*package*/ native boolean
setDevicePropertyNative(byte[] address, int type, byte[] val)1359         setDevicePropertyNative(byte[] address, int type, byte[] val);
getDevicePropertyNative(byte[] address, int type)1360     /*package*/ native boolean getDevicePropertyNative(byte[] address, int type);
1361 
createBondNative(byte[] address)1362     /*package*/ native boolean createBondNative(byte[] address);
removeBondNative(byte[] address)1363     /*package*/ native boolean removeBondNative(byte[] address);
cancelBondNative(byte[] address)1364     /*package*/ native boolean cancelBondNative(byte[] address);
1365 
startDiscoveryNative()1366     private native boolean startDiscoveryNative();
cancelDiscoveryNative()1367     private native boolean cancelDiscoveryNative();
1368 
pinReplyNative(byte[] address, boolean accept, int len, byte[] pin)1369     private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin);
sspReplyNative(byte[] address, int type, boolean accept, int passkey)1370     private native boolean sspReplyNative(byte[] address, int type, boolean
1371             accept, int passkey);
1372 
getRemoteServicesNative(byte[] address)1373     /*package*/ native boolean getRemoteServicesNative(byte[] address);
1374 
1375     // TODO(BT) move this to ../btsock dir
connectSocketNative(byte[] address, int type, byte[] uuid, int port, int flag)1376     private native int connectSocketNative(byte[] address, int type,
1377                                            byte[] uuid, int port, int flag);
createSocketChannelNative(int type, String serviceName, byte[] uuid, int port, int flag)1378     private native int createSocketChannelNative(int type, String serviceName,
1379                                                  byte[] uuid, int port, int flag);
1380 
finalize()1381     protected void finalize() {
1382         cleanup();
1383         if (TRACE_REF) {
1384             synchronized (AdapterService.class) {
1385                 sRefCount--;
1386                 Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount);
1387             }
1388         }
1389     }
1390 }
1391