Home | History | Annotate | Download | only in btservice
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  * @hide
     19  */
     20 
     21 package com.android.bluetooth.btservice;
     22 
     23 import android.app.Application;
     24 import android.app.Service;
     25 import android.bluetooth.BluetoothAdapter;
     26 import android.bluetooth.BluetoothDevice;
     27 import android.bluetooth.BluetoothProfile;
     28 import android.bluetooth.IBluetooth;
     29 import android.bluetooth.IBluetoothCallback;
     30 import android.bluetooth.IBluetoothManager;
     31 import android.bluetooth.IBluetoothManagerCallback;
     32 import android.content.BroadcastReceiver;
     33 import android.content.ContentResolver;
     34 import android.content.Context;
     35 import android.content.Intent;
     36 import android.content.IntentFilter;
     37 import android.os.Binder;
     38 import android.os.Bundle;
     39 import android.os.Handler;
     40 import android.os.IBinder;
     41 import android.os.Message;
     42 import android.os.ParcelFileDescriptor;
     43 import android.os.ParcelUuid;
     44 import android.os.Process;
     45 import android.os.RemoteCallbackList;
     46 import android.os.RemoteException;
     47 import android.provider.Settings;
     48 import android.util.Log;
     49 import android.util.Pair;
     50 import com.android.bluetooth.a2dp.A2dpService;
     51 import com.android.bluetooth.hid.HidService;
     52 import com.android.bluetooth.hfp.HeadsetService;
     53 import com.android.bluetooth.hdp.HealthService;
     54 import com.android.bluetooth.pan.PanService;
     55 import com.android.bluetooth.R;
     56 import com.android.bluetooth.Utils;
     57 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
     58 import java.io.FileDescriptor;
     59 import java.io.IOException;
     60 import java.util.ArrayList;
     61 import java.util.HashMap;
     62 import java.util.Set;
     63 import java.util.Map;
     64 import java.util.Iterator;
     65 import java.util.Map.Entry;
     66 import java.util.List;
     67 import android.content.pm.PackageManager;
     68 import android.os.ServiceManager;
     69 
     70 public class AdapterService extends Service {
     71     private static final String TAG = "BluetoothAdapterService";
     72     private static final boolean DBG = false;
     73     private static final boolean TRACE_REF = true;
     74     //For Debugging only
     75     private static int sRefCount=0;
     76 
     77     public static final String ACTION_LOAD_ADAPTER_PROPERTIES =
     78         "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES";
     79     public static final String ACTION_SERVICE_STATE_CHANGED =
     80         "com.android.bluetooth.btservice.action.STATE_CHANGED";
     81     public static final String EXTRA_ACTION="action";
     82     public static final int PROFILE_CONN_CONNECTED  = 1;
     83     public static final int PROFILE_CONN_REJECTED  = 2;
     84 
     85     static final String BLUETOOTH_ADMIN_PERM =
     86         android.Manifest.permission.BLUETOOTH_ADMIN;
     87     static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
     88 
     89     private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY;
     90 
     91     static {
     92         classInitNative();
     93     }
     94 
     95     private static AdapterService sAdapterService;
     96     public static synchronized AdapterService getAdapterService(){
     97         if (sAdapterService != null && !sAdapterService.mCleaningUp) {
     98             if (DBG) Log.d(TAG, "getAdapterService(): returning " + sAdapterService);
     99             return sAdapterService;
    100         }
    101         if (DBG)  {
    102             if (sAdapterService == null) {
    103                 Log.d(TAG, "getAdapterService(): service not available");
    104             } else if (sAdapterService.mCleaningUp) {
    105                 Log.d(TAG,"getAdapterService(): service is cleaning up");
    106             }
    107         }
    108         return null;
    109     }
    110 
    111     private static synchronized void setAdapterService(AdapterService instance) {
    112         if (instance != null && !instance.mCleaningUp) {
    113             if (DBG) Log.d(TAG, "setAdapterService(): set to: " + sAdapterService);
    114             sAdapterService = instance;
    115         } else {
    116             if (DBG)  {
    117                 if (sAdapterService == null) {
    118                     Log.d(TAG, "setAdapterService(): service not available");
    119                 } else if (sAdapterService.mCleaningUp) {
    120                     Log.d(TAG,"setAdapterService(): service is cleaning up");
    121                 }
    122             }
    123         }
    124     }
    125 
    126     private static synchronized void clearAdapterService() {
    127         sAdapterService = null;
    128     }
    129 
    130     private AdapterProperties mAdapterProperties;
    131     private AdapterState mAdapterStateMachine;
    132     private BondStateMachine mBondStateMachine;
    133     private JniCallbacks mJniCallbacks;
    134     private RemoteDevices mRemoteDevices;
    135     private boolean mProfilesStarted;
    136     private boolean mNativeAvailable;
    137     private boolean mCleaningUp;
    138     private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>();
    139     private RemoteCallbackList<IBluetoothCallback> mCallbacks;//Only BluetoothManagerService should be registered
    140     private int mCurrentRequestId;
    141     private boolean mQuietmode = false;
    142 
    143     public AdapterService() {
    144         super();
    145         if (TRACE_REF) {
    146             synchronized (AdapterService.class) {
    147                 sRefCount++;
    148                 Log.d(TAG, "REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount);
    149             }
    150         }
    151     }
    152 
    153     public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
    154         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED);
    155         m.obj = device;
    156         m.arg1 = profileId;
    157         m.arg2 = newState;
    158         Bundle b = new Bundle(1);
    159         b.putInt("prevState", prevState);
    160         m.setData(b);
    161         mHandler.sendMessage(m);
    162     }
    163 
    164     private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
    165         if (((profileId == BluetoothProfile.A2DP) ||(profileId == BluetoothProfile.HEADSET)) &&
    166             (newState == BluetoothProfile.STATE_CONNECTED)){
    167             if (DBG) debugLog( "Profile connected. Schedule missing profile connection if any");
    168             connectOtherProfile(device, PROFILE_CONN_CONNECTED);
    169             setProfileAutoConnectionPriority(device, profileId);
    170         }
    171         IBluetooth.Stub binder = mBinder;
    172         if (binder != null) {
    173             try {
    174                 binder.sendConnectionStateChange(device, profileId, newState,prevState);
    175             } catch (RemoteException re) {
    176                 Log.e(TAG, "",re);
    177             }
    178         }
    179     }
    180 
    181     public void onProfileServiceStateChanged(String serviceName, int state) {
    182         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
    183         m.obj=serviceName;
    184         m.arg1 = state;
    185         mHandler.sendMessage(m);
    186     }
    187 
    188     private void processProfileServiceStateChanged(String serviceName, int state) {
    189         boolean doUpdate=false;
    190         boolean isTurningOn;
    191         boolean isTurningOff;
    192 
    193         synchronized (mProfileServicesState) {
    194             Integer prevState = mProfileServicesState.get(serviceName);
    195             if (prevState != null && prevState != state) {
    196                 mProfileServicesState.put(serviceName,state);
    197                 doUpdate=true;
    198             }
    199         }
    200         if (DBG) Log.d(TAG,"onProfileServiceStateChange: serviceName=" + serviceName + ", state = " + state +", doUpdate = " + doUpdate);
    201 
    202         if (!doUpdate) {
    203             return;
    204         }
    205 
    206         synchronized (mAdapterStateMachine) {
    207             isTurningOff = mAdapterStateMachine.isTurningOff();
    208             isTurningOn = mAdapterStateMachine.isTurningOn();
    209         }
    210 
    211         if (isTurningOff) {
    212             //Process stop or disable pending
    213             //Check if all services are stopped if so, do cleanup
    214             //if (DBG) Log.d(TAG,"Checking if all profiles are stopped...");
    215             synchronized (mProfileServicesState) {
    216                 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
    217                 while (i.hasNext()) {
    218                     Map.Entry<String,Integer> entry = i.next();
    219                     if (BluetoothAdapter.STATE_OFF != entry.getValue()) {
    220                         Log.d(TAG, "Profile still running: " + entry.getKey());
    221                         return;
    222                     }
    223                 }
    224             }
    225             if (DBG) Log.d(TAG, "All profile services stopped...");
    226             //Send message to state machine
    227             mProfilesStarted=false;
    228             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STOPPED));
    229         } else if (isTurningOn) {
    230             //Process start pending
    231             //Check if all services are started if so, update state
    232             //if (DBG) Log.d(TAG,"Checking if all profiles are running...");
    233             synchronized (mProfileServicesState) {
    234                 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
    235                 while (i.hasNext()) {
    236                     Map.Entry<String,Integer> entry = i.next();
    237                     if (BluetoothAdapter.STATE_ON != entry.getValue()) {
    238                         Log.d(TAG, "Profile still not running:" + entry.getKey());
    239                         return;
    240                     }
    241                 }
    242             }
    243             if (DBG) Log.d(TAG, "All profile services started.");
    244             mProfilesStarted=true;
    245             //Send message to state machine
    246             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
    247         }
    248     }
    249 
    250     @Override
    251     public void onCreate() {
    252         super.onCreate();
    253         if (DBG) debugLog("onCreate");
    254         mBinder = new AdapterServiceBinder(this);
    255         mAdapterProperties = new AdapterProperties(this);
    256         mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);
    257         mJniCallbacks =  new JniCallbacks(mAdapterStateMachine, mAdapterProperties);
    258         initNative();
    259         mNativeAvailable=true;
    260         mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
    261         //Load the name and address
    262         getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
    263         getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
    264 
    265     }
    266 
    267     @Override
    268     public IBinder onBind(Intent intent) {
    269         if (DBG) debugLog("onBind");
    270         return mBinder;
    271     }
    272     public boolean onUnbind(Intent intent) {
    273         if (DBG) debugLog("onUnbind, calling cleanup");
    274         cleanup();
    275         return super.onUnbind(intent);
    276     }
    277 
    278     public void onDestroy() {
    279         debugLog("****onDestroy()********");
    280     }
    281 
    282     void processStart() {
    283         if (DBG) debugLog("processStart()");
    284         Class[] supportedProfileServices = Config.getSupportedProfiles();
    285         //Initialize data objects
    286         for (int i=0; i < supportedProfileServices.length;i++) {
    287             mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
    288         }
    289         mRemoteDevices = new RemoteDevices(this);
    290         mAdapterProperties.init(mRemoteDevices);
    291 
    292         if (DBG) {debugLog("processStart(): Make Bond State Machine");}
    293         mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
    294 
    295         mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
    296 
    297         //FIXME: Set static instance here???
    298         setAdapterService(this);
    299 
    300         //Start profile services
    301         if (!mProfilesStarted && supportedProfileServices.length >0) {
    302             //Startup all profile services
    303             setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
    304         }else {
    305             if (DBG) {debugLog("processStart(): Profile Services alreay started");}
    306             mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
    307         }
    308     }
    309 
    310     void startBluetoothDisable() {
    311         mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE));
    312     }
    313 
    314     boolean stopProfileServices() {
    315         Class[] supportedProfileServices = Config.getSupportedProfiles();
    316         if (mProfilesStarted && supportedProfileServices.length>0) {
    317             setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
    318             return true;
    319         } else {
    320             if (DBG) {debugLog("stopProfileServices(): No profiles services to stop or already stopped.");}
    321             return false;
    322         }
    323     }
    324 
    325      void updateAdapterState(int prevState, int newState){
    326         if (mCallbacks !=null) {
    327             int n=mCallbacks.beginBroadcast();
    328             Log.d(TAG,"Broadcasting updateAdapterState() to " + n + " receivers.");
    329             for (int i=0; i <n;i++) {
    330                 try {
    331                     mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);
    332                 }  catch (RemoteException e) {
    333                     Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
    334                 }
    335             }
    336             mCallbacks.finishBroadcast();
    337         }
    338     }
    339 
    340     void cleanup () {
    341         if (DBG)debugLog("cleanup()");
    342         if (mCleaningUp) {
    343             Log.w(TAG,"*************service already starting to cleanup... Ignoring cleanup request.........");
    344             return;
    345         }
    346 
    347         mCleaningUp = true;
    348 
    349         if (mAdapterStateMachine != null) {
    350             mAdapterStateMachine.doQuit();
    351             mAdapterStateMachine.cleanup();
    352         }
    353 
    354         if (mBondStateMachine != null) {
    355             mBondStateMachine.doQuit();
    356             mBondStateMachine.cleanup();
    357         }
    358 
    359         if (mRemoteDevices != null) {
    360             mRemoteDevices.cleanup();
    361         }
    362 
    363         if (mNativeAvailable) {
    364             Log.d(TAG, "Cleaning up adapter native....");
    365             cleanupNative();
    366             Log.d(TAG, "Done cleaning up adapter native....");
    367             mNativeAvailable=false;
    368         }
    369 
    370         if (mAdapterProperties != null) {
    371             mAdapterProperties.cleanup();
    372         }
    373 
    374         if (mJniCallbacks != null) {
    375             mJniCallbacks.cleanup();
    376         }
    377 
    378         if (mProfileServicesState != null) {
    379             mProfileServicesState.clear();
    380         }
    381 
    382         clearAdapterService();
    383 
    384         if (mBinder != null) {
    385             mBinder.cleanup();
    386             mBinder = null;  //Do not remove. Otherwise Binder leak!
    387         }
    388 
    389         if (mCallbacks !=null) {
    390             mCallbacks.kill();
    391         }
    392 
    393         if (DBG)debugLog("cleanup() done");
    394     }
    395 
    396     private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1;
    397     private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20;
    398     private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30;
    399     private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000;
    400 
    401     private final Handler mHandler = new Handler() {
    402         @Override
    403         public void handleMessage(Message msg) {
    404             if (DBG) debugLog("Message: " + msg.what);
    405 
    406             switch (msg.what) {
    407                 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: {
    408                     if(DBG) debugLog("MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
    409                     processProfileServiceStateChanged((String) msg.obj, msg.arg1);
    410                 }
    411                     break;
    412                 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: {
    413                     if (DBG) debugLog( "MESSAGE_PROFILE_CONNECTION_STATE_CHANGED");
    414                     processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR));
    415                 }
    416                     break;
    417                 case MESSAGE_CONNECT_OTHER_PROFILES: {
    418                     if (DBG) debugLog( "MESSAGE_CONNECT_OTHER_PROFILES");
    419                     processConnectOtherProfiles((BluetoothDevice) msg.obj,msg.arg1);
    420                 }
    421                     break;
    422             }
    423         }
    424     };
    425 
    426     @SuppressWarnings("rawtypes")
    427     private void setProfileServiceState(Class[] services, int state) {
    428         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
    429             Log.w(TAG,"setProfileServiceState(): invalid state...Leaving...");
    430             return;
    431         }
    432 
    433         int expectedCurrentState= BluetoothAdapter.STATE_OFF;
    434         int pendingState = BluetoothAdapter.STATE_TURNING_ON;
    435         if (state == BluetoothAdapter.STATE_OFF) {
    436             expectedCurrentState= BluetoothAdapter.STATE_ON;
    437             pendingState = BluetoothAdapter.STATE_TURNING_OFF;
    438         }
    439 
    440         for (int i=0; i <services.length;i++) {
    441             String serviceName = services[i].getName();
    442             Integer serviceState = mProfileServicesState.get(serviceName);
    443             if(serviceState != null && serviceState != expectedCurrentState) {
    444                 Log.w(TAG, "Unable to " + (state == BluetoothAdapter.STATE_OFF? "start" : "stop" ) +" service " +
    445                         serviceName+". Invalid state: " + serviceState);
    446                 continue;
    447             }
    448 
    449             if (DBG) {
    450                 Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " +
    451                         serviceName);
    452             }
    453 
    454             mProfileServicesState.put(serviceName,pendingState);
    455             Intent intent = new Intent(this,services[i]);
    456             intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
    457             intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
    458             startService(intent);
    459         }
    460     }
    461 
    462     private boolean isAvailable() {
    463         return !mCleaningUp;
    464     }
    465 
    466     /**
    467      * Handlers for incoming service calls
    468      */
    469     private AdapterServiceBinder mBinder;
    470 
    471     /**
    472      * The Binder implementation must be declared to be a static class, with
    473      * the AdapterService instance passed in the constructor. Furthermore,
    474      * when the AdapterService shuts down, the reference to the AdapterService
    475      * must be explicitly removed.
    476      *
    477      * Otherwise, a memory leak can occur from repeated starting/stopping the
    478      * service...Please refer to android.os.Binder for further details on
    479      * why an inner instance class should be avoided.
    480      *
    481      */
    482     private static class AdapterServiceBinder extends IBluetooth.Stub {
    483         private AdapterService mService;
    484 
    485         public AdapterServiceBinder(AdapterService svc) {
    486             mService = svc;
    487         }
    488         public boolean cleanup() {
    489             mService = null;
    490             return true;
    491         }
    492 
    493         public AdapterService getService() {
    494             if (mService  != null && mService.isAvailable()) {
    495                 return mService;
    496             }
    497             return null;
    498         }
    499         public boolean isEnabled() {
    500             // don't check caller, may be called from system UI
    501             AdapterService service = getService();
    502             if (service == null) return false;
    503             return service.isEnabled();
    504         }
    505 
    506         public int getState() {
    507             // don't check caller, may be called from system UI
    508             AdapterService service = getService();
    509             if (service == null) return  BluetoothAdapter.STATE_OFF;
    510             return service.getState();
    511         }
    512 
    513         public boolean enable() {
    514             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    515                 (!Utils.checkCaller())) {
    516                 Log.w(TAG,"enable(): not allowed for non-active user and non system user");
    517                 return false;
    518 	    }
    519 
    520             AdapterService service = getService();
    521             if (service == null) return false;
    522             return service.enable();
    523         }
    524 
    525         public boolean enableNoAutoConnect() {
    526             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    527                 (!Utils.checkCaller())) {
    528                 Log.w(TAG,"enableNoAuto(): not allowed for non-active user and non system user");
    529                 return false;
    530 	    }
    531 
    532             AdapterService service = getService();
    533             if (service == null) return false;
    534             return service.enableNoAutoConnect();
    535         }
    536 
    537         public boolean disable() {
    538             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    539                 (!Utils.checkCaller())) {
    540                 Log.w(TAG,"disable(): not allowed for non-active user and non system user");
    541                 return false;
    542 	    }
    543 
    544             AdapterService service = getService();
    545             if (service == null) return false;
    546             return service.disable();
    547         }
    548 
    549         public String getAddress() {
    550             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    551                 (!Utils.checkCaller())) {
    552                 Log.w(TAG,"getAddress(): not allowed for non-active user and non system user");
    553                 return null;
    554 	    }
    555 
    556             AdapterService service = getService();
    557             if (service == null) return null;
    558             return service.getAddress();
    559         }
    560 
    561         public ParcelUuid[] getUuids() {
    562             if (!Utils.checkCaller()) {
    563                 Log.w(TAG,"getUuids(): not allowed for non-active user");
    564                 return new ParcelUuid[0];
    565             }
    566 
    567             AdapterService service = getService();
    568             if (service == null) return new ParcelUuid[0];
    569             return service.getUuids();
    570         }
    571 
    572         public String getName() {
    573             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    574                 (!Utils.checkCaller())) {
    575                 Log.w(TAG,"getName(): not allowed for non-active user and non system user");
    576                 return null;
    577 	    }
    578 
    579             AdapterService service = getService();
    580             if (service == null) return null;
    581             return service.getName();
    582         }
    583 
    584         public boolean setName(String name) {
    585             if (!Utils.checkCaller()) {
    586                 Log.w(TAG,"setName(): not allowed for non-active user");
    587                 return false;
    588             }
    589 
    590             AdapterService service = getService();
    591             if (service == null) return false;
    592             return service.setName(name);
    593         }
    594 
    595         public int getScanMode() {
    596             if (!Utils.checkCaller()) {
    597                 Log.w(TAG,"getScanMode(): not allowed for non-active user");
    598                 return BluetoothAdapter.SCAN_MODE_NONE;
    599             }
    600 
    601             AdapterService service = getService();
    602             if (service == null) return BluetoothAdapter.SCAN_MODE_NONE;
    603             return service.getScanMode();
    604         }
    605 
    606         public boolean setScanMode(int mode, int duration) {
    607             if (!Utils.checkCaller()) {
    608                 Log.w(TAG,"setScanMode(): not allowed for non-active user");
    609                 return false;
    610             }
    611 
    612             AdapterService service = getService();
    613             if (service == null) return false;
    614             return service.setScanMode(mode,duration);
    615         }
    616 
    617         public int getDiscoverableTimeout() {
    618             if (!Utils.checkCaller()) {
    619                 Log.w(TAG,"getDiscoverableTimeout(): not allowed for non-active user");
    620                 return 0;
    621             }
    622 
    623             AdapterService service = getService();
    624             if (service == null) return 0;
    625             return service.getDiscoverableTimeout();
    626         }
    627 
    628         public boolean setDiscoverableTimeout(int timeout) {
    629             if (!Utils.checkCaller()) {
    630                 Log.w(TAG,"setDiscoverableTimeout(): not allowed for non-active user");
    631                 return false;
    632             }
    633 
    634             AdapterService service = getService();
    635             if (service == null) return false;
    636             return service.setDiscoverableTimeout(timeout);
    637         }
    638 
    639         public boolean startDiscovery() {
    640             if (!Utils.checkCaller()) {
    641                 Log.w(TAG,"startDiscovery(): not allowed for non-active user");
    642                 return false;
    643             }
    644 
    645             AdapterService service = getService();
    646             if (service == null) return false;
    647             return service.startDiscovery();
    648         }
    649 
    650         public boolean cancelDiscovery() {
    651             if (!Utils.checkCaller()) {
    652                 Log.w(TAG,"cancelDiscovery(): not allowed for non-active user");
    653                 return false;
    654             }
    655 
    656             AdapterService service = getService();
    657             if (service == null) return false;
    658             return service.cancelDiscovery();
    659         }
    660         public boolean isDiscovering() {
    661             if (!Utils.checkCaller()) {
    662                 Log.w(TAG,"isDiscovering(): not allowed for non-active user");
    663                 return false;
    664             }
    665 
    666             AdapterService service = getService();
    667             if (service == null) return false;
    668             return service.isDiscovering();
    669         }
    670 
    671         public BluetoothDevice[] getBondedDevices() {
    672             // don't check caller, may be called from system UI
    673             AdapterService service = getService();
    674             if (service == null) return new BluetoothDevice[0];
    675             return service.getBondedDevices();
    676         }
    677 
    678         public int getAdapterConnectionState() {
    679             // don't check caller, may be called from system UI
    680             AdapterService service = getService();
    681             if (service == null) return BluetoothAdapter.STATE_DISCONNECTED;
    682             return service.getAdapterConnectionState();
    683         }
    684 
    685         public int getProfileConnectionState(int profile) {
    686             if (!Utils.checkCaller()) {
    687                 Log.w(TAG,"getProfileConnectionState: not allowed for non-active user");
    688                 return BluetoothProfile.STATE_DISCONNECTED;
    689             }
    690 
    691             AdapterService service = getService();
    692             if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
    693             return service.getProfileConnectionState(profile);
    694         }
    695 
    696         public boolean createBond(BluetoothDevice device) {
    697             if (!Utils.checkCaller()) {
    698                 Log.w(TAG,"createBond(): not allowed for non-active user");
    699                 return false;
    700             }
    701 
    702             AdapterService service = getService();
    703             if (service == null) return false;
    704             return service.createBond(device);
    705         }
    706 
    707         public boolean cancelBondProcess(BluetoothDevice device) {
    708             if (!Utils.checkCaller()) {
    709                 Log.w(TAG,"cancelBondProcess(): not allowed for non-active user");
    710                 return false;
    711             }
    712 
    713             AdapterService service = getService();
    714             if (service == null) return false;
    715             return service.cancelBondProcess(device);
    716         }
    717 
    718         public boolean removeBond(BluetoothDevice device) {
    719             if (!Utils.checkCaller()) {
    720                 Log.w(TAG,"removeBond(): not allowed for non-active user");
    721                 return false;
    722             }
    723 
    724             AdapterService service = getService();
    725             if (service == null) return false;
    726             return service.removeBond(device);
    727         }
    728 
    729         public int getBondState(BluetoothDevice device) {
    730             // don't check caller, may be called from system UI
    731             AdapterService service = getService();
    732             if (service == null) return BluetoothDevice.BOND_NONE;
    733             return service.getBondState(device);
    734         }
    735 
    736         public String getRemoteName(BluetoothDevice device) {
    737             if (!Utils.checkCaller()) {
    738                 Log.w(TAG,"getRemoteName(): not allowed for non-active user");
    739                 return null;
    740             }
    741 
    742             AdapterService service = getService();
    743             if (service == null) return null;
    744             return service.getRemoteName(device);
    745         }
    746 
    747         public int getRemoteType(BluetoothDevice device) {
    748             if (!Utils.checkCaller()) {
    749                 Log.w(TAG,"getRemoteType(): not allowed for non-active user");
    750                 return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
    751             }
    752 
    753             AdapterService service = getService();
    754             if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
    755             return service.getRemoteType(device);
    756         }
    757 
    758         public String getRemoteAlias(BluetoothDevice device) {
    759             if (!Utils.checkCaller()) {
    760                 Log.w(TAG,"getRemoteAlias(): not allowed for non-active user");
    761                 return null;
    762             }
    763 
    764             AdapterService service = getService();
    765             if (service == null) return null;
    766             return service.getRemoteAlias(device);
    767         }
    768 
    769         public boolean setRemoteAlias(BluetoothDevice device, String name) {
    770             if (!Utils.checkCaller()) {
    771                 Log.w(TAG,"setRemoteAlias(): not allowed for non-active user");
    772                 return false;
    773             }
    774 
    775             AdapterService service = getService();
    776             if (service == null) return false;
    777             return service.setRemoteAlias(device, name);
    778         }
    779 
    780         public int getRemoteClass(BluetoothDevice device) {
    781             if (!Utils.checkCaller()) {
    782                 Log.w(TAG,"getRemoteClass(): not allowed for non-active user");
    783                 return 0;
    784             }
    785 
    786             AdapterService service = getService();
    787             if (service == null) return 0;
    788             return service.getRemoteClass(device);
    789         }
    790 
    791         public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
    792             if (!Utils.checkCaller()) {
    793                 Log.w(TAG,"getRemoteUuids(): not allowed for non-active user");
    794                 return new ParcelUuid[0];
    795             }
    796 
    797             AdapterService service = getService();
    798             if (service == null) return new ParcelUuid[0];
    799             return service.getRemoteUuids(device);
    800         }
    801 
    802         public boolean fetchRemoteUuids(BluetoothDevice device) {
    803             if (!Utils.checkCaller()) {
    804                 Log.w(TAG,"fetchRemoteUuids(): not allowed for non-active user");
    805                 return false;
    806             }
    807 
    808             AdapterService service = getService();
    809             if (service == null) return false;
    810             return service.fetchRemoteUuids(device);
    811         }
    812 
    813         public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
    814             if (!Utils.checkCaller()) {
    815                 Log.w(TAG,"setPin(): not allowed for non-active user");
    816                 return false;
    817             }
    818 
    819             AdapterService service = getService();
    820             if (service == null) return false;
    821             return service.setPin(device, accept, len, pinCode);
    822         }
    823 
    824         public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
    825             if (!Utils.checkCaller()) {
    826                 Log.w(TAG,"setPasskey(): not allowed for non-active user");
    827                 return false;
    828             }
    829 
    830             AdapterService service = getService();
    831             if (service == null) return false;
    832             return service.setPasskey(device, accept, len, passkey);
    833         }
    834 
    835         public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
    836             if (!Utils.checkCaller()) {
    837                 Log.w(TAG,"setPairingConfirmation(): not allowed for non-active user");
    838                 return false;
    839             }
    840 
    841             AdapterService service = getService();
    842             if (service == null) return false;
    843             return service.setPairingConfirmation(device, accept);
    844         }
    845 
    846         public void sendConnectionStateChange(BluetoothDevice
    847                 device, int profile, int state, int prevState) {
    848             AdapterService service = getService();
    849             if (service == null) return;
    850             service.sendConnectionStateChange(device, profile, state, prevState);
    851         }
    852 
    853         public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
    854                                                   ParcelUuid uuid, int port, int flag) {
    855             if (!Utils.checkCaller()) {
    856                 Log.w(TAG,"connectSocket(): not allowed for non-active user");
    857                 return null;
    858             }
    859 
    860             AdapterService service = getService();
    861             if (service == null) return null;
    862             return service.connectSocket(device, type, uuid, port, flag);
    863         }
    864 
    865         public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
    866                                                         ParcelUuid uuid, int port, int flag) {
    867             if (!Utils.checkCaller()) {
    868                 Log.w(TAG,"createSocketChannel(): not allowed for non-active user");
    869                 return null;
    870             }
    871 
    872             AdapterService service = getService();
    873             if (service == null) return null;
    874             return service.createSocketChannel(type, serviceName, uuid, port, flag);
    875         }
    876 
    877         public boolean configHciSnoopLog(boolean enable) {
    878             if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
    879                 (!Utils.checkCaller())) {
    880                 Log.w(TAG,"configHciSnoopLog(): not allowed for non-active user");
    881                 return false;
    882             }
    883 
    884             AdapterService service = getService();
    885             if (service == null) return false;
    886             return service.configHciSnoopLog(enable);
    887         }
    888 
    889         public void registerCallback(IBluetoothCallback cb) {
    890             AdapterService service = getService();
    891             if (service == null) return ;
    892             service.registerCallback(cb);
    893          }
    894 
    895          public void unregisterCallback(IBluetoothCallback cb) {
    896              AdapterService service = getService();
    897              if (service == null) return ;
    898              service.unregisterCallback(cb);
    899          }
    900     };
    901 
    902 
    903     //----API Methods--------
    904      boolean isEnabled() {
    905         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    906 
    907         return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
    908     }
    909 
    910      int getState() {
    911         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    912 
    913         if (mAdapterProperties == null){
    914             return  BluetoothAdapter.STATE_OFF;
    915         }
    916         else {
    917             if (DBG) debugLog("getState(): mAdapterProperties: " + mAdapterProperties);
    918             return mAdapterProperties.getState();
    919         }
    920     }
    921 
    922      boolean enable() {
    923         return enable (false);
    924     }
    925 
    926       public boolean enableNoAutoConnect() {
    927          return enable (true);
    928      }
    929 
    930      public synchronized boolean enable(boolean quietMode) {
    931          enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
    932                                         "Need BLUETOOTH ADMIN permission");
    933          if (DBG)debugLog("Enable called with quiet mode status =  " + mQuietmode);
    934          mQuietmode  = quietMode;
    935          Message m =
    936                  mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
    937          mAdapterStateMachine.sendMessage(m);
    938          return true;
    939      }
    940 
    941      boolean disable() {
    942         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
    943                                        "Need BLUETOOTH ADMIN permission");
    944 
    945         if (DBG) debugLog("disable() called...");
    946         Message m =
    947                 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
    948         mAdapterStateMachine.sendMessage(m);
    949         return true;
    950     }
    951 
    952      String getAddress() {
    953         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    954 
    955         String addrString = null;
    956         byte[] address = mAdapterProperties.getAddress();
    957         return Utils.getAddressStringFromByte(address);
    958     }
    959 
    960      ParcelUuid[] getUuids() {
    961         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    962 
    963         return mAdapterProperties.getUuids();
    964     }
    965 
    966      String getName() {
    967         enforceCallingOrSelfPermission(BLUETOOTH_PERM,
    968                                        "Need BLUETOOTH permission");
    969 
    970         try {
    971             return mAdapterProperties.getName();
    972         } catch (Throwable t) {
    973             Log.d(TAG, "Unexpected exception while calling getName()",t);
    974         }
    975         return null;
    976     }
    977 
    978      boolean setName(String name) {
    979         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
    980                                        "Need BLUETOOTH ADMIN permission");
    981 
    982         return mAdapterProperties.setName(name);
    983     }
    984 
    985      int getScanMode() {
    986         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    987 
    988         return mAdapterProperties.getScanMode();
    989     }
    990 
    991      boolean setScanMode(int mode, int duration) {
    992         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
    993 
    994         setDiscoverableTimeout(duration);
    995 
    996         int newMode = convertScanModeToHal(mode);
    997         return mAdapterProperties.setScanMode(newMode);
    998     }
    999 
   1000      int getDiscoverableTimeout() {
   1001         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1002 
   1003         return mAdapterProperties.getDiscoverableTimeout();
   1004     }
   1005 
   1006      boolean setDiscoverableTimeout(int timeout) {
   1007         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1008 
   1009         return mAdapterProperties.setDiscoverableTimeout(timeout);
   1010     }
   1011 
   1012      boolean startDiscovery() {
   1013         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1014                                        "Need BLUETOOTH ADMIN permission");
   1015 
   1016         return startDiscoveryNative();
   1017     }
   1018 
   1019      boolean cancelDiscovery() {
   1020         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1021                                        "Need BLUETOOTH ADMIN permission");
   1022 
   1023         return cancelDiscoveryNative();
   1024     }
   1025 
   1026      boolean isDiscovering() {
   1027         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1028 
   1029         return mAdapterProperties.isDiscovering();
   1030     }
   1031 
   1032      BluetoothDevice[] getBondedDevices() {
   1033         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1034         debugLog("Get Bonded Devices being called");
   1035         return mAdapterProperties.getBondedDevices();
   1036     }
   1037 
   1038      int getAdapterConnectionState() {
   1039         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1040 
   1041         return mAdapterProperties.getConnectionState();
   1042     }
   1043 
   1044      int getProfileConnectionState(int profile) {
   1045         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1046 
   1047         return mAdapterProperties.getProfileConnectionState(profile);
   1048     }
   1049 
   1050      boolean createBond(BluetoothDevice device) {
   1051         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1052             "Need BLUETOOTH ADMIN permission");
   1053         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1054         if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
   1055             return false;
   1056         }
   1057 
   1058         // Pairing is unreliable while scanning, so cancel discovery
   1059         // Note, remove this when native stack improves
   1060         cancelDiscoveryNative();
   1061 
   1062         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
   1063         msg.obj = device;
   1064         mBondStateMachine.sendMessage(msg);
   1065         return true;
   1066     }
   1067 
   1068       public boolean isQuietModeEnabled() {
   1069           if (DBG) debugLog("Quiet mode Enabled = " + mQuietmode);
   1070           return mQuietmode;
   1071      }
   1072 
   1073      public void autoConnect(){
   1074         if (getState() != BluetoothAdapter.STATE_ON){
   1075              errorLog("BT is not ON. Exiting autoConnect");
   1076              return;
   1077          }
   1078          if (isQuietModeEnabled() == false) {
   1079             if (DBG) debugLog( "Initiate auto connection on BT on...");
   1080              autoConnectHeadset();
   1081              autoConnectA2dp();
   1082          }
   1083          else {
   1084              if (DBG) debugLog( "BT is in Quiet mode. Not initiating  auto connections");
   1085          }
   1086     }
   1087 
   1088      private void autoConnectHeadset(){
   1089         HeadsetService  hsService = HeadsetService.getHeadsetService();
   1090 
   1091         BluetoothDevice bondedDevices[] = getBondedDevices();
   1092         if ((bondedDevices == null) ||(hsService == null)) {
   1093             return;
   1094         }
   1095         for (BluetoothDevice device : bondedDevices) {
   1096             if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){
   1097                 Log.d(TAG,"Auto Connecting Headset Profile with device " + device.toString());
   1098                 hsService.connect(device);
   1099                 }
   1100         }
   1101     }
   1102 
   1103      private void autoConnectA2dp(){
   1104         A2dpService a2dpSservice = A2dpService.getA2dpService();
   1105         BluetoothDevice bondedDevices[] = getBondedDevices();
   1106         if ((bondedDevices == null) ||(a2dpSservice == null)) {
   1107             return;
   1108         }
   1109         for (BluetoothDevice device : bondedDevices) {
   1110             if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){
   1111                 Log.d(TAG,"Auto Connecting A2DP Profile with device " + device.toString());
   1112                 a2dpSservice.connect(device);
   1113                 }
   1114         }
   1115     }
   1116 
   1117      public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){
   1118         if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) &&
   1119             (isQuietModeEnabled()== false)){
   1120             Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES);
   1121             m.obj = device;
   1122             m.arg1 = (int)firstProfileStatus;
   1123             mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT);
   1124         }
   1125     }
   1126 
   1127      private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){
   1128         if (getState()!= BluetoothAdapter.STATE_ON){
   1129             return;
   1130         }
   1131         HeadsetService  hsService = HeadsetService.getHeadsetService();
   1132         A2dpService a2dpService = A2dpService.getA2dpService();
   1133         // if any of the profile service is  null, second profile connection not required
   1134         if ((hsService == null) ||(a2dpService == null )){
   1135             return;
   1136         }
   1137         List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices();
   1138         List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices();
   1139         // Check if the device is in disconnected state and if so return
   1140         // We ned to connect other profile only if one of the profile is still in connected state
   1141         // This is required to avoide a race condition in which profiles would
   1142         // automaticlly connect if the disconnection is initiated within 6 seconds of connection
   1143         //First profile connection being rejected is an exception
   1144         if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&&
   1145             (PROFILE_CONN_CONNECTED  == firstProfileStatus)){
   1146             return;
   1147         }
   1148         if((hfConnDevList.isEmpty()) &&
   1149             (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){
   1150             hsService.connect(device);
   1151         }
   1152         else if((a2dpConnDevList.isEmpty()) &&
   1153             (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){
   1154             a2dpService.connect(device);
   1155         }
   1156     }
   1157 
   1158      private void adjustOtherHeadsetPriorities(HeadsetService  hsService,
   1159                                                     BluetoothDevice connectedDevice) {
   1160         for (BluetoothDevice device : getBondedDevices()) {
   1161            if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1162                !device.equals(connectedDevice)) {
   1163                hsService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1164            }
   1165         }
   1166      }
   1167 
   1168      private void adjustOtherSinkPriorities(A2dpService a2dpService,
   1169                                                 BluetoothDevice connectedDevice) {
   1170          for (BluetoothDevice device : getBondedDevices()) {
   1171              if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT &&
   1172                  !device.equals(connectedDevice)) {
   1173                  a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
   1174              }
   1175          }
   1176      }
   1177 
   1178      void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){
   1179          if (profileId == BluetoothProfile.HEADSET) {
   1180              HeadsetService  hsService = HeadsetService.getHeadsetService();
   1181              if ((hsService != null) &&
   1182                 (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){
   1183                  adjustOtherHeadsetPriorities(hsService, device);
   1184                  hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1185              }
   1186          }
   1187          else if (profileId ==  BluetoothProfile.A2DP) {
   1188              A2dpService a2dpService = A2dpService.getA2dpService();
   1189              if ((a2dpService != null) &&
   1190                 (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))){
   1191                  adjustOtherSinkPriorities(a2dpService, device);
   1192                  a2dpService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT);
   1193              }
   1194          }
   1195     }
   1196 
   1197      boolean cancelBondProcess(BluetoothDevice device) {
   1198         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
   1199         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1200         return cancelBondNative(addr);
   1201     }
   1202 
   1203      boolean removeBond(BluetoothDevice device) {
   1204         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
   1205         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1206         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
   1207             return false;
   1208         }
   1209         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
   1210         msg.obj = device;
   1211         mBondStateMachine.sendMessage(msg);
   1212         return true;
   1213     }
   1214 
   1215      int getBondState(BluetoothDevice device) {
   1216         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1217         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1218         if (deviceProp == null) {
   1219             return BluetoothDevice.BOND_NONE;
   1220         }
   1221         return deviceProp.getBondState();
   1222     }
   1223 
   1224      String getRemoteName(BluetoothDevice device) {
   1225         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1226         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1227         if (deviceProp == null) return null;
   1228         return deviceProp.getName();
   1229     }
   1230 
   1231      int getRemoteType(BluetoothDevice device) {
   1232         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1233         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1234         if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
   1235         return deviceProp.getDeviceType();
   1236     }
   1237 
   1238      String getRemoteAlias(BluetoothDevice device) {
   1239         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1240         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1241         if (deviceProp == null) return null;
   1242         return deviceProp.getAlias();
   1243     }
   1244 
   1245      boolean setRemoteAlias(BluetoothDevice device, String name) {
   1246         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1247         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1248         if (deviceProp == null) return false;
   1249         deviceProp.setAlias(name);
   1250         return true;
   1251     }
   1252 
   1253      int getRemoteClass(BluetoothDevice device) {
   1254         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1255         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1256         if (deviceProp == null) return 0;
   1257 
   1258         return deviceProp.getBluetoothClass();
   1259     }
   1260 
   1261      ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
   1262         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1263         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1264         if (deviceProp == null) return null;
   1265         return deviceProp.getUuids();
   1266     }
   1267 
   1268      boolean fetchRemoteUuids(BluetoothDevice device) {
   1269         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1270         mRemoteDevices.fetchUuids(device);
   1271         return true;
   1272     }
   1273 
   1274      boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
   1275         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1276                                        "Need BLUETOOTH ADMIN permission");
   1277         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1278         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
   1279             return false;
   1280         }
   1281 
   1282         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1283         return pinReplyNative(addr, accept, len, pinCode);
   1284     }
   1285 
   1286      boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
   1287         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1288         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1289         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
   1290             return false;
   1291         }
   1292 
   1293         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1294         return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
   1295                 Utils.byteArrayToInt(passkey));
   1296     }
   1297 
   1298      boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
   1299         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
   1300                                        "Need BLUETOOTH ADMIN permission");
   1301         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
   1302         if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
   1303             return false;
   1304         }
   1305 
   1306         byte[] addr = Utils.getBytesFromAddress(device.getAddress());
   1307         return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
   1308                 accept, 0);
   1309     }
   1310 
   1311      void sendConnectionStateChange(BluetoothDevice
   1312             device, int profile, int state, int prevState) {
   1313         // TODO(BT) permission check?
   1314         // Since this is a binder call check if Bluetooth is on still
   1315         if (getState() == BluetoothAdapter.STATE_OFF) return;
   1316 
   1317         mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
   1318 
   1319     }
   1320 
   1321      ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
   1322                                               ParcelUuid uuid, int port, int flag) {
   1323         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1324         int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()),
   1325                    type, Utils.uuidToByteArray(uuid), port, flag);
   1326         if (fd < 0) {
   1327             errorLog("Failed to connect socket");
   1328             return null;
   1329         }
   1330         return ParcelFileDescriptor.adoptFd(fd);
   1331     }
   1332 
   1333      ParcelFileDescriptor createSocketChannel(int type, String serviceName,
   1334                                                     ParcelUuid uuid, int port, int flag) {
   1335         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1336         int fd =  createSocketChannelNative(type, serviceName,
   1337                                  Utils.uuidToByteArray(uuid), port, flag);
   1338         if (fd < 0) {
   1339             errorLog("Failed to create socket channel");
   1340             return null;
   1341         }
   1342         return ParcelFileDescriptor.adoptFd(fd);
   1343     }
   1344 
   1345     boolean configHciSnoopLog(boolean enable) {
   1346         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
   1347         return configHciSnoopLogNative(enable);
   1348     }
   1349 
   1350      void registerCallback(IBluetoothCallback cb) {
   1351          mCallbacks.register(cb);
   1352       }
   1353 
   1354       void unregisterCallback(IBluetoothCallback cb) {
   1355          mCallbacks.unregister(cb);
   1356       }
   1357 
   1358     private static int convertScanModeToHal(int mode) {
   1359         switch (mode) {
   1360             case BluetoothAdapter.SCAN_MODE_NONE:
   1361                 return AbstractionLayer.BT_SCAN_MODE_NONE;
   1362             case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
   1363                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
   1364             case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
   1365                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
   1366         }
   1367        // errorLog("Incorrect scan mode in convertScanModeToHal");
   1368         return -1;
   1369     }
   1370 
   1371     static int convertScanModeFromHal(int mode) {
   1372         switch (mode) {
   1373             case AbstractionLayer.BT_SCAN_MODE_NONE:
   1374                 return BluetoothAdapter.SCAN_MODE_NONE;
   1375             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
   1376                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
   1377             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
   1378                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
   1379         }
   1380         //errorLog("Incorrect scan mode in convertScanModeFromHal");
   1381         return -1;
   1382     }
   1383 
   1384     private void debugLog(String msg) {
   1385         Log.d(TAG +"(" +hashCode()+")", msg);
   1386     }
   1387 
   1388     private void errorLog(String msg) {
   1389         Log.e(TAG +"(" +hashCode()+")", msg);
   1390     }
   1391 
   1392     private native static void classInitNative();
   1393     private native boolean initNative();
   1394     private native void cleanupNative();
   1395     /*package*/ native boolean enableNative();
   1396     /*package*/ native boolean disableNative();
   1397     /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val);
   1398     /*package*/ native boolean getAdapterPropertiesNative();
   1399     /*package*/ native boolean getAdapterPropertyNative(int type);
   1400     /*package*/ native boolean setAdapterPropertyNative(int type);
   1401     /*package*/ native boolean
   1402         setDevicePropertyNative(byte[] address, int type, byte[] val);
   1403     /*package*/ native boolean getDevicePropertyNative(byte[] address, int type);
   1404 
   1405     /*package*/ native boolean createBondNative(byte[] address);
   1406     /*package*/ native boolean removeBondNative(byte[] address);
   1407     /*package*/ native boolean cancelBondNative(byte[] address);
   1408 
   1409     private native boolean startDiscoveryNative();
   1410     private native boolean cancelDiscoveryNative();
   1411 
   1412     private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin);
   1413     private native boolean sspReplyNative(byte[] address, int type, boolean
   1414             accept, int passkey);
   1415 
   1416     /*package*/ native boolean getRemoteServicesNative(byte[] address);
   1417 
   1418     // TODO(BT) move this to ../btsock dir
   1419     private native int connectSocketNative(byte[] address, int type,
   1420                                            byte[] uuid, int port, int flag);
   1421     private native int createSocketChannelNative(int type, String serviceName,
   1422                                                  byte[] uuid, int port, int flag);
   1423 
   1424     /*package*/ native boolean configHciSnoopLogNative(boolean enable);
   1425 
   1426     protected void finalize() {
   1427         cleanup();
   1428         if (TRACE_REF) {
   1429             synchronized (AdapterService.class) {
   1430                 sRefCount--;
   1431                 Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount);
   1432             }
   1433         }
   1434     }
   1435 }