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