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