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