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