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