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