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