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