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