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