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