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