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