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