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