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