AdapterService.java revision 90d55ae85dc19e33fffe1e51787df2b8dd40c230
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        if (!isMock()) {
468            // TODO(b/27859763)
469            Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack");
470            System.exit(0);
471        }
472    }
473
474    void BleOnProcessStart() {
475        debugLog("BleOnProcessStart()");
476
477        if (getResources().getBoolean(
478                R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
479            Config.init(getApplicationContext());
480        }
481
482        Class[] supportedProfileServices = Config.getSupportedProfiles();
483        //Initialize data objects
484        for (int i=0; i < supportedProfileServices.length;i++) {
485            mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
486        }
487
488        // Reset |mRemoteDevices| whenever BLE is turned off then on
489        // This is to replace the fact that |mRemoteDevices| was
490        // reinitialized in previous code.
491        //
492        // TODO(apanicke): The reason is unclear but
493        // I believe it is to clear the variable every time BLE was
494        // turned off then on. The same effect can be achieved by
495        // calling cleanup but this may not be necessary at all
496        // We should figure out why this is needed later
497        mRemoteDevices.cleanup();
498        mAdapterProperties.init(mRemoteDevices);
499
500        debugLog("BleOnProcessStart() - Make Bond State Machine");
501        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
502
503        mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
504
505        try {
506            mBatteryStats.noteResetBleScan();
507        } catch (RemoteException e) {
508            // Ignore.
509        }
510
511        //Start Gatt service
512        setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
513    }
514
515    void startCoreServices()
516    {
517        debugLog("startCoreServices()");
518        Class[] supportedProfileServices = Config.getSupportedProfiles();
519
520        //Start profile services
521        if (!mProfilesStarted && supportedProfileServices.length >0) {
522            //Startup all profile services
523            setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
524        }else {
525            debugLog("startCoreProfiles(): Profile Services alreay started");
526            mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED));
527        }
528    }
529
530    void startBluetoothDisable() {
531        mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE));
532    }
533
534    boolean stopProfileServices() {
535        Class[] supportedProfileServices = Config.getSupportedProfiles();
536        if (mProfilesStarted && supportedProfileServices.length>0) {
537            setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
538            return true;
539        }
540        debugLog("stopProfileServices() - No profiles services to stop or already stopped.");
541        return false;
542    }
543
544    boolean stopGattProfileService() {
545        //TODO: can optimize this instead of looping around all supported profiles
546        debugLog("stopGattProfileService()");
547        Class[] supportedProfileServices = Config.getSupportedProfiles();
548
549        setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF);
550        return true;
551    }
552
553
554     void updateAdapterState(int prevState, int newState){
555        if (mCallbacks !=null) {
556            int n=mCallbacks.beginBroadcast();
557            debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers.");
558            for (int i=0; i <n;i++) {
559                try {
560                    mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);
561                }  catch (RemoteException e) {
562                    debugLog("updateAdapterState() - Callback #" + i + " failed ("  + e + ")");
563                }
564            }
565            mCallbacks.finishBroadcast();
566        }
567    }
568
569    void cleanup () {
570        debugLog("cleanup()");
571        if (mCleaningUp) {
572            errorLog("cleanup() - Service already starting to cleanup, ignoring request...");
573            return;
574        }
575
576        mCleaningUp = true;
577
578        unregisterReceiver(mAlarmBroadcastReceiver);
579
580        if (mPendingAlarm != null) {
581            mAlarmManager.cancel(mPendingAlarm);
582            mPendingAlarm = null;
583        }
584
585        // This wake lock release may also be called concurrently by
586        // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here.
587        synchronized (this) {
588            if (mWakeLock != null) {
589                if (mWakeLock.isHeld())
590                    mWakeLock.release();
591                mWakeLock = null;
592            }
593        }
594
595        if (mAdapterStateMachine != null) {
596            mAdapterStateMachine.doQuit();
597            mAdapterStateMachine.cleanup();
598        }
599
600        if (mBondStateMachine != null) {
601            mBondStateMachine.doQuit();
602            mBondStateMachine.cleanup();
603        }
604
605        if (mRemoteDevices != null) {
606            mRemoteDevices.cleanup();
607        }
608
609        if(mSdpManager != null) {
610            mSdpManager.cleanup();
611            mSdpManager = null;
612        }
613
614        if (mNativeAvailable) {
615            debugLog("cleanup() - Cleaning up adapter native");
616            cleanupNative();
617            mNativeAvailable=false;
618        }
619
620        if (mAdapterProperties != null) {
621            mAdapterProperties.cleanup();
622        }
623
624        if (mJniCallbacks != null) {
625            mJniCallbacks.cleanup();
626        }
627
628        if (mPhonePolicy != null) {
629            mPhonePolicy.cleanup();
630        }
631
632        if (mProfileServicesState != null) {
633            mProfileServicesState.clear();
634        }
635
636        clearAdapterService();
637
638        if (mBinder != null) {
639            mBinder.cleanup();
640            mBinder = null;  //Do not remove. Otherwise Binder leak!
641        }
642
643        if (mCallbacks !=null) {
644            mCallbacks.kill();
645        }
646    }
647
648    private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1;
649
650    private final Handler mHandler = new Handler() {
651        @Override
652        public void handleMessage(Message msg) {
653            debugLog("handleMessage() - Message: " + msg.what);
654
655            switch (msg.what) {
656                case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: {
657                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
658                    processProfileServiceStateChanged((String) msg.obj, msg.arg1);
659                }
660                    break;
661            }
662        }
663    };
664
665    @SuppressWarnings("rawtypes")
666    private void setGattProfileServiceState(Class[] services, int state) {
667        if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
668            Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving...");
669            return;
670        }
671
672        int expectedCurrentState= BluetoothAdapter.STATE_OFF;
673        int pendingState = BluetoothAdapter.STATE_TURNING_ON;
674
675        if (state == BluetoothAdapter.STATE_OFF) {
676            expectedCurrentState= BluetoothAdapter.STATE_ON;
677            pendingState = BluetoothAdapter.STATE_TURNING_OFF;
678        }
679
680        for (int i=0; i <services.length;i++) {
681            String serviceName = services[i].getName();
682            String simpleName = services[i].getSimpleName();
683
684            if (simpleName.equals("GattService")) {
685                Integer serviceState = mProfileServicesState.get(serviceName);
686
687                if(serviceState != null && serviceState != expectedCurrentState) {
688                    debugLog("setProfileServiceState() - Unable to "
689                        + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
690                        + " service " + serviceName
691                        + ". Invalid state: " + serviceState);
692                        continue;
693                }
694                debugLog("setProfileServiceState() - "
695                    + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
696                    + " service " + serviceName);
697
698                mProfileServicesState.put(serviceName,pendingState);
699                Intent intent = new Intent(this,services[i]);
700                intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
701                intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
702                startService(intent);
703                return;
704            }
705        }
706    }
707
708
709    @SuppressWarnings("rawtypes")
710    private void setProfileServiceState(Class[] services, int state) {
711        if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
712            debugLog("setProfileServiceState() - Invalid state, leaving...");
713            return;
714        }
715
716        int expectedCurrentState= BluetoothAdapter.STATE_OFF;
717        int pendingState = BluetoothAdapter.STATE_TURNING_ON;
718        if (state == BluetoothAdapter.STATE_OFF) {
719            expectedCurrentState= BluetoothAdapter.STATE_ON;
720            pendingState = BluetoothAdapter.STATE_TURNING_OFF;
721        }
722
723        for (int i=0; i <services.length;i++) {
724            String serviceName = services[i].getName();
725            String simpleName = services[i].getSimpleName();
726
727            if (simpleName.equals("GattService")) continue;
728
729            Integer serviceState = mProfileServicesState.get(serviceName);
730            if(serviceState != null && serviceState != expectedCurrentState) {
731                debugLog("setProfileServiceState() - Unable to "
732                    + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
733                    + " service " + serviceName
734                    + ". Invalid state: " + serviceState);
735                continue;
736            }
737
738            debugLog("setProfileServiceState() - "
739                + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
740                + " service " + serviceName);
741
742            mProfileServicesState.put(serviceName,pendingState);
743            Intent intent = new Intent(this,services[i]);
744            intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
745            intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
746            startService(intent);
747        }
748    }
749
750    private boolean isAvailable() {
751        return !mCleaningUp;
752    }
753
754    /**
755     * Handlers for incoming service calls
756     */
757    private AdapterServiceBinder mBinder;
758
759    /**
760     * The Binder implementation must be declared to be a static class, with
761     * the AdapterService instance passed in the constructor. Furthermore,
762     * when the AdapterService shuts down, the reference to the AdapterService
763     * must be explicitly removed.
764     *
765     * Otherwise, a memory leak can occur from repeated starting/stopping the
766     * service...Please refer to android.os.Binder for further details on
767     * why an inner instance class should be avoided.
768     *
769     */
770    private static class AdapterServiceBinder extends IBluetooth.Stub {
771        private AdapterService mService;
772
773        public AdapterServiceBinder(AdapterService svc) {
774            mService = svc;
775        }
776        public boolean cleanup() {
777            mService = null;
778            return true;
779        }
780
781        public AdapterService getService() {
782            if (mService  != null && mService.isAvailable()) {
783                return mService;
784            }
785            return null;
786        }
787        public boolean isEnabled() {
788            // don't check caller, may be called from system UI
789            AdapterService service = getService();
790            if (service == null) return false;
791            return service.isEnabled();
792        }
793
794        public int getState() {
795            // don't check caller, may be called from system UI
796            AdapterService service = getService();
797            if (service == null) return  BluetoothAdapter.STATE_OFF;
798            return service.getState();
799        }
800
801        public boolean enable() {
802            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
803                (!Utils.checkCaller())) {
804                Log.w(TAG, "enable() - Not allowed for non-active user and non system user");
805                return false;
806            }
807            AdapterService service = getService();
808            if (service == null) return false;
809            return service.enable();
810        }
811
812        public boolean enableNoAutoConnect() {
813            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
814                (!Utils.checkCaller())) {
815                Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user");
816                return false;
817            }
818
819            AdapterService service = getService();
820            if (service == null) return false;
821            return service.enableNoAutoConnect();
822        }
823
824        public boolean disable() {
825            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
826                (!Utils.checkCaller())) {
827                Log.w(TAG, "disable() - Not allowed for non-active user and non system user");
828                return false;
829            }
830
831            AdapterService service = getService();
832            if (service == null) return false;
833            return service.disable();
834        }
835
836        public String getAddress() {
837            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
838                (!Utils.checkCallerAllowManagedProfiles(mService))) {
839                Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user");
840                return null;
841            }
842
843            AdapterService service = getService();
844            if (service == null) return null;
845            return service.getAddress();
846        }
847
848        public ParcelUuid[] getUuids() {
849            if (!Utils.checkCaller()) {
850                Log.w(TAG, "getUuids() - Not allowed for non-active user");
851                return new ParcelUuid[0];
852            }
853
854            AdapterService service = getService();
855            if (service == null) return new ParcelUuid[0];
856            return service.getUuids();
857        }
858
859        public String getName() {
860            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
861                (!Utils.checkCaller())) {
862                Log.w(TAG, "getName() - Not allowed for non-active user and non system user");
863                return null;
864            }
865
866            AdapterService service = getService();
867            if (service == null) return null;
868            return service.getName();
869        }
870
871        public boolean setName(String name) {
872            if (!Utils.checkCaller()) {
873                Log.w(TAG, "setName() - Not allowed for non-active user");
874                return false;
875            }
876
877            AdapterService service = getService();
878            if (service == null) return false;
879            return service.setName(name);
880        }
881
882        public int getScanMode() {
883            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
884                Log.w(TAG, "getScanMode() - Not allowed for non-active user");
885                return BluetoothAdapter.SCAN_MODE_NONE;
886            }
887
888            AdapterService service = getService();
889            if (service == null) return BluetoothAdapter.SCAN_MODE_NONE;
890            return service.getScanMode();
891        }
892
893        public boolean setScanMode(int mode, int duration) {
894            if (!Utils.checkCaller()) {
895                Log.w(TAG, "setScanMode() - Not allowed for non-active user");
896                return false;
897            }
898
899            AdapterService service = getService();
900            if (service == null) return false;
901            return service.setScanMode(mode,duration);
902        }
903
904        public int getDiscoverableTimeout() {
905            if (!Utils.checkCaller()) {
906                Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user");
907                return 0;
908            }
909
910            AdapterService service = getService();
911            if (service == null) return 0;
912            return service.getDiscoverableTimeout();
913        }
914
915        public boolean setDiscoverableTimeout(int timeout) {
916            if (!Utils.checkCaller()) {
917                Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user");
918                return false;
919            }
920
921            AdapterService service = getService();
922            if (service == null) return false;
923            return service.setDiscoverableTimeout(timeout);
924        }
925
926        public boolean startDiscovery() {
927            if (!Utils.checkCaller()) {
928                Log.w(TAG, "startDiscovery() - Not allowed for non-active user");
929                return false;
930            }
931
932            AdapterService service = getService();
933            if (service == null) return false;
934            return service.startDiscovery();
935        }
936
937        public boolean cancelDiscovery() {
938            if (!Utils.checkCaller()) {
939                Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user");
940                return false;
941            }
942
943            AdapterService service = getService();
944            if (service == null) return false;
945            return service.cancelDiscovery();
946        }
947
948        public boolean isDiscovering() {
949            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
950                Log.w(TAG, "isDiscovering() - Not allowed for non-active user");
951                return false;
952            }
953
954            AdapterService service = getService();
955            if (service == null) return false;
956            return service.isDiscovering();
957        }
958
959        public long getDiscoveryEndMillis() {
960            if (!Utils.checkCaller()) {
961                Log.w(TAG, "getDiscoveryEndMillis() - Not allowed for non-active user");
962                return -1;
963            }
964
965            AdapterService service = getService();
966            if (service == null) return -1;
967            return service.getDiscoveryEndMillis();
968        }
969
970        public BluetoothDevice[] getBondedDevices() {
971            // don't check caller, may be called from system UI
972            AdapterService service = getService();
973            if (service == null) return new BluetoothDevice[0];
974            return service.getBondedDevices();
975        }
976
977        public int getAdapterConnectionState() {
978            // don't check caller, may be called from system UI
979            AdapterService service = getService();
980            if (service == null) return BluetoothAdapter.STATE_DISCONNECTED;
981            return service.getAdapterConnectionState();
982        }
983
984        public int getProfileConnectionState(int profile) {
985            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
986                Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user");
987                return BluetoothProfile.STATE_DISCONNECTED;
988            }
989
990            AdapterService service = getService();
991            if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
992            return service.getProfileConnectionState(profile);
993        }
994
995        public boolean createBond(BluetoothDevice device, int transport) {
996            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
997                Log.w(TAG, "createBond() - Not allowed for non-active user");
998                return false;
999            }
1000
1001            AdapterService service = getService();
1002            if (service == null) return false;
1003            return service.createBond(device, transport, null);
1004        }
1005
1006        public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) {
1007            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1008                Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user");
1009                return false;
1010            }
1011
1012            AdapterService service = getService();
1013            if (service == null) return false;
1014            return service.createBond(device, transport, oobData);
1015        }
1016
1017        public boolean cancelBondProcess(BluetoothDevice device) {
1018            if (!Utils.checkCaller()) {
1019                Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user");
1020                return false;
1021            }
1022
1023            AdapterService service = getService();
1024            if (service == null) return false;
1025            return service.cancelBondProcess(device);
1026        }
1027
1028        public boolean removeBond(BluetoothDevice device) {
1029            if (!Utils.checkCaller()) {
1030                Log.w(TAG, "removeBond() - Not allowed for non-active user");
1031                return false;
1032            }
1033
1034            AdapterService service = getService();
1035            if (service == null) return false;
1036            return service.removeBond(device);
1037        }
1038
1039        public int getBondState(BluetoothDevice device) {
1040            // don't check caller, may be called from system UI
1041            AdapterService service = getService();
1042            if (service == null) return BluetoothDevice.BOND_NONE;
1043            return service.getBondState(device);
1044        }
1045
1046        public boolean isBondingInitiatedLocally(BluetoothDevice device) {
1047            // don't check caller, may be called from system UI
1048            AdapterService service = getService();
1049            if (service == null) return false;
1050            return service.isBondingInitiatedLocally(device);
1051        }
1052
1053        public long getSupportedProfiles() {
1054            AdapterService service = getService();
1055            if (service == null) return 0;
1056            return service.getSupportedProfiles();
1057        }
1058
1059        public int getConnectionState(BluetoothDevice device) {
1060            AdapterService service = getService();
1061            if (service == null) return 0;
1062            return service.getConnectionState(device);
1063        }
1064
1065        public String getRemoteName(BluetoothDevice device) {
1066            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1067                Log.w(TAG, "getRemoteName() - Not allowed for non-active user");
1068                return null;
1069            }
1070
1071            AdapterService service = getService();
1072            if (service == null) return null;
1073            return service.getRemoteName(device);
1074        }
1075
1076        public int getRemoteType(BluetoothDevice device) {
1077            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1078                Log.w(TAG, "getRemoteType() - Not allowed for non-active user");
1079                return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
1080            }
1081
1082            AdapterService service = getService();
1083            if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
1084            return service.getRemoteType(device);
1085        }
1086
1087        public String getRemoteAlias(BluetoothDevice device) {
1088            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1089                Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user");
1090                return null;
1091            }
1092
1093            AdapterService service = getService();
1094            if (service == null) return null;
1095            return service.getRemoteAlias(device);
1096        }
1097
1098        public boolean setRemoteAlias(BluetoothDevice device, String name) {
1099            if (!Utils.checkCaller()) {
1100                Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user");
1101                return false;
1102            }
1103
1104            AdapterService service = getService();
1105            if (service == null) return false;
1106            return service.setRemoteAlias(device, name);
1107        }
1108
1109        public int getRemoteClass(BluetoothDevice device) {
1110            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1111                Log.w(TAG, "getRemoteClass() - Not allowed for non-active user");
1112                return 0;
1113            }
1114
1115            AdapterService service = getService();
1116            if (service == null) return 0;
1117            return service.getRemoteClass(device);
1118        }
1119
1120        public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
1121            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1122                Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user");
1123                return new ParcelUuid[0];
1124            }
1125
1126            AdapterService service = getService();
1127            if (service == null) return new ParcelUuid[0];
1128            return service.getRemoteUuids(device);
1129        }
1130
1131        public boolean fetchRemoteUuids(BluetoothDevice device) {
1132            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1133                Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user");
1134                return false;
1135            }
1136
1137            AdapterService service = getService();
1138            if (service == null) return false;
1139            return service.fetchRemoteUuids(device);
1140        }
1141
1142
1143
1144        public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
1145            if (!Utils.checkCaller()) {
1146                Log.w(TAG, "setPin() - Not allowed for non-active user");
1147                return false;
1148            }
1149
1150            AdapterService service = getService();
1151            if (service == null) return false;
1152            return service.setPin(device, accept, len, pinCode);
1153        }
1154
1155        public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
1156            if (!Utils.checkCaller()) {
1157                Log.w(TAG, "setPasskey() - Not allowed for non-active user");
1158                return false;
1159            }
1160
1161            AdapterService service = getService();
1162            if (service == null) return false;
1163            return service.setPasskey(device, accept, len, passkey);
1164        }
1165
1166        public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
1167            if (!Utils.checkCaller()) {
1168                Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user");
1169                return false;
1170            }
1171
1172            AdapterService service = getService();
1173            if (service == null) return false;
1174            return service.setPairingConfirmation(device, accept);
1175        }
1176
1177        public int getPhonebookAccessPermission(BluetoothDevice device) {
1178            if (!Utils.checkCaller()) {
1179                Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user");
1180                return BluetoothDevice.ACCESS_UNKNOWN;
1181            }
1182
1183            AdapterService service = getService();
1184            if (service == null) return BluetoothDevice.ACCESS_UNKNOWN;
1185            return service.getPhonebookAccessPermission(device);
1186        }
1187
1188        public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) {
1189            if (!Utils.checkCaller()) {
1190                Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user");
1191                return false;
1192            }
1193
1194            AdapterService service = getService();
1195            if (service == null) return false;
1196            return service.setPhonebookAccessPermission(device, value);
1197        }
1198
1199        public int getMessageAccessPermission(BluetoothDevice device) {
1200            if (!Utils.checkCaller()) {
1201                Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user");
1202                return BluetoothDevice.ACCESS_UNKNOWN;
1203            }
1204
1205            AdapterService service = getService();
1206            if (service == null) return BluetoothDevice.ACCESS_UNKNOWN;
1207            return service.getMessageAccessPermission(device);
1208        }
1209
1210        public boolean setMessageAccessPermission(BluetoothDevice device, int value) {
1211            if (!Utils.checkCaller()) {
1212                Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user");
1213                return false;
1214            }
1215
1216            AdapterService service = getService();
1217            if (service == null) return false;
1218            return service.setMessageAccessPermission(device, value);
1219        }
1220
1221        public int getSimAccessPermission(BluetoothDevice device) {
1222            if (!Utils.checkCaller()) {
1223                Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user");
1224                return BluetoothDevice.ACCESS_UNKNOWN;
1225            }
1226
1227            AdapterService service = getService();
1228            if (service == null) return BluetoothDevice.ACCESS_UNKNOWN;
1229            return service.getSimAccessPermission(device);
1230        }
1231
1232        public boolean setSimAccessPermission(BluetoothDevice device, int value) {
1233            if (!Utils.checkCaller()) {
1234                Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user");
1235                return false;
1236            }
1237
1238            AdapterService service = getService();
1239            if (service == null) return false;
1240            return service.setSimAccessPermission(device, value);
1241        }
1242
1243        public void sendConnectionStateChange(BluetoothDevice
1244                device, int profile, int state, int prevState) {
1245            AdapterService service = getService();
1246            if (service == null) return;
1247            service.sendConnectionStateChange(device, profile, state, prevState);
1248        }
1249
1250        public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
1251                                                  ParcelUuid uuid, int port, int flag) {
1252            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1253                Log.w(TAG, "connectSocket() - Not allowed for non-active user");
1254                return null;
1255            }
1256
1257            AdapterService service = getService();
1258            if (service == null) return null;
1259            return service.connectSocket(device, type, uuid, port, flag);
1260        }
1261
1262        public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
1263                                                        ParcelUuid uuid, int port, int flag) {
1264            if (!Utils.checkCallerAllowManagedProfiles(mService)) {
1265                Log.w(TAG, "createSocketChannel() - Not allowed for non-active user");
1266                return null;
1267            }
1268
1269            AdapterService service = getService();
1270            if (service == null) return null;
1271            return service.createSocketChannel(type, serviceName, uuid, port, flag);
1272        }
1273        public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) {
1274            if (!Utils.checkCaller()) {
1275                Log.w(TAG,"sdpSea(): not allowed for non-active user");
1276                return false;
1277            }
1278
1279            AdapterService service = getService();
1280            if (service == null) return false;
1281            return service.sdpSearch(device,uuid);
1282        }
1283
1284        public boolean factoryReset() {
1285            AdapterService service = getService();
1286            if (service == null) return false;
1287            service.disable();
1288            return service.factoryReset();
1289
1290        }
1291
1292        public void registerCallback(IBluetoothCallback cb) {
1293            AdapterService service = getService();
1294            if (service == null) return ;
1295            service.registerCallback(cb);
1296         }
1297
1298         public void unregisterCallback(IBluetoothCallback cb) {
1299             AdapterService service = getService();
1300             if (service == null) return ;
1301             service.unregisterCallback(cb);
1302         }
1303
1304         public boolean isMultiAdvertisementSupported() {
1305             AdapterService service = getService();
1306             if (service == null) return false;
1307             return service.isMultiAdvertisementSupported();
1308         }
1309
1310         public boolean isOffloadedFilteringSupported() {
1311             AdapterService service = getService();
1312             if (service == null) return false;
1313             int val = service.getNumOfOffloadedScanFilterSupported();
1314             return (val >= MIN_OFFLOADED_FILTERS);
1315         }
1316
1317         public boolean isOffloadedScanBatchingSupported() {
1318             AdapterService service = getService();
1319             if (service == null) return false;
1320             int val = service.getOffloadedScanResultStorage();
1321             return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES);
1322         }
1323
1324         public boolean isLe2MPhySupported() {
1325             AdapterService service = getService();
1326             if (service == null) return false;
1327             return service.isLe2MPhySupported();
1328         }
1329
1330         public boolean isLeCodedPhySupported() {
1331             AdapterService service = getService();
1332             if (service == null) return false;
1333             return service.isLeCodedPhySupported();
1334         }
1335
1336         public boolean isLeExtendedAdvertisingSupported() {
1337             AdapterService service = getService();
1338             if (service == null) return false;
1339             return service.isLeExtendedAdvertisingSupported();
1340         }
1341
1342         public boolean isLePeriodicAdvertisingSupported() {
1343             AdapterService service = getService();
1344             if (service == null) return false;
1345             return service.isLePeriodicAdvertisingSupported();
1346         }
1347
1348         public int getLeMaximumAdvertisingDataLength() {
1349             AdapterService service = getService();
1350             if (service == null) return 0;
1351             return service.getLeMaximumAdvertisingDataLength();
1352         }
1353
1354         public boolean isActivityAndEnergyReportingSupported() {
1355             AdapterService service = getService();
1356             if (service == null) return false;
1357             return service.isActivityAndEnergyReportingSupported();
1358         }
1359
1360         public BluetoothActivityEnergyInfo reportActivityInfo() {
1361             AdapterService service = getService();
1362             if (service == null) return null;
1363             return service.reportActivityInfo();
1364         }
1365
1366         public void requestActivityInfo(ResultReceiver result) {
1367             Bundle bundle = new Bundle();
1368             bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY,
1369                     reportActivityInfo());
1370             result.send(0, bundle);
1371         }
1372
1373        public void onLeServiceUp(){
1374             AdapterService service = getService();
1375             if (service == null) return;
1376             service.onLeServiceUp();
1377         }
1378
1379         public void onBrEdrDown(){
1380             AdapterService service = getService();
1381             if (service == null) return;
1382             service.onBrEdrDown();
1383         }
1384
1385         public void dump(FileDescriptor fd, String[] args) {
1386            PrintWriter writer = new PrintWriter(new FileOutputStream(fd));
1387            AdapterService service = getService();
1388            if (service == null) return;
1389            service.dump(fd, writer, args);
1390         }
1391    };
1392
1393    // ----API Methods--------
1394
1395    public boolean isEnabled() {
1396        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1397        return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
1398     }
1399
1400     public int getState() {
1401         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1402         if (mAdapterProperties != null) return mAdapterProperties.getState();
1403         return BluetoothAdapter.STATE_OFF;
1404     }
1405
1406     public boolean enable() {
1407         return enable(false);
1408     }
1409
1410     public boolean enableNoAutoConnect() {
1411         return enable (true);
1412     }
1413
1414     public synchronized boolean enable(boolean quietMode) {
1415         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1416
1417         // Enforce the user restriction for disallowing Bluetooth if it was set.
1418         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
1419            debugLog("enable() called when Bluetooth was disallowed");
1420            return false;
1421         }
1422
1423         debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);
1424         mQuietmode = quietMode;
1425         Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
1426         mAdapterStateMachine.sendMessage(m);
1427         mBluetoothStartTime = System.currentTimeMillis();
1428         return true;
1429     }
1430
1431     boolean disable() {
1432        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1433
1434        debugLog("disable() called...");
1435        Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF);
1436        mAdapterStateMachine.sendMessage(m);
1437        return true;
1438    }
1439
1440     String getAddress() {
1441        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1442
1443        String addrString = null;
1444        byte[] address = mAdapterProperties.getAddress();
1445        return Utils.getAddressStringFromByte(address);
1446    }
1447
1448     ParcelUuid[] getUuids() {
1449        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1450
1451        return mAdapterProperties.getUuids();
1452    }
1453
1454    public String getName() {
1455        enforceCallingOrSelfPermission(BLUETOOTH_PERM,
1456                                       "Need BLUETOOTH permission");
1457
1458        try {
1459            return mAdapterProperties.getName();
1460        } catch (Throwable t) {
1461            debugLog("getName() - Unexpected exception (" + t + ")");
1462        }
1463        return null;
1464    }
1465
1466     boolean setName(String name) {
1467        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1468                                       "Need BLUETOOTH ADMIN permission");
1469
1470        return mAdapterProperties.setName(name);
1471    }
1472
1473     int getScanMode() {
1474        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1475
1476        return mAdapterProperties.getScanMode();
1477    }
1478
1479     boolean setScanMode(int mode, int duration) {
1480        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1481
1482        setDiscoverableTimeout(duration);
1483
1484        int newMode = convertScanModeToHal(mode);
1485        return mAdapterProperties.setScanMode(newMode);
1486    }
1487
1488     int getDiscoverableTimeout() {
1489        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1490
1491        return mAdapterProperties.getDiscoverableTimeout();
1492    }
1493
1494     boolean setDiscoverableTimeout(int timeout) {
1495        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1496
1497        return mAdapterProperties.setDiscoverableTimeout(timeout);
1498    }
1499
1500     boolean startDiscovery() {
1501        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1502                                       "Need BLUETOOTH ADMIN permission");
1503
1504        return startDiscoveryNative();
1505    }
1506
1507     boolean cancelDiscovery() {
1508        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1509                                       "Need BLUETOOTH ADMIN permission");
1510
1511        return cancelDiscoveryNative();
1512    }
1513
1514     boolean isDiscovering() {
1515        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1516
1517        return mAdapterProperties.isDiscovering();
1518    }
1519
1520    long getDiscoveryEndMillis() {
1521        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1522
1523        return mAdapterProperties.discoveryEndMillis();
1524    }
1525
1526    public BluetoothDevice[] getBondedDevices() {
1527        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1528        return mAdapterProperties.getBondedDevices();
1529    }
1530
1531    int getAdapterConnectionState() {
1532        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1533        return mAdapterProperties.getConnectionState();
1534    }
1535
1536     int getProfileConnectionState(int profile) {
1537        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1538
1539        return mAdapterProperties.getProfileConnectionState(profile);
1540    }
1541     boolean sdpSearch(BluetoothDevice device,ParcelUuid uuid) {
1542         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1543         if(mSdpManager != null) {
1544             mSdpManager.sdpSearch(device,uuid);
1545             return true;
1546         } else {
1547             return false;
1548         }
1549     }
1550
1551     boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
1552        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1553            "Need BLUETOOTH ADMIN permission");
1554        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1555        if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
1556            return false;
1557        }
1558
1559        mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
1560
1561        // Pairing is unreliable while scanning, so cancel discovery
1562        // Note, remove this when native stack improves
1563        cancelDiscoveryNative();
1564
1565        Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
1566        msg.obj = device;
1567        msg.arg1 = transport;
1568
1569        if (oobData != null) {
1570            Bundle oobDataBundle = new Bundle();
1571            oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
1572            msg.setData(oobDataBundle);
1573        }
1574        mBondStateMachine.sendMessage(msg);
1575        return true;
1576    }
1577
1578      public boolean isQuietModeEnabled() {
1579          debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode);
1580          return mQuietmode;
1581     }
1582
1583    public void updateUuids() {
1584        debugLog( "updateUuids() - Updating UUIDs for bonded devices");
1585        BluetoothDevice[] bondedDevices = getBondedDevices();
1586        if (bondedDevices == null) return;
1587
1588        for (BluetoothDevice device : bondedDevices) {
1589            mRemoteDevices.updateUuids(device);
1590        }
1591    }
1592
1593    boolean cancelBondProcess(BluetoothDevice device) {
1594        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1595        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1596
1597        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1598        if (deviceProp != null) {
1599            deviceProp.setBondingInitiatedLocally(false);
1600        }
1601
1602        return cancelBondNative(addr);
1603    }
1604
1605    boolean removeBond(BluetoothDevice device) {
1606        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1607        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1608        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
1609            return false;
1610        }
1611        deviceProp.setBondingInitiatedLocally(false);
1612
1613        Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
1614        msg.obj = device;
1615        mBondStateMachine.sendMessage(msg);
1616        return true;
1617    }
1618
1619    int getBondState(BluetoothDevice device) {
1620        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1621        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1622        if (deviceProp == null) {
1623            return BluetoothDevice.BOND_NONE;
1624        }
1625        return deviceProp.getBondState();
1626    }
1627
1628    boolean isBondingInitiatedLocally(BluetoothDevice device) {
1629        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1630        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1631        if (deviceProp == null) {
1632            return false;
1633        }
1634        return deviceProp.isBondingInitiatedLocally();
1635    }
1636
1637    long getSupportedProfiles() {
1638        return Config.getSupportedProfilesBitMask();
1639    }
1640
1641    int getConnectionState(BluetoothDevice device) {
1642        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1643        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1644        return getConnectionStateNative(addr);
1645    }
1646
1647    String getRemoteName(BluetoothDevice device) {
1648        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1649        if (mRemoteDevices == null) return null;
1650        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1651        if (deviceProp == null) return null;
1652        return deviceProp.getName();
1653    }
1654
1655    int getRemoteType(BluetoothDevice device) {
1656        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1657        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1658        if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
1659        return deviceProp.getDeviceType();
1660    }
1661
1662    String getRemoteAlias(BluetoothDevice device) {
1663        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1664        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1665        if (deviceProp == null) return null;
1666        return deviceProp.getAlias();
1667    }
1668
1669    boolean setRemoteAlias(BluetoothDevice device, String name) {
1670        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1671        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1672        if (deviceProp == null) return false;
1673        deviceProp.setAlias(device, name);
1674        return true;
1675    }
1676
1677    int getRemoteClass(BluetoothDevice device) {
1678        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1679        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1680        if (deviceProp == null) return 0;
1681
1682        return deviceProp.getBluetoothClass();
1683    }
1684
1685    ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
1686        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1687        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1688        if (deviceProp == null) return null;
1689        return deviceProp.getUuids();
1690    }
1691
1692    boolean fetchRemoteUuids(BluetoothDevice device) {
1693        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1694        mRemoteDevices.fetchUuids(device);
1695        return true;
1696    }
1697
1698    boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
1699        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
1700        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1701        // Only allow setting a pin in bonding state, or bonded state in case of security upgrade.
1702        if (deviceProp == null
1703                || (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING
1704                           && deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) {
1705            return false;
1706        }
1707
1708        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1709        return pinReplyNative(addr, accept, len, pinCode);
1710    }
1711
1712    boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
1713        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1714        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1715        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1716            return false;
1717        }
1718
1719        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1720        return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
1721                Utils.byteArrayToInt(passkey));
1722    }
1723
1724    boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
1725        enforceCallingOrSelfPermission(
1726                BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission");
1727        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
1728        if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
1729            return false;
1730        }
1731
1732        byte[] addr = Utils.getBytesFromAddress(device.getAddress());
1733        return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
1734                accept, 0);
1735    }
1736
1737    int getPhonebookAccessPermission(BluetoothDevice device) {
1738        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1739        SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
1740                Context.MODE_PRIVATE);
1741        if (!pref.contains(device.getAddress())) {
1742            return BluetoothDevice.ACCESS_UNKNOWN;
1743        }
1744        return pref.getBoolean(device.getAddress(), false)
1745                ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED;
1746    }
1747
1748    boolean setPhonebookAccessPermission(BluetoothDevice device, int value) {
1749        enforceCallingOrSelfPermission(
1750                BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission");
1751        SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
1752                Context.MODE_PRIVATE);
1753        SharedPreferences.Editor editor = pref.edit();
1754        if (value == BluetoothDevice.ACCESS_UNKNOWN) {
1755            editor.remove(device.getAddress());
1756        } else {
1757            editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
1758        }
1759        editor.apply();
1760        return true;
1761    }
1762
1763    int getMessageAccessPermission(BluetoothDevice device) {
1764        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1765        SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
1766                Context.MODE_PRIVATE);
1767        if (!pref.contains(device.getAddress())) {
1768            return BluetoothDevice.ACCESS_UNKNOWN;
1769        }
1770        return pref.getBoolean(device.getAddress(), false)
1771                ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED;
1772    }
1773
1774    boolean setMessageAccessPermission(BluetoothDevice device, int value) {
1775        enforceCallingOrSelfPermission(
1776                BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission");
1777        SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
1778                Context.MODE_PRIVATE);
1779        SharedPreferences.Editor editor = pref.edit();
1780        if (value == BluetoothDevice.ACCESS_UNKNOWN) {
1781            editor.remove(device.getAddress());
1782        } else {
1783            editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
1784        }
1785        editor.apply();
1786        return true;
1787    }
1788
1789    int getSimAccessPermission(BluetoothDevice device) {
1790        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1791        SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE,
1792                Context.MODE_PRIVATE);
1793        if (!pref.contains(device.getAddress())) {
1794            return BluetoothDevice.ACCESS_UNKNOWN;
1795        }
1796        return pref.getBoolean(device.getAddress(), false)
1797                ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED;
1798    }
1799
1800    boolean setSimAccessPermission(BluetoothDevice device, int value) {
1801        enforceCallingOrSelfPermission(
1802                BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission");
1803        SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE,
1804                Context.MODE_PRIVATE);
1805        SharedPreferences.Editor editor = pref.edit();
1806        if (value == BluetoothDevice.ACCESS_UNKNOWN) {
1807            editor.remove(device.getAddress());
1808        } else {
1809            editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
1810        }
1811        editor.apply();
1812        return true;
1813    }
1814
1815    void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
1816        // TODO(BT) permission check?
1817        // Since this is a binder call check if Bluetooth is on still
1818        if (getState() == BluetoothAdapter.STATE_OFF) return;
1819
1820        mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
1821
1822    }
1823
1824    ParcelFileDescriptor connectSocket(
1825            BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag) {
1826        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1827        int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), type,
1828                Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid());
1829        if (fd < 0) {
1830            errorLog("Failed to connect socket");
1831            return null;
1832        }
1833        return ParcelFileDescriptor.adoptFd(fd);
1834    }
1835
1836    ParcelFileDescriptor createSocketChannel(
1837            int type, String serviceName, ParcelUuid uuid, int port, int flag) {
1838        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1839        int fd = createSocketChannelNative(
1840                type, serviceName, Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid());
1841        if (fd < 0) {
1842            errorLog("Failed to create socket channel");
1843            return null;
1844        }
1845        return ParcelFileDescriptor.adoptFd(fd);
1846    }
1847
1848    boolean factoryReset() {
1849        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
1850        return factoryResetNative();
1851    }
1852
1853    void registerCallback(IBluetoothCallback cb) {
1854        mCallbacks.register(cb);
1855    }
1856
1857    void unregisterCallback(IBluetoothCallback cb) {
1858        mCallbacks.unregister(cb);
1859    }
1860
1861    public int getNumOfAdvertisementInstancesSupported() {
1862        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1863        return mAdapterProperties.getNumOfAdvertisementInstancesSupported();
1864    }
1865
1866    public boolean isMultiAdvertisementSupported() {
1867        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1868        return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA;
1869    }
1870
1871    public boolean isRpaOffloadSupported() {
1872        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1873        return mAdapterProperties.isRpaOffloadSupported();
1874    }
1875
1876    public int getNumOfOffloadedIrkSupported() {
1877        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1878        return mAdapterProperties.getNumOfOffloadedIrkSupported();
1879    }
1880
1881    public int getNumOfOffloadedScanFilterSupported() {
1882        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1883        return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
1884    }
1885
1886    public int getOffloadedScanResultStorage() {
1887        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1888        return mAdapterProperties.getOffloadedScanResultStorage();
1889    }
1890
1891    private boolean isActivityAndEnergyReportingSupported() {
1892        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
1893        return mAdapterProperties.isActivityAndEnergyReportingSupported();
1894    }
1895
1896    public boolean isLe2MPhySupported() {
1897        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1898        return mAdapterProperties.isLe2MPhySupported();
1899    }
1900
1901    public boolean isLeCodedPhySupported() {
1902        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1903        return mAdapterProperties.isLeCodedPhySupported();
1904    }
1905
1906    public boolean isLeExtendedAdvertisingSupported() {
1907        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1908        return mAdapterProperties.isLeExtendedAdvertisingSupported();
1909    }
1910
1911    public boolean isLePeriodicAdvertisingSupported() {
1912        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1913        return mAdapterProperties.isLePeriodicAdvertisingSupported();
1914    }
1915
1916    public int getLeMaximumAdvertisingDataLength() {
1917        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1918        return mAdapterProperties.getLeMaximumAdvertisingDataLength();
1919    }
1920
1921    private BluetoothActivityEnergyInfo reportActivityInfo() {
1922        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission");
1923        if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON ||
1924                !mAdapterProperties.isActivityAndEnergyReportingSupported()) {
1925            return null;
1926        }
1927
1928        // Pull the data. The callback will notify mEnergyInfoLock.
1929        readEnergyInfo();
1930
1931        synchronized (mEnergyInfoLock) {
1932            try {
1933                mEnergyInfoLock.wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS);
1934            } catch (InterruptedException e) {
1935                // Just continue, the energy data may be stale but we won't miss anything next time
1936                // we query.
1937            }
1938
1939            final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(
1940                    SystemClock.elapsedRealtime(),
1941                    mStackReportedState,
1942                    mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs,
1943                    mEnergyUsedTotalVoltAmpSecMicro);
1944
1945            // Count the number of entries that have byte counts > 0
1946            int arrayLen = 0;
1947            for (int i = 0; i < mUidTraffic.size(); i++) {
1948                final UidTraffic traffic = mUidTraffic.valueAt(i);
1949                if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
1950                    arrayLen++;
1951                }
1952            }
1953
1954            // Copy the traffic objects whose byte counts are > 0 and reset the originals.
1955            final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null;
1956            int putIdx = 0;
1957            for (int i = 0; i < mUidTraffic.size(); i++) {
1958                final UidTraffic traffic = mUidTraffic.valueAt(i);
1959                if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
1960                    result[putIdx++] = traffic.clone();
1961                    traffic.setRxBytes(0);
1962                    traffic.setTxBytes(0);
1963                }
1964            }
1965
1966            info.setUidTraffic(result);
1967
1968            // Read on clear values; a record of data is created with
1969            // timstamp and new samples are collected until read again
1970            mStackReportedState = 0;
1971            mTxTimeTotalMs = 0;
1972            mRxTimeTotalMs = 0;
1973            mIdleTimeTotalMs = 0;
1974            mEnergyUsedTotalVoltAmpSecMicro = 0;
1975            return info;
1976        }
1977    }
1978
1979    public int getTotalNumOfTrackableAdvertisements() {
1980        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1981        return mAdapterProperties.getTotalNumOfTrackableAdvertisements();
1982    }
1983
1984    public void onLeServiceUp() {
1985        Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
1986        mAdapterStateMachine.sendMessage(m);
1987    }
1988
1989    public void onBrEdrDown() {
1990        Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
1991        mAdapterStateMachine.sendMessage(m);
1992    }
1993
1994    private static int convertScanModeToHal(int mode) {
1995        switch (mode) {
1996            case BluetoothAdapter.SCAN_MODE_NONE:
1997                return AbstractionLayer.BT_SCAN_MODE_NONE;
1998            case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
1999                return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
2000            case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
2001                return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
2002        }
2003        // errorLog("Incorrect scan mode in convertScanModeToHal");
2004        return -1;
2005    }
2006
2007    static int convertScanModeFromHal(int mode) {
2008        switch (mode) {
2009            case AbstractionLayer.BT_SCAN_MODE_NONE:
2010                return BluetoothAdapter.SCAN_MODE_NONE;
2011            case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
2012                return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
2013            case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
2014                return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
2015        }
2016        //errorLog("Incorrect scan mode in convertScanModeFromHal");
2017        return -1;
2018    }
2019
2020    // This function is called from JNI. It allows native code to set a single wake
2021    // alarm. If an alarm is already pending and a new request comes in, the alarm
2022    // will be rescheduled (i.e. the previously set alarm will be cancelled).
2023    private boolean setWakeAlarm(long delayMillis, boolean shouldWake) {
2024        synchronized (this) {
2025            if (mPendingAlarm != null) {
2026                mAlarmManager.cancel(mPendingAlarm);
2027            }
2028
2029            long wakeupTime = SystemClock.elapsedRealtime() + delayMillis;
2030            int type = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP
2031                                  : AlarmManager.ELAPSED_REALTIME;
2032
2033            Intent intent = new Intent(ACTION_ALARM_WAKEUP);
2034            mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
2035            mAlarmManager.setExact(type, wakeupTime, mPendingAlarm);
2036            return true;
2037        }
2038    }
2039
2040    // This function is called from JNI. It allows native code to acquire a single wake lock.
2041    // If the wake lock is already held, this function returns success. Although this function
2042    // only supports acquiring a single wake lock at a time right now, it will eventually be
2043    // extended to allow acquiring an arbitrary number of wake locks. The current interface
2044    // takes |lockName| as a parameter in anticipation of that implementation.
2045    private boolean acquireWakeLock(String lockName) {
2046        synchronized (this) {
2047            if (mWakeLock == null) {
2048                mWakeLockName = lockName;
2049                mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
2050            }
2051
2052            if (!mWakeLock.isHeld())
2053                mWakeLock.acquire();
2054        }
2055        return true;
2056    }
2057
2058    // This function is called from JNI. It allows native code to release a wake lock acquired
2059    // by |acquireWakeLock|. If the wake lock is not held, this function returns failure.
2060    // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is
2061    // needed here. See the comment for |acquireWakeLock| for an explanation of the interface.
2062    private boolean releaseWakeLock(String lockName) {
2063        synchronized (this) {
2064            if (mWakeLock == null) {
2065                errorLog("Repeated wake lock release; aborting release: " + lockName);
2066                return false;
2067            }
2068
2069            if (mWakeLock.isHeld())
2070                mWakeLock.release();
2071        }
2072        return true;
2073    }
2074
2075    private void energyInfoCallback(int status, int ctrl_state, long tx_time, long rx_time,
2076            long idle_time, long energy_used, UidTraffic[] data) throws RemoteException {
2077        if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID
2078                && ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) {
2079            // Energy is product of mA, V and ms. If the chipset doesn't
2080            // report it, we have to compute it from time
2081            if (energy_used == 0) {
2082                try {
2083                    final long txMah = Math.multiplyExact(tx_time, getTxCurrentMa());
2084                    final long rxMah = Math.multiplyExact(rx_time, getRxCurrentMa());
2085                    final long idleMah = Math.multiplyExact(idle_time, getIdleCurrentMa());
2086                    energy_used = (long) (Math.addExact(Math.addExact(txMah, rxMah), idleMah)
2087                            * getOperatingVolt());
2088                } catch (ArithmeticException e) {
2089                    Slog.wtf(TAG, "overflow in bluetooth energy callback", e);
2090                    // Energy is already 0 if the exception was thrown.
2091                }
2092            }
2093
2094            synchronized (mEnergyInfoLock) {
2095                mStackReportedState = ctrl_state;
2096                long totalTxTimeMs;
2097                long totalRxTimeMs;
2098                long totalIdleTimeMs;
2099                long totalEnergy;
2100                try {
2101                    totalTxTimeMs = Math.addExact(mTxTimeTotalMs, tx_time);
2102                    totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rx_time);
2103                    totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idle_time);
2104                    totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energy_used);
2105                } catch (ArithmeticException e) {
2106                    // This could be because we accumulated a lot of time, or we got a very strange
2107                    // value from the controller (more likely). Discard this data.
2108                    Slog.wtf(TAG, "overflow in bluetooth energy callback", e);
2109                    totalTxTimeMs = mTxTimeTotalMs;
2110                    totalRxTimeMs = mRxTimeTotalMs;
2111                    totalIdleTimeMs = mIdleTimeTotalMs;
2112                    totalEnergy = mEnergyUsedTotalVoltAmpSecMicro;
2113                }
2114
2115                mTxTimeTotalMs = totalTxTimeMs;
2116                mRxTimeTotalMs = totalRxTimeMs;
2117                mIdleTimeTotalMs = totalIdleTimeMs;
2118                mEnergyUsedTotalVoltAmpSecMicro = totalEnergy;
2119
2120                for (UidTraffic traffic : data) {
2121                    UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid());
2122                    if (existingTraffic == null) {
2123                        mUidTraffic.put(traffic.getUid(), traffic);
2124                    } else {
2125                        existingTraffic.addRxBytes(traffic.getRxBytes());
2126                        existingTraffic.addTxBytes(traffic.getTxBytes());
2127                    }
2128                }
2129                mEnergyInfoLock.notifyAll();
2130            }
2131        }
2132
2133        verboseLog("energyInfoCallback() status = " + status + "tx_time = " + tx_time + "rx_time = "
2134                + rx_time + "idle_time = " + idle_time + "energy_used = " + energy_used
2135                + "ctrl_state = " + ctrl_state + "traffic = " + Arrays.toString(data));
2136    }
2137
2138    private int getIdleCurrentMa() {
2139        return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma);
2140    }
2141
2142    private int getTxCurrentMa() {
2143        return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma);
2144    }
2145
2146    private int getRxCurrentMa() {
2147        return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma);
2148    }
2149
2150    private double getOperatingVolt() {
2151        return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0;
2152    }
2153
2154    @Override
2155    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2156        enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
2157
2158        if (args.length == 0) {
2159            writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section.");
2160            writer.println("Use --print argument for dumpsys direct from AdapterService.");
2161            return;
2162        }
2163
2164        if (args.length > 0) {
2165            verboseLog(
2166                    "dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args));
2167            if (args[0].startsWith("--proto")) {
2168                if (args[0].equals("--proto-java-bin")) {
2169                    dumpJava(fd);
2170                } else {
2171                    dumpNative(fd, args);
2172                }
2173                return;
2174            }
2175        }
2176
2177        writer.println("Bonded devices:");
2178        for (BluetoothDevice device : getBondedDevices()) {
2179            writer.println("  " + device.getAddress() + " [" + DEVICE_TYPE_NAMES[device.getType()]
2180                    + "] " + device.getName());
2181        }
2182
2183        // Dump profile information
2184        StringBuilder sb = new StringBuilder();
2185        synchronized (mProfiles) {
2186            for (ProfileService profile : mProfiles) {
2187                profile.dump(sb);
2188            }
2189        }
2190
2191        writer.write(sb.toString());
2192        writer.flush();
2193
2194        dumpNative(fd, args);
2195    }
2196
2197    private void dumpJava(FileDescriptor fd) {
2198        BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog();
2199        log.setNumBondedDevices(getBondedDevices().length);
2200
2201        for (ProfileService profile : mProfiles) {
2202            profile.dumpProto(log);
2203        }
2204
2205        try {
2206            FileOutputStream protoOut = new FileOutputStream(fd);
2207            String protoOutString = Base64.encodeToString(log.toByteArray(), Base64.DEFAULT);
2208            protoOut.write(protoOutString.getBytes(StandardCharsets.UTF_8));
2209            protoOut.close();
2210        } catch (IOException e) {
2211            errorLog("Unable to write Java protobuf to file descriptor.");
2212        }
2213    }
2214
2215    private void debugLog(String msg) {
2216        if (DBG) Log.d(TAG, msg);
2217    }
2218
2219    private void verboseLog(String msg) {
2220        if (VERBOSE) Log.v(TAG, msg);
2221    }
2222
2223    private void errorLog(String msg) {
2224        Log.e(TAG, msg);
2225    }
2226
2227    private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() {
2228        @Override
2229        public void onReceive(Context context, Intent intent) {
2230            synchronized (AdapterService.this) {
2231                mPendingAlarm = null;
2232                alarmFiredNative();
2233            }
2234        }
2235    };
2236
2237    private native static void classInitNative();
2238    private native boolean initNative();
2239    private native void cleanupNative();
2240    /*package*/ native boolean enableNative(boolean startRestricted);
2241    /*package*/ native boolean disableNative();
2242    /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val);
2243    /*package*/ native boolean getAdapterPropertiesNative();
2244    /*package*/ native boolean getAdapterPropertyNative(int type);
2245    /*package*/ native boolean setAdapterPropertyNative(int type);
2246    /*package*/ native boolean setDevicePropertyNative(byte[] address, int type, byte[] val);
2247    /*package*/ native boolean getDevicePropertyNative(byte[] address, int type);
2248
2249    /*package*/ native boolean createBondNative(byte[] address, int transport);
2250    /*package*/ native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData);
2251    /*package*/ native boolean removeBondNative(byte[] address);
2252    /*package*/ native boolean cancelBondNative(byte[] address);
2253    /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid);
2254
2255    /*package*/ native int getConnectionStateNative(byte[] address);
2256
2257    private native boolean startDiscoveryNative();
2258    private native boolean cancelDiscoveryNative();
2259
2260    private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin);
2261    private native boolean sspReplyNative(byte[] address, int type, boolean
2262            accept, int passkey);
2263
2264    /*package*/ native boolean getRemoteServicesNative(byte[] address);
2265    /*package*/ native boolean getRemoteMasInstancesNative(byte[] address);
2266
2267    private native int readEnergyInfo();
2268    // TODO(BT) move this to ../btsock dir
2269    private native int connectSocketNative(
2270            byte[] address, int type, byte[] uuid, int port, int flag, int callingUid);
2271    private native int createSocketChannelNative(
2272            int type, String serviceName, byte[] uuid, int port, int flag, int callingUid);
2273
2274    /*package*/ native boolean factoryResetNative();
2275
2276    private native void alarmFiredNative();
2277    private native void dumpNative(FileDescriptor fd, String[] arguments);
2278
2279    private native void interopDatabaseClearNative();
2280    private native void interopDatabaseAddNative(int feature, byte[] address, int length);
2281
2282    protected void finalize() {
2283        debugLog("finalize() - clean up object " + this);
2284        cleanup();
2285        if (TRACE_REF) {
2286            synchronized (AdapterService.class) {
2287                sRefCount--;
2288                debugLog("finalize() - REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount);
2289            }
2290        }
2291    }
2292
2293    // Returns if this is a mock object. This is currently used in testing so that we may not call
2294    // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up
2295    // calling finalize() which in turn calls System.exit() and the process crashes.
2296    //
2297    // Mock this in your testing framework to return true to avoid the mentioned behavior. In
2298    // production this has no effect.
2299    public boolean isMock() {
2300        return false;
2301    }
2302}
2303