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.PendingIntent;
     25 import android.app.Service;
     26 import android.bluetooth.BluetoothAdapter;
     27 import android.bluetooth.BluetoothDevice;
     28 import android.bluetooth.BluetoothProfile;
     29 import android.bluetooth.BluetoothUuid;
     30 import android.bluetooth.IBluetooth;
     31 import android.bluetooth.IBluetoothCallback;
     32 import android.bluetooth.BluetoothActivityEnergyInfo;
     33 import android.bluetooth.OobData;
     34 import android.bluetooth.UidTraffic;
     35 import android.content.BroadcastReceiver;
     36 import android.content.Context;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.content.SharedPreferences;
     40 import android.os.BatteryStats;
     41 import android.os.Binder;
     42 import android.os.Bundle;
     43 import android.os.Handler;
     44 import android.os.IBinder;
     45 import android.os.Message;
     46 import android.os.ParcelFileDescriptor;
     47 import android.os.ParcelUuid;
     48 import android.os.PowerManager;
     49 import android.os.Process;
     50 import android.os.RemoteCallbackList;
     51 import android.os.RemoteException;
     52 import android.os.ResultReceiver;
     53 import android.os.SystemClock;
     54 import android.provider.Settings;
     55 import android.text.TextUtils;
     56 import android.util.Base64;
     57 import android.util.EventLog;
     58 import android.util.Log;
     59 
     60 import android.util.Slog;
     61 import android.util.SparseArray;
     62 import com.android.bluetooth.a2dp.A2dpService;
     63 import com.android.bluetooth.a2dpsink.A2dpSinkService;
     64 import com.android.bluetooth.hid.HidService;
     65 import com.android.bluetooth.hfp.HeadsetService;
     66 import com.android.bluetooth.hfpclient.HeadsetClientService;
     67 import com.android.bluetooth.pbapclient.PbapClientService;
     68 import com.android.bluetooth.sdp.SdpManager;
     69 import com.android.internal.R;
     70 import com.android.bluetooth.Utils;
     71 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
     72 
     73 import java.io.FileDescriptor;
     74 import java.io.FileOutputStream;
     75 import java.io.IOException;
     76 import java.io.PrintWriter;
     77 import java.nio.charset.StandardCharsets;
     78 import java.util.ArrayList;
     79 import java.util.Arrays;
     80 import java.util.HashMap;
     81 import java.util.Map;
     82 import java.util.Iterator;
     83 import java.util.List;
     84 
     85 import android.os.ServiceManager;
     86 import com.android.internal.app.IBatteryStats;
     87 
     88 public class AdapterService extends Service {
     89     private static final String TAG = "BluetoothAdapterService";
     90     private static final boolean DBG = false;
     91     private static final boolean TRACE_REF = false;
     92     private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
     93     private static final int MIN_OFFLOADED_FILTERS = 10;
     94     private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024;
     95     //For Debugging only
     96     private static int sRefCount = 0;
     97     private long mBluetoothStartTime = 0;
     98 
     99     private final Object mEnergyInfoLock = new Object();
    100     private int mStackReportedState;
    101     private long mTxTimeTotalMs;
    102     private long mRxTimeTotalMs;
    103     private long mIdleTimeTotalMs;
    104     private long mEnergyUsedTotalVoltAmpSecMicro;
    105     private SparseArray<UidTraffic> mUidTraffic = new SparseArray<>();
    106 
    107     private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>();
    108 
    109     public static final String ACTION_LOAD_ADAPTER_PROPERTIES =
    110         "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES";
    111     public static final String ACTION_SERVICE_STATE_CHANGED =
    112         "com.android.bluetooth.btservice.action.STATE_CHANGED";
    113     public static final String EXTRA_ACTION="action";
    114     public static final int PROFILE_CONN_CONNECTED  = 1;
    115     public static final int PROFILE_CONN_REJECTED  = 2;
    116 
    117     private static final String ACTION_ALARM_WAKEUP =
    118         "com.android.bluetooth.btservice.action.ALARM_WAKEUP";
    119 
    120     public static final String BLUETOOTH_ADMIN_PERM =
    121         android.Manifest.permission.BLUETOOTH_ADMIN;
    122     public static final String BLUETOOTH_PRIVILEGED =
    123                 android.Manifest.permission.BLUETOOTH_PRIVILEGED;
    124     static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
    125     static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP;
    126 
    127     private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE =
    128             "phonebook_access_permission";
    129     private static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE =
    130             "message_access_permission";
    131     private static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE =
    132             "sim_access_permission";
    133 
    134     private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY;
    135 
    136     private static final String[] DEVICE_TYPE_NAMES = new String[] {
    137       "???",
    138       "BR/EDR",
    139       "LE",
    140       "DUAL"
    141     };
    142 
    143     private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30;
    144 
    145     static {
    146         classInitNative();
    147     }
    148 
    149     private static AdapterService sAdapterService;
    150     public static synchronized AdapterService getAdapterService(){
    151         if (sAdapterService != null && !sAdapterService.mCleaningUp) {
    152             Log.d(TAG, "getAdapterService() - returning " + sAdapterService);
    153             return sAdapterService;
    154         }
    155         if (DBG)  {
    156             if (sAdapterService == null) {
    157                 Log.d(TAG, "getAdapterService() - Service not available");
    158             } else if (sAdapterService.mCleaningUp) {
    159                 Log.d(TAG,"getAdapterService() - Service is cleaning up");
    160             }
    161         }
    162         return null;
    163     }
    164 
    165     private static synchronized void setAdapterService(AdapterService instance) {
    166         if (instance != null && !instance.mCleaningUp) {
    167             if (DBG) Log.d(TAG, "setAdapterService() - set to: " + sAdapterService);
    168             sAdapterService = instance;
    169         } else {
    170             if (DBG)  {
    171                 if (sAdapterService == null) {
    172                     Log.d(TAG, "setAdapterService() - Service not available");
    173                 } else if (sAdapterService.mCleaningUp) {
    174                     Log.d(TAG,"setAdapterService() - Service is cleaning up");
    175                 }
    176             }
    177         }
    178     }
    179 
    180     private static synchronized void clearAdapterService() {
    181         sAdapterService = null;
    182     }
    183 
    184     private AdapterProperties mAdapterProperties;
    185     private AdapterState mAdapterStateMachine;
    186     private BondStateMachine mBondStateMachine;
    187     private JniCallbacks mJniCallbacks;
    188     private RemoteDevices mRemoteDevices;
    189 
    190     /* TODO: Consider to remove the search API from this class, if changed to use call-back */
    191     private SdpManager mSdpManager = null;
    192 
    193     private boolean mProfilesStarted;
    194     private boolean mNativeAvailable;
    195     private boolean mCleaningUp;
    196     private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>();
    197     //Only BluetoothManagerService should be registered
    198     private RemoteCallbackList<IBluetoothCallback> mCallbacks;
    199     private int mCurrentRequestId;
    200     private boolean mQuietmode = false;
    201 
    202     private AlarmManager mAlarmManager;
    203     private PendingIntent mPendingAlarm;
    204     private IBatteryStats mBatteryStats;
    205     private PowerManager mPowerManager;
    206     private PowerManager.WakeLock mWakeLock;
    207     private String mWakeLockName;
    208 
    209     private ProfileObserver mProfileObserver;
    210 
    211     public AdapterService() {
    212         super();
    213         if (TRACE_REF) {
    214             synchronized (AdapterService.class) {
    215                 sRefCount++;
    216                 debugLog("AdapterService() - REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount);
    217             }
    218         }
    219 
    220         // This is initialized at the beginning in order to prevent
    221         // NullPointerException from happening if AdapterService
    222         // functions are called before BLE is turned on due to
    223         // |mRemoteDevices| being null.
    224         mRemoteDevices = new RemoteDevices(this);
    225     }
    226 
    227     public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
    228         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED);
    229         m.obj = device;
    230         m.arg1 = profileId;
    231         m.arg2 = newState;
    232         Bundle b = new Bundle(1);
    233         b.putInt("prevState", prevState);
    234         m.setData(b);
    235         mHandler.sendMessage(m);
    236     }
    237 
    238     public void initProfilePriorities(BluetoothDevice device, ParcelUuid[] mUuids) {
    239         if(mUuids == null) return;
    240         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES);
    241         m.obj = device;
    242         m.arg1 = mUuids.length;
    243         Bundle b = new Bundle(1);
    244         for(int i=0; i<mUuids.length; i++) {
    245             b.putParcelable("uuids" + i, mUuids[i]);
    246         }
    247         m.setData(b);
    248         mHandler.sendMessage(m);
    249     }
    250 
    251     private void processInitProfilePriorities (BluetoothDevice device, ParcelUuid[] uuids){
    252         HidService hidService = HidService.getHidService();
    253         A2dpService a2dpService = A2dpService.getA2dpService();
    254         A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService();
    255         HeadsetService headsetService = HeadsetService.getHeadsetService();
    256         HeadsetClientService headsetClientService = HeadsetClientService.getHeadsetClientService();
    257         PbapClientService pbapClientService = PbapClientService.getPbapClientService();
    258 
    259         // Set profile priorities only for the profiles discovered on the remote device.
    260         // This avoids needless auto-connect attempts to profiles non-existent on the remote device
    261         if ((hidService != null) &&
    262             (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) ||
    263              BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) &&
    264             (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
    265             hidService.setPriority(device,BluetoothProfile.PRIORITY_ON);
    266         }
    267 
    268         // If we do not have a stored priority for HFP/A2DP (all roles) then default to on.
    269         if ((headsetService != null) &&
    270             ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP) ||
    271                     BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) &&
    272             (headsetService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) {
    273             headsetService.setPriority(device,BluetoothProfile.PRIORITY_ON);
    274         }
    275 
    276         if ((a2dpService != null) &&
    277             (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink) ||
    278             BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AdvAudioDist)) &&
    279             (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
    280             a2dpService.setPriority(device,BluetoothProfile.PRIORITY_ON);
    281         }
    282 
    283         if ((headsetClientService != null) &&
    284             ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
    285               BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) &&
    286              (headsetClientService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) {
    287             headsetClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    288         }
    289 
    290         if ((a2dpSinkService != null) &&
    291             (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource) &&
    292              (a2dpSinkService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) {
    293             a2dpSinkService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    294         }
    295 
    296         if ((pbapClientService != null) &&
    297             (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.PBAP_PSE) &&
    298              (pbapClientService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))) {
    299             pbapClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    300         }
    301     }
    302 
    303     private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
    304         // Profiles relevant to phones.
    305         if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET)) &&
    306              (newState == BluetoothProfile.STATE_CONNECTED)){
    307             debugLog( "Profile connected. Schedule missing profile connection if any");
    308             connectOtherProfile(device, PROFILE_CONN_CONNECTED);
    309             setProfileAutoConnectionPriority(device, profileId);
    310         }
    311 
    312         // Profiles relevant to Car Kitts.
    313         if (((profileId == BluetoothProfile.A2DP_SINK) ||
    314              (profileId == BluetoothProfile.HEADSET_CLIENT)) &&
    315             (newState == BluetoothProfile.STATE_CONNECTED)) {
    316             debugLog( "Profile connected. Schedule missing profile connection if any");
    317             connectOtherProfile(device, PROFILE_CONN_CONNECTED);
    318             setProfileAutoConnectionPriority(device, profileId);
    319         }
    320 
    321         IBluetooth.Stub binder = mBinder;
    322         if (binder != null) {
    323             try {
    324                 binder.sendConnectionStateChange(device, profileId, newState,prevState);
    325             } catch (RemoteException re) {
    326                 errorLog("" + re);
    327             }
    328         }
    329     }
    330 
    331     public void addProfile(ProfileService profile) {
    332         synchronized (mProfiles) {
    333             if (!mProfiles.contains(profile)) {
    334                 mProfiles.add(profile);
    335             }
    336         }
    337     }
    338 
    339     public void removeProfile(ProfileService profile) {
    340         synchronized (mProfiles) {
    341             mProfiles.remove(profile);
    342         }
    343     }
    344 
    345     public void onProfileServiceStateChanged(String serviceName, int state) {
    346         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
    347         m.obj=serviceName;
    348         m.arg1 = state;
    349         mHandler.sendMessage(m);
    350     }
    351 
    352     private void processProfileServiceStateChanged(String serviceName, int state) {
    353         boolean doUpdate=false;
    354         boolean isBleTurningOn;
    355         boolean isBleTurningOff;
    356         boolean isTurningOn;
    357         boolean isTurningOff;
    358 
    359         synchronized (mProfileServicesState) {
    360             Integer prevState = mProfileServicesState.get(serviceName);
    361             if (prevState != null && prevState != state) {
    362                 mProfileServicesState.put(serviceName,state);
    363                 doUpdate=true;
    364             }
    365         }
    366         debugLog("processProfileServiceStateChanged() serviceName=" + serviceName
    367             + ", state=" + state +", doUpdate=" + doUpdate);
    368 
    369         if (!doUpdate) {
    370             return;
    371         }
    372 
    373         synchronized (mAdapterStateMachine) {
    374             isTurningOff = mAdapterStateMachine.isTurningOff();
    375             isTurningOn = mAdapterStateMachine.isTurningOn();
    376             isBleTurningOn = mAdapterStateMachine.isBleTurningOn();
    377             isBleTurningOff = mAdapterStateMachine.isBleTurningOff();
    378         }
    379 
    380         debugLog("processProfileServiceStateChanged() - serviceName=" + serviceName +
    381                  " isTurningOn=" + isTurningOn + " isTurningOff=" + isTurningOff +
    382                  " isBleTurningOn=" + isBleTurningOn + " isBleTurningOff=" + isBleTurningOff);
    383 
    384         if (isBleTurningOn) {
    385             if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
    386                 debugLog("GattService is started");
    387                 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));
    388                 return;
    389             }
    390 
    391         } else if(isBleTurningOff) {
    392             if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
    393                 debugLog("GattService stopped");
    394                 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STOPPED));
    395                 return;
    396             }
    397 
    398         } else if (isTurningOff) {
    399             //On to BLE_ON
    400             //Process stop or disable pending
    401             //Check if all services are stopped if so, do cleanup
    402             synchronized (mProfileServicesState) {
    403                 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
    404                 while (i.hasNext()) {
    405                     Map.Entry<String,Integer> entry = i.next();
    406                     debugLog("Service: " + entry.getKey());
    407                     if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) {
    408                         debugLog("Skip GATT service - already started before");
    409                         continue;
    410                     }
    411                     if (BluetoothAdapter.STATE_OFF != entry.getValue()) {
    412                         debugLog("onProfileServiceStateChange() - Profile still running: "
    413                             + entry.getKey());
    414                         return;
    415                     }
    416                 }
    417             }
    418             debugLog("onProfileServiceStateChange() - All profile services stopped...");
    419             //Send message to state machine
    420             mProfilesStarted=false;
    421             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED));
    422 
    423         } else if (isTurningOn) {
    424             updateInteropDatabase();
    425 
    426             //Process start pending
    427             //Check if all services are started if so, update state
    428             synchronized (mProfileServicesState) {
    429                 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
    430                 while (i.hasNext()) {
    431                     Map.Entry<String,Integer> entry = i.next();
    432                     debugLog("Service: " + entry.getKey());
    433                     if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) {
    434                         debugLog("Skip GATT service - already started before");
    435                         continue;
    436                     }
    437                     if (BluetoothAdapter.STATE_ON != entry.getValue()) {
    438                         debugLog("onProfileServiceStateChange() - Profile still not running:"
    439                             + entry.getKey());
    440                         return;
    441                     }
    442                 }
    443             }
    444             debugLog("onProfileServiceStateChange() - All profile services started.");
    445             mProfilesStarted=true;
    446             //Send message to state machine
    447             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED));
    448         }
    449     }
    450 
    451     private void updateInteropDatabase() {
    452         interopDatabaseClearNative();
    453 
    454         String interop_string = Settings.Global.getString(getContentResolver(),
    455                                             Settings.Global.BLUETOOTH_INTEROPERABILITY_LIST);
    456         if (interop_string == null) return;
    457         Log.d(TAG, "updateInteropDatabase: [" + interop_string + "]");
    458 
    459         String[] entries = interop_string.split(";");
    460         for (String entry : entries) {
    461             String[] tokens = entry.split(",");
    462             if (tokens.length != 2) continue;
    463 
    464             // Get feature
    465             int feature = 0;
    466             try {
    467                 feature = Integer.parseInt(tokens[1]);
    468             } catch (NumberFormatException e) {
    469                 Log.e(TAG, "updateInteropDatabase: Invalid feature '" + tokens[1] + "'");
    470                 continue;
    471             }
    472 
    473             // Get address bytes and length
    474             int length = (tokens[0].length() + 1) / 3;
    475             if (length < 1 || length > 6) {
    476                 Log.e(TAG, "updateInteropDatabase: Malformed address string '" + tokens[0] + "'");
    477                 continue;
    478             }
    479 
    480             byte[] addr = new byte[6];
    481             int offset = 0;
    482             for (int i = 0; i < tokens[0].length(); ) {
    483                 if (tokens[0].charAt(i) == ':') {
    484                     i += 1;
    485                 } else {
    486                     try {
    487                         addr[offset++] = (byte) Integer.parseInt(tokens[0].substring(i, i + 2), 16);
    488                     } catch (NumberFormatException e) {
    489                         offset = 0;
    490                         break;
    491                     }
    492                     i += 2;
    493                 }
    494             }
    495 
    496             // Check if address was parsed ok, otherwise, move on...
    497             if (offset == 0) continue;
    498 
    499             // Add entry
    500             interopDatabaseAddNative(feature, addr, length);
    501         }
    502     }
    503 
    504     @Override
    505     public void onCreate() {
    506         super.onCreate();
    507         debugLog("onCreate()");
    508         mBinder = new AdapterServiceBinder(this);
    509         mAdapterProperties = new AdapterProperties(this);
    510         mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);
    511         mJniCallbacks =  new JniCallbacks(mAdapterStateMachine, mAdapterProperties);
    512         initNative();
    513         mNativeAvailable=true;
    514         mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
    515         //Load the name and address
    516         getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
    517         getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
    518         mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    519         mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    520         mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
    521                 BatteryStats.SERVICE_NAME));
    522 
    523         mSdpManager = SdpManager.init(this);
    524         registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP));
    525         mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler());
    526         mProfileObserver.start();
    527     }
    528 
    529     @Override
    530     public IBinder onBind(Intent intent) {
    531         debugLog("onBind()");
    532         return mBinder;
    533     }
    534     public boolean onUnbind(Intent intent) {
    535         debugLog("onUnbind() - calling cleanup");
    536         cleanup();
    537         return super.onUnbind(intent);
    538     }
    539 
    540     public void onDestroy() {
    541         debugLog("onDestroy()");
    542         mProfileObserver.stop();
    543     }
    544 
    545     void BleOnProcessStart() {
    546         debugLog("BleOnProcessStart()");
    547 
    548         if (getApplicationContext().getResources().getBoolean(
    549                 R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
    550             Config.init(getApplicationContext());
    551         }
    552 
    553         Class[] supportedProfileServices = Config.getSupportedProfiles();
    554         //Initialize data objects
    555         for (int i=0; i < supportedProfileServices.length;i++) {
    556             mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
    557         }
    558 
    559         // Reset |mRemoteDevices| whenever BLE is turned off then on
    560         // This is to replace the fact that |mRemoteDevices| was
    561         // reinitialized in previous code.
    562         //
    563         // TODO(apanicke): The reason is unclear but
    564         // I believe it is to clear the variable every time BLE was
    565         // turned off then on. The same effect can be achieved by
    566         // calling cleanup but this may not be necessary at all
    567         // We should figure out why this is needed later
    568         mRemoteDevices.cleanup();
    569         mAdapterProperties.init(mRemoteDevices);
    570 
    571         debugLog("BleOnProcessStart() - Make Bond State Machine");
    572         mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
    573 
    574         mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
    575 
    576         try {
    577             mBatteryStats.noteResetBleScan();
    578         } catch (RemoteException e) {
    579             // Ignore.
    580         }
    581 
    582         //FIXME: Set static instance here???
    583         setAdapterService(this);
    584 
    585         //Start Gatt service
    586         setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
    587     }
    588 
    589     void startCoreServices()
    590     {
    591         debugLog("startCoreServices()");
    592         Class[] supportedProfileServices = Config.getSupportedProfiles();
    593 
    594         //Start profile services
    595         if (!mProfilesStarted && supportedProfileServices.length >0) {
    596             //Startup all profile services
    597             setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
    598         }else {
    599             debugLog("startCoreProfiles(): Profile Services alreay started");
    600             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED));
    601         }
    602     }
    603 
    604     void startBluetoothDisable() {
    605         mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE));
    606     }
    607 
    608     boolean stopProfileServices() {
    609         Class[] supportedProfileServices = Config.getSupportedProfiles();
    610         if (mProfilesStarted && supportedProfileServices.length>0) {
    611             setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
    612             return true;
    613         }
    614         debugLog("stopProfileServices() - No profiles services to stop or already stopped.");
    615         return false;
    616     }
    617 
    618     boolean stopGattProfileService() {
    619         //TODO: can optimize this instead of looping around all supported profiles
    620         debugLog("stopGattProfileService()");
    621         Class[] supportedProfileServices = Config.getSupportedProfiles();
    622 
    623         setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
    624         return true;
    625     }
    626 
    627 
    628      void updateAdapterState(int prevState, int newState){
    629         if (mCallbacks !=null) {
    630             int n=mCallbacks.beginBroadcast();
    631             debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers.");
    632             for (int i=0; i <n;i++) {
    633                 try {
    634                     mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);
    635                 }  catch (RemoteException e) {
    636                     debugLog("updateAdapterState() - Callback #" + i + " failed ("  + e + ")");
    637                 }
    638             }
    639             mCallbacks.finishBroadcast();
    640         }
    641     }
    642 
    643     void cleanup () {
    644         debugLog("cleanup()");
    645         if (mCleaningUp) {
    646             errorLog("cleanup() - Service already starting to cleanup, ignoring request...");
    647             return;
    648         }
    649 
    650         mCleaningUp = true;
    651 
    652         unregisterReceiver(mAlarmBroadcastReceiver);
    653 
    654         if (mPendingAlarm != null) {
    655             mAlarmManager.cancel(mPendingAlarm);
    656             mPendingAlarm = null;
    657         }
    658 
    659         // This wake lock release may also be called concurrently by
    660         // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here.
    661         synchronized (this) {
    662             if (mWakeLock != null) {
    663                 if (mWakeLock.isHeld())
    664                     mWakeLock.release();
    665                 mWakeLock = null;
    666             }
    667         }
    668 
    669         if (mAdapterStateMachine != null) {
    670             mAdapterStateMachine.doQuit();
    671             mAdapterStateMachine.cleanup();
    672         }
    673 
    674         if (mBondStateMachine != null) {
    675             mBondStateMachine.doQuit();
    676             mBondStateMachine.cleanup();
    677         }
    678 
    679         if (mRemoteDevices != null) {
    680             mRemoteDevices.cleanup();
    681         }
    682 
    683         if(mSdpManager != null) {
    684             mSdpManager.cleanup();
    685             mSdpManager = null;
    686         }
    687 
    688         if (mNativeAvailable) {
    689             debugLog("cleanup() - Cleaning up adapter native");
    690             cleanupNative();
    691             mNativeAvailable=false;
    692         }
    693 
    694         if (mAdapterProperties != null) {
    695             mAdapterProperties.cleanup();
    696         }
    697 
    698         if (mJniCallbacks != null) {
    699             mJniCallbacks.cleanup();
    700         }
    701 
    702         if (mProfileServicesState != null) {
    703             mProfileServicesState.clear();
    704         }
    705 
    706         clearAdapterService();
    707 
    708         if (mBinder != null) {
    709             mBinder.cleanup();
    710             mBinder = null;  //Do not remove. Otherwise Binder leak!
    711         }
    712 
    713         if (mCallbacks !=null) {
    714             mCallbacks.kill();
    715         }
    716 
    717         System.exit(0);
    718     }
    719 
    720     private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1;
    721     private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20;
    722     private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30;
    723     private static final int MESSAGE_PROFILE_INIT_PRIORITIES=40;
    724     private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000;
    725 
    726     private final Handler mHandler = new Handler() {
    727         @Override
    728         public void handleMessage(Message msg) {
    729             debugLog("handleMessage() - Message: " + msg.what);
    730 
    731             switch (msg.what) {
    732                 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: {
    733                     debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
    734                     processProfileServiceStateChanged((String) msg.obj, msg.arg1);
    735                 }
    736                     break;
    737                 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: {
    738                     debugLog( "handleMessage() - MESSAGE_PROFILE_CONNECTION_STATE_CHANGED");
    739                     processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR));
    740                 }
    741                     break;
    742                 case MESSAGE_PROFILE_INIT_PRIORITIES: {
    743                     debugLog( "handleMessage() - MESSAGE_PROFILE_INIT_PRIORITIES");
    744                     ParcelUuid[] mUuids = new ParcelUuid[msg.arg1];
    745                     for(int i=0; i<mUuids.length; i++) {
    746                         mUuids[i] = msg.getData().getParcelable("uuids" + i);
    747                     }
    748                     processInitProfilePriorities((BluetoothDevice) msg.obj, mUuids);
    749                 }
    750                     break;
    751                 case MESSAGE_CONNECT_OTHER_PROFILES: {
    752                     debugLog( "handleMessage() - MESSAGE_CONNECT_OTHER_PROFILES");
    753                     processConnectOtherProfiles((BluetoothDevice) msg.obj,msg.arg1);
    754                 }
    755                     break;
    756             }
    757         }
    758     };
    759 
    760     @SuppressWarnings("rawtypes")
    761     private void setGattProfileServiceState(Class[] services, int state) {
    762         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
    763             Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving...");
    764             return;
    765         }
    766 
    767         int expectedCurrentState= BluetoothAdapter.STATE_OFF;
    768         int pendingState = BluetoothAdapter.STATE_TURNING_ON;
    769 
    770         if (state == BluetoothAdapter.STATE_OFF) {
    771             expectedCurrentState= BluetoothAdapter.STATE_ON;
    772             pendingState = BluetoothAdapter.STATE_TURNING_OFF;
    773         }
    774 
    775         for (int i=0; i <services.length;i++) {
    776             String serviceName = services[i].getName();
    777             String simpleName = services[i].getSimpleName();
    778 
    779             if (simpleName.equals("GattService")) {
    780                 Integer serviceState = mProfileServicesState.get(serviceName);
    781 
    782                 if(serviceState != null && serviceState != expectedCurrentState) {
    783                     debugLog("setProfileServiceState() - Unable to "
    784                         + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
    785                         + " service " + serviceName
    786                         + ". Invalid state: " + serviceState);
    787                         continue;
    788                 }
    789                 debugLog("setProfileServiceState() - "
    790                     + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
    791                     + " service " + serviceName);
    792 
    793                 mProfileServicesState.put(serviceName,pendingState);
    794                 Intent intent = new Intent(this,services[i]);
    795                 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
    796                 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
    797                 startService(intent);
    798                 return;
    799             }
    800         }
    801     }
    802 
    803 
    804     @SuppressWarnings("rawtypes")
    805     private void setProfileServiceState(Class[] services, int state) {
    806         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
    807             debugLog("setProfileServiceState() - Invalid state, leaving...");
    808             return;
    809         }
    810 
    811         int expectedCurrentState= BluetoothAdapter.STATE_OFF;
    812         int pendingState = BluetoothAdapter.STATE_TURNING_ON;
    813         if (state == BluetoothAdapter.STATE_OFF) {
    814             expectedCurrentState= BluetoothAdapter.STATE_ON;
    815             pendingState = BluetoothAdapter.STATE_TURNING_OFF;
    816         }
    817 
    818         for (int i=0; i <services.length;i++) {
    819             String serviceName = services[i].getName();
    820             String simpleName = services[i].getSimpleName();
    821 
    822             if (simpleName.equals("GattService")) continue;
    823 
    824             Integer serviceState = mProfileServicesState.get(serviceName);
    825             if(serviceState != null && serviceState != expectedCurrentState) {
    826                 debugLog("setProfileServiceState() - Unable to "
    827                     + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
    828                     + " service " + serviceName
    829                     + ". Invalid state: " + serviceState);
    830                 continue;
    831             }
    832 
    833             debugLog("setProfileServiceState() - "
    834                 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
    835                 + " service " + serviceName);
    836 
    837             mProfileServicesState.put(serviceName,pendingState);
    838             Intent intent = new Intent(this,services[i]);
    839             intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
    840             intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
    841             startService(intent);
    842         }
    843     }
    844 
    845     private boolean isAvailable() {
    846         return !mCleaningUp;
    847     }
    848 
    849     /**
    850      * Handlers for incoming service calls
    851      */
    852     private AdapterServiceBinder mBinder;
    853 
    854     /**
    855      * The Binder implementation must be declared to be a static class, with
    856      * the AdapterService instance passed in the constructor. Furthermore,
    857      * when the AdapterService shuts down, the reference to the AdapterService
    858      * must be explicitly removed.
    859      *
    860      * Otherwise, a memory leak can occur from repeated starting/stopping the
    861      * service...Please refer to android.os.Binder for further details on
    862      * why an inner instance class should be avoided.
    863      *
    864      */
    865     private static class AdapterServiceBinder extends IBluetooth.Stub {
    866         private AdapterService mService;
    867 
    868         public AdapterServiceBinder(AdapterService svc) {
    869             mService = svc;
    870         }
    871         public boolean cleanup() {
    872             mService = null;
    873             return true;
    874         }
    875 
    876         public AdapterService getService() {
    877             if (mService  != null && mService.isAvailable()) {
    878                 return mService;
    879             }
    880             return null;
    881         }
    882         public boolean isEnabled() {
    883             // don't check caller, may be called from system UI
    884             AdapterService service = getService();
    885             if (service == null) return false;
    886             return service.isEnabled();
    887         }
    888 
    889         public int getState() {
    890             // don't check caller, may be called from system UI
    891             AdapterService service = getService();
    892             if (service == null) return  BluetoothAdapter.STATE_OFF;
    893             return service.getState();
    894         }
    895 
    896         public boolean enable() {
    897             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    898                 (!Utils.checkCaller())) {
    899                 Log.w(TAG, "enable() - Not allowed for non-active user and non system user");
    900                 return false;
    901             }
    902             AdapterService service = getService();
    903             if (service == null) return false;
    904             return service.enable();
    905         }
    906 
    907         public boolean enableNoAutoConnect() {
    908             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    909                 (!Utils.checkCaller())) {
    910                 Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user");
    911                 return false;
    912             }
    913 
    914             AdapterService service = getService();
    915             if (service == null) return false;
    916             return service.enableNoAutoConnect();
    917         }
    918 
    919         public boolean disable() {
    920             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    921                 (!Utils.checkCaller())) {
    922                 Log.w(TAG, "disable() - Not allowed for non-active user and non system user");
    923                 return false;
    924             }
    925 
    926             AdapterService service = getService();
    927             if (service == null) return false;
    928             return service.disable();
    929         }
    930 
    931         public String getAddress() {
    932             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    933                 (!Utils.checkCallerAllowManagedProfiles(mService))) {
    934                 Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user");
    935                 return null;
    936             }
    937 
    938             AdapterService service = getService();
    939             if (service == null) return null;
    940             return service.getAddress();
    941         }
    942 
    943         public ParcelUuid[] getUuids() {
    944             if (!Utils.checkCaller()) {
    945                 Log.w(TAG, "getUuids() - Not allowed for non-active user");
    946                 return new ParcelUuid[0];
    947             }
    948 
    949             AdapterService service = getService();
    950             if (service == null) return new ParcelUuid[0];
    951             return service.getUuids();
    952         }
    953 
    954         public String getName() {
    955             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    956                 (!Utils.checkCaller())) {
    957                 Log.w(TAG, "getName() - Not allowed for non-active user and non system user");
    958                 return null;
    959             }
    960 
    961             AdapterService service = getService();
    962             if (service == null) return null;
    963             return service.getName();
    964         }
    965 
    966         public boolean setName(String name) {
    967             if (!Utils.checkCaller()) {
    968                 Log.w(TAG, "setName() - Not allowed for non-active user");
    969                 return false;
    970             }
    971 
    972             AdapterService service = getService();
    973             if (service == null) return false;
    974             return service.setName(name);
    975         }
    976 
    977         public int getScanMode() {
    978             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
    979                 Log.w(TAG, "getScanMode() - Not allowed for non-active user");
    980                 return BluetoothAdapter.SCAN_MODE_NONE;
    981             }
    982 
    983             AdapterService service = getService();
    984             if (service == null) return BluetoothAdapter.SCAN_MODE_NONE;
    985             return service.getScanMode();
    986         }
    987 
    988         public boolean setScanMode(int mode, int duration) {
    989             if (!Utils.checkCaller()) {
    990                 Log.w(TAG, "setScanMode() - Not allowed for non-active user");
    991                 return false;
    992             }
    993 
    994             AdapterService service = getService();
    995             if (service == null) return false;
    996             return service.setScanMode(mode,duration);
    997         }
    998 
    999         public int getDiscoverableTimeout() {
   1000             if (!Utils.checkCaller()) {
   1001                 Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user");
   1002                 return 0;
   1003             }
   1004 
   1005             AdapterService service = getService();
   1006             if (service == null) return 0;
   1007             return service.getDiscoverableTimeout();
   1008         }
   1009 
   1010         public boolean setDiscoverableTimeout(int timeout) {
   1011             if (!Utils.checkCaller()) {
   1012                 Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user");
   1013                 return false;
   1014             }
   1015 
   1016             AdapterService service = getService();
   1017             if (service == null) return false;
   1018             return service.setDiscoverableTimeout(timeout);
   1019         }
   1020 
   1021         public boolean startDiscovery() {
   1022             if (!Utils.checkCaller()) {
   1023                 Log.w(TAG, "startDiscovery() - Not allowed for non-active user");
   1024                 return false;
   1025             }
   1026 
   1027             AdapterService service = getService();
   1028             if (service == null) return false;
   1029             return service.startDiscovery();
   1030         }
   1031 
   1032         public boolean cancelDiscovery() {
   1033             if (!Utils.checkCaller()) {
   1034                 Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user");
   1035                 return false;
   1036             }
   1037 
   1038             AdapterService service = getService();
   1039             if (service == null) return false;
   1040             return service.cancelDiscovery();
   1041         }
   1042         public boolean isDiscovering() {
   1043             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1044                 Log.w(TAG, "isDiscovering() - Not allowed for non-active user");
   1045                 return false;
   1046             }
   1047 
   1048             AdapterService service = getService();
   1049             if (service == null) return false;
   1050             return service.isDiscovering();
   1051         }
   1052 
   1053         public BluetoothDevice[] getBondedDevices() {
   1054             // don't check caller, may be called from system UI
   1055             AdapterService service = getService();
   1056             if (service == null) return new BluetoothDevice[0];
   1057             return service.getBondedDevices();
   1058         }
   1059 
   1060         public int getAdapterConnectionState() {
   1061             // don't check caller, may be called from system UI
   1062             AdapterService service = getService();
   1063             if (service == null) return BluetoothAdapter.STATE_DISCONNECTED;
   1064             return service.getAdapterConnectionState();
   1065         }
   1066 
   1067         public int getProfileConnectionState(int profile) {
   1068             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1069                 Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user");
   1070                 return BluetoothProfile.STATE_DISCONNECTED;
   1071             }
   1072 
   1073             AdapterService service = getService();
   1074             if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
   1075             return service.getProfileConnectionState(profile);
   1076         }
   1077 
   1078         public boolean createBond(BluetoothDevice device, int transport) {
   1079             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1080                 Log.w(TAG, "createBond() - Not allowed for non-active user");
   1081                 return false;
   1082             }
   1083 
   1084             AdapterService service = getService();
   1085             if (service == null) return false;
   1086             return service.createBond(device, transport, null);
   1087         }
   1088 
   1089         public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) {
   1090             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1091                 Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user");
   1092                 return false;
   1093             }
   1094 
   1095             AdapterService service = getService();
   1096             if (service == null) return false;
   1097             return service.createBond(device, transport, oobData);
   1098         }
   1099 
   1100         public boolean cancelBondProcess(BluetoothDevice device) {
   1101             if (!Utils.checkCaller()) {
   1102                 Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user");
   1103                 return false;
   1104             }
   1105 
   1106             AdapterService service = getService();
   1107             if (service == null) return false;
   1108             return service.cancelBondProcess(device);
   1109         }
   1110 
   1111         public boolean removeBond(BluetoothDevice device) {
   1112             if (!Utils.checkCaller()) {
   1113                 Log.w(TAG, "removeBond() - Not allowed for non-active user");
   1114                 return false;
   1115             }
   1116 
   1117             AdapterService service = getService();
   1118             if (service == null) return false;
   1119             return service.removeBond(device);
   1120         }
   1121 
   1122         public int getBondState(BluetoothDevice device) {
   1123             // don't check caller, may be called from system UI
   1124             AdapterService service = getService();
   1125             if (service == null) return BluetoothDevice.BOND_NONE;
   1126             return service.getBondState(device);
   1127         }
   1128 
   1129         public int getConnectionState(BluetoothDevice device) {
   1130             AdapterService service = getService();
   1131             if (service == null) return 0;
   1132             return service.getConnectionState(device);
   1133         }
   1134 
   1135         public String getRemoteName(BluetoothDevice device) {
   1136             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1137                 Log.w(TAG, "getRemoteName() - Not allowed for non-active user");
   1138                 return null;
   1139             }
   1140 
   1141             AdapterService service = getService();
   1142             if (service == null) return null;
   1143             return service.getRemoteName(device);
   1144         }
   1145 
   1146         public int getRemoteType(BluetoothDevice device) {
   1147             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1148                 Log.w(TAG, "getRemoteType() - Not allowed for non-active user");
   1149                 return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
   1150             }
   1151 
   1152             AdapterService service = getService();
   1153             if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
   1154             return service.getRemoteType(device);
   1155         }
   1156 
   1157         public String getRemoteAlias(BluetoothDevice device) {
   1158             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1159                 Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user");
   1160                 return null;
   1161             }
   1162 
   1163             AdapterService service = getService();
   1164             if (service == null) return null;
   1165             return service.getRemoteAlias(device);
   1166         }
   1167 
   1168         public boolean setRemoteAlias(BluetoothDevice device, String name) {
   1169             if (!Utils.checkCaller()) {
   1170                 Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user");
   1171                 return false;
   1172             }
   1173 
   1174             AdapterService service = getService();
   1175             if (service == null) return false;
   1176             return service.setRemoteAlias(device, name);
   1177         }
   1178 
   1179         public int getRemoteClass(BluetoothDevice device) {
   1180             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1181                 Log.w(TAG, "getRemoteClass() - Not allowed for non-active user");
   1182                 return 0;
   1183             }
   1184 
   1185             AdapterService service = getService();
   1186             if (service == null) return 0;
   1187             return service.getRemoteClass(device);
   1188         }
   1189 
   1190         public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
   1191             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1192                 Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user");
   1193                 return new ParcelUuid[0];
   1194             }
   1195 
   1196             AdapterService service = getService();
   1197             if (service == null) return new ParcelUuid[0];
   1198             return service.getRemoteUuids(device);
   1199         }
   1200 
   1201         public boolean fetchRemoteUuids(BluetoothDevice device) {
   1202             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1203                 Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user");
   1204                 return false;
   1205             }
   1206 
   1207             AdapterService service = getService();
   1208             if (service == null) return false;
   1209             return service.fetchRemoteUuids(device);
   1210         }
   1211 
   1212 
   1213 
   1214         public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
   1215             if (!Utils.checkCaller()) {
   1216                 Log.w(TAG, "setPin() - Not allowed for non-active user");
   1217                 return false;
   1218             }
   1219 
   1220             AdapterService service = getService();
   1221             if (service == null) return false;
   1222             return service.setPin(device, accept, len, pinCode);
   1223         }
   1224 
   1225         public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
   1226             if (!Utils.checkCaller()) {
   1227                 Log.w(TAG, "setPasskey() - Not allowed for non-active user");
   1228                 return false;
   1229             }
   1230 
   1231             AdapterService service = getService();
   1232             if (service == null) return false;
   1233             return service.setPasskey(device, accept, len, passkey);
   1234         }
   1235 
   1236         public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
   1237             if (!Utils.checkCaller()) {
   1238                 Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user");
   1239                 return false;
   1240             }
   1241 
   1242             AdapterService service = getService();
   1243             if (service == null) return false;
   1244             return service.setPairingConfirmation(device, accept);
   1245         }
   1246 
   1247         public int getPhonebookAccessPermission(BluetoothDevice device) {
   1248             if (!Utils.checkCaller()) {
   1249                 Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user");
   1250                 return BluetoothDevice.ACCESS_UNKNOWN;
   1251             }
   1252 
   1253             AdapterService service = getService();
   1254             if (service == null) return BluetoothDevice.ACCESS_UNKNOWN;
   1255             return service.getPhonebookAccessPermission(device);
   1256         }
   1257 
   1258         public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) {
   1259             if (!Utils.checkCaller()) {
   1260                 Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user");
   1261                 return false;
   1262             }
   1263 
   1264             AdapterService service = getService();
   1265             if (service == null) return false;
   1266             return service.setPhonebookAccessPermission(device, value);
   1267         }
   1268 
   1269         public int getMessageAccessPermission(BluetoothDevice device) {
   1270             if (!Utils.checkCaller()) {
   1271                 Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user");
   1272                 return BluetoothDevice.ACCESS_UNKNOWN;
   1273             }
   1274 
   1275             AdapterService service = getService();
   1276             if (service == null) return BluetoothDevice.ACCESS_UNKNOWN;
   1277             return service.getMessageAccessPermission(device);
   1278         }
   1279 
   1280         public boolean setMessageAccessPermission(BluetoothDevice device, int value) {
   1281             if (!Utils.checkCaller()) {
   1282                 Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user");
   1283                 return false;
   1284             }
   1285 
   1286             AdapterService service = getService();
   1287             if (service == null) return false;
   1288             return service.setMessageAccessPermission(device, value);
   1289         }
   1290 
   1291         public int getSimAccessPermission(BluetoothDevice device) {
   1292             if (!Utils.checkCaller()) {
   1293                 Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user");
   1294                 return BluetoothDevice.ACCESS_UNKNOWN;
   1295             }
   1296 
   1297             AdapterService service = getService();
   1298             if (service == null) return BluetoothDevice.ACCESS_UNKNOWN;
   1299             return service.getSimAccessPermission(device);
   1300         }
   1301 
   1302         public boolean setSimAccessPermission(BluetoothDevice device, int value) {
   1303             if (!Utils.checkCaller()) {
   1304                 Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user");
   1305                 return false;
   1306             }
   1307 
   1308             AdapterService service = getService();
   1309             if (service == null) return false;
   1310             return service.setSimAccessPermission(device, value);
   1311         }
   1312 
   1313         public void sendConnectionStateChange(BluetoothDevice
   1314                 device, int profile, int state, int prevState) {
   1315             AdapterService service = getService();
   1316             if (service == null) return;
   1317             service.sendConnectionStateChange(device, profile, state, prevState);
   1318         }
   1319 
   1320         public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
   1321                                                   ParcelUuid uuid, int port, int flag) {
   1322             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1323                 Log.w(TAG, "connectSocket() - Not allowed for non-active user");
   1324                 return null;
   1325             }
   1326 
   1327             AdapterService service = getService();
   1328             if (service == null) return null;
   1329             return service.connectSocket(device, type, uuid, port, flag);
   1330         }
   1331 
   1332         public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
   1333                                                         ParcelUuid uuid, int port, int flag) {
   1334             if (!Utils.checkCallerAllowManagedProfiles(mService)) {
   1335                 Log.w(TAG, "createSocketChannel() - Not allowed for non-active user");
   1336                 return null;
   1337             }
   1338 
   1339             AdapterService service = getService();
   1340             if (service == null) return null;
   1341             return service.createSocketChannel(type, serviceName, uuid, port, flag);
   1342         }
   1343         public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) {
   1344             if (!Utils.checkCaller()) {
   1345                 Log.w(TAG,"sdpSea(): not allowed for non-active user");
   1346                 return false;
   1347             }
   1348 
   1349             AdapterService service = getService();
   1350             if (service == null) return false;
   1351             return service.sdpSearch(device,uuid);
   1352         }
   1353 
   1354         public boolean configHciSnoopLog(boolean enable) {
   1355             if (Binder.getCallingUid() != Process.SYSTEM_UID) {
   1356                 EventLog.writeEvent(0x534e4554 /* SNET */, "Bluetooth", Binder.getCallingUid(),
   1357                         "configHciSnoopLog() - Not allowed for non-active user b/18643224");
   1358                 return false;
   1359             }
   1360 
   1361             AdapterService service = getService();
   1362             if (service == null) return false;
   1363             return service.configHciSnoopLog(enable);
   1364         }
   1365 
   1366         public boolean factoryReset() {
   1367             AdapterService service = getService();
   1368             if (service == null) return false;
   1369             service.disable();
   1370             return service.factoryReset();
   1371 
   1372         }
   1373 
   1374         public void registerCallback(IBluetoothCallback cb) {
   1375             AdapterService service = getService();
   1376             if (service == null) return ;
   1377             service.registerCallback(cb);
   1378          }
   1379 
   1380          public void unregisterCallback(IBluetoothCallback cb) {
   1381              AdapterService service = getService();
   1382              if (service == null) return ;
   1383              service.unregisterCallback(cb);
   1384          }
   1385 
   1386          public boolean isMultiAdvertisementSupported() {
   1387              AdapterService service = getService();
   1388              if (service == null) return false;
   1389              return service.isMultiAdvertisementSupported();
   1390          }
   1391 
   1392          public boolean isPeripheralModeSupported() {
   1393              AdapterService service = getService();
   1394              if (service == null) return false;
   1395              return service.isPeripheralModeSupported();
   1396          }
   1397 
   1398          public boolean isOffloadedFilteringSupported() {
   1399              AdapterService service = getService();
   1400              if (service == null) return false;
   1401              int val = service.getNumOfOffloadedScanFilterSupported();
   1402              return (val >= MIN_OFFLOADED_FILTERS);
   1403          }
   1404 
   1405          public boolean isOffloadedScanBatchingSupported() {
   1406              AdapterService service = getService();
   1407              if (service == null) return false;
   1408              int val = service.getOffloadedScanResultStorage();
   1409              return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES);
   1410          }
   1411 
   1412          public boolean isActivityAndEnergyReportingSupported() {
   1413              AdapterService service = getService();
   1414              if (service == null) return false;
   1415              return service.isActivityAndEnergyReportingSupported();
   1416          }
   1417 
   1418          public BluetoothActivityEnergyInfo reportActivityInfo() {
   1419              AdapterService service = getService();
   1420              if (service == null) return null;
   1421              return service.reportActivityInfo();
   1422          }
   1423 
   1424          public void requestActivityInfo(ResultReceiver result) {
   1425              Bundle bundle = new Bundle();
   1426              bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY,
   1427                      reportActivityInfo());
   1428              result.send(0, bundle);
   1429          }
   1430 
   1431         public void onLeServiceUp(){
   1432              AdapterService service = getService();
   1433              if (service == null) return;
   1434              service.onLeServiceUp();
   1435          }
   1436 
   1437          public void onBrEdrDown(){
   1438              AdapterService service = getService();
   1439              if (service == null) return;
   1440              service.onBrEdrDown();
   1441          }
   1442 
   1443          public void dump(FileDescriptor fd, String[] args) {
   1444             PrintWriter writer = new PrintWriter(new FileOutputStream(fd));
   1445             AdapterService service = getService();
   1446             if (service == null) return;
   1447             service.dump(fd, writer, args);
   1448          }
   1449     };
   1450 
   1451     // ----API Methods--------
   1452 
   1453      boolean isEnabled() {
   1454         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1455         return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
   1456      }
   1457 
   1458      int getState() {
   1459         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1460         if (mAdapterProperties != null) return mAdapterProperties.getState();
   1461         return  BluetoothAdapter.STATE_OFF;
   1462      }
   1463 
   1464      boolean enable() {
   1465         return enable (false);
   1466      }
   1467 
   1468       public boolean enableNoAutoConnect() {
   1469          return enable (true);
   1470      }
   1471 
   1472      public synchronized boolean enable(boolean quietMode) {
   1473          enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
   1474 
   1475          debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);
   1476          mQuietmode = quietMode;
   1477          Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
   1478          mAdapterStateMachine.sendMessage(m);
   1479          mBluetoothStartTime = System.currentTimeMillis();
   1480          return true;
   1481      }
   1482 
   1483      boolean disable() {
   1484         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
   1485 
   1486         debugLog("disable() called...");
   1487         Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF);
   1488         mAdapterStateMachine.sendMessage(m);
   1489         return true;
   1490     }
   1491 
   1492      String getAddress() {
   1493         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1494 
   1495         String addrString = null;
   1496         byte[] address = mAdapterProperties.getAddress();
   1497         return Utils.getAddressStringFromByte(address);
   1498     }
   1499 
   1500      ParcelUuid[] getUuids() {
   1501         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1502 
   1503         return mAdapterProperties.getUuids();
   1504     }
   1505 
   1506      String getName() {
   1507         enforceCallingOrSelfPermission(BLUETOOTH_PERM,
   1508                                        "Need BLUETOOTH permission");
   1509 
   1510         try {
   1511             return mAdapterProperties.getName();
   1512         } catch (Throwable t) {
   1513             debugLog("getName() - Unexpected exception (" + t + ")");
   1514         }
   1515         return null;
   1516     }
   1517 
   1518      boolean setName(String name) {
   1519         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1520                                        "Need BLUETOOTH ADMIN permission");
   1521 
   1522         return mAdapterProperties.setName(name);
   1523     }
   1524 
   1525      int getScanMode() {
   1526         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1527 
   1528         return mAdapterProperties.getScanMode();
   1529     }
   1530 
   1531      boolean setScanMode(int mode, int duration) {
   1532         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1533 
   1534         setDiscoverableTimeout(duration);
   1535 
   1536         int newMode = convertScanModeToHal(mode);
   1537         return mAdapterProperties.setScanMode(newMode);
   1538     }
   1539 
   1540      int getDiscoverableTimeout() {
   1541         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1542 
   1543         return mAdapterProperties.getDiscoverableTimeout();
   1544     }
   1545 
   1546      boolean setDiscoverableTimeout(int timeout) {
   1547         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1548 
   1549         return mAdapterProperties.setDiscoverableTimeout(timeout);
   1550     }
   1551 
   1552      boolean startDiscovery() {
   1553         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1554                                        "Need BLUETOOTH ADMIN permission");
   1555 
   1556         return startDiscoveryNative();
   1557     }
   1558 
   1559      boolean cancelDiscovery() {
   1560         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1561                                        "Need BLUETOOTH ADMIN permission");
   1562 
   1563         return cancelDiscoveryNative();
   1564     }
   1565 
   1566      boolean isDiscovering() {
   1567         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1568 
   1569         return mAdapterProperties.isDiscovering();
   1570     }
   1571 
   1572      BluetoothDevice[] getBondedDevices() {
   1573         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1574         return mAdapterProperties.getBondedDevices();
   1575     }
   1576 
   1577      int getAdapterConnectionState() {
   1578         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1579         return mAdapterProperties.getConnectionState();
   1580     }
   1581 
   1582      int getProfileConnectionState(int profile) {
   1583         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1584 
   1585         return mAdapterProperties.getProfileConnectionState(profile);
   1586     }
   1587      boolean sdpSearch(BluetoothDevice device,ParcelUuid uuid) {
   1588          enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1589          if(mSdpManager != null) {
   1590              mSdpManager.sdpSearch(device,uuid);
   1591              return true;
   1592          } else {
   1593              return false;
   1594          }
   1595      }
   1596 
   1597      boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
   1598         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1599             "Need BLUETOOTH ADMIN permission");
   1600         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1601         if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
   1602             return false;
   1603         }
   1604 
   1605         // Pairing is unreliable while scanning, so cancel discovery
   1606         // Note, remove this when native stack improves
   1607         cancelDiscoveryNative();
   1608 
   1609         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
   1610         msg.obj = device;
   1611         msg.arg1 = transport;
   1612 
   1613         if (oobData != null) {
   1614             Bundle oobDataBundle = new Bundle();
   1615             oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
   1616             msg.setData(oobDataBundle);
   1617         }
   1618         mBondStateMachine.sendMessage(msg);
   1619         return true;
   1620     }
   1621 
   1622       public boolean isQuietModeEnabled() {
   1623           debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode);
   1624           return mQuietmode;
   1625      }
   1626 
   1627      public void autoConnect(){
   1628         if (getState() != BluetoothAdapter.STATE_ON){
   1629              errorLog("autoConnect() - BT is not ON. Exiting autoConnect");
   1630              return;
   1631          }
   1632          if (isQuietModeEnabled() == false) {
   1633              debugLog( "autoConnect() - Initiate auto connection on BT on...");
   1634              // Phone profiles.
   1635              autoConnectHeadset();
   1636              autoConnectA2dp();
   1637 
   1638              // Car Kitt profiles.
   1639              autoConnectHeadsetClient();
   1640              autoConnectA2dpSink();
   1641              autoConnectPbapClient();
   1642          }
   1643          else {
   1644              debugLog( "autoConnect() - BT is in quiet mode. Not initiating auto connections");
   1645          }
   1646     }
   1647 
   1648     public void updateUuids() {
   1649         debugLog( "updateUuids() - Updating UUIDs for bonded devices");
   1650         BluetoothDevice[] bondedDevices = getBondedDevices();
   1651         if (bondedDevices == null) return;
   1652 
   1653         for (BluetoothDevice device : bondedDevices) {
   1654             mRemoteDevices.updateUuids(device);
   1655         }
   1656     }
   1657 
   1658      private void autoConnectHeadset(){
   1659         HeadsetService  hsService = HeadsetService.getHeadsetService();
   1660 
   1661         BluetoothDevice bondedDevices[] = getBondedDevices();
   1662         if ((bondedDevices == null) ||(hsService == null)) {
   1663             return;
   1664         }
   1665         for (BluetoothDevice device : bondedDevices) {
   1666             if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){
   1667                 debugLog("autoConnectHeadset() - Connecting HFP with " + device.toString());
   1668                 hsService.connect(device);
   1669             }
   1670         }
   1671     }
   1672 
   1673      private void autoConnectA2dp(){
   1674         A2dpService a2dpSservice = A2dpService.getA2dpService();
   1675         BluetoothDevice bondedDevices[] = getBondedDevices();
   1676         if ((bondedDevices == null) ||(a2dpSservice == null)) {
   1677             return;
   1678         }
   1679         for (BluetoothDevice device : bondedDevices) {
   1680             if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){
   1681                 debugLog("autoConnectA2dp() - Connecting A2DP with " + device.toString());
   1682                 a2dpSservice.connect(device);
   1683             }
   1684         }
   1685     }
   1686 
   1687     private void autoConnectHeadsetClient() {
   1688         HeadsetClientService headsetClientService = HeadsetClientService.getHeadsetClientService();
   1689         BluetoothDevice bondedDevices[] = getBondedDevices();
   1690         if ((bondedDevices == null) || (headsetClientService == null)) {
   1691             return;
   1692         }
   1693 
   1694         for (BluetoothDevice device : bondedDevices) {
   1695             if (headsetClientService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT){
   1696             debugLog("autoConnectHeadsetClient() - Connecting Headset Client with " +
   1697                 device.toString());
   1698             headsetClientService.connect(device);
   1699             }
   1700         }
   1701     }
   1702 
   1703     private void autoConnectA2dpSink() {
   1704          A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService();
   1705          BluetoothDevice bondedDevices[] = getBondedDevices();
   1706          if ((bondedDevices == null) || (a2dpSinkService == null)) {
   1707              return;
   1708          }
   1709 
   1710          for (BluetoothDevice device : bondedDevices) {
   1711              if (a2dpSinkService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
   1712                  debugLog("autoConnectA2dpSink() - Connecting A2DP Sink with " + device.toString());
   1713                  a2dpSinkService.connect(device);
   1714              }
   1715          }
   1716      }
   1717 
   1718      private void autoConnectPbapClient(){
   1719          PbapClientService pbapClientService = PbapClientService.getPbapClientService();
   1720          BluetoothDevice bondedDevices[] = getBondedDevices();
   1721          if ((bondedDevices == null) || (pbapClientService == null)) {
   1722              return;
   1723          }
   1724          for (BluetoothDevice device : bondedDevices) {
   1725              if (pbapClientService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
   1726                  debugLog("autoConnectPbapClient() - Connecting PBAP Client with " +
   1727                          device.toString());
   1728                  pbapClientService.connect(device);
   1729              }
   1730          }
   1731     }
   1732 
   1733 
   1734      public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){
   1735         if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) &&
   1736             (isQuietModeEnabled()== false)){
   1737             Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES);
   1738             m.obj = device;
   1739             m.arg1 = (int)firstProfileStatus;
   1740             mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT);
   1741         }
   1742     }
   1743 
   1744      private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){
   1745         if (getState()!= BluetoothAdapter.STATE_ON){
   1746             return;
   1747         }
   1748         HeadsetService  hsService = HeadsetService.getHeadsetService();
   1749         A2dpService a2dpService = A2dpService.getA2dpService();
   1750 
   1751         // if any of the profile service is  null, second profile connection not required
   1752         if ((hsService == null) ||(a2dpService == null )){
   1753             return;
   1754         }
   1755         List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices();
   1756         List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices();
   1757         // Check if the device is in disconnected state and if so return
   1758         // We ned to connect other profile only if one of the profile is still in connected state
   1759         // This is required to avoide a race condition in which profiles would
   1760         // automaticlly connect if the disconnection is initiated within 6 seconds of connection
   1761         //First profile connection being rejected is an exception
   1762         if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&&
   1763             (PROFILE_CONN_CONNECTED  == firstProfileStatus)){
   1764             return;
   1765         }
   1766         if((hfConnDevList.isEmpty()) &&
   1767             (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){
   1768             hsService.connect(device);
   1769         }
   1770         else if((a2dpConnDevList.isEmpty()) &&
   1771             (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){
   1772             a2dpService.connect(device);
   1773         }
   1774     }
   1775 
   1776      private void adjustOtherHeadsetPriorities(HeadsetService  hsService,
   1777              List<BluetoothDevice> connectedDeviceList) {
   1778         for (BluetoothDevice device : getBondedDevices()) {
   1779            if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1780                !connectedDeviceList.contains(device)) {
   1781                hsService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1782            }
   1783         }
   1784      }
   1785 
   1786     private void adjustOtherSinkPriorities(A2dpService a2dpService,
   1787              BluetoothDevice connectedDevice) {
   1788          for (BluetoothDevice device : getBondedDevices()) {
   1789              if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1790                  !device.equals(connectedDevice)) {
   1791                  a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1792              }
   1793          }
   1794      }
   1795 
   1796     private void adjustOtherHeadsetClientPriorities(HeadsetClientService hsService,
   1797             BluetoothDevice connectedDevice) {
   1798         for (BluetoothDevice device : getBondedDevices()) {
   1799            if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1800                !device.equals(connectedDevice)) {
   1801                hsService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1802            }
   1803         }
   1804      }
   1805 
   1806     private void adjustOtherA2dpSinkPriorities(A2dpSinkService a2dpService,
   1807             BluetoothDevice connectedDevice) {
   1808         for (BluetoothDevice device : getBondedDevices()) {
   1809             if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1810                 !device.equals(connectedDevice)) {
   1811                 a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1812             }
   1813         }
   1814     }
   1815 
   1816     private void adjustOtherPbapClientPriorities(PbapClientService pbapService,
   1817             BluetoothDevice connectedDevice) {
   1818         for (BluetoothDevice device : getBondedDevices()) {
   1819            if (pbapService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1820                !device.equals(connectedDevice)) {
   1821                pbapService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1822            }
   1823         }
   1824      }
   1825 
   1826     void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){
   1827         switch (profileId) {
   1828             case BluetoothProfile.HEADSET:
   1829                 HeadsetService  hsService = HeadsetService.getHeadsetService();
   1830                 List<BluetoothDevice> deviceList = hsService.getConnectedDevices();
   1831                 if ((hsService != null) &&
   1832                    (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))) {
   1833                     adjustOtherHeadsetPriorities(hsService, deviceList);
   1834                     hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1835                 }
   1836                 break;
   1837 
   1838             case BluetoothProfile.A2DP:
   1839                 A2dpService a2dpService = A2dpService.getA2dpService();
   1840                 if ((a2dpService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT !=
   1841                         a2dpService.getPriority(device))) {
   1842                     adjustOtherSinkPriorities(a2dpService, device);
   1843                     a2dpService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1844                 }
   1845                 break;
   1846 
   1847            case BluetoothProfile.A2DP_SINK:
   1848                 A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService();
   1849                 if ((a2dpSinkService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT !=
   1850                         a2dpSinkService.getPriority(device))) {
   1851                     adjustOtherA2dpSinkPriorities(a2dpSinkService, device);
   1852                     a2dpSinkService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1853                 }
   1854                 break;
   1855 
   1856             case BluetoothProfile.HEADSET_CLIENT:
   1857                 HeadsetClientService headsetClientService =
   1858                         HeadsetClientService.getHeadsetClientService();
   1859                 if ((headsetClientService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT !=
   1860                         headsetClientService.getPriority(device))) {
   1861                     adjustOtherHeadsetClientPriorities(headsetClientService, device);
   1862                     headsetClientService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1863                 }
   1864                 break;
   1865 
   1866             case BluetoothProfile.PBAP_CLIENT:
   1867                 PbapClientService pbapClientService = PbapClientService.getPbapClientService();
   1868                 if ((pbapClientService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT !=
   1869                         pbapClientService.getPriority(device))) {
   1870                     adjustOtherPbapClientPriorities(pbapClientService, device);
   1871                     pbapClientService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1872                 }
   1873                 break;
   1874 
   1875             default:
   1876                 Log.w(TAG, "Attempting to set Auto Connect priority on invalid profile");
   1877                 break;
   1878          }
   1879     }
   1880 
   1881      boolean cancelBondProcess(BluetoothDevice device) {
   1882         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
   1883         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1884         return cancelBondNative(addr);
   1885     }
   1886 
   1887      boolean removeBond(BluetoothDevice device) {
   1888         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
   1889         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1890         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
   1891             return false;
   1892         }
   1893         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
   1894         msg.obj = device;
   1895         mBondStateMachine.sendMessage(msg);
   1896         return true;
   1897     }
   1898 
   1899     int getBondState(BluetoothDevice device) {
   1900         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1901         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1902         if (deviceProp == null) {
   1903             return BluetoothDevice.BOND_NONE;
   1904         }
   1905         return deviceProp.getBondState();
   1906     }
   1907 
   1908     int getConnectionState(BluetoothDevice device) {
   1909         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1910         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1911         return getConnectionStateNative(addr);
   1912     }
   1913 
   1914      String getRemoteName(BluetoothDevice device) {
   1915         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1916         if (mRemoteDevices == null) return null;
   1917         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1918         if (deviceProp == null) return null;
   1919         return deviceProp.getName();
   1920     }
   1921 
   1922      int getRemoteType(BluetoothDevice device) {
   1923         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1924         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1925         if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
   1926         return deviceProp.getDeviceType();
   1927     }
   1928 
   1929      String getRemoteAlias(BluetoothDevice device) {
   1930         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1931         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1932         if (deviceProp == null) return null;
   1933         return deviceProp.getAlias();
   1934     }
   1935 
   1936      boolean setRemoteAlias(BluetoothDevice device, String name) {
   1937         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1938         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1939         if (deviceProp == null) return false;
   1940         deviceProp.setAlias(device, name);
   1941         return true;
   1942     }
   1943 
   1944      int getRemoteClass(BluetoothDevice device) {
   1945         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1946         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1947         if (deviceProp == null) return 0;
   1948 
   1949         return deviceProp.getBluetoothClass();
   1950     }
   1951 
   1952      ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
   1953         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1954         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1955         if (deviceProp == null) return null;
   1956         return deviceProp.getUuids();
   1957     }
   1958 
   1959      boolean fetchRemoteUuids(BluetoothDevice device) {
   1960         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1961         mRemoteDevices.fetchUuids(device);
   1962         return true;
   1963     }
   1964 
   1965 
   1966      boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
   1967         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1968                                        "Need BLUETOOTH ADMIN permission");
   1969         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1970         // Only allow setting a pin in bonding state, or bonded state in case of security upgrade.
   1971         if (deviceProp == null ||
   1972             (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING &&
   1973              deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) {
   1974             return false;
   1975         }
   1976 
   1977         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1978         return pinReplyNative(addr, accept, len, pinCode);
   1979     }
   1980 
   1981      boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
   1982         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1983         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1984         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
   1985             return false;
   1986         }
   1987 
   1988         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1989         return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
   1990                 Utils.byteArrayToInt(passkey));
   1991     }
   1992 
   1993      boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
   1994         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1995                                        "Need BLUETOOTH ADMIN permission");
   1996         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1997         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
   1998             return false;
   1999         }
   2000 
   2001         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   2002         return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
   2003                 accept, 0);
   2004     }
   2005 
   2006     int getPhonebookAccessPermission(BluetoothDevice device) {
   2007         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2008         SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
   2009                 Context.MODE_PRIVATE);
   2010         if (!pref.contains(device.getAddress())) {
   2011             return BluetoothDevice.ACCESS_UNKNOWN;
   2012         }
   2013         return pref.getBoolean(device.getAddress(), false)
   2014                 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED;
   2015     }
   2016 
   2017     boolean setPhonebookAccessPermission(BluetoothDevice device, int value) {
   2018         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
   2019                                        "Need BLUETOOTH PRIVILEGED permission");
   2020         SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
   2021                 Context.MODE_PRIVATE);
   2022         SharedPreferences.Editor editor = pref.edit();
   2023         if (value == BluetoothDevice.ACCESS_UNKNOWN) {
   2024             editor.remove(device.getAddress());
   2025         } else {
   2026             editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
   2027         }
   2028         return editor.commit();
   2029     }
   2030 
   2031     int getMessageAccessPermission(BluetoothDevice device) {
   2032         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2033         SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
   2034                 Context.MODE_PRIVATE);
   2035         if (!pref.contains(device.getAddress())) {
   2036             return BluetoothDevice.ACCESS_UNKNOWN;
   2037         }
   2038         return pref.getBoolean(device.getAddress(), false)
   2039                 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED;
   2040     }
   2041 
   2042     boolean setMessageAccessPermission(BluetoothDevice device, int value) {
   2043         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
   2044                                        "Need BLUETOOTH PRIVILEGED permission");
   2045         SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
   2046                 Context.MODE_PRIVATE);
   2047         SharedPreferences.Editor editor = pref.edit();
   2048         if (value == BluetoothDevice.ACCESS_UNKNOWN) {
   2049             editor.remove(device.getAddress());
   2050         } else {
   2051             editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
   2052         }
   2053         return editor.commit();
   2054     }
   2055 
   2056     int getSimAccessPermission(BluetoothDevice device) {
   2057         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2058         SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE,
   2059                 Context.MODE_PRIVATE);
   2060         if (!pref.contains(device.getAddress())) {
   2061             return BluetoothDevice.ACCESS_UNKNOWN;
   2062         }
   2063         return pref.getBoolean(device.getAddress(), false)
   2064                 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED;
   2065     }
   2066 
   2067     boolean setSimAccessPermission(BluetoothDevice device, int value) {
   2068         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
   2069                                        "Need BLUETOOTH PRIVILEGED permission");
   2070         SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE,
   2071                 Context.MODE_PRIVATE);
   2072         SharedPreferences.Editor editor = pref.edit();
   2073         if (value == BluetoothDevice.ACCESS_UNKNOWN) {
   2074             editor.remove(device.getAddress());
   2075         } else {
   2076             editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
   2077         }
   2078         return editor.commit();
   2079     }
   2080 
   2081      void sendConnectionStateChange(BluetoothDevice
   2082             device, int profile, int state, int prevState) {
   2083         // TODO(BT) permission check?
   2084         // Since this is a binder call check if Bluetooth is on still
   2085         if (getState() == BluetoothAdapter.STATE_OFF) return;
   2086 
   2087         mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
   2088 
   2089     }
   2090 
   2091      ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
   2092                                               ParcelUuid uuid, int port, int flag) {
   2093         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2094         int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()),
   2095                    type, Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid());
   2096         if (fd < 0) {
   2097             errorLog("Failed to connect socket");
   2098             return null;
   2099         }
   2100         return ParcelFileDescriptor.adoptFd(fd);
   2101     }
   2102 
   2103      ParcelFileDescriptor createSocketChannel(int type, String serviceName,
   2104                                                     ParcelUuid uuid, int port, int flag) {
   2105         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2106         int fd =  createSocketChannelNative(type, serviceName,
   2107                                  Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid());
   2108         if (fd < 0) {
   2109             errorLog("Failed to create socket channel");
   2110             return null;
   2111         }
   2112         return ParcelFileDescriptor.adoptFd(fd);
   2113     }
   2114 
   2115     boolean configHciSnoopLog(boolean enable) {
   2116         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2117         return configHciSnoopLogNative(enable);
   2118     }
   2119 
   2120     boolean factoryReset() {
   2121         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
   2122         return factoryResetNative();
   2123     }
   2124 
   2125      void registerCallback(IBluetoothCallback cb) {
   2126          mCallbacks.register(cb);
   2127       }
   2128 
   2129       void unregisterCallback(IBluetoothCallback cb) {
   2130          mCallbacks.unregister(cb);
   2131       }
   2132 
   2133     public int getNumOfAdvertisementInstancesSupported() {
   2134         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2135         return mAdapterProperties.getNumOfAdvertisementInstancesSupported();
   2136     }
   2137 
   2138     public boolean isMultiAdvertisementSupported() {
   2139         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2140         return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA;
   2141     }
   2142 
   2143     public boolean isRpaOffloadSupported() {
   2144         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2145         return mAdapterProperties.isRpaOffloadSupported();
   2146     }
   2147 
   2148     public int getNumOfOffloadedIrkSupported() {
   2149         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2150         return mAdapterProperties.getNumOfOffloadedIrkSupported();
   2151     }
   2152 
   2153     public int getNumOfOffloadedScanFilterSupported() {
   2154         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2155         return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
   2156     }
   2157 
   2158     public boolean isPeripheralModeSupported() {
   2159         return getResources().getBoolean(R.bool.config_bluetooth_le_peripheral_mode_supported);
   2160     }
   2161 
   2162     public int getOffloadedScanResultStorage() {
   2163         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2164         return mAdapterProperties.getOffloadedScanResultStorage();
   2165     }
   2166 
   2167     private boolean isActivityAndEnergyReportingSupported() {
   2168           enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
   2169           return mAdapterProperties.isActivityAndEnergyReportingSupported();
   2170     }
   2171 
   2172     private BluetoothActivityEnergyInfo reportActivityInfo() {
   2173         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
   2174         if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON ||
   2175                 !mAdapterProperties.isActivityAndEnergyReportingSupported()) {
   2176             return null;
   2177         }
   2178 
   2179         // Pull the data. The callback will notify mEnergyInfoLock.
   2180         readEnergyInfo();
   2181 
   2182         synchronized (mEnergyInfoLock) {
   2183             try {
   2184                 mEnergyInfoLock.wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS);
   2185             } catch (InterruptedException e) {
   2186                 // Just continue, the energy data may be stale but we won't miss anything next time
   2187                 // we query.
   2188             }
   2189 
   2190             final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(
   2191                     SystemClock.elapsedRealtime(),
   2192                     mStackReportedState,
   2193                     mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs,
   2194                     mEnergyUsedTotalVoltAmpSecMicro);
   2195 
   2196             // Count the number of entries that have byte counts > 0
   2197             int arrayLen = 0;
   2198             for (int i = 0; i < mUidTraffic.size(); i++) {
   2199                 final UidTraffic traffic = mUidTraffic.valueAt(i);
   2200                 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
   2201                     arrayLen++;
   2202                 }
   2203             }
   2204 
   2205             // Copy the traffic objects whose byte counts are > 0 and reset the originals.
   2206             final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null;
   2207             int putIdx = 0;
   2208             for (int i = 0; i < mUidTraffic.size(); i++) {
   2209                 final UidTraffic traffic = mUidTraffic.valueAt(i);
   2210                 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
   2211                     result[putIdx++] = traffic.clone();
   2212                     traffic.setRxBytes(0);
   2213                     traffic.setTxBytes(0);
   2214                 }
   2215             }
   2216 
   2217             info.setUidTraffic(result);
   2218 
   2219             // Read on clear values; a record of data is created with
   2220             // timstamp and new samples are collected until read again
   2221             mStackReportedState = 0;
   2222             mTxTimeTotalMs = 0;
   2223             mRxTimeTotalMs = 0;
   2224             mIdleTimeTotalMs = 0;
   2225             mEnergyUsedTotalVoltAmpSecMicro = 0;
   2226             return info;
   2227         }
   2228     }
   2229 
   2230     public int getTotalNumOfTrackableAdvertisements() {
   2231         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   2232         return mAdapterProperties.getTotalNumOfTrackableAdvertisements();
   2233     }
   2234 
   2235     public void onLeServiceUp() {
   2236         Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
   2237         mAdapterStateMachine.sendMessage(m);
   2238     }
   2239 
   2240     public void onBrEdrDown() {
   2241         Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
   2242         mAdapterStateMachine.sendMessage(m);
   2243     }
   2244 
   2245     private static int convertScanModeToHal(int mode) {
   2246         switch (mode) {
   2247             case BluetoothAdapter.SCAN_MODE_NONE:
   2248                 return AbstractionLayer.BT_SCAN_MODE_NONE;
   2249             case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
   2250                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
   2251             case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
   2252                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
   2253         }
   2254        // errorLog("Incorrect scan mode in convertScanModeToHal");
   2255         return -1;
   2256     }
   2257 
   2258     static int convertScanModeFromHal(int mode) {
   2259         switch (mode) {
   2260             case AbstractionLayer.BT_SCAN_MODE_NONE:
   2261                 return BluetoothAdapter.SCAN_MODE_NONE;
   2262             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
   2263                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
   2264             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
   2265                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
   2266         }
   2267         //errorLog("Incorrect scan mode in convertScanModeFromHal");
   2268         return -1;
   2269     }
   2270 
   2271     // This function is called from JNI. It allows native code to set a single wake
   2272     // alarm. If an alarm is already pending and a new request comes in, the alarm
   2273     // will be rescheduled (i.e. the previously set alarm will be cancelled).
   2274     private boolean setWakeAlarm(long delayMillis, boolean shouldWake) {
   2275         synchronized (this) {
   2276             if (mPendingAlarm != null) {
   2277                 mAlarmManager.cancel(mPendingAlarm);
   2278             }
   2279 
   2280             long wakeupTime = SystemClock.elapsedRealtime() + delayMillis;
   2281             int type = shouldWake
   2282                 ? AlarmManager.ELAPSED_REALTIME_WAKEUP
   2283                 : AlarmManager.ELAPSED_REALTIME;
   2284 
   2285             Intent intent = new Intent(ACTION_ALARM_WAKEUP);
   2286             mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
   2287             mAlarmManager.setExact(type, wakeupTime, mPendingAlarm);
   2288             return true;
   2289         }
   2290     }
   2291 
   2292     // This function is called from JNI. It allows native code to acquire a single wake lock.
   2293     // If the wake lock is already held, this function returns success. Although this function
   2294     // only supports acquiring a single wake lock at a time right now, it will eventually be
   2295     // extended to allow acquiring an arbitrary number of wake locks. The current interface
   2296     // takes |lockName| as a parameter in anticipation of that implementation.
   2297     private boolean acquireWakeLock(String lockName) {
   2298         synchronized (this) {
   2299             if (mWakeLock == null) {
   2300                 mWakeLockName = lockName;
   2301                 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
   2302             }
   2303 
   2304             if (!mWakeLock.isHeld())
   2305                 mWakeLock.acquire();
   2306         }
   2307         return true;
   2308     }
   2309 
   2310     // This function is called from JNI. It allows native code to release a wake lock acquired
   2311     // by |acquireWakeLock|. If the wake lock is not held, this function returns failure.
   2312     // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is
   2313     // needed here. See the comment for |acquireWakeLock| for an explanation of the interface.
   2314     private boolean releaseWakeLock(String lockName) {
   2315         synchronized (this) {
   2316             if (mWakeLock == null) {
   2317                 errorLog("Repeated wake lock release; aborting release: " + lockName);
   2318                 return false;
   2319             }
   2320 
   2321             if (mWakeLock.isHeld())
   2322                 mWakeLock.release();
   2323         }
   2324         return true;
   2325     }
   2326 
   2327     private void energyInfoCallback(int status, int ctrl_state, long tx_time, long rx_time,
   2328                                     long idle_time, long energy_used, UidTraffic[] data)
   2329             throws RemoteException {
   2330         if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID &&
   2331                 ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) {
   2332             // Energy is product of mA, V and ms. If the chipset doesn't
   2333             // report it, we have to compute it from time
   2334             if (energy_used == 0) {
   2335                 try {
   2336                     final long txMah = Math.multiplyExact(tx_time, getTxCurrentMa());
   2337                     final long rxMah = Math.multiplyExact(rx_time, getRxCurrentMa());
   2338                     final long idleMah = Math.multiplyExact(idle_time, getIdleCurrentMa());
   2339                     energy_used = (long) (Math.addExact(Math.addExact(txMah, rxMah), idleMah)
   2340                             * getOperatingVolt());
   2341                 } catch (ArithmeticException e) {
   2342                     Slog.wtf(TAG, "overflow in bluetooth energy callback", e);
   2343                     // Energy is already 0 if the exception was thrown.
   2344                 }
   2345             }
   2346 
   2347             synchronized (mEnergyInfoLock) {
   2348                 mStackReportedState = ctrl_state;
   2349                 long totalTxTimeMs;
   2350                 long totalRxTimeMs;
   2351                 long totalIdleTimeMs;
   2352                 long totalEnergy;
   2353                 try {
   2354                     totalTxTimeMs = Math.addExact(mTxTimeTotalMs, tx_time);
   2355                     totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rx_time);
   2356                     totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idle_time);
   2357                     totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energy_used);
   2358                 } catch (ArithmeticException e) {
   2359                     // This could be because we accumulated a lot of time, or we got a very strange
   2360                     // value from the controller (more likely). Discard this data.
   2361                     Slog.wtf(TAG, "overflow in bluetooth energy callback", e);
   2362                     totalTxTimeMs = mTxTimeTotalMs;
   2363                     totalRxTimeMs = mRxTimeTotalMs;
   2364                     totalIdleTimeMs = mIdleTimeTotalMs;
   2365                     totalEnergy = mEnergyUsedTotalVoltAmpSecMicro;
   2366                 }
   2367 
   2368                 mTxTimeTotalMs = totalTxTimeMs;
   2369                 mRxTimeTotalMs = totalRxTimeMs;
   2370                 mIdleTimeTotalMs = totalIdleTimeMs;
   2371                 mEnergyUsedTotalVoltAmpSecMicro = totalEnergy;
   2372 
   2373                 for (UidTraffic traffic : data) {
   2374                     UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid());
   2375                     if (existingTraffic == null) {
   2376                         mUidTraffic.put(traffic.getUid(), traffic);
   2377                     } else {
   2378                         existingTraffic.addRxBytes(traffic.getRxBytes());
   2379                         existingTraffic.addTxBytes(traffic.getTxBytes());
   2380                     }
   2381                 }
   2382                 mEnergyInfoLock.notifyAll();
   2383             }
   2384         }
   2385 
   2386         debugLog("energyInfoCallback() status = " + status +
   2387                 "tx_time = " + tx_time + "rx_time = " + rx_time +
   2388                 "idle_time = " + idle_time + "energy_used = " + energy_used +
   2389                 "ctrl_state = " + ctrl_state +
   2390                 "traffic = " + Arrays.toString(data));
   2391     }
   2392 
   2393     private int getIdleCurrentMa() {
   2394         return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma);
   2395     }
   2396 
   2397     private int getTxCurrentMa() {
   2398         return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma);
   2399     }
   2400 
   2401     private int getRxCurrentMa() {
   2402         return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma);
   2403     }
   2404 
   2405     private double getOperatingVolt() {
   2406         return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0;
   2407     }
   2408 
   2409     private String getStateString() {
   2410         int state = getState();
   2411         switch (state) {
   2412             case BluetoothAdapter.STATE_OFF:
   2413                 return "STATE_OFF";
   2414             case BluetoothAdapter.STATE_TURNING_ON:
   2415                 return "STATE_TURNING_ON";
   2416             case BluetoothAdapter.STATE_ON:
   2417                 return "STATE_ON";
   2418             case BluetoothAdapter.STATE_TURNING_OFF:
   2419                 return "STATE_TURNING_OFF";
   2420             case BluetoothAdapter.STATE_BLE_TURNING_ON:
   2421                 return "STATE_BLE_TURNING_ON";
   2422             case BluetoothAdapter.STATE_BLE_ON:
   2423                 return "STATE_BLE_ON";
   2424             case BluetoothAdapter.STATE_BLE_TURNING_OFF:
   2425                 return "STATE_BLE_TURNING_OFF";
   2426             default:
   2427                 return "UNKNOWN STATE: " + state;
   2428         }
   2429     }
   2430 
   2431     @Override
   2432     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
   2433         enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
   2434 
   2435         if (args.length > 0) {
   2436             debugLog("dumpsys arguments, check for protobuf output: " +
   2437                     TextUtils.join(" ", args));
   2438             if (args[0].startsWith("--proto")) {
   2439                 if (args[0].equals("--proto-java-bin")) {
   2440                     dumpJava(fd);
   2441                 } else {
   2442                     dumpNative(fd, args);
   2443                 }
   2444                 return;
   2445             }
   2446         }
   2447 
   2448         long onDuration = System.currentTimeMillis() - mBluetoothStartTime;
   2449         String onDurationString = String.format("%02d:%02d:%02d.%03d",
   2450                                       (int)(onDuration / (1000 * 60 * 60)),
   2451                                       (int)((onDuration / (1000 * 60)) % 60),
   2452                                       (int)((onDuration / 1000) % 60),
   2453                                       (int)(onDuration % 1000));
   2454 
   2455         writer.println("Bluetooth Status");
   2456         writer.println("  enabled: " + isEnabled());
   2457         writer.println("  state: " + getStateString());
   2458         writer.println("  address: " + getAddress());
   2459         writer.println("  name: " + getName());
   2460         writer.println("  time since enabled: " + onDurationString + "\n");
   2461 
   2462         writer.println("Bonded devices:");
   2463         for (BluetoothDevice device : getBondedDevices()) {
   2464           writer.println("  " + device.getAddress() +
   2465               " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " +
   2466               device.getName());
   2467         }
   2468 
   2469         // Dump profile information
   2470         StringBuilder sb = new StringBuilder();
   2471         synchronized (mProfiles) {
   2472             for (ProfileService profile : mProfiles) {
   2473                 profile.dump(sb);
   2474             }
   2475         }
   2476 
   2477         writer.write(sb.toString());
   2478         writer.flush();
   2479 
   2480         dumpNative(fd, args);
   2481     }
   2482 
   2483     private void dumpJava(FileDescriptor fd) {
   2484         BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog();
   2485 
   2486         for (ProfileService profile : mProfiles) {
   2487             profile.dumpProto(log);
   2488         }
   2489 
   2490         try {
   2491             FileOutputStream protoOut = new FileOutputStream(fd);
   2492             String protoOutString =
   2493                 Base64.encodeToString(log.toByteArray(), Base64.DEFAULT);
   2494             protoOut.write(protoOutString.getBytes(StandardCharsets.UTF_8));
   2495             protoOut.close();
   2496         } catch (IOException e) {
   2497             errorLog("Unable to write Java protobuf to file descriptor.");
   2498         }
   2499     }
   2500 
   2501     private void debugLog(String msg) {
   2502         if (DBG) Log.d(TAG, msg);
   2503     }
   2504 
   2505     private void errorLog(String msg) {
   2506         Log.e(TAG, msg);
   2507     }
   2508 
   2509     private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() {
   2510         @Override
   2511         public void onReceive(Context context, Intent intent) {
   2512             synchronized (AdapterService.this) {
   2513                 mPendingAlarm = null;
   2514                 alarmFiredNative();
   2515             }
   2516         }
   2517     };
   2518 
   2519     private native static void classInitNative();
   2520     private native boolean initNative();
   2521     private native void cleanupNative();
   2522     /*package*/ native boolean enableNative(boolean startRestricted);
   2523     /*package*/ native boolean disableNative();
   2524     /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val);
   2525     /*package*/ native boolean getAdapterPropertiesNative();
   2526     /*package*/ native boolean getAdapterPropertyNative(int type);
   2527     /*package*/ native boolean setAdapterPropertyNative(int type);
   2528     /*package*/ native boolean
   2529         setDevicePropertyNative(byte[] address, int type, byte[] val);
   2530     /*package*/ native boolean getDevicePropertyNative(byte[] address, int type);
   2531 
   2532     /*package*/ native boolean createBondNative(byte[] address, int transport);
   2533     /*package*/ native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData);
   2534     /*package*/ native boolean removeBondNative(byte[] address);
   2535     /*package*/ native boolean cancelBondNative(byte[] address);
   2536     /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid);
   2537 
   2538     /*package*/ native int getConnectionStateNative(byte[] address);
   2539 
   2540     private native boolean startDiscoveryNative();
   2541     private native boolean cancelDiscoveryNative();
   2542 
   2543     private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin);
   2544     private native boolean sspReplyNative(byte[] address, int type, boolean
   2545             accept, int passkey);
   2546 
   2547     /*package*/ native boolean getRemoteServicesNative(byte[] address);
   2548     /*package*/ native boolean getRemoteMasInstancesNative(byte[] address);
   2549 
   2550     private native int readEnergyInfo();
   2551     // TODO(BT) move this to ../btsock dir
   2552     private native int connectSocketNative(byte[] address, int type,
   2553                                            byte[] uuid, int port, int flag, int callingUid);
   2554     private native int createSocketChannelNative(int type, String serviceName,
   2555                                                  byte[] uuid, int port, int flag, int callingUid);
   2556 
   2557     /*package*/ native boolean configHciSnoopLogNative(boolean enable);
   2558     /*package*/ native boolean factoryResetNative();
   2559 
   2560     private native void alarmFiredNative();
   2561     private native void dumpNative(FileDescriptor fd, String[] arguments);
   2562 
   2563     private native void interopDatabaseClearNative();
   2564     private native void interopDatabaseAddNative(int feature, byte[] address, int length);
   2565 
   2566     protected void finalize() {
   2567         cleanup();
   2568         if (TRACE_REF) {
   2569             synchronized (AdapterService.class) {
   2570                 sRefCount--;
   2571                 debugLog("finalize() - REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount);
   2572             }
   2573         }
   2574     }
   2575 }
   2576