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