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.server;
18
19import android.Manifest;
20import android.app.ActivityManager;
21import android.app.AppGlobals;
22import android.bluetooth.BluetoothAdapter;
23import android.bluetooth.BluetoothProfile;
24import android.bluetooth.IBluetooth;
25import android.bluetooth.IBluetoothCallback;
26import android.bluetooth.IBluetoothGatt;
27import android.bluetooth.IBluetoothHeadset;
28import android.bluetooth.IBluetoothManager;
29import android.bluetooth.IBluetoothManagerCallback;
30import android.bluetooth.IBluetoothProfileServiceConnection;
31import android.bluetooth.IBluetoothStateChangeCallback;
32import android.content.ActivityNotFoundException;
33import android.content.BroadcastReceiver;
34import android.content.ComponentName;
35import android.content.ContentResolver;
36import android.content.Context;
37import android.content.Intent;
38import android.content.IntentFilter;
39import android.content.ServiceConnection;
40import android.content.pm.ApplicationInfo;
41import android.content.pm.IPackageManager;
42import android.content.pm.PackageManager;
43import android.content.pm.UserInfo;
44import android.database.ContentObserver;
45import android.os.Binder;
46import android.os.Bundle;
47import android.os.Handler;
48import android.os.IBinder;
49import android.os.Looper;
50import android.os.Message;
51import android.os.Process;
52import android.os.RemoteCallbackList;
53import android.os.RemoteException;
54import android.os.SystemClock;
55import android.os.UserHandle;
56import android.os.UserManager;
57import android.os.UserManagerInternal;
58import android.os.UserManagerInternal.UserRestrictionsListener;
59import android.provider.Settings;
60import android.provider.Settings.SettingNotFoundException;
61import android.util.Slog;
62
63import com.android.internal.util.DumpUtils;
64import com.android.server.pm.UserRestrictionsUtils;
65
66import java.io.FileDescriptor;
67import java.io.PrintWriter;
68import java.util.HashMap;
69import java.util.LinkedList;
70import java.util.Map;
71import java.util.concurrent.ConcurrentHashMap;
72import java.util.concurrent.locks.ReentrantReadWriteLock;
73
74
75class BluetoothManagerService extends IBluetoothManager.Stub {
76    private static final String TAG = "BluetoothManagerService";
77    private static final boolean DBG = true;
78
79    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
80    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
81
82    private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
83    private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
84    private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
85
86    private static final int ACTIVE_LOG_MAX_SIZE = 20;
87    private static final int CRASH_LOG_MAX_SIZE = 100;
88    private static final String REASON_AIRPLANE_MODE = "airplane mode";
89    private static final String REASON_DISALLOWED = "disallowed by system";
90    private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system";
91    private static final String REASON_RESTARTED = "automatic restart";
92    private static final String REASON_START_CRASH = "turn-on crash";
93    private static final String REASON_SYSTEM_BOOT = "system boot";
94    private static final String REASON_UNEXPECTED = "unexpected crash";
95    private static final String REASON_USER_SWITCH = "user switch";
96    private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
97
98    private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
99    //Maximum msec to wait for service restart
100    private static final int SERVICE_RESTART_TIME_MS = 200;
101    //Maximum msec to wait for restart due to error
102    private static final int ERROR_RESTART_TIME_MS = 3000;
103    //Maximum msec to delay MESSAGE_USER_SWITCHED
104    private static final int USER_SWITCHED_TIME_MS = 200;
105    // Delay for the addProxy function in msec
106    private static final int ADD_PROXY_DELAY_MS = 100;
107
108    private static final int MESSAGE_ENABLE = 1;
109    private static final int MESSAGE_DISABLE = 2;
110    private static final int MESSAGE_REGISTER_ADAPTER = 20;
111    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
112    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
113    private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
114    private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
115    private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
116    private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
117    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
118    private static final int MESSAGE_TIMEOUT_BIND = 100;
119    private static final int MESSAGE_TIMEOUT_UNBIND = 101;
120    private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
121    private static final int MESSAGE_USER_SWITCHED = 300;
122    private static final int MESSAGE_USER_UNLOCKED = 301;
123    private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
124    private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
125    private static final int MESSAGE_RESTORE_USER_SETTING = 500;
126
127    private static final int RESTORE_SETTING_TO_ON = 1;
128    private static final int RESTORE_SETTING_TO_OFF = 0;
129
130    private static final int MAX_ERROR_RESTART_RETRIES = 6;
131
132    // Bluetooth persisted setting is off
133    private static final int BLUETOOTH_OFF=0;
134    // Bluetooth persisted setting is on
135    // and Airplane mode won't affect Bluetooth state at start up
136    private static final int BLUETOOTH_ON_BLUETOOTH=1;
137    // Bluetooth persisted setting is on
138    // but Airplane mode will affect Bluetooth state at start up
139    // and Airplane mode will have higher priority.
140    private static final int BLUETOOTH_ON_AIRPLANE=2;
141
142    private static final int SERVICE_IBLUETOOTH = 1;
143    private static final int SERVICE_IBLUETOOTHGATT = 2;
144
145    private final Context mContext;
146
147    // Locks are not provided for mName and mAddress.
148    // They are accessed in handler or broadcast receiver, same thread context.
149    private String mAddress;
150    private String mName;
151    private final ContentResolver mContentResolver;
152    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
153    private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
154    private IBinder mBluetoothBinder;
155    private IBluetooth mBluetooth;
156    private IBluetoothGatt mBluetoothGatt;
157    private final ReentrantReadWriteLock mBluetoothLock =
158        new ReentrantReadWriteLock();
159    private boolean mBinding;
160    private boolean mUnbinding;
161
162    // used inside handler thread
163    private boolean mQuietEnable = false;
164    private boolean mEnable;
165
166    private CharSequence timeToLog(long timestamp) {
167        return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
168    }
169
170    /**
171     * Used for tracking apps that enabled / disabled Bluetooth.
172     */
173    private class ActiveLog {
174        private String mPackageName;
175        private boolean mEnable;
176        private long mTimestamp;
177
178        public ActiveLog(String packageName, boolean enable, long timestamp) {
179            mPackageName = packageName;
180            mEnable = enable;
181            mTimestamp = timestamp;
182        }
183
184        public long getTime() {
185            return mTimestamp;
186        }
187
188        public String toString() {
189            return  timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ") + " by "
190                + mPackageName;
191        }
192
193    }
194
195    private LinkedList<ActiveLog> mActiveLogs;
196    private LinkedList<Long> mCrashTimestamps;
197    private int mCrashes;
198
199    // configuration from external IBinder call which is used to
200    // synchronize with broadcast receiver.
201    private boolean mQuietEnableExternal;
202    private boolean mEnableExternal;
203
204    // Map of apps registered to keep BLE scanning on.
205    private Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
206
207    private int mState;
208    private final BluetoothHandler mHandler;
209    private int mErrorRecoveryRetryCounter;
210    private final int mSystemUiUid;
211
212    // Save a ProfileServiceConnections object for each of the bound
213    // bluetooth profile services
214    private final Map <Integer, ProfileServiceConnections> mProfileServices =
215            new HashMap <Integer, ProfileServiceConnections>();
216
217    private final boolean mPermissionReviewRequired;
218
219    private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
220        @Override
221        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {
222            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
223            mHandler.sendMessage(msg);
224        }
225    };
226
227    private final UserRestrictionsListener mUserRestrictionsListener =
228            new UserRestrictionsListener() {
229        @Override
230        public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
231                Bundle prevRestrictions) {
232
233            if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
234                    UserManager.DISALLOW_BLUETOOTH_SHARING)) {
235                updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
236                        UserManager.DISALLOW_BLUETOOTH_SHARING));
237            }
238
239            // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
240            if (userId == UserHandle.USER_SYSTEM &&
241                UserRestrictionsUtils.restrictionsChanged(
242                    prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
243                if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
244                        UserManager.DISALLOW_BLUETOOTH)) {
245                    updateOppLauncherComponentState(userId, true); // Sharing disallowed
246                    sendDisableMsg(REASON_DISALLOWED);
247                } else {
248                    updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
249                            UserManager.DISALLOW_BLUETOOTH_SHARING));
250                }
251            }
252        }
253    };
254
255    private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
256        @Override
257        public void onChange(boolean unused) {
258            synchronized(this) {
259                if (isBluetoothPersistedStateOn()) {
260                    if (isAirplaneModeOn()) {
261                        persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
262                    } else {
263                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
264                    }
265                }
266
267                int st = BluetoothAdapter.STATE_OFF;
268                try {
269                    mBluetoothLock.readLock().lock();
270                    if (mBluetooth != null) {
271                        st = mBluetooth.getState();
272                    }
273                } catch (RemoteException e) {
274                    Slog.e(TAG, "Unable to call getState", e);
275                    return;
276                } finally {
277                    mBluetoothLock.readLock().unlock();
278                }
279
280                Slog.d(TAG, "Airplane Mode change - current state:  " +
281                          BluetoothAdapter.nameForState(st));
282
283                if (isAirplaneModeOn()) {
284                    // Clear registered LE apps to force shut-off
285                    clearBleApps();
286
287                    // If state is BLE_ON make sure we trigger disableBLE
288                    if (st == BluetoothAdapter.STATE_BLE_ON) {
289                        try {
290                            mBluetoothLock.readLock().lock();
291                            if (mBluetooth != null) {
292                                mBluetooth.onBrEdrDown();
293                                mEnable = false;
294                                mEnableExternal = false;
295                            }
296                        } catch (RemoteException e) {
297                            Slog.e(TAG,"Unable to call onBrEdrDown", e);
298                        } finally {
299                            mBluetoothLock.readLock().unlock();
300                        }
301                    } else if (st == BluetoothAdapter.STATE_ON){
302                        sendDisableMsg(REASON_AIRPLANE_MODE);
303                    }
304                } else if (mEnableExternal) {
305                    sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE);
306                }
307            }
308        }
309    };
310
311    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
312        @Override
313        public void onReceive(Context context, Intent intent) {
314            String action = intent.getAction();
315            if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
316                String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
317                if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
318                if (newName != null) {
319                    storeNameAndAddress(newName, null);
320                }
321            } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
322                String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
323                if (newAddress != null) {
324                    if (DBG) Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
325                    storeNameAndAddress(null, newAddress);
326                } else {
327                    if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found");
328                }
329            } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
330                final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
331                if (Settings.Global.BLUETOOTH_ON.equals(name)) {
332                    // The Bluetooth On state may be changed during system restore.
333                    final String prevValue = intent.getStringExtra(
334                            Intent.EXTRA_SETTING_PREVIOUS_VALUE);
335                    final String newValue = intent.getStringExtra(
336                            Intent.EXTRA_SETTING_NEW_VALUE);
337
338                    if (DBG) Slog.d(TAG, "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" +
339                                    prevValue + ", newValue=" + newValue);
340
341                    if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
342                        Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
343                                                             newValue.equals("0") ?
344                                                             RESTORE_SETTING_TO_OFF :
345                                                             RESTORE_SETTING_TO_ON, 0);
346                        mHandler.sendMessage(msg);
347                    }
348                }
349            }
350        }
351    };
352
353    BluetoothManagerService(Context context) {
354        mHandler = new BluetoothHandler(IoThread.get().getLooper());
355
356        mContext = context;
357
358        mPermissionReviewRequired = context.getResources().getBoolean(
359                com.android.internal.R.bool.config_permissionReviewRequired);
360
361        mActiveLogs = new LinkedList<ActiveLog>();
362        mCrashTimestamps = new LinkedList<Long>();
363        mCrashes = 0;
364        mBluetooth = null;
365        mBluetoothBinder = null;
366        mBluetoothGatt = null;
367        mBinding = false;
368        mUnbinding = false;
369        mEnable = false;
370        mState = BluetoothAdapter.STATE_OFF;
371        mQuietEnableExternal = false;
372        mEnableExternal = false;
373        mAddress = null;
374        mName = null;
375        mErrorRecoveryRetryCounter = 0;
376        mContentResolver = context.getContentResolver();
377        // Observe BLE scan only mode settings change.
378        registerForBleScanModeChange();
379        mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
380        mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
381
382        IntentFilter filter = new IntentFilter();
383        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
384        filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
385        filter.addAction(Intent.ACTION_SETTING_RESTORED);
386        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
387        mContext.registerReceiver(mReceiver, filter);
388
389        loadStoredNameAndAddress();
390        if (isBluetoothPersistedStateOn()) {
391            if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
392            mEnableExternal = true;
393        }
394
395        String airplaneModeRadios = Settings.Global.getString(mContentResolver,
396            Settings.Global.AIRPLANE_MODE_RADIOS);
397        if (airplaneModeRadios == null ||
398            airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) {
399            mContentResolver.registerContentObserver(
400                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
401                true, mAirplaneModeObserver);
402        }
403
404        int systemUiUid = -1;
405        try {
406            systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
407                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
408        } catch (PackageManager.NameNotFoundException e) {
409            // Some platforms, such as wearables do not have a system ui.
410            Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
411        }
412        mSystemUiUid = systemUiUid;
413    }
414
415    /**
416     *  Returns true if airplane mode is currently on
417     */
418    private final boolean isAirplaneModeOn() {
419        return Settings.Global.getInt(mContext.getContentResolver(),
420                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
421    }
422
423    /**
424     *  Returns true if the Bluetooth saved state is "on"
425     */
426    private final boolean isBluetoothPersistedStateOn() {
427        int state = Settings.Global.getInt(mContentResolver,
428                                           Settings.Global.BLUETOOTH_ON, -1);
429        if (DBG) Slog.d(TAG, "Bluetooth persisted state: " + state);
430        return state != BLUETOOTH_OFF;
431    }
432
433    /**
434     *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
435     */
436    private final boolean isBluetoothPersistedStateOnBluetooth() {
437        return Settings.Global.getInt(mContentResolver,
438                Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
439    }
440
441    /**
442     *  Save the Bluetooth on/off state
443     */
444    private void persistBluetoothSetting(int value) {
445        if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
446        // waive WRITE_SECURE_SETTINGS permission check
447        long callingIdentity = Binder.clearCallingIdentity();
448        Settings.Global.putInt(mContext.getContentResolver(),
449                               Settings.Global.BLUETOOTH_ON,
450                               value);
451        Binder.restoreCallingIdentity(callingIdentity);
452    }
453
454    /**
455     * Returns true if the Bluetooth Adapter's name and address is
456     * locally cached
457     * @return
458     */
459    private boolean isNameAndAddressSet() {
460        return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0;
461    }
462
463    /**
464     * Retrieve the Bluetooth Adapter's name and address and save it in
465     * in the local cache
466     */
467    private void loadStoredNameAndAddress() {
468        if (DBG) Slog.d(TAG, "Loading stored name and address");
469        if (mContext.getResources().getBoolean
470            (com.android.internal.R.bool.config_bluetooth_address_validation) &&
471             Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) {
472            // if the valid flag is not set, don't load the address and name
473            if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored");
474            return;
475        }
476        mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
477        mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
478        if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
479    }
480
481    /**
482     * Save the Bluetooth name and address in the persistent store.
483     * Only non-null values will be saved.
484     * @param name
485     * @param address
486     */
487    private void storeNameAndAddress(String name, String address) {
488        if (name != null) {
489            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
490            mName = name;
491            if (DBG) Slog.d(TAG,"Stored Bluetooth name: " +
492                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
493        }
494
495        if (address != null) {
496            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
497            mAddress=address;
498            if (DBG)  Slog.d(TAG,"Stored Bluetoothaddress: " +
499                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
500        }
501
502        if ((name != null) && (address != null)) {
503            Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
504        }
505    }
506
507    public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
508        if (callback == null) {
509            Slog.w(TAG, "Callback is null in registerAdapter");
510            return null;
511        }
512        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
513        msg.obj = callback;
514        mHandler.sendMessage(msg);
515
516        return mBluetooth;
517    }
518
519    public void unregisterAdapter(IBluetoothManagerCallback callback) {
520        if (callback == null) {
521            Slog.w(TAG, "Callback is null in unregisterAdapter");
522            return;
523        }
524        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
525                                                "Need BLUETOOTH permission");
526        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
527        msg.obj = callback;
528        mHandler.sendMessage(msg);
529    }
530
531    public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
532        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
533                                                "Need BLUETOOTH permission");
534        if (callback == null) {
535          Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
536          return;
537        }
538        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
539        msg.obj = callback;
540        mHandler.sendMessage(msg);
541    }
542
543    public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
544        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
545                                                "Need BLUETOOTH permission");
546        if (callback == null) {
547          Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
548          return;
549        }
550        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
551        msg.obj = callback;
552        mHandler.sendMessage(msg);
553    }
554
555    public boolean isEnabled() {
556        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
557            (!checkIfCallerIsForegroundUser())) {
558            Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user");
559            return false;
560        }
561
562        try {
563            mBluetoothLock.readLock().lock();
564            if (mBluetooth != null) return mBluetooth.isEnabled();
565        } catch (RemoteException e) {
566            Slog.e(TAG, "isEnabled()", e);
567        } finally {
568            mBluetoothLock.readLock().unlock();
569        }
570        return false;
571    }
572
573    public int getState() {
574        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
575                (!checkIfCallerIsForegroundUser())) {
576            Slog.w(TAG, "getState(): report OFF for non-active and non system user");
577            return BluetoothAdapter.STATE_OFF;
578        }
579
580        try {
581            mBluetoothLock.readLock().lock();
582            if (mBluetooth != null) return mBluetooth.getState();
583        } catch (RemoteException e) {
584            Slog.e(TAG, "getState()", e);
585        } finally {
586            mBluetoothLock.readLock().unlock();
587        }
588        return BluetoothAdapter.STATE_OFF;
589    }
590
591    class ClientDeathRecipient implements IBinder.DeathRecipient {
592        private String mPackageName;
593
594        public ClientDeathRecipient(String packageName) {
595            mPackageName = packageName;
596        }
597
598        public void binderDied() {
599            if (DBG) Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
600            if (isBleAppPresent()) {
601              // Nothing to do, another app is here.
602              return;
603            }
604            if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash");
605            try {
606                mBluetoothLock.readLock().lock();
607                if (mBluetooth != null &&
608                    mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
609                    mEnable = false;
610                    mBluetooth.onBrEdrDown();
611                }
612            } catch (RemoteException e) {
613                 Slog.e(TAG,"Unable to call onBrEdrDown", e);
614            } finally {
615                mBluetoothLock.readLock().unlock();
616            }
617        }
618
619        public String getPackageName() {
620            return mPackageName;
621        }
622    }
623
624    @Override
625    public boolean isBleScanAlwaysAvailable() {
626        if (isAirplaneModeOn() && !mEnable) {
627            return false;
628        }
629        try {
630            return (Settings.Global.getInt(mContentResolver,
631                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
632        } catch (SettingNotFoundException e) {
633        }
634        return false;
635    }
636
637    // Monitor change of BLE scan only mode settings.
638    private void registerForBleScanModeChange() {
639        ContentObserver contentObserver = new ContentObserver(null) {
640            @Override
641            public void onChange(boolean selfChange) {
642                if (isBleScanAlwaysAvailable()) {
643                  // Nothing to do
644                  return;
645                }
646                // BLE scan is not available.
647                disableBleScanMode();
648                clearBleApps();
649                try {
650                    mBluetoothLock.readLock().lock();
651                    if (mBluetooth != null) mBluetooth.onBrEdrDown();
652                } catch (RemoteException e) {
653                    Slog.e(TAG, "error when disabling bluetooth", e);
654                } finally {
655                    mBluetoothLock.readLock().unlock();
656                }
657            }
658        };
659
660        mContentResolver.registerContentObserver(
661                Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE),
662                false, contentObserver);
663    }
664
665    // Disable ble scan only mode.
666    private void disableBleScanMode() {
667        try {
668            mBluetoothLock.writeLock().lock();
669            if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
670                if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable");
671                mEnable = false;
672            }
673        } catch (RemoteException e) {
674            Slog.e(TAG, "getState()", e);
675        } finally {
676            mBluetoothLock.writeLock().unlock();
677        }
678    }
679
680    public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
681        ClientDeathRecipient r = mBleApps.get(token);
682        if (r == null && enable) {
683            ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
684            try {
685                token.linkToDeath(deathRec, 0);
686            } catch (RemoteException ex) {
687                throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
688            }
689            mBleApps.put(token, deathRec);
690            if (DBG) Slog.d(TAG, "Registered for death of " + packageName);
691        } else if (!enable && r != null) {
692            // Unregister death recipient as the app goes away.
693            token.unlinkToDeath(r, 0);
694            mBleApps.remove(token);
695            if (DBG) Slog.d(TAG, "Unregistered for death of " + packageName);
696        }
697        int appCount = mBleApps.size();
698        if (DBG) Slog.d(TAG, appCount + " registered Ble Apps");
699        if (appCount == 0 && mEnable) {
700            disableBleScanMode();
701        }
702        if (appCount == 0 && !mEnableExternal) {
703            sendBrEdrDownCallback();
704        }
705        return appCount;
706    }
707
708    // Clear all apps using BLE scan only mode.
709    private void clearBleApps() {
710        mBleApps.clear();
711    }
712
713    /** @hide */
714    public boolean isBleAppPresent() {
715        if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
716        return mBleApps.size() > 0;
717    }
718
719    /**
720     * Action taken when GattService is turned on
721     */
722    private void onBluetoothGattServiceUp() {
723        if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up");
724        try {
725            mBluetoothLock.readLock().lock();
726            if (mBluetooth == null) {
727                if (DBG) Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!");
728                return;
729            }
730            int st = mBluetooth.getState();
731            if (st != BluetoothAdapter.STATE_BLE_ON) {
732                if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " +
733                        BluetoothAdapter.nameForState(st));
734                return;
735            }
736            if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
737                // This triggers transition to STATE_ON
738                mBluetooth.onLeServiceUp();
739                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
740            }
741        } catch (RemoteException e) {
742            Slog.e(TAG,"Unable to call onServiceUp", e);
743        } finally {
744            mBluetoothLock.readLock().unlock();
745        }
746    }
747
748    /**
749     * Inform BluetoothAdapter instances that BREDR part is down
750     * and turn off all service and stack if no LE app needs it
751     */
752    private void sendBrEdrDownCallback() {
753        if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks");
754
755        if (mBluetooth == null) {
756            Slog.w(TAG, "Bluetooth handle is null");
757            return;
758        }
759
760        if (isBleAppPresent()) {
761            // Need to stay at BLE ON. Disconnect all Gatt connections
762            try {
763                mBluetoothGatt.unregAll();
764            } catch (RemoteException e) {
765                Slog.e(TAG, "Unable to disconnect all apps.", e);
766            }
767        } else {
768            try {
769                mBluetoothLock.readLock().lock();
770                if (mBluetooth != null) mBluetooth.onBrEdrDown();
771            } catch (RemoteException e) {
772                Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
773            } finally {
774                mBluetoothLock.readLock().unlock();
775            }
776        }
777
778    }
779
780    public boolean enableNoAutoConnect(String packageName)
781    {
782        if (isBluetoothDisallowed()) {
783            if (DBG) {
784                Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
785            }
786            return false;
787        }
788
789        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
790                                                "Need BLUETOOTH ADMIN permission");
791
792        if (DBG) {
793            Slog.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
794                    " mBinding = " + mBinding);
795        }
796        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
797
798        if (callingAppId != Process.NFC_UID) {
799            throw new SecurityException("no permission to enable Bluetooth quietly");
800        }
801
802        synchronized(mReceiver) {
803            mQuietEnableExternal = true;
804            mEnableExternal = true;
805            sendEnableMsg(true, packageName);
806        }
807        return true;
808    }
809
810    public boolean enable(String packageName) throws RemoteException {
811        final int callingUid = Binder.getCallingUid();
812        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
813
814        if (isBluetoothDisallowed()) {
815            if (DBG) {
816                Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
817            }
818            return false;
819        }
820
821        if (!callerSystem) {
822            if (!checkIfCallerIsForegroundUser()) {
823                Slog.w(TAG, "enable(): not allowed for non-active and non system user");
824                return false;
825            }
826
827            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
828                    "Need BLUETOOTH ADMIN permission");
829
830            if (!isEnabled() && mPermissionReviewRequired
831                    && startConsentUiIfNeeded(packageName, callingUid,
832                            BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
833                return false;
834            }
835        }
836
837        if (DBG) {
838            Slog.d(TAG,"enable(" + packageName + "):  mBluetooth =" + mBluetooth +
839                    " mBinding = " + mBinding + " mState = " +
840                    BluetoothAdapter.nameForState(mState));
841        }
842
843        synchronized(mReceiver) {
844            mQuietEnableExternal = false;
845            mEnableExternal = true;
846            // waive WRITE_SECURE_SETTINGS permission check
847            sendEnableMsg(false, packageName);
848        }
849        if (DBG) Slog.d(TAG, "enable returning");
850        return true;
851    }
852
853    public boolean disable(String packageName, boolean persist) throws RemoteException {
854        final int callingUid = Binder.getCallingUid();
855        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
856
857        if (!callerSystem) {
858            if (!checkIfCallerIsForegroundUser()) {
859                Slog.w(TAG, "disable(): not allowed for non-active and non system user");
860                return false;
861            }
862
863            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
864                    "Need BLUETOOTH ADMIN permission");
865
866            if (isEnabled() && mPermissionReviewRequired
867                    && startConsentUiIfNeeded(packageName, callingUid,
868                            BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
869                return false;
870            }
871        }
872
873        if (DBG) {
874            Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth +
875                " mBinding = " + mBinding);
876        }
877
878        synchronized(mReceiver) {
879            if (persist) {
880                persistBluetoothSetting(BLUETOOTH_OFF);
881            }
882            mEnableExternal = false;
883            sendDisableMsg(packageName);
884        }
885        return true;
886    }
887
888    private boolean startConsentUiIfNeeded(String packageName,
889            int callingUid, String intentAction) throws RemoteException {
890        try {
891            // Validate the package only if we are going to use it
892            ApplicationInfo applicationInfo = mContext.getPackageManager()
893                    .getApplicationInfoAsUser(packageName,
894                            PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
895                            UserHandle.getUserId(callingUid));
896            if (applicationInfo.uid != callingUid) {
897                throw new SecurityException("Package " + callingUid
898                        + " not in uid " + callingUid);
899            }
900
901            Intent intent = new Intent(intentAction);
902            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
903            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
904                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
905            try {
906                mContext.startActivity(intent);
907            } catch (ActivityNotFoundException e) {
908                // Shouldn't happen
909                Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
910                return false;
911            }
912            return true;
913        } catch (PackageManager.NameNotFoundException e) {
914            throw new RemoteException(e.getMessage());
915        }
916    }
917
918    public void unbindAndFinish() {
919        if (DBG) {
920            Slog.d(TAG,"unbindAndFinish(): " + mBluetooth +
921                " mBinding = " + mBinding + " mUnbinding = " + mUnbinding);
922        }
923
924        try {
925            mBluetoothLock.writeLock().lock();
926            if (mUnbinding) return;
927            mUnbinding = true;
928            mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
929            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
930            if (mBluetooth != null) {
931                //Unregister callback object
932                try {
933                    mBluetooth.unregisterCallback(mBluetoothCallback);
934                } catch (RemoteException re) {
935                    Slog.e(TAG, "Unable to unregister BluetoothCallback",re);
936                }
937                mBluetoothBinder = null;
938                mBluetooth = null;
939                mContext.unbindService(mConnection);
940                mUnbinding = false;
941                mBinding = false;
942            } else {
943                mUnbinding = false;
944            }
945            mBluetoothGatt = null;
946        } finally {
947            mBluetoothLock.writeLock().unlock();
948        }
949    }
950
951    public IBluetoothGatt getBluetoothGatt() {
952        // sync protection
953        return mBluetoothGatt;
954    }
955
956    @Override
957    public boolean bindBluetoothProfileService(int bluetoothProfile,
958            IBluetoothProfileServiceConnection proxy) {
959        if (!mEnable) {
960            if (DBG) {
961                Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
962                        ", while Bluetooth was disabled");
963            }
964            return false;
965        }
966        synchronized (mProfileServices) {
967            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
968            if (psc == null) {
969                if (DBG) {
970                    Slog.d(TAG, "Creating new ProfileServiceConnections object for"
971                            + " profile: " + bluetoothProfile);
972                }
973
974                if (bluetoothProfile != BluetoothProfile.HEADSET) return false;
975
976                Intent intent = new Intent(IBluetoothHeadset.class.getName());
977                psc = new ProfileServiceConnections(intent);
978                if (!psc.bindService()) return false;
979
980                mProfileServices.put(new Integer(bluetoothProfile), psc);
981            }
982        }
983
984        // Introducing a delay to give the client app time to prepare
985        Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
986        addProxyMsg.arg1 = bluetoothProfile;
987        addProxyMsg.obj = proxy;
988        mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
989        return true;
990    }
991
992    @Override
993    public void unbindBluetoothProfileService(int bluetoothProfile,
994            IBluetoothProfileServiceConnection proxy) {
995        synchronized (mProfileServices) {
996            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
997            if (psc == null) {
998                return;
999            }
1000            psc.removeProxy(proxy);
1001        }
1002    }
1003
1004    private void unbindAllBluetoothProfileServices() {
1005        synchronized (mProfileServices) {
1006            for (Integer i : mProfileServices.keySet()) {
1007                ProfileServiceConnections psc = mProfileServices.get(i);
1008                try {
1009                    mContext.unbindService(psc);
1010                } catch (IllegalArgumentException e) {
1011                    Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
1012                }
1013                psc.removeAllProxies();
1014            }
1015            mProfileServices.clear();
1016        }
1017    }
1018
1019    /**
1020     * Send enable message and set adapter name and address. Called when the boot phase becomes
1021     * PHASE_SYSTEM_SERVICES_READY.
1022     */
1023    public void handleOnBootPhase() {
1024        if (DBG) Slog.d(TAG, "Bluetooth boot completed");
1025        UserManagerInternal userManagerInternal =
1026                LocalServices.getService(UserManagerInternal.class);
1027        userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
1028        final boolean isBluetoothDisallowed = isBluetoothDisallowed();
1029        if (isBluetoothDisallowed) {
1030            return;
1031        }
1032        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
1033            if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
1034            sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT);
1035        } else if (!isNameAndAddressSet()) {
1036            if (DBG) Slog.d(TAG, "Getting adapter name and address");
1037            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1038            mHandler.sendMessage(getMsg);
1039        }
1040    }
1041
1042    /**
1043     * Called when switching to a different foreground user.
1044     */
1045    public void handleOnSwitchUser(int userHandle) {
1046        if (DBG) Slog.d(TAG, "User " + userHandle + " switched");
1047        mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
1048    }
1049
1050    /**
1051     * Called when user is unlocked.
1052     */
1053    public void handleOnUnlockUser(int userHandle) {
1054        if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked");
1055        mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
1056    }
1057
1058    /**
1059     * This class manages the clients connected to a given ProfileService
1060     * and maintains the connection with that service.
1061     */
1062    final private class ProfileServiceConnections implements ServiceConnection,
1063            IBinder.DeathRecipient {
1064        final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
1065                new RemoteCallbackList <IBluetoothProfileServiceConnection>();
1066        IBinder mService;
1067        ComponentName mClassName;
1068        Intent mIntent;
1069        boolean mInvokingProxyCallbacks = false;
1070
1071        ProfileServiceConnections(Intent intent) {
1072            mService = null;
1073            mClassName = null;
1074            mIntent = intent;
1075        }
1076
1077        private boolean bindService() {
1078            if (mIntent != null && mService == null &&
1079                    doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
1080                Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1081                msg.obj = this;
1082                mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1083                return true;
1084            }
1085            Slog.w(TAG, "Unable to bind with intent: " + mIntent);
1086            return false;
1087        }
1088
1089        private void addProxy(IBluetoothProfileServiceConnection proxy) {
1090            mProxies.register(proxy);
1091            if (mService != null) {
1092                try{
1093                    proxy.onServiceConnected(mClassName, mService);
1094                } catch (RemoteException e) {
1095                    Slog.e(TAG, "Unable to connect to proxy", e);
1096                }
1097            } else {
1098                if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
1099                    Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1100                    msg.obj = this;
1101                    mHandler.sendMessage(msg);
1102                }
1103            }
1104        }
1105
1106        private void removeProxy(IBluetoothProfileServiceConnection proxy) {
1107            if (proxy != null) {
1108                if (mProxies.unregister(proxy)) {
1109                    try {
1110                        proxy.onServiceDisconnected(mClassName);
1111                    } catch (RemoteException e) {
1112                        Slog.e(TAG, "Unable to disconnect proxy", e);
1113                    }
1114                }
1115            } else {
1116                Slog.w(TAG, "Trying to remove a null proxy");
1117            }
1118        }
1119
1120        private void removeAllProxies() {
1121            onServiceDisconnected(mClassName);
1122            mProxies.kill();
1123        }
1124
1125        @Override
1126        public void onServiceConnected(ComponentName className, IBinder service) {
1127            // remove timeout message
1128            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
1129            mService = service;
1130            mClassName = className;
1131            try {
1132                mService.linkToDeath(this, 0);
1133            } catch (RemoteException e) {
1134                Slog.e(TAG, "Unable to linkToDeath", e);
1135            }
1136
1137            if (mInvokingProxyCallbacks) {
1138                Slog.e(TAG, "Proxy callbacks already in progress.");
1139                return;
1140            }
1141            mInvokingProxyCallbacks = true;
1142
1143            final int n = mProxies.beginBroadcast();
1144            try {
1145                for (int i = 0; i < n; i++) {
1146                    try {
1147                        mProxies.getBroadcastItem(i).onServiceConnected(className, service);
1148                    } catch (RemoteException e) {
1149                        Slog.e(TAG, "Unable to connect to proxy", e);
1150                    }
1151                }
1152            } finally {
1153                mProxies.finishBroadcast();
1154                mInvokingProxyCallbacks = false;
1155            }
1156        }
1157
1158        @Override
1159        public void onServiceDisconnected(ComponentName className) {
1160            if (mService == null) return;
1161            mService.unlinkToDeath(this, 0);
1162            mService = null;
1163            mClassName = null;
1164
1165            if (mInvokingProxyCallbacks) {
1166                Slog.e(TAG, "Proxy callbacks already in progress.");
1167                return;
1168            }
1169            mInvokingProxyCallbacks = true;
1170
1171            final int n = mProxies.beginBroadcast();
1172            try {
1173                for (int i = 0; i < n; i++) {
1174                    try {
1175                        mProxies.getBroadcastItem(i).onServiceDisconnected(className);
1176                    } catch (RemoteException e) {
1177                        Slog.e(TAG, "Unable to disconnect from proxy", e);
1178                    }
1179                }
1180            } finally {
1181                mProxies.finishBroadcast();
1182                mInvokingProxyCallbacks = false;
1183            }
1184        }
1185
1186        @Override
1187        public void binderDied() {
1188            if (DBG) {
1189                Slog.w(TAG, "Profile service for profile: " + mClassName
1190                        + " died.");
1191            }
1192            onServiceDisconnected(mClassName);
1193            // Trigger rebind
1194            Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1195            msg.obj = this;
1196            mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1197        }
1198    }
1199
1200    private void sendBluetoothStateCallback(boolean isUp) {
1201        try {
1202            int n = mStateChangeCallbacks.beginBroadcast();
1203            if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
1204            for (int i=0; i <n;i++) {
1205                try {
1206                    mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
1207                } catch (RemoteException e) {
1208                    Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
1209                }
1210            }
1211        } finally {
1212            mStateChangeCallbacks.finishBroadcast();
1213        }
1214    }
1215
1216    /**
1217     * Inform BluetoothAdapter instances that Adapter service is up
1218     */
1219    private void sendBluetoothServiceUpCallback() {
1220        try {
1221            int n = mCallbacks.beginBroadcast();
1222            Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
1223            for (int i=0; i <n;i++) {
1224                try {
1225                    mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
1226                }  catch (RemoteException e) {
1227                    Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
1228                }
1229            }
1230        } finally {
1231            mCallbacks.finishBroadcast();
1232        }
1233    }
1234    /**
1235     * Inform BluetoothAdapter instances that Adapter service is down
1236     */
1237    private void sendBluetoothServiceDownCallback() {
1238        try {
1239            int n = mCallbacks.beginBroadcast();
1240            Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
1241            for (int i=0; i <n;i++) {
1242                try {
1243                    mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
1244                }  catch (RemoteException e) {
1245                    Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
1246                }
1247            }
1248        } finally {
1249            mCallbacks.finishBroadcast();
1250        }
1251    }
1252
1253    public String getAddress() {
1254        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
1255                "Need BLUETOOTH permission");
1256
1257        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
1258                (!checkIfCallerIsForegroundUser())) {
1259            Slog.w(TAG,"getAddress(): not allowed for non-active and non system user");
1260            return null;
1261        }
1262
1263        if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
1264                != PackageManager.PERMISSION_GRANTED) {
1265            return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
1266        }
1267
1268        try {
1269            mBluetoothLock.readLock().lock();
1270            if (mBluetooth != null) return mBluetooth.getAddress();
1271        } catch (RemoteException e) {
1272            Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e);
1273        } finally {
1274            mBluetoothLock.readLock().unlock();
1275        }
1276
1277        // mAddress is accessed from outside.
1278        // It is alright without a lock. Here, bluetooth is off, no other thread is
1279        // changing mAddress
1280        return mAddress;
1281    }
1282
1283    public String getName() {
1284        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
1285                                                "Need BLUETOOTH permission");
1286
1287        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
1288            (!checkIfCallerIsForegroundUser())) {
1289            Slog.w(TAG,"getName(): not allowed for non-active and non system user");
1290            return null;
1291        }
1292
1293        try {
1294            mBluetoothLock.readLock().lock();
1295            if (mBluetooth != null) return mBluetooth.getName();
1296        } catch (RemoteException e) {
1297            Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1298        } finally {
1299            mBluetoothLock.readLock().unlock();
1300        }
1301
1302        // mName is accessed from outside.
1303        // It alright without a lock. Here, bluetooth is off, no other thread is
1304        // changing mName
1305        return mName;
1306    }
1307
1308    private class BluetoothServiceConnection implements ServiceConnection {
1309        public void onServiceConnected(ComponentName componentName, IBinder service) {
1310            String name = componentName.getClassName();
1311            if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name);
1312            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
1313            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
1314                msg.arg1 = SERVICE_IBLUETOOTH;
1315            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
1316                msg.arg1 = SERVICE_IBLUETOOTHGATT;
1317            } else {
1318                Slog.e(TAG, "Unknown service connected: " + name);
1319                return;
1320            }
1321            msg.obj = service;
1322            mHandler.sendMessage(msg);
1323        }
1324
1325        public void onServiceDisconnected(ComponentName componentName) {
1326            // Called if we unexpectedly disconnect.
1327            String name = componentName.getClassName();
1328            if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
1329            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
1330            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
1331                msg.arg1 = SERVICE_IBLUETOOTH;
1332            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
1333                msg.arg1 = SERVICE_IBLUETOOTHGATT;
1334            } else {
1335                Slog.e(TAG, "Unknown service disconnected: " + name);
1336                return;
1337            }
1338            mHandler.sendMessage(msg);
1339        }
1340    }
1341
1342    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
1343
1344    private class BluetoothHandler extends Handler {
1345        boolean mGetNameAddressOnly = false;
1346
1347        public BluetoothHandler(Looper looper) {
1348            super(looper);
1349        }
1350
1351        @Override
1352        public void handleMessage(Message msg) {
1353            switch (msg.what) {
1354                case MESSAGE_GET_NAME_AND_ADDRESS:
1355                    if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1356                    try {
1357                        mBluetoothLock.writeLock().lock();
1358                        if ((mBluetooth == null) && (!mBinding)) {
1359                            if (DBG) Slog.d(TAG, "Binding to service to get name and address");
1360                            mGetNameAddressOnly = true;
1361                            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1362                            mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
1363                            Intent i = new Intent(IBluetooth.class.getName());
1364                            if (!doBind(i, mConnection,
1365                                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1366                                UserHandle.CURRENT)) {
1367                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1368                            } else {
1369                                mBinding = true;
1370                            }
1371                        } else if (mBluetooth != null) {
1372                            try {
1373                                storeNameAndAddress(mBluetooth.getName(),
1374                                                    mBluetooth.getAddress());
1375                            } catch (RemoteException re) {
1376                                Slog.e(TAG, "Unable to grab names", re);
1377                            }
1378                            if (mGetNameAddressOnly && !mEnable) {
1379                                unbindAndFinish();
1380                            }
1381                            mGetNameAddressOnly = false;
1382                        }
1383                    } finally {
1384                        mBluetoothLock.writeLock().unlock();
1385                    }
1386                    break;
1387
1388                case MESSAGE_ENABLE:
1389                    if (DBG) {
1390                        Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
1391                    }
1392                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1393                    mEnable = true;
1394
1395                    // Use service interface to get the exact state
1396                    try {
1397                        mBluetoothLock.readLock().lock();
1398                        if (mBluetooth != null) {
1399                            int state = mBluetooth.getState();
1400                            if (state == BluetoothAdapter.STATE_BLE_ON) {
1401                                Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
1402                                mBluetooth.onLeServiceUp();
1403                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
1404                                break;
1405                            }
1406                        }
1407                    } catch (RemoteException e) {
1408                        Slog.e(TAG, "", e);
1409                    } finally {
1410                        mBluetoothLock.readLock().unlock();
1411                    }
1412
1413                    mQuietEnable = (msg.arg1 == 1);
1414                    if (mBluetooth == null) {
1415                        handleEnable(mQuietEnable);
1416                    } else {
1417                        //
1418                        // We need to wait until transitioned to STATE_OFF and
1419                        // the previous Bluetooth process has exited. The
1420                        // waiting period has three components:
1421                        // (a) Wait until the local state is STATE_OFF. This
1422                        //     is accomplished by "waitForOnOff(false, true)".
1423                        // (b) Wait until the STATE_OFF state is updated to
1424                        //     all components.
1425                        // (c) Wait until the Bluetooth process exits, and
1426                        //     ActivityManager detects it.
1427                        // The waiting for (b) and (c) is accomplished by
1428                        // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
1429                        // message. On slower devices, that delay needs to be
1430                        // on the order of (2 * SERVICE_RESTART_TIME_MS).
1431                        //
1432                        waitForOnOff(false, true);
1433                        Message restartMsg = mHandler.obtainMessage(
1434                                MESSAGE_RESTART_BLUETOOTH_SERVICE);
1435                        mHandler.sendMessageDelayed(restartMsg,
1436                                2 * SERVICE_RESTART_TIME_MS);
1437                    }
1438                    break;
1439
1440                case MESSAGE_DISABLE:
1441                    if (DBG) Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
1442                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
1443                    if (mEnable && mBluetooth != null) {
1444                        waitForOnOff(true, false);
1445                        mEnable = false;
1446                        handleDisable();
1447                        waitForOnOff(false, false);
1448                    } else {
1449                        mEnable = false;
1450                        handleDisable();
1451                    }
1452                    break;
1453
1454                case MESSAGE_RESTORE_USER_SETTING:
1455                    try {
1456                        if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1457                            if (DBG) Slog.d(TAG, "Restore Bluetooth state to disabled");
1458                            disable(REASON_RESTORE_USER_SETTING, true);
1459                        } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1460                            if (DBG) Slog.d(TAG, "Restore Bluetooth state to enabled");
1461                            enable(REASON_RESTORE_USER_SETTING);
1462                        }
1463                    } catch (RemoteException e) {
1464                        Slog.e(TAG,"Unable to change Bluetooth On setting", e);
1465                    }
1466                    break;
1467
1468                case MESSAGE_REGISTER_ADAPTER:
1469                {
1470                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
1471                    mCallbacks.register(callback);
1472                    break;
1473                }
1474                case MESSAGE_UNREGISTER_ADAPTER:
1475                {
1476                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
1477                    mCallbacks.unregister(callback);
1478                    break;
1479                }
1480                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
1481                {
1482                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
1483                    mStateChangeCallbacks.register(callback);
1484                    break;
1485                }
1486                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
1487                {
1488                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
1489                    mStateChangeCallbacks.unregister(callback);
1490                    break;
1491                }
1492                case MESSAGE_ADD_PROXY_DELAYED:
1493                {
1494                    ProfileServiceConnections psc = mProfileServices.get(
1495                            new Integer(msg.arg1));
1496                    if (psc == null) {
1497                        break;
1498                    }
1499                    IBluetoothProfileServiceConnection proxy =
1500                            (IBluetoothProfileServiceConnection) msg.obj;
1501                    psc.addProxy(proxy);
1502                    break;
1503                }
1504                case MESSAGE_BIND_PROFILE_SERVICE:
1505                {
1506                    ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
1507                    removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
1508                    if (psc == null) {
1509                        break;
1510                    }
1511                    psc.bindService();
1512                    break;
1513                }
1514                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
1515                {
1516                    if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
1517
1518                    IBinder service = (IBinder) msg.obj;
1519                    try {
1520                        mBluetoothLock.writeLock().lock();
1521                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1522                            mBluetoothGatt = IBluetoothGatt.Stub
1523                                    .asInterface(Binder.allowBlocking(service));
1524                            onBluetoothGattServiceUp();
1525                            break;
1526                        } // else must be SERVICE_IBLUETOOTH
1527
1528                        //Remove timeout
1529                        mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1530
1531                        mBinding = false;
1532                        mBluetoothBinder = service;
1533                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
1534
1535                        if (!isNameAndAddressSet()) {
1536                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
1537                            mHandler.sendMessage(getMsg);
1538                            if (mGetNameAddressOnly) return;
1539                        }
1540
1541                        //Register callback object
1542                        try {
1543                            mBluetooth.registerCallback(mBluetoothCallback);
1544                        } catch (RemoteException re) {
1545                            Slog.e(TAG, "Unable to register BluetoothCallback",re);
1546                        }
1547                        //Inform BluetoothAdapter instances that service is up
1548                        sendBluetoothServiceUpCallback();
1549
1550                        //Do enable request
1551                        try {
1552                            if (mQuietEnable == false) {
1553                                if (!mBluetooth.enable()) {
1554                                    Slog.e(TAG,"IBluetooth.enable() returned false");
1555                                }
1556                            } else {
1557                                if (!mBluetooth.enableNoAutoConnect()) {
1558                                    Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
1559                                }
1560                            }
1561                        } catch (RemoteException e) {
1562                            Slog.e(TAG,"Unable to call enable()",e);
1563                        }
1564                    } finally {
1565                        mBluetoothLock.writeLock().unlock();
1566                    }
1567
1568                    if (!mEnable) {
1569                        waitForOnOff(true, false);
1570                        handleDisable();
1571                        waitForOnOff(false, false);
1572                    }
1573                    break;
1574                }
1575                case MESSAGE_BLUETOOTH_STATE_CHANGE:
1576                {
1577                    int prevState = msg.arg1;
1578                    int newState = msg.arg2;
1579                    if (DBG) {
1580                      Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(prevState) + " > " +
1581                        BluetoothAdapter.nameForState(newState));
1582                    }
1583                    mState = newState;
1584                    bluetoothStateChangeHandler(prevState, newState);
1585                    // handle error state transition case from TURNING_ON to OFF
1586                    // unbind and rebind bluetooth service and enable bluetooth
1587                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) &&
1588                            (newState == BluetoothAdapter.STATE_OFF) &&
1589                            (mBluetooth != null) && mEnable) {
1590                        recoverBluetoothServiceFromError(false);
1591                    }
1592                    if ((prevState == BluetoothAdapter.STATE_TURNING_ON) &&
1593                            (newState == BluetoothAdapter.STATE_BLE_ON) &&
1594                            (mBluetooth != null) && mEnable) {
1595                        recoverBluetoothServiceFromError(true);
1596                    }
1597                    // If we tried to enable BT while BT was in the process of shutting down,
1598                    // wait for the BT process to fully tear down and then force a restart
1599                    // here.  This is a bit of a hack (b/29363429).
1600                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) &&
1601                            (newState == BluetoothAdapter.STATE_OFF)) {
1602                        if (mEnable) {
1603                            Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1604                            waitForOnOff(false, true);
1605                            Message restartMsg = mHandler.obtainMessage(
1606                                    MESSAGE_RESTART_BLUETOOTH_SERVICE);
1607                            mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
1608                        }
1609                    }
1610                    if (newState == BluetoothAdapter.STATE_ON ||
1611                            newState == BluetoothAdapter.STATE_BLE_ON) {
1612                        // bluetooth is working, reset the counter
1613                        if (mErrorRecoveryRetryCounter != 0) {
1614                            Slog.w(TAG, "bluetooth is recovered from error");
1615                            mErrorRecoveryRetryCounter = 0;
1616                        }
1617                    }
1618                    break;
1619                }
1620                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
1621                {
1622                    Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
1623                    try {
1624                        mBluetoothLock.writeLock().lock();
1625                        if (msg.arg1 == SERVICE_IBLUETOOTH) {
1626                            // if service is unbinded already, do nothing and return
1627                            if (mBluetooth == null) break;
1628                            mBluetooth = null;
1629                        } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1630                            mBluetoothGatt = null;
1631                            break;
1632                        } else {
1633                            Slog.e(TAG, "Unknown argument for service disconnect!");
1634                            break;
1635                        }
1636                    } finally {
1637                        mBluetoothLock.writeLock().unlock();
1638                    }
1639
1640                    // log the unexpected crash
1641                    addCrashLog();
1642                    addActiveLog(REASON_UNEXPECTED, false);
1643                    if (mEnable) {
1644                        mEnable = false;
1645                        // Send a Bluetooth Restart message
1646                        Message restartMsg = mHandler.obtainMessage(
1647                            MESSAGE_RESTART_BLUETOOTH_SERVICE);
1648                        mHandler.sendMessageDelayed(restartMsg,
1649                            SERVICE_RESTART_TIME_MS);
1650                    }
1651
1652                    sendBluetoothServiceDownCallback();
1653
1654                    // Send BT state broadcast to update
1655                    // the BT icon correctly
1656                    if ((mState == BluetoothAdapter.STATE_TURNING_ON) ||
1657                            (mState == BluetoothAdapter.STATE_ON)) {
1658                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
1659                                                    BluetoothAdapter.STATE_TURNING_OFF);
1660                        mState = BluetoothAdapter.STATE_TURNING_OFF;
1661                    }
1662                    if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1663                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
1664                                                    BluetoothAdapter.STATE_OFF);
1665                    }
1666
1667                    mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1668                    mState = BluetoothAdapter.STATE_OFF;
1669                    break;
1670                }
1671                case MESSAGE_RESTART_BLUETOOTH_SERVICE:
1672                {
1673                    Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE");
1674                    /* Enable without persisting the setting as
1675                     it doesnt change when IBluetooth
1676                     service restarts */
1677                    mEnable = true;
1678                    addActiveLog(REASON_RESTARTED, true);
1679                    handleEnable(mQuietEnable);
1680                    break;
1681                }
1682                case MESSAGE_TIMEOUT_BIND: {
1683                    Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
1684                    mBluetoothLock.writeLock().lock();
1685                    mBinding = false;
1686                    mBluetoothLock.writeLock().unlock();
1687                    break;
1688                }
1689                case MESSAGE_TIMEOUT_UNBIND:
1690                {
1691                    Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
1692                    mBluetoothLock.writeLock().lock();
1693                    mUnbinding = false;
1694                    mBluetoothLock.writeLock().unlock();
1695                    break;
1696                }
1697
1698                case MESSAGE_USER_SWITCHED: {
1699                    if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED");
1700                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
1701
1702                    /* disable and enable BT when detect a user switch */
1703                    if (mBluetooth != null && isEnabled()) {
1704                        try {
1705                            mBluetoothLock.readLock().lock();
1706                            if (mBluetooth != null) {
1707                                mBluetooth.unregisterCallback(mBluetoothCallback);
1708                            }
1709                        } catch (RemoteException re) {
1710                            Slog.e(TAG, "Unable to unregister", re);
1711                        } finally {
1712                            mBluetoothLock.readLock().unlock();
1713                        }
1714
1715                        if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1716                            // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
1717                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
1718                            mState = BluetoothAdapter.STATE_OFF;
1719                        }
1720                        if (mState == BluetoothAdapter.STATE_OFF) {
1721                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
1722                            mState = BluetoothAdapter.STATE_TURNING_ON;
1723                        }
1724
1725                        waitForOnOff(true, false);
1726
1727                        if (mState == BluetoothAdapter.STATE_TURNING_ON) {
1728                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
1729                        }
1730
1731                        unbindAllBluetoothProfileServices();
1732                        // disable
1733                        addActiveLog(REASON_USER_SWITCH, false);
1734                        handleDisable();
1735                        // Pbap service need receive STATE_TURNING_OFF intent to close
1736                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
1737                                                    BluetoothAdapter.STATE_TURNING_OFF);
1738
1739                        boolean didDisableTimeout = !waitForOnOff(false, true);
1740
1741                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
1742                                                    BluetoothAdapter.STATE_OFF);
1743                        sendBluetoothServiceDownCallback();
1744
1745                        try {
1746                            mBluetoothLock.writeLock().lock();
1747                            if (mBluetooth != null) {
1748                                mBluetooth = null;
1749                                // Unbind
1750                                mContext.unbindService(mConnection);
1751                            }
1752                            mBluetoothGatt = null;
1753                        } finally {
1754                            mBluetoothLock.writeLock().unlock();
1755                        }
1756
1757                        //
1758                        // If disabling Bluetooth times out, wait for an
1759                        // additional amount of time to ensure the process is
1760                        // shut down completely before attempting to restart.
1761                        //
1762                        if (didDisableTimeout) {
1763                            SystemClock.sleep(3000);
1764                        } else {
1765                            SystemClock.sleep(100);
1766                        }
1767
1768                        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1769                        mState = BluetoothAdapter.STATE_OFF;
1770                        // enable
1771                        addActiveLog(REASON_USER_SWITCH, true);
1772                        // mEnable flag could have been reset on disableBLE. Reenable it.
1773                        mEnable = true;
1774                        handleEnable(mQuietEnable);
1775                    } else if (mBinding || mBluetooth != null) {
1776                        Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
1777                        userMsg.arg2 = 1 + msg.arg2;
1778                        // if user is switched when service is binding retry after a delay
1779                        mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
1780                        if (DBG) {
1781                            Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
1782                        }
1783                    }
1784                    break;
1785                }
1786                case MESSAGE_USER_UNLOCKED: {
1787                    if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
1788                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
1789
1790                    if (mEnable && !mBinding && (mBluetooth == null)) {
1791                        // We should be connected, but we gave up for some
1792                        // reason; maybe the Bluetooth service wasn't encryption
1793                        // aware, so try binding again.
1794                        if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock");
1795                        handleEnable(mQuietEnable);
1796                    }
1797                }
1798            }
1799        }
1800    }
1801
1802    private void handleEnable(boolean quietMode) {
1803        mQuietEnable = quietMode;
1804
1805        try {
1806            mBluetoothLock.writeLock().lock();
1807            if ((mBluetooth == null) && (!mBinding)) {
1808                //Start bind timeout and bind
1809                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1810                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
1811                Intent i = new Intent(IBluetooth.class.getName());
1812                if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1813                        UserHandle.CURRENT)) {
1814                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1815                } else {
1816                    mBinding = true;
1817                }
1818            } else if (mBluetooth != null) {
1819                //Enable bluetooth
1820                try {
1821                    if (!mQuietEnable) {
1822                        if(!mBluetooth.enable()) {
1823                            Slog.e(TAG,"IBluetooth.enable() returned false");
1824                        }
1825                    }
1826                    else {
1827                        if(!mBluetooth.enableNoAutoConnect()) {
1828                            Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
1829                        }
1830                    }
1831                } catch (RemoteException e) {
1832                    Slog.e(TAG,"Unable to call enable()",e);
1833                }
1834            }
1835        } finally {
1836            mBluetoothLock.writeLock().unlock();
1837        }
1838    }
1839
1840    boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
1841        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
1842        intent.setComponent(comp);
1843        if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
1844            Slog.e(TAG, "Fail to bind to: " + intent);
1845            return false;
1846        }
1847        return true;
1848    }
1849
1850    private void handleDisable() {
1851        try {
1852            mBluetoothLock.readLock().lock();
1853            if (mBluetooth != null) {
1854                if (DBG) Slog.d(TAG,"Sending off request.");
1855                if (!mBluetooth.disable()) {
1856                    Slog.e(TAG,"IBluetooth.disable() returned false");
1857                }
1858            }
1859        } catch (RemoteException e) {
1860            Slog.e(TAG,"Unable to call disable()",e);
1861        } finally {
1862            mBluetoothLock.readLock().unlock();
1863        }
1864    }
1865
1866    private boolean checkIfCallerIsForegroundUser() {
1867        int foregroundUser;
1868        int callingUser = UserHandle.getCallingUserId();
1869        int callingUid = Binder.getCallingUid();
1870        long callingIdentity = Binder.clearCallingIdentity();
1871        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1872        UserInfo ui = um.getProfileParent(callingUser);
1873        int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
1874        int callingAppId = UserHandle.getAppId(callingUid);
1875        boolean valid = false;
1876        try {
1877            foregroundUser = ActivityManager.getCurrentUser();
1878            valid = (callingUser == foregroundUser) ||
1879                    parentUser == foregroundUser    ||
1880                    callingAppId == Process.NFC_UID ||
1881                    callingAppId == mSystemUiUid;
1882            if (DBG && !valid) {
1883                Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
1884                    + " callingUser=" + callingUser
1885                    + " parentUser=" + parentUser
1886                    + " foregroundUser=" + foregroundUser);
1887            }
1888        } finally {
1889            Binder.restoreCallingIdentity(callingIdentity);
1890        }
1891        return valid;
1892    }
1893
1894    private void sendBleStateChanged(int prevState, int newState) {
1895        if (DBG) Slog.d(TAG,"Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) +
1896            " > " + BluetoothAdapter.nameForState(newState));
1897        // Send broadcast message to everyone else
1898        Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
1899        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
1900        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
1901        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1902        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
1903    }
1904
1905    private void bluetoothStateChangeHandler(int prevState, int newState) {
1906        boolean isStandardBroadcast = true;
1907        if (prevState == newState) { // No change. Nothing to do.
1908            return;
1909        }
1910        // Notify all proxy objects first of adapter state change
1911        if (newState == BluetoothAdapter.STATE_BLE_ON ||
1912                newState == BluetoothAdapter.STATE_OFF) {
1913            boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
1914               && newState == BluetoothAdapter.STATE_BLE_ON);
1915
1916            if (newState == BluetoothAdapter.STATE_OFF) {
1917                // If Bluetooth is off, send service down event to proxy objects, and unbind
1918                if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down");
1919                sendBluetoothServiceDownCallback();
1920                unbindAndFinish();
1921                sendBleStateChanged(prevState, newState);
1922                // Don't broadcast as it has already been broadcast before
1923                isStandardBroadcast = false;
1924
1925            } else if (!intermediate_off) {
1926                // connect to GattService
1927                if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode");
1928                if (mBluetoothGatt != null) {
1929                    if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp");
1930                    onBluetoothGattServiceUp();
1931                } else {
1932                    if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service");
1933                    if (mContext.getPackageManager().hasSystemFeature(
1934                                                    PackageManager.FEATURE_BLUETOOTH_LE)) {
1935                        Intent i = new Intent(IBluetoothGatt.class.getName());
1936                        doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT);
1937                    }
1938                }
1939                sendBleStateChanged(prevState, newState);
1940                //Don't broadcase this as std intent
1941                isStandardBroadcast = false;
1942
1943            } else if (intermediate_off) {
1944                if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode");
1945                // For LE only mode, broadcast as is
1946                sendBleStateChanged(prevState, newState);
1947                sendBluetoothStateCallback(false); // BT is OFF for general users
1948                // Broadcast as STATE_OFF
1949                newState = BluetoothAdapter.STATE_OFF;
1950                sendBrEdrDownCallback();
1951            }
1952        } else if (newState == BluetoothAdapter.STATE_ON) {
1953            boolean isUp = (newState == BluetoothAdapter.STATE_ON);
1954            sendBluetoothStateCallback(isUp);
1955            sendBleStateChanged(prevState, newState);
1956
1957        } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON ||
1958                newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
1959            sendBleStateChanged(prevState, newState);
1960            isStandardBroadcast = false;
1961
1962        } else if (newState == BluetoothAdapter.STATE_TURNING_ON ||
1963                newState == BluetoothAdapter.STATE_TURNING_OFF) {
1964            sendBleStateChanged(prevState, newState);
1965        }
1966
1967        if (isStandardBroadcast) {
1968            if (prevState == BluetoothAdapter.STATE_BLE_ON) {
1969                // Show prevState of BLE_ON as OFF to standard users
1970                prevState = BluetoothAdapter.STATE_OFF;
1971            }
1972            Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
1973            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
1974            intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
1975            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1976            mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
1977        }
1978    }
1979
1980    /**
1981     *  if on is true, wait for state become ON
1982     *  if off is true, wait for state become OFF
1983     *  if both on and off are false, wait for state not ON
1984     */
1985    private boolean waitForOnOff(boolean on, boolean off) {
1986        int i = 0;
1987        while (i < 10) {
1988            try {
1989                mBluetoothLock.readLock().lock();
1990                if (mBluetooth == null) break;
1991                if (on) {
1992                    if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
1993                } else if (off) {
1994                    if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
1995                } else {
1996                    if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
1997                }
1998            } catch (RemoteException e) {
1999                Slog.e(TAG, "getState()", e);
2000                break;
2001            } finally {
2002                mBluetoothLock.readLock().unlock();
2003            }
2004            if (on || off) {
2005                SystemClock.sleep(300);
2006            } else {
2007                SystemClock.sleep(50);
2008            }
2009            i++;
2010        }
2011        Slog.e(TAG,"waitForOnOff time out");
2012        return false;
2013    }
2014
2015    private void sendDisableMsg(String packageName) {
2016        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
2017        addActiveLog(packageName, false);
2018    }
2019
2020    private void sendEnableMsg(boolean quietMode, String packageName) {
2021        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
2022                             quietMode ? 1 : 0, 0));
2023        addActiveLog(packageName, true);
2024    }
2025
2026    private void addActiveLog(String packageName, boolean enable) {
2027        synchronized (mActiveLogs) {
2028            if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
2029                mActiveLogs.remove();
2030            }
2031            mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
2032        }
2033    }
2034
2035    private void addCrashLog() {
2036      synchronized (mCrashTimestamps) {
2037        if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) mCrashTimestamps.removeFirst();
2038        mCrashTimestamps.add(System.currentTimeMillis());
2039        mCrashes++;
2040      }
2041    }
2042
2043    private void recoverBluetoothServiceFromError(boolean clearBle) {
2044        Slog.e(TAG,"recoverBluetoothServiceFromError");
2045        try {
2046            mBluetoothLock.readLock().lock();
2047            if (mBluetooth != null) {
2048                //Unregister callback object
2049                mBluetooth.unregisterCallback(mBluetoothCallback);
2050            }
2051        } catch (RemoteException re) {
2052            Slog.e(TAG, "Unable to unregister", re);
2053        } finally {
2054            mBluetoothLock.readLock().unlock();
2055        }
2056
2057        SystemClock.sleep(500);
2058
2059        // disable
2060        addActiveLog(REASON_START_CRASH, false);
2061        handleDisable();
2062
2063        waitForOnOff(false, true);
2064
2065        sendBluetoothServiceDownCallback();
2066
2067        try {
2068            mBluetoothLock.writeLock().lock();
2069            if (mBluetooth != null) {
2070                mBluetooth = null;
2071                // Unbind
2072                mContext.unbindService(mConnection);
2073            }
2074            mBluetoothGatt = null;
2075        } finally {
2076            mBluetoothLock.writeLock().unlock();
2077        }
2078
2079        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2080        mState = BluetoothAdapter.STATE_OFF;
2081
2082        if (clearBle) {
2083          clearBleApps();
2084        }
2085
2086        mEnable = false;
2087
2088        if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) {
2089            // Send a Bluetooth Restart message to reenable bluetooth
2090            Message restartMsg = mHandler.obtainMessage(
2091                             MESSAGE_RESTART_BLUETOOTH_SERVICE);
2092            mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
2093        } else {
2094            // todo: notify user to power down and power up phone to make bluetooth work.
2095        }
2096    }
2097
2098    private boolean isBluetoothDisallowed() {
2099        long callingIdentity = Binder.clearCallingIdentity();
2100        try {
2101            return mContext.getSystemService(UserManager.class)
2102                    .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
2103        } finally {
2104            Binder.restoreCallingIdentity(callingIdentity);
2105        }
2106    }
2107
2108    /**
2109     * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
2110     * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
2111     * state if Bluetooth is not disallowed.
2112     *
2113     * @param userId user to disable bluetooth sharing for.
2114     * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
2115     */
2116    private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
2117        final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
2118                "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
2119        final int newState = bluetoothSharingDisallowed
2120                ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
2121                : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2122        try {
2123            final IPackageManager imp = AppGlobals.getPackageManager();
2124            imp.setComponentEnabledSetting(oppLauncherComponent, newState,
2125                    PackageManager.DONT_KILL_APP, userId);
2126        } catch (Exception e) {
2127            // The component was not found, do nothing.
2128        }
2129    }
2130
2131    @Override
2132    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2133        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
2134        String errorMsg = null;
2135
2136        boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
2137
2138        if (!protoOut) {
2139            writer.println("Bluetooth Status");
2140            writer.println("  enabled: " + isEnabled());
2141            writer.println("  state: " + BluetoothAdapter.nameForState(mState));
2142            writer.println("  address: " + mAddress);
2143            writer.println("  name: " + mName);
2144            if (mEnable) {
2145                long onDuration = System.currentTimeMillis() - mActiveLogs.getLast().getTime();
2146                String onDurationString = String.format("%02d:%02d:%02d.%03d",
2147                                          (int)(onDuration / (1000 * 60 * 60)),
2148                                          (int)((onDuration / (1000 * 60)) % 60),
2149                                          (int)((onDuration / 1000) % 60),
2150                                          (int)(onDuration % 1000));
2151                writer.println("  time since enabled: " + onDurationString + "\n");
2152            }
2153
2154            if (mActiveLogs.size() == 0) {
2155                writer.println("Bluetooth never enabled!");
2156            } else {
2157                writer.println("Enable log:");
2158                for (ActiveLog log : mActiveLogs) {
2159                    writer.println("  " + log);
2160                }
2161            }
2162
2163            writer.println("Bluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2164            if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2165            for (Long time : mCrashTimestamps) {
2166              writer.println("  " + timeToLog(time.longValue()));
2167            }
2168
2169            String bleAppString = "No BLE Apps registered.";
2170            if (mBleApps.size() == 1) {
2171                bleAppString = "1 BLE App registered:";
2172            } else if (mBleApps.size() > 1) {
2173                bleAppString = mBleApps.size() + " BLE Apps registered:";
2174            }
2175            writer.println("\n" + bleAppString);
2176            for (ClientDeathRecipient app : mBleApps.values()) {
2177                writer.println("  " + app.getPackageName());
2178            }
2179
2180            writer.println("");
2181            writer.flush();
2182            if (args.length == 0) {
2183                // Add arg to produce output
2184                args = new String[1];
2185                args[0] = "--print";
2186            }
2187        }
2188
2189        if (mBluetoothBinder == null) {
2190            errorMsg = "Bluetooth Service not connected";
2191        } else {
2192            try {
2193                mBluetoothBinder.dump(fd, args);
2194            } catch (RemoteException re) {
2195                errorMsg = "RemoteException while dumping Bluetooth Service";
2196            }
2197        }
2198        if (errorMsg != null) {
2199            // Silently return if we are extracting metrics in Protobuf format
2200            if (protoOut) return;
2201            writer.println(errorMsg);
2202        }
2203    }
2204}
2205