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