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