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