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