10f42037eb7b5118015c2caca635538324ccf0ccffredc/*
2fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Copyright (C) 2012 The Android Open Source Project
3fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *
4fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Licensed under the Apache License, Version 2.0 (the "License");
5fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * you may not use this file except in compliance with the License.
6fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * You may obtain a copy of the License at
7fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *
8fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *      http://www.apache.org/licenses/LICENSE-2.0
9fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu *
10fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * Unless required by applicable law or agreed to in writing, software
11fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * distributed under the License is distributed on an "AS IS" BASIS,
12fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * See the License for the specific language governing permissions and
14fa0fd39a4bf296d254aa398c1b19ec960efa641dZhihai Xu * limitations under the License.
150f42037eb7b5118015c2caca635538324ccf0ccffredc */
160f42037eb7b5118015c2caca635538324ccf0ccffredc
170f42037eb7b5118015c2caca635538324ccf0ccffredcpackage com.android.server;
180f42037eb7b5118015c2caca635538324ccf0ccffredc
19408abf7f1bec3253675d0225300d7ee39481d286Svet Ganovimport android.Manifest;
2040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.app.ActivityManager;
214f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafovimport android.app.AppGlobals;
220f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.BluetoothAdapter;
23e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.bluetooth.BluetoothProfile;
240f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetooth;
25bf072a712f584ae1c01022835b0de21c40513d06fredcimport android.bluetooth.IBluetoothCallback;
26e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wangimport android.bluetooth.IBluetoothGatt;
27e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.bluetooth.IBluetoothHeadset;
280f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManager;
290f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManagerCallback;
30e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.bluetooth.IBluetoothProfileServiceConnection;
310f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothStateChangeCallback;
3277df6f315d6fbb22622ca46ae5735a5c73cc367dSvet Ganovimport android.content.ActivityNotFoundException;
330f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.BroadcastReceiver;
340f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ComponentName;
350f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ContentResolver;
360f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Context;
370f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.Intent;
380f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.IntentFilter;
390f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.content.ServiceConnection;
40ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganovimport android.content.pm.ApplicationInfo;
414f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafovimport android.content.pm.IPackageManager;
4232ab77b4c52db78aea22cb32824c7fd68d6f8c21Matthew Xieimport android.content.pm.PackageManager;
43e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.content.pm.UserInfo;
44e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wangimport android.database.ContentObserver;
4540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Binder;
4663d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtovaimport android.os.Bundle;
470f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Handler;
480f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.IBinder;
4940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Looper;
500f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.Message;
5140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.Process;
52d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredcimport android.os.RemoteCallbackList;
530f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.RemoteException;
5440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xuimport android.os.SystemClock;
555ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
56e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.os.UserManager;
5763d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtovaimport android.os.UserManagerInternal;
5863d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtovaimport android.os.UserManagerInternal.UserRestrictionsListener;
590f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.provider.Settings;
6067d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wangimport android.provider.Settings.SettingNotFoundException;
6167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkeyimport android.util.Slog;
62726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood
63fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
644f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafovimport com.android.server.pm.UserRestrictionsUtils;
65c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova
66726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwoodimport java.io.FileDescriptor;
67726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwoodimport java.io.PrintWriter;
68e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport java.util.HashMap;
695980456040217f330289e3fa59df4efaafb1c6c5Marie Janssenimport java.util.LinkedList;
70e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport java.util.Map;
714f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafovimport java.util.concurrent.ConcurrentHashMap;
724f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafovimport java.util.concurrent.locks.ReentrantReadWriteLock;
73658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou
745980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
750f42037eb7b5118015c2caca635538324ccf0ccffredcclass BluetoothManagerService extends IBluetoothManager.Stub {
760f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final String TAG = "BluetoothManagerService";
77414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov    private static final boolean DBG = true;
780f42037eb7b5118015c2caca635538324ccf0ccffredc
790f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
800f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
81e54b42237f749f37f0d920c89f52977871c07004Marie Janssen
82d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu    private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
830f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
840f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
85e54b42237f749f37f0d920c89f52977871c07004Marie Janssen
86e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private static final int ACTIVE_LOG_MAX_SIZE = 20;
87e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private static final int CRASH_LOG_MAX_SIZE = 100;
88467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker    private static final String REASON_AIRPLANE_MODE = "airplane mode";
897c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson    private static final String REASON_DISALLOWED = "disallowed by system";
907c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson    private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system";
91e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private static final String REASON_RESTARTED = "automatic restart";
92e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private static final String REASON_START_CRASH = "turn-on crash";
93467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker    private static final String REASON_SYSTEM_BOOT = "system boot";
94e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private static final String REASON_UNEXPECTED = "unexpected crash";
95e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private static final String REASON_USER_SWITCH = "user switch";
96873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng    private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
97e54b42237f749f37f0d920c89f52977871c07004Marie Janssen
980f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
991223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M    //Maximum msec to wait for service restart
1001223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M    private static final int SERVICE_RESTART_TIME_MS = 200;
101dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu    //Maximum msec to wait for restart due to error
102dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu    private static final int ERROR_RESTART_TIME_MS = 3000;
10340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    //Maximum msec to delay MESSAGE_USER_SWITCHED
10440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private static final int USER_SWITCHED_TIME_MS = 200;
105e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    // Delay for the addProxy function in msec
106e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    private static final int ADD_PROXY_DELAY_MS = 100;
1070f42037eb7b5118015c2caca635538324ccf0ccffredc
1080f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final int MESSAGE_ENABLE = 1;
1090f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final int MESSAGE_DISABLE = 2;
110649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private static final int MESSAGE_REGISTER_ADAPTER = 20;
111649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
112649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
113649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
114649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
115649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
1161223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M    private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
117aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
118aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    private static final int MESSAGE_TIMEOUT_BIND = 100;
119aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    private static final int MESSAGE_TIMEOUT_UNBIND = 101;
1204bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker    private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
12140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private static final int MESSAGE_USER_SWITCHED = 300;
122aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    private static final int MESSAGE_USER_UNLOCKED = 301;
123e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
124e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
125873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng    private static final int MESSAGE_RESTORE_USER_SETTING = 500;
126873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng
127873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng    private static final int RESTORE_SETTING_TO_ON = 1;
128873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng    private static final int RESTORE_SETTING_TO_OFF = 0;
129cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen
130aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    private static final int MAX_ERROR_RESTART_RETRIES = 6;
131dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
132401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // Bluetooth persisted setting is off
133401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private static final int BLUETOOTH_OFF=0;
134401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // Bluetooth persisted setting is on
135401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // and Airplane mode won't affect Bluetooth state at start up
136401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private static final int BLUETOOTH_ON_BLUETOOTH=1;
137401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // Bluetooth persisted setting is on
138401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // but Airplane mode will affect Bluetooth state at start up
139401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // and Airplane mode will have higher priority.
140401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private static final int BLUETOOTH_ON_AIRPLANE=2;
1410f42037eb7b5118015c2caca635538324ccf0ccffredc
142ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int SERVICE_IBLUETOOTH = 1;
143ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int SERVICE_IBLUETOOTHGATT = 2;
144ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
1450f42037eb7b5118015c2caca635538324ccf0ccffredc    private final Context mContext;
146cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie
147cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie    // Locks are not provided for mName and mAddress.
148cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie    // They are accessed in handler or broadcast receiver, same thread context.
1490f42037eb7b5118015c2caca635538324ccf0ccffredc    private String mAddress;
1500f42037eb7b5118015c2caca635538324ccf0ccffredc    private String mName;
1516fde3098074ab2551867d1cd919958383b15725fMatthew Xie    private final ContentResolver mContentResolver;
1526fde3098074ab2551867d1cd919958383b15725fMatthew Xie    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
1536fde3098074ab2551867d1cd919958383b15725fMatthew Xie    private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
1549db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen    private IBinder mBluetoothBinder;
155649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private IBluetooth mBluetooth;
156ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private IBluetoothGatt mBluetoothGatt;
157eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov    private final ReentrantReadWriteLock mBluetoothLock =
158eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        new ReentrantReadWriteLock();
159649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private boolean mBinding;
160649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private boolean mUnbinding;
1615980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
162401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // used inside handler thread
163fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta    private boolean mQuietEnable = false;
1645980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private boolean mEnable;
1655980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
166e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private CharSequence timeToLog(long timestamp) {
167e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
168e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    }
169e54b42237f749f37f0d920c89f52977871c07004Marie Janssen
1705980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    /**
1715980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen     * Used for tracking apps that enabled / disabled Bluetooth.
1725980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen     */
1735980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private class ActiveLog {
1745980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        private String mPackageName;
1755980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        private boolean mEnable;
1765980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        private long mTimestamp;
1775980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
1785980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        public ActiveLog(String packageName, boolean enable, long timestamp) {
1795980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mPackageName = packageName;
1805980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mEnable = enable;
1815980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mTimestamp = timestamp;
1825980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
1835980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
1845980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        public long getTime() {
1855980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            return mTimestamp;
1865980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
1875980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
1885980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        public String toString() {
189e54b42237f749f37f0d920c89f52977871c07004Marie Janssen            return  timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ") + " by "
190e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                + mPackageName;
1915980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
1925980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
1935980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    }
1945980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
1955980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private LinkedList<ActiveLog> mActiveLogs;
196e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private LinkedList<Long> mCrashTimestamps;
197e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private int mCrashes;
1985980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
1995980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    // configuration from external IBinder call which is used to
200401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    // synchronize with broadcast receiver.
201401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private boolean mQuietEnableExternal;
202401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private boolean mEnableExternal;
2035980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
2045980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    // Map of apps registered to keep BLE scanning on.
2055980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
2065980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
20740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private int mState;
20840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private final BluetoothHandler mHandler;
209dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu    private int mErrorRecoveryRetryCounter;
210bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos    private final int mSystemUiUid;
2110f42037eb7b5118015c2caca635538324ccf0ccffredc
212e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    // Save a ProfileServiceConnections object for each of the bound
213e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    // bluetooth profile services
214e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    private final Map <Integer, ProfileServiceConnections> mProfileServices =
215e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            new HashMap <Integer, ProfileServiceConnections>();
216e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
217ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov    private final boolean mPermissionReviewRequired;
218ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
2195980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
220bf072a712f584ae1c01022835b0de21c40513d06fredc        @Override
221bf072a712f584ae1c01022835b0de21c40513d06fredc        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {
222bf072a712f584ae1c01022835b0de21c40513d06fredc            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
223bf072a712f584ae1c01022835b0de21c40513d06fredc            mHandler.sendMessage(msg);
224bf072a712f584ae1c01022835b0de21c40513d06fredc        }
225bf072a712f584ae1c01022835b0de21c40513d06fredc    };
226bf072a712f584ae1c01022835b0de21c40513d06fredc
22763d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova    private final UserRestrictionsListener mUserRestrictionsListener =
22863d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            new UserRestrictionsListener() {
22963d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        @Override
23063d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
23163d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova                Bundle prevRestrictions) {
2324f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov
2337c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson            if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
2347c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                    UserManager.DISALLOW_BLUETOOTH_SHARING)) {
2357c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
2367c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                        UserManager.DISALLOW_BLUETOOTH_SHARING));
2377c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson            }
2384f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov
2397c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson            // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
2407c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson            if (userId == UserHandle.USER_SYSTEM &&
2417c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                UserRestrictionsUtils.restrictionsChanged(
2427c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                    prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
2437c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
2447c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                        UserManager.DISALLOW_BLUETOOTH)) {
2457c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                    updateOppLauncherComponentState(userId, true); // Sharing disallowed
2467c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                    sendDisableMsg(REASON_DISALLOWED);
2477c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                } else {
2487c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                    updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
2497c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                            UserManager.DISALLOW_BLUETOOTH_SHARING));
25063d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova                }
25163d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            }
25263d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        }
25363d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova    };
25463d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova
255467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker    private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
256467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker        @Override
257467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker        public void onChange(boolean unused) {
258467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker            synchronized(this) {
259467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                if (isBluetoothPersistedStateOn()) {
260467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    if (isAirplaneModeOn()) {
261467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
262467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    } else {
263467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
264467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    }
265467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                }
266467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker
267467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                int st = BluetoothAdapter.STATE_OFF;
268467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                try {
269467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    mBluetoothLock.readLock().lock();
270467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    if (mBluetooth != null) {
271467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        st = mBluetooth.getState();
272467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    }
273467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                } catch (RemoteException e) {
274467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    Slog.e(TAG, "Unable to call getState", e);
275467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    return;
276467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                } finally {
277467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    mBluetoothLock.readLock().unlock();
278467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                }
279467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker
280467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                Slog.d(TAG, "Airplane Mode change - current state:  " +
281467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                          BluetoothAdapter.nameForState(st));
282467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker
283467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                if (isAirplaneModeOn()) {
284467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    // Clear registered LE apps to force shut-off
285467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    clearBleApps();
286467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker
287467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    // If state is BLE_ON make sure we trigger disableBLE
288467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    if (st == BluetoothAdapter.STATE_BLE_ON) {
289467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        try {
290467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                            mBluetoothLock.readLock().lock();
291467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                            if (mBluetooth != null) {
292467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                                mBluetooth.onBrEdrDown();
293467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                                mEnable = false;
294467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                                mEnableExternal = false;
295467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                            }
296467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        } catch (RemoteException e) {
297467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                            Slog.e(TAG,"Unable to call onBrEdrDown", e);
298467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        } finally {
299467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                            mBluetoothLock.readLock().unlock();
300467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        }
301467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    } else if (st == BluetoothAdapter.STATE_ON){
302467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                        sendDisableMsg(REASON_AIRPLANE_MODE);
303467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    }
304467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                } else if (mEnableExternal) {
305467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                    sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE);
306467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                }
307467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker            }
308467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker        }
309467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker    };
310467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker
311bf072a712f584ae1c01022835b0de21c40513d06fredc    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
3120f42037eb7b5118015c2caca635538324ccf0ccffredc        @Override
3130f42037eb7b5118015c2caca635538324ccf0ccffredc        public void onReceive(Context context, Intent intent) {
3140f42037eb7b5118015c2caca635538324ccf0ccffredc            String action = intent.getAction();
315bf072a712f584ae1c01022835b0de21c40513d06fredc            if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
3160f42037eb7b5118015c2caca635538324ccf0ccffredc                String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
31767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
3180f42037eb7b5118015c2caca635538324ccf0ccffredc                if (newName != null) {
3190f42037eb7b5118015c2caca635538324ccf0ccffredc                    storeNameAndAddress(newName, null);
3200f42037eb7b5118015c2caca635538324ccf0ccffredc                }
321dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng            } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
322dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
323dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                if (newAddress != null) {
324dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                    if (DBG) Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
325dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                    storeNameAndAddress(null, newAddress);
326dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                } else {
327dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                    if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found");
328dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng                }
329873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng            } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
330873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
331873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                if (Settings.Global.BLUETOOTH_ON.equals(name)) {
332873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    // The Bluetooth On state may be changed during system restore.
333873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    final String prevValue = intent.getStringExtra(
334873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                            Intent.EXTRA_SETTING_PREVIOUS_VALUE);
335873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    final String newValue = intent.getStringExtra(
336873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                            Intent.EXTRA_SETTING_NEW_VALUE);
337873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng
338873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    if (DBG) Slog.d(TAG, "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" +
339873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                                    prevValue + ", newValue=" + newValue);
340873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng
341873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
342873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                        Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
343873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                                                             newValue.equals("0") ?
344873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                                                             RESTORE_SETTING_TO_OFF :
345873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                                                             RESTORE_SETTING_TO_ON, 0);
346873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                        mHandler.sendMessage(msg);
347873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    }
348873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                }
3490f42037eb7b5118015c2caca635538324ccf0ccffredc            }
3500f42037eb7b5118015c2caca635538324ccf0ccffredc        }
3510f42037eb7b5118015c2caca635538324ccf0ccffredc    };
3520f42037eb7b5118015c2caca635538324ccf0ccffredc
3530f42037eb7b5118015c2caca635538324ccf0ccffredc    BluetoothManagerService(Context context) {
3548d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn        mHandler = new BluetoothHandler(IoThread.get().getLooper());
35540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
3560f42037eb7b5118015c2caca635538324ccf0ccffredc        mContext = context;
357ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
35877df6f315d6fbb22622ca46ae5735a5c73cc367dSvet Ganov        mPermissionReviewRequired = context.getResources().getBoolean(
359ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                com.android.internal.R.bool.config_permissionReviewRequired);
360ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
3615980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        mActiveLogs = new LinkedList<ActiveLog>();
362e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        mCrashTimestamps = new LinkedList<Long>();
363e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        mCrashes = 0;
3640f42037eb7b5118015c2caca635538324ccf0ccffredc        mBluetooth = null;
3659db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen        mBluetoothBinder = null;
366d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        mBluetoothGatt = null;
3670f42037eb7b5118015c2caca635538324ccf0ccffredc        mBinding = false;
3680f42037eb7b5118015c2caca635538324ccf0ccffredc        mUnbinding = false;
36940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        mEnable = false;
37040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        mState = BluetoothAdapter.STATE_OFF;
371401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        mQuietEnableExternal = false;
372401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        mEnableExternal = false;
3730f42037eb7b5118015c2caca635538324ccf0ccffredc        mAddress = null;
3740f42037eb7b5118015c2caca635538324ccf0ccffredc        mName = null;
375dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        mErrorRecoveryRetryCounter = 0;
3760f42037eb7b5118015c2caca635538324ccf0ccffredc        mContentResolver = context.getContentResolver();
377e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        // Observe BLE scan only mode settings change.
378e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        registerForBleScanModeChange();
379d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc        mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
380d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc        mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
381873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng
382873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng        IntentFilter filter = new IntentFilter();
383873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
384873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng        filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
385873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng        filter.addAction(Intent.ACTION_SETTING_RESTORED);
386dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
387dd749b0f61de8e0fc8bf48f7907009b5c5eb77deStanley Tng        mContext.registerReceiver(mReceiver, filter);
388873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng
3890f42037eb7b5118015c2caca635538324ccf0ccffredc        loadStoredNameAndAddress();
390401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        if (isBluetoothPersistedStateOn()) {
3919fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen            if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
392401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            mEnableExternal = true;
3930f42037eb7b5118015c2caca635538324ccf0ccffredc        }
394bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos
395467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker        String airplaneModeRadios = Settings.Global.getString(mContentResolver,
396467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker            Settings.Global.AIRPLANE_MODE_RADIOS);
397467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker        if (airplaneModeRadios == null ||
398467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker            airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) {
399467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker            mContentResolver.registerContentObserver(
400467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
401467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker                true, mAirplaneModeObserver);
402467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker        }
403467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker
4045980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        int systemUiUid = -1;
405bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos        try {
4065980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
407c5967e9862489024c932b0c7fcb84ed0af2a7fd7Jeff Sharkey                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
408bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos        } catch (PackageManager.NameNotFoundException e) {
409acddf2b34965da479efe46bd87871234ac6a5aabJoe LaPenna            // Some platforms, such as wearables do not have a system ui.
41067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
411bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos        }
4125980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        mSystemUiUid = systemUiUid;
4130f42037eb7b5118015c2caca635538324ccf0ccffredc    }
4140f42037eb7b5118015c2caca635538324ccf0ccffredc
415649fe497cea2f19e937f84218d1080bdcefe47f2fredc    /**
416649fe497cea2f19e937f84218d1080bdcefe47f2fredc     *  Returns true if airplane mode is currently on
417649fe497cea2f19e937f84218d1080bdcefe47f2fredc     */
418649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private final boolean isAirplaneModeOn() {
419c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate        return Settings.Global.getInt(mContext.getContentResolver(),
420c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
421649fe497cea2f19e937f84218d1080bdcefe47f2fredc    }
422649fe497cea2f19e937f84218d1080bdcefe47f2fredc
423649fe497cea2f19e937f84218d1080bdcefe47f2fredc    /**
424649fe497cea2f19e937f84218d1080bdcefe47f2fredc     *  Returns true if the Bluetooth saved state is "on"
425649fe497cea2f19e937f84218d1080bdcefe47f2fredc     */
426649fe497cea2f19e937f84218d1080bdcefe47f2fredc    private final boolean isBluetoothPersistedStateOn() {
4279fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen        int state = Settings.Global.getInt(mContentResolver,
4289fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen                                           Settings.Global.BLUETOOTH_ON, -1);
4299fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen        if (DBG) Slog.d(TAG, "Bluetooth persisted state: " + state);
4309fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen        return state != BLUETOOTH_OFF;
431401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    }
432401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu
433401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    /**
434401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu     *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
435401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu     */
436401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private final boolean isBluetoothPersistedStateOnBluetooth() {
437401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        return Settings.Global.getInt(mContentResolver,
4388c18431be868e0960e80638c1a974d71a0df05b4Andre Eisenbach                Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
439649fe497cea2f19e937f84218d1080bdcefe47f2fredc    }
440649fe497cea2f19e937f84218d1080bdcefe47f2fredc
441649fe497cea2f19e937f84218d1080bdcefe47f2fredc    /**
442649fe497cea2f19e937f84218d1080bdcefe47f2fredc     *  Save the Bluetooth on/off state
443649fe497cea2f19e937f84218d1080bdcefe47f2fredc     */
444401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private void persistBluetoothSetting(int value) {
4459fa24918509151bcd30ac763a26c50c4f24d5e7aMarie Janssen        if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
446fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen        // waive WRITE_SECURE_SETTINGS permission check
447fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen        long callingIdentity = Binder.clearCallingIdentity();
448bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown        Settings.Global.putInt(mContext.getContentResolver(),
449bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown                               Settings.Global.BLUETOOTH_ON,
450401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                               value);
451fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen        Binder.restoreCallingIdentity(callingIdentity);
452649fe497cea2f19e937f84218d1080bdcefe47f2fredc    }
453649fe497cea2f19e937f84218d1080bdcefe47f2fredc
454649fe497cea2f19e937f84218d1080bdcefe47f2fredc    /**
455649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * Returns true if the Bluetooth Adapter's name and address is
456649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * locally cached
457649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * @return
458649fe497cea2f19e937f84218d1080bdcefe47f2fredc     */
4590f42037eb7b5118015c2caca635538324ccf0ccffredc    private boolean isNameAndAddressSet() {
4600f42037eb7b5118015c2caca635538324ccf0ccffredc        return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0;
4610f42037eb7b5118015c2caca635538324ccf0ccffredc    }
4620f42037eb7b5118015c2caca635538324ccf0ccffredc
463649fe497cea2f19e937f84218d1080bdcefe47f2fredc    /**
464649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * Retrieve the Bluetooth Adapter's name and address and save it in
465649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * in the local cache
466649fe497cea2f19e937f84218d1080bdcefe47f2fredc     */
4670f42037eb7b5118015c2caca635538324ccf0ccffredc    private void loadStoredNameAndAddress() {
46867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        if (DBG) Slog.d(TAG, "Loading stored name and address");
469d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu        if (mContext.getResources().getBoolean
470d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu            (com.android.internal.R.bool.config_bluetooth_address_validation) &&
471d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu             Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) {
472d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu            // if the valid flag is not set, don't load the address and name
47367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored");
474d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu            return;
475d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu        }
4760f42037eb7b5118015c2caca635538324ccf0ccffredc        mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
4770f42037eb7b5118015c2caca635538324ccf0ccffredc        mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
47867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
4790f42037eb7b5118015c2caca635538324ccf0ccffredc    }
4800f42037eb7b5118015c2caca635538324ccf0ccffredc
481649fe497cea2f19e937f84218d1080bdcefe47f2fredc    /**
482649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * Save the Bluetooth name and address in the persistent store.
483649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * Only non-null values will be saved.
484649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * @param name
485649fe497cea2f19e937f84218d1080bdcefe47f2fredc     * @param address
486649fe497cea2f19e937f84218d1080bdcefe47f2fredc     */
4870f42037eb7b5118015c2caca635538324ccf0ccffredc    private void storeNameAndAddress(String name, String address) {
4880f42037eb7b5118015c2caca635538324ccf0ccffredc        if (name != null) {
4890f42037eb7b5118015c2caca635538324ccf0ccffredc            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
4900f42037eb7b5118015c2caca635538324ccf0ccffredc            mName = name;
49167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            if (DBG) Slog.d(TAG,"Stored Bluetooth name: " +
492649fe497cea2f19e937f84218d1080bdcefe47f2fredc                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
4930f42037eb7b5118015c2caca635538324ccf0ccffredc        }
4940f42037eb7b5118015c2caca635538324ccf0ccffredc
4950f42037eb7b5118015c2caca635538324ccf0ccffredc        if (address != null) {
4960f42037eb7b5118015c2caca635538324ccf0ccffredc            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
4970f42037eb7b5118015c2caca635538324ccf0ccffredc            mAddress=address;
49867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            if (DBG)  Slog.d(TAG,"Stored Bluetoothaddress: " +
499649fe497cea2f19e937f84218d1080bdcefe47f2fredc                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
5000f42037eb7b5118015c2caca635538324ccf0ccffredc        }
501d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu
502d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu        if ((name != null) && (address != null)) {
503d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu            Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
504d31c32217c17f402c295514a862347dd68c9e16dZhihai Xu        }
5050f42037eb7b5118015c2caca635538324ccf0ccffredc    }
5060f42037eb7b5118015c2caca635538324ccf0ccffredc
5070f42037eb7b5118015c2caca635538324ccf0ccffredc    public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
50855db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich        if (callback == null) {
50967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG, "Callback is null in registerAdapter");
51055db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich            return null;
51155db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich        }
5120f42037eb7b5118015c2caca635538324ccf0ccffredc        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
5130f42037eb7b5118015c2caca635538324ccf0ccffredc        msg.obj = callback;
5140f42037eb7b5118015c2caca635538324ccf0ccffredc        mHandler.sendMessage(msg);
515eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov
516eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        return mBluetooth;
5170f42037eb7b5118015c2caca635538324ccf0ccffredc    }
5180f42037eb7b5118015c2caca635538324ccf0ccffredc
5190f42037eb7b5118015c2caca635538324ccf0ccffredc    public void unregisterAdapter(IBluetoothManagerCallback callback) {
52055db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich        if (callback == null) {
52167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG, "Callback is null in unregisterAdapter");
52255db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich            return;
52355db646c4e43fd24386bf522aef13c0b3075593cNatalie Silvanovich        }
5240f42037eb7b5118015c2caca635538324ccf0ccffredc        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
5250f42037eb7b5118015c2caca635538324ccf0ccffredc                                                "Need BLUETOOTH permission");
5260f42037eb7b5118015c2caca635538324ccf0ccffredc        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
5270f42037eb7b5118015c2caca635538324ccf0ccffredc        msg.obj = callback;
5280f42037eb7b5118015c2caca635538324ccf0ccffredc        mHandler.sendMessage(msg);
5290f42037eb7b5118015c2caca635538324ccf0ccffredc    }
5300f42037eb7b5118015c2caca635538324ccf0ccffredc
5310f42037eb7b5118015c2caca635538324ccf0ccffredc    public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
5320f42037eb7b5118015c2caca635538324ccf0ccffredc        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
5330f42037eb7b5118015c2caca635538324ccf0ccffredc                                                "Need BLUETOOTH permission");
534cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        if (callback == null) {
535cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen          Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
536cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen          return;
537cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        }
5380f42037eb7b5118015c2caca635538324ccf0ccffredc        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
5390f42037eb7b5118015c2caca635538324ccf0ccffredc        msg.obj = callback;
5400f42037eb7b5118015c2caca635538324ccf0ccffredc        mHandler.sendMessage(msg);
5410f42037eb7b5118015c2caca635538324ccf0ccffredc    }
5420f42037eb7b5118015c2caca635538324ccf0ccffredc
5430f42037eb7b5118015c2caca635538324ccf0ccffredc    public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
5440f42037eb7b5118015c2caca635538324ccf0ccffredc        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
5450f42037eb7b5118015c2caca635538324ccf0ccffredc                                                "Need BLUETOOTH permission");
546cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        if (callback == null) {
547cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen          Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
548cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen          return;
549cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        }
5500f42037eb7b5118015c2caca635538324ccf0ccffredc        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
5510f42037eb7b5118015c2caca635538324ccf0ccffredc        msg.obj = callback;
5520f42037eb7b5118015c2caca635538324ccf0ccffredc        mHandler.sendMessage(msg);
5530f42037eb7b5118015c2caca635538324ccf0ccffredc    }
5540f42037eb7b5118015c2caca635538324ccf0ccffredc
5550f42037eb7b5118015c2caca635538324ccf0ccffredc    public boolean isEnabled() {
5566eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
5576eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu            (!checkIfCallerIsForegroundUser())) {
55867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user");
55940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            return false;
56040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
56140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
562eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
563eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().lock();
564eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            if (mBluetooth != null) return mBluetooth.isEnabled();
565eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } catch (RemoteException e) {
566eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            Slog.e(TAG, "isEnabled()", e);
567eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
568eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().unlock();
5690f42037eb7b5118015c2caca635538324ccf0ccffredc        }
5700f42037eb7b5118015c2caca635538324ccf0ccffredc        return false;
5710f42037eb7b5118015c2caca635538324ccf0ccffredc    }
5720f42037eb7b5118015c2caca635538324ccf0ccffredc
573995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom    public int getState() {
574995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
575995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom                (!checkIfCallerIsForegroundUser())) {
576cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            Slog.w(TAG, "getState(): report OFF for non-active and non system user");
577995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom            return BluetoothAdapter.STATE_OFF;
578995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        }
579995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom
580995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        try {
581995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom            mBluetoothLock.readLock().lock();
582995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom            if (mBluetooth != null) return mBluetooth.getState();
583995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        } catch (RemoteException e) {
584995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom            Slog.e(TAG, "getState()", e);
585995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        } finally {
586995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom            mBluetoothLock.readLock().unlock();
587995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        }
588995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom        return BluetoothAdapter.STATE_OFF;
589995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom    }
590995c90aa1856e8ef7b3397b775720941d3dcb133Christine Hallstrom
591d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    class ClientDeathRecipient implements IBinder.DeathRecipient {
5925980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        private String mPackageName;
5935980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
5945980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        public ClientDeathRecipient(String packageName) {
5955980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mPackageName = packageName;
5965980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
5975980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
598d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        public void binderDied() {
5995980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            if (DBG) Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
6002977c3e372070a540330a6761fbadd201822fff1Marie Janssen            if (isBleAppPresent()) {
6012977c3e372070a540330a6761fbadd201822fff1Marie Janssen              // Nothing to do, another app is here.
6022977c3e372070a540330a6761fbadd201822fff1Marie Janssen              return;
6032977c3e372070a540330a6761fbadd201822fff1Marie Janssen            }
6042977c3e372070a540330a6761fbadd201822fff1Marie Janssen            if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash");
6052977c3e372070a540330a6761fbadd201822fff1Marie Janssen            try {
6062977c3e372070a540330a6761fbadd201822fff1Marie Janssen                mBluetoothLock.readLock().lock();
6072977c3e372070a540330a6761fbadd201822fff1Marie Janssen                if (mBluetooth != null &&
6082977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
6092977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    mEnable = false;
6102977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    mBluetooth.onBrEdrDown();
611d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                }
6122977c3e372070a540330a6761fbadd201822fff1Marie Janssen            } catch (RemoteException e) {
6132977c3e372070a540330a6761fbadd201822fff1Marie Janssen                 Slog.e(TAG,"Unable to call onBrEdrDown", e);
6142977c3e372070a540330a6761fbadd201822fff1Marie Janssen            } finally {
6152977c3e372070a540330a6761fbadd201822fff1Marie Janssen                mBluetoothLock.readLock().unlock();
616d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            }
617d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        }
618d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
6195980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        public String getPackageName() {
6205980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            return mPackageName;
6215980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
6225980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    }
623d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
62467d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang    @Override
62567d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang    public boolean isBleScanAlwaysAvailable() {
626a80d745c656f1e09aa9331002f613883220ca029Marie Janssen        if (isAirplaneModeOn() && !mEnable) {
627a80d745c656f1e09aa9331002f613883220ca029Marie Janssen            return false;
628a80d745c656f1e09aa9331002f613883220ca029Marie Janssen        }
62967d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang        try {
63067d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang            return (Settings.Global.getInt(mContentResolver,
63167d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
63267d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang        } catch (SettingNotFoundException e) {
63367d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang        }
63467d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang        return false;
63567d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang    }
63667d8416b8eb092dbf960c92cd6a2b2564d212d79Wei Wang
637e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    // Monitor change of BLE scan only mode settings.
638e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    private void registerForBleScanModeChange() {
639e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        ContentObserver contentObserver = new ContentObserver(null) {
640e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang            @Override
641e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang            public void onChange(boolean selfChange) {
6422977c3e372070a540330a6761fbadd201822fff1Marie Janssen                if (isBleScanAlwaysAvailable()) {
6432977c3e372070a540330a6761fbadd201822fff1Marie Janssen                  // Nothing to do
6442977c3e372070a540330a6761fbadd201822fff1Marie Janssen                  return;
6452977c3e372070a540330a6761fbadd201822fff1Marie Janssen                }
6462977c3e372070a540330a6761fbadd201822fff1Marie Janssen                // BLE scan is not available.
6472977c3e372070a540330a6761fbadd201822fff1Marie Janssen                disableBleScanMode();
6482977c3e372070a540330a6761fbadd201822fff1Marie Janssen                clearBleApps();
6492977c3e372070a540330a6761fbadd201822fff1Marie Janssen                try {
6502977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    mBluetoothLock.readLock().lock();
6512977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    if (mBluetooth != null) mBluetooth.onBrEdrDown();
6522977c3e372070a540330a6761fbadd201822fff1Marie Janssen                } catch (RemoteException e) {
6532977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    Slog.e(TAG, "error when disabling bluetooth", e);
6542977c3e372070a540330a6761fbadd201822fff1Marie Janssen                } finally {
6552977c3e372070a540330a6761fbadd201822fff1Marie Janssen                    mBluetoothLock.readLock().unlock();
656e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang                }
657e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang            }
658e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        };
659e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang
660e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        mContentResolver.registerContentObserver(
661e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang                Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE),
662e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang                false, contentObserver);
663e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    }
664e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang
665e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    // Disable ble scan only mode.
666e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    private void disableBleScanMode() {
667e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        try {
668eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.writeLock().lock();
669e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang            if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
67067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable");
671e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang                mEnable = false;
672e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang            }
673e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        } catch (RemoteException e) {
67467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.e(TAG, "getState()", e);
675eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
676eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.writeLock().unlock();
677e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang        }
678e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    }
679e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang
6805980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
6815980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        ClientDeathRecipient r = mBleApps.get(token);
6825980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        if (r == null && enable) {
6835980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
6845980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            try {
6855980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                token.linkToDeath(deathRec, 0);
6865980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            } catch (RemoteException ex) {
6875980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
688d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            }
6895980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mBleApps.put(token, deathRec);
6905980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            if (DBG) Slog.d(TAG, "Registered for death of " + packageName);
6915980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        } else if (!enable && r != null) {
6925980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            // Unregister death recipient as the app goes away.
6935980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            token.unlinkToDeath(r, 0);
6945980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mBleApps.remove(token);
6955980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            if (DBG) Slog.d(TAG, "Unregistered for death of " + packageName);
696d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        }
6972977c3e372070a540330a6761fbadd201822fff1Marie Janssen        int appCount = mBleApps.size();
6982977c3e372070a540330a6761fbadd201822fff1Marie Janssen        if (DBG) Slog.d(TAG, appCount + " registered Ble Apps");
6992977c3e372070a540330a6761fbadd201822fff1Marie Janssen        if (appCount == 0 && mEnable) {
700e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang            disableBleScanMode();
701d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        }
702c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham        if (appCount == 0 && !mEnableExternal) {
703c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham            sendBrEdrDownCallback();
704c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham        }
7052977c3e372070a540330a6761fbadd201822fff1Marie Janssen        return appCount;
706d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    }
707d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
708e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    // Clear all apps using BLE scan only mode.
709e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    private void clearBleApps() {
7102977c3e372070a540330a6761fbadd201822fff1Marie Janssen        mBleApps.clear();
711e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang    }
712e4a744b626085e3669dba0cd40c0adcab7979d14Wei Wang
7135980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    /** @hide */
714d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    public boolean isBleAppPresent() {
7152977c3e372070a540330a6761fbadd201822fff1Marie Janssen        if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
7162977c3e372070a540330a6761fbadd201822fff1Marie Janssen        return mBleApps.size() > 0;
717d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    }
718d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
719d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    /**
720fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen     * Action taken when GattService is turned on
721d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora     */
722d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    private void onBluetoothGattServiceUp() {
72367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up");
724eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
725eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().lock();
726fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen            if (mBluetooth == null) {
727fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen                if (DBG) Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!");
728fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen                return;
729fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen            }
730fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen            int st = mBluetooth.getState();
731fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen            if (st != BluetoothAdapter.STATE_BLE_ON) {
732fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen                if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " +
733fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen                        BluetoothAdapter.nameForState(st));
734fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen                return;
735fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen            }
736fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen            if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
737fa63068deb3b42b1907c0c2214204e2f4e31bd0cMarie Janssen                // This triggers transition to STATE_ON
738d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                mBluetooth.onLeServiceUp();
739d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
740d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            }
741eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } catch (RemoteException e) {
742eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            Slog.e(TAG,"Unable to call onServiceUp", e);
743eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
744eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().unlock();
745d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        }
746d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    }
747d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
748d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    /**
749d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora     * Inform BluetoothAdapter instances that BREDR part is down
750d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora     * and turn off all service and stack if no LE app needs it
751d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora     */
752d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    private void sendBrEdrDownCallback() {
75367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks");
754bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora
755eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        if (mBluetooth == null) {
75667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG, "Bluetooth handle is null");
757bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora            return;
758bdfaa7f566a0fbe59dfc6bc14cd9d4d92b9259faNitin Arora        }
759d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
760c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham        if (isBleAppPresent()) {
761c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham            // Need to stay at BLE ON. Disconnect all Gatt connections
762c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham            try {
763c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham                mBluetoothGatt.unregAll();
764c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham            } catch (RemoteException e) {
765c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham                Slog.e(TAG, "Unable to disconnect all apps.", e);
766c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham            }
767c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham        } else {
768d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            try {
769eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                mBluetoothLock.readLock().lock();
770eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                if (mBluetooth != null) mBluetooth.onBrEdrDown();
771eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            } catch (RemoteException e) {
77267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
773eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            } finally {
774eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                mBluetoothLock.readLock().unlock();
775d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            }
776d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        }
777c2b062263402c7ada36fe84ee1ed9b5bb1bbefbdMartin Brabham
778d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    }
779d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
7805980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    public boolean enableNoAutoConnect(String packageName)
781fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta    {
78263d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        if (isBluetoothDisallowed()) {
78363d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            if (DBG) {
78463d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova                Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
78563d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            }
78663d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            return false;
78763d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        }
78863d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova
789fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
790fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                                                "Need BLUETOOTH ADMIN permission");
79140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
792fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta        if (DBG) {
79367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
794fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                    " mBinding = " + mBinding);
795fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta        }
7968385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
7978385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen
7988385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen        if (callingAppId != Process.NFC_UID) {
799fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta            throw new SecurityException("no permission to enable Bluetooth quietly");
800fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta        }
8018385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen
802401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        synchronized(mReceiver) {
803401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            mQuietEnableExternal = true;
804401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            mEnableExternal = true;
8055980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            sendEnableMsg(true, packageName);
806401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        }
807fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta        return true;
808fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta    }
8094bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker
810ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov    public boolean enable(String packageName) throws RemoteException {
811ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        final int callingUid = Binder.getCallingUid();
812ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
813ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
81463d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        if (isBluetoothDisallowed()) {
81563d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            if (DBG) {
81663d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova                Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
81763d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            }
81863d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            return false;
81963d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        }
82063d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova
821ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        if (!callerSystem) {
822ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            if (!checkIfCallerIsForegroundUser()) {
823ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                Slog.w(TAG, "enable(): not allowed for non-active and non system user");
824ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                return false;
825ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            }
826ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
827ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
828ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                    "Need BLUETOOTH ADMIN permission");
829ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
830ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            if (!isEnabled() && mPermissionReviewRequired
831ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                    && startConsentUiIfNeeded(packageName, callingUid,
832ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                            BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
833ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                return false;
834ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            }
835f24588615efa6c781ad963f1a5bbdf47359e1b53fredc        }
836f24588615efa6c781ad963f1a5bbdf47359e1b53fredc
837401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        if (DBG) {
8385980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            Slog.d(TAG,"enable(" + packageName + "):  mBluetooth =" + mBluetooth +
839cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    " mBinding = " + mBinding + " mState = " +
840cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    BluetoothAdapter.nameForState(mState));
841090bf551308e68b1b2a996c959b608cabd025c5cSanket Agarwal        }
842401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu
843401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        synchronized(mReceiver) {
844401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            mQuietEnableExternal = false;
845401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            mEnableExternal = true;
846401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            // waive WRITE_SECURE_SETTINGS permission check
8475980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            sendEnableMsg(false, packageName);
848401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        }
84967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        if (DBG) Slog.d(TAG, "enable returning");
850401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        return true;
8510f42037eb7b5118015c2caca635538324ccf0ccffredc    }
8520f42037eb7b5118015c2caca635538324ccf0ccffredc
853ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov    public boolean disable(String packageName, boolean persist) throws RemoteException {
854ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        final int callingUid = Binder.getCallingUid();
855ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
85640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
857ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        if (!callerSystem) {
858ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            if (!checkIfCallerIsForegroundUser()) {
859ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                Slog.w(TAG, "disable(): not allowed for non-active and non system user");
860ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                return false;
861ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            }
862ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
863ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
864ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                    "Need BLUETOOTH ADMIN permission");
865ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
866ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            if (isEnabled() && mPermissionReviewRequired
867ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                    && startConsentUiIfNeeded(packageName, callingUid,
868ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                            BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
869ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                return false;
870ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            }
87140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
87240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
873f24588615efa6c781ad963f1a5bbdf47359e1b53fredc        if (DBG) {
87467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth +
875cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                " mBinding = " + mBinding);
876cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        }
877f24588615efa6c781ad963f1a5bbdf47359e1b53fredc
878401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        synchronized(mReceiver) {
879401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            if (persist) {
880401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                persistBluetoothSetting(BLUETOOTH_OFF);
881401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            }
882401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu            mEnableExternal = false;
8835980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            sendDisableMsg(packageName);
884401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        }
8850f42037eb7b5118015c2caca635538324ccf0ccffredc        return true;
8860f42037eb7b5118015c2caca635538324ccf0ccffredc    }
8870f42037eb7b5118015c2caca635538324ccf0ccffredc
888ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov    private boolean startConsentUiIfNeeded(String packageName,
889ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            int callingUid, String intentAction) throws RemoteException {
890ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        try {
891ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            // Validate the package only if we are going to use it
892ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            ApplicationInfo applicationInfo = mContext.getPackageManager()
893ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                    .getApplicationInfoAsUser(packageName,
894ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                            PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
895ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                            UserHandle.getUserId(callingUid));
896ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            if (applicationInfo.uid != callingUid) {
897ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                throw new SecurityException("Package " + callingUid
898ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov                        + " not in uid " + callingUid);
899ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            }
900ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
901d2d32b1f32603d29b18325bcbfb3df79c2d35abcIvan Podogov            Intent intent = new Intent(intentAction);
9021ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
9031ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
9041ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
9051ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov            try {
9061ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov                mContext.startActivity(intent);
9071ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov            } catch (ActivityNotFoundException e) {
9081ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov                // Shouldn't happen
9091ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov                Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
9101ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov                return false;
911ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            }
9121ab8725378c28bb9096677d305765f5d9e2a871cIvan Podogov            return true;
913ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        } catch (PackageManager.NameNotFoundException e) {
914ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov            throw new RemoteException(e.getMessage());
915ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov        }
916ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov    }
917ac69be543f89ea6e9a27204492e0a170d9b3450eSvetoslav Ganov
918649fe497cea2f19e937f84218d1080bdcefe47f2fredc    public void unbindAndFinish() {
919f24588615efa6c781ad963f1a5bbdf47359e1b53fredc        if (DBG) {
92067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.d(TAG,"unbindAndFinish(): " + mBluetooth +
921cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                " mBinding = " + mBinding + " mUnbinding = " + mUnbinding);
922f24588615efa6c781ad963f1a5bbdf47359e1b53fredc        }
923f24588615efa6c781ad963f1a5bbdf47359e1b53fredc
924eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
925eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.writeLock().lock();
9260f42037eb7b5118015c2caca635538324ccf0ccffredc            if (mUnbinding) return;
9270f42037eb7b5118015c2caca635538324ccf0ccffredc            mUnbinding = true;
928e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov            mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
92974f60c0de8a9bc436b4dd891e359d014a748e1dePavlin Radoslavov            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
93040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            if (mBluetooth != null) {
931305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                //Unregister callback object
932305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                try {
933305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    mBluetooth.unregisterCallback(mBluetoothCallback);
934305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                } catch (RemoteException re) {
93567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "Unable to unregister BluetoothCallback",re);
936bf072a712f584ae1c01022835b0de21c40513d06fredc                }
9379db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen                mBluetoothBinder = null;
938d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc                mBluetooth = null;
9390f42037eb7b5118015c2caca635538324ccf0ccffredc                mContext.unbindService(mConnection);
940d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc                mUnbinding = false;
94140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                mBinding = false;
942f24588615efa6c781ad963f1a5bbdf47359e1b53fredc            } else {
943cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                mUnbinding = false;
9440f42037eb7b5118015c2caca635538324ccf0ccffredc            }
945d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            mBluetoothGatt = null;
946eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
947eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.writeLock().unlock();
9480f42037eb7b5118015c2caca635538324ccf0ccffredc        }
9490f42037eb7b5118015c2caca635538324ccf0ccffredc    }
9500f42037eb7b5118015c2caca635538324ccf0ccffredc
951ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    public IBluetoothGatt getBluetoothGatt() {
952ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        // sync protection
953ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        return mBluetoothGatt;
954ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    }
955ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
956e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    @Override
957e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    public boolean bindBluetoothProfileService(int bluetoothProfile,
958e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            IBluetoothProfileServiceConnection proxy) {
959e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        if (!mEnable) {
960e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            if (DBG) {
96167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
962e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                        ", while Bluetooth was disabled");
963e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
964e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            return false;
965e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
966e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        synchronized (mProfileServices) {
967e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
968e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            if (psc == null) {
969e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                if (DBG) {
97067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.d(TAG, "Creating new ProfileServiceConnections object for"
971e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                            + " profile: " + bluetoothProfile);
972e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
9735b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz
9745b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                if (bluetoothProfile != BluetoothProfile.HEADSET) return false;
9755b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz
9765b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                Intent intent = new Intent(IBluetoothHeadset.class.getName());
977e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                psc = new ProfileServiceConnections(intent);
9785b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                if (!psc.bindService()) return false;
9795b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz
980e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                mProfileServices.put(new Integer(bluetoothProfile), psc);
981e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
982e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
983e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
984e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        // Introducing a delay to give the client app time to prepare
985e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
986e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        addProxyMsg.arg1 = bluetoothProfile;
987e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        addProxyMsg.obj = proxy;
988e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
989e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        return true;
990e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    }
991e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
992e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    @Override
993e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    public void unbindBluetoothProfileService(int bluetoothProfile,
994e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            IBluetoothProfileServiceConnection proxy) {
995e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        synchronized (mProfileServices) {
996e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
997e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            if (psc == null) {
998e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                return;
999e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1000e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            psc.removeProxy(proxy);
1001e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1002e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    }
1003e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1004e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    private void unbindAllBluetoothProfileServices() {
1005e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        synchronized (mProfileServices) {
1006e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            for (Integer i : mProfileServices.keySet()) {
1007e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                ProfileServiceConnections psc = mProfileServices.get(i);
10085b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                try {
10095b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                    mContext.unbindService(psc);
10105b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                } catch (IllegalArgumentException e) {
101167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
10125b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                }
1013e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                psc.removeAllProxies();
1014e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1015e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mProfileServices.clear();
1016e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1017e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    }
1018e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1019e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    /**
1020658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou     * Send enable message and set adapter name and address. Called when the boot phase becomes
1021658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou     * PHASE_SYSTEM_SERVICES_READY.
1022658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou     */
1023658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou    public void handleOnBootPhase() {
102467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        if (DBG) Slog.d(TAG, "Bluetooth boot completed");
102563d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        UserManagerInternal userManagerInternal =
102663d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova                LocalServices.getService(UserManagerInternal.class);
102763d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
1028c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova        final boolean isBluetoothDisallowed = isBluetoothDisallowed();
1029c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova        if (isBluetoothDisallowed) {
103063d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            return;
103163d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        }
1032658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
103367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
1034467bc04b0d9a091444bc2b6affbb50f9f1eab3e2Ajay Panicker            sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT);
1035bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker        } else if (!isNameAndAddressSet()) {
1036bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker            if (DBG) Slog.d(TAG, "Getting adapter name and address");
10374bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
10384bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker            mHandler.sendMessage(getMsg);
1039658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou        }
1040658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou    }
1041658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou
1042658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou    /**
1043658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou     * Called when switching to a different foreground user.
1044658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou     */
1045658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou    public void handleOnSwitchUser(int userHandle) {
1046aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey        if (DBG) Slog.d(TAG, "User " + userHandle + " switched");
1047aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey        mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
1048aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    }
1049aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey
1050aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    /**
1051aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey     * Called when user is unlocked.
1052aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey     */
1053aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey    public void handleOnUnlockUser(int userHandle) {
1054aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey        if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked");
1055aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey        mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
1056658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou    }
1057658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou
1058658bf2fa6d3bb1121c3c96abb62ca01d3abe95dbMiao Chou    /**
1059e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz     * This class manages the clients connected to a given ProfileService
1060e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz     * and maintains the connection with that service.
1061e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz     */
1062e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    final private class ProfileServiceConnections implements ServiceConnection,
1063e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            IBinder.DeathRecipient {
1064e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
1065e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                new RemoteCallbackList <IBluetoothProfileServiceConnection>();
1066e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        IBinder mService;
1067e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        ComponentName mClassName;
1068e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        Intent mIntent;
10693bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach        boolean mInvokingProxyCallbacks = false;
1070e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1071e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        ProfileServiceConnections(Intent intent) {
1072e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mService = null;
1073e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mClassName = null;
1074e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mIntent = intent;
1075e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1076e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
10775b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz        private boolean bindService() {
10785b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz            if (mIntent != null && mService == null &&
10795b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                    doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
1080e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1081e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                msg.obj = this;
1082e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
10835b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz                return true;
1084e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
108567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG, "Unable to bind with intent: " + mIntent);
10865b614593e1a212e8ad9ac4a1e22a2954bb499233Benjamin Franz            return false;
1087e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1088e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1089e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        private void addProxy(IBluetoothProfileServiceConnection proxy) {
1090e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mProxies.register(proxy);
1091e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            if (mService != null) {
1092e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                try{
1093e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    proxy.onServiceConnected(mClassName, mService);
1094e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                } catch (RemoteException e) {
109567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "Unable to connect to proxy", e);
1096e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
1097e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            } else {
1098e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
1099e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1100e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    msg.obj = this;
1101e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    mHandler.sendMessage(msg);
1102e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
1103e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1104e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1105e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1106e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        private void removeProxy(IBluetoothProfileServiceConnection proxy) {
1107e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            if (proxy != null) {
1108e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                if (mProxies.unregister(proxy)) {
1109e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    try {
1110e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                        proxy.onServiceDisconnected(mClassName);
1111e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    } catch (RemoteException e) {
111267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                        Slog.e(TAG, "Unable to disconnect proxy", e);
1113e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    }
1114e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
1115e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            } else {
111667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.w(TAG, "Trying to remove a null proxy");
1117e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1118e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1119e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1120e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        private void removeAllProxies() {
1121e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            onServiceDisconnected(mClassName);
1122e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mProxies.kill();
1123e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1124e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1125e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        @Override
1126e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        public void onServiceConnected(ComponentName className, IBinder service) {
1127e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            // remove timeout message
1128e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
1129e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mService = service;
1130e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mClassName = className;
1131e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            try {
1132e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                mService.linkToDeath(this, 0);
1133e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            } catch (RemoteException e) {
113467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.e(TAG, "Unable to linkToDeath", e);
1135e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
11363bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach
11373bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            if (mInvokingProxyCallbacks) {
113867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.e(TAG, "Proxy callbacks already in progress.");
11393bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                return;
11403bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            }
11413bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            mInvokingProxyCallbacks = true;
11423bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach
11433bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            final int n = mProxies.beginBroadcast();
11443bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            try {
11453bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                for (int i = 0; i < n; i++) {
11463bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    try {
11473bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                        mProxies.getBroadcastItem(i).onServiceConnected(className, service);
11483bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    } catch (RemoteException e) {
114967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                        Slog.e(TAG, "Unable to connect to proxy", e);
11503bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    }
1151e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
11523bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            } finally {
11533bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                mProxies.finishBroadcast();
11543bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                mInvokingProxyCallbacks = false;
1155e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1156e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1157e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1158e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        @Override
1159e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        public void onServiceDisconnected(ComponentName className) {
11603bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            if (mService == null) return;
1161e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mService.unlinkToDeath(this, 0);
1162e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mService = null;
1163e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mClassName = null;
11643bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach
11653bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            if (mInvokingProxyCallbacks) {
116667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.e(TAG, "Proxy callbacks already in progress.");
11673bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                return;
11683bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            }
11693bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            mInvokingProxyCallbacks = true;
11703bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach
11713bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            final int n = mProxies.beginBroadcast();
11723bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            try {
11733bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                for (int i = 0; i < n; i++) {
11743bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    try {
11753bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                        mProxies.getBroadcastItem(i).onServiceDisconnected(className);
11763bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    } catch (RemoteException e) {
117767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                        Slog.e(TAG, "Unable to disconnect from proxy", e);
11783bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    }
1179e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
11803bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            } finally {
11813bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                mProxies.finishBroadcast();
11823bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                mInvokingProxyCallbacks = false;
1183e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1184e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1185e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1186e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        @Override
1187e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        public void binderDied() {
1188e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            if (DBG) {
118967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.w(TAG, "Profile service for profile: " + mClassName
1190e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                        + " died.");
1191e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            }
1192e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            onServiceDisconnected(mClassName);
1193e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            // Trigger rebind
1194e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
1195e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            msg.obj = this;
1196e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz            mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
1197e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        }
1198e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz    }
1199e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz
1200bf072a712f584ae1c01022835b0de21c40513d06fredc    private void sendBluetoothStateCallback(boolean isUp) {
12013bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach        try {
12023bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            int n = mStateChangeCallbacks.beginBroadcast();
120367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
12043bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            for (int i=0; i <n;i++) {
12053bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                try {
12063bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                    mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
12073bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                } catch (RemoteException e) {
120867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
12093bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach                }
1210bf072a712f584ae1c01022835b0de21c40513d06fredc            }
12113bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach        } finally {
12123bf1ac54edc77d2249dc9a0ab8291efa70ff76b9Andre Eisenbach            mStateChangeCallbacks.finishBroadcast();
1213bf072a712f584ae1c01022835b0de21c40513d06fredc        }
1214bf072a712f584ae1c01022835b0de21c40513d06fredc    }
1215bf072a712f584ae1c01022835b0de21c40513d06fredc
1216bf072a712f584ae1c01022835b0de21c40513d06fredc    /**
121740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu     * Inform BluetoothAdapter instances that Adapter service is up
121840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu     */
121940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private void sendBluetoothServiceUpCallback() {
1220305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach        try {
1221305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            int n = mCallbacks.beginBroadcast();
122267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
1223305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            for (int i=0; i <n;i++) {
1224305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                try {
1225305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
1226305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                }  catch (RemoteException e) {
122767609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
122840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                }
122940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            }
1230305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach        } finally {
1231305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            mCallbacks.finishBroadcast();
123240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
123340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    }
123440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    /**
1235bf072a712f584ae1c01022835b0de21c40513d06fredc     * Inform BluetoothAdapter instances that Adapter service is down
1236bf072a712f584ae1c01022835b0de21c40513d06fredc     */
1237bf072a712f584ae1c01022835b0de21c40513d06fredc    private void sendBluetoothServiceDownCallback() {
1238305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach        try {
1239305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            int n = mCallbacks.beginBroadcast();
124067609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
1241305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            for (int i=0; i <n;i++) {
1242305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                try {
1243305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
1244305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                }  catch (RemoteException e) {
124567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
1246d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc                }
1247d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc            }
1248305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach        } finally {
1249305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            mCallbacks.finishBroadcast();
1250d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc        }
1251d6883533e4ac3f73d2fde1db9a1dddf06dac6709fredc    }
1252408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov
12530f42037eb7b5118015c2caca635538324ccf0ccffredc    public String getAddress() {
1254af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
1255408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov                "Need BLUETOOTH permission");
125640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
12576eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
1258408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov                (!checkIfCallerIsForegroundUser())) {
125967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG,"getAddress(): not allowed for non-active and non system user");
12606eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu            return null;
126140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
126240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1263408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov        if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
1264408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov                != PackageManager.PERMISSION_GRANTED) {
1265408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov            return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
1266408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov        }
1267408abf7f1bec3253675d0225300d7ee39481d286Svet Ganov
1268eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
1269eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().lock();
1270eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            if (mBluetooth != null) return mBluetooth.getAddress();
1271eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } catch (RemoteException e) {
1272eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e);
1273eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
1274eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().unlock();
1275116d1d4696ac8e300c83dd8a95e20e67717ef520fredc        }
1276bf796d87777e998cc284b8634e9cfdcd371e63f8Ajay Panicker
1277cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        // mAddress is accessed from outside.
1278cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        // It is alright without a lock. Here, bluetooth is off, no other thread is
1279cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        // changing mAddress
12800f42037eb7b5118015c2caca635538324ccf0ccffredc        return mAddress;
12810f42037eb7b5118015c2caca635538324ccf0ccffredc    }
1282649fe497cea2f19e937f84218d1080bdcefe47f2fredc
12830f42037eb7b5118015c2caca635538324ccf0ccffredc    public String getName() {
1284af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
1285af5ddbfcf59e1e0bcbd43f1f88270f822c5083b8Matthew Xie                                                "Need BLUETOOTH permission");
128640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
12876eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
12886eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu            (!checkIfCallerIsForegroundUser())) {
128967609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.w(TAG,"getName(): not allowed for non-active and non system user");
12906eb7652b04b92b0c3786d96e6a97f5f4e46aec69Zhihai Xu            return null;
129140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
129240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1293eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
1294eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().lock();
1295eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            if (mBluetooth != null) return mBluetooth.getName();
1296eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } catch (RemoteException e) {
1297eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
1298eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
1299eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().unlock();
1300116d1d4696ac8e300c83dd8a95e20e67717ef520fredc        }
1301eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov
1302cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        // mName is accessed from outside.
1303cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        // It alright without a lock. Here, bluetooth is off, no other thread is
1304cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        // changing mName
13050f42037eb7b5118015c2caca635538324ccf0ccffredc        return mName;
13060f42037eb7b5118015c2caca635538324ccf0ccffredc    }
13070f42037eb7b5118015c2caca635538324ccf0ccffredc
13080f42037eb7b5118015c2caca635538324ccf0ccffredc    private class BluetoothServiceConnection implements ServiceConnection {
1309cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        public void onServiceConnected(ComponentName componentName, IBinder service) {
1310cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            String name = componentName.getClassName();
1311cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name);
13120f42037eb7b5118015c2caca635538324ccf0ccffredc            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
1313cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
1314ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                msg.arg1 = SERVICE_IBLUETOOTH;
1315cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
1316ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                msg.arg1 = SERVICE_IBLUETOOTHGATT;
1317ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            } else {
1318cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                Slog.e(TAG, "Unknown service connected: " + name);
1319ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return;
1320ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
13210f42037eb7b5118015c2caca635538324ccf0ccffredc            msg.obj = service;
13220f42037eb7b5118015c2caca635538324ccf0ccffredc            mHandler.sendMessage(msg);
13230f42037eb7b5118015c2caca635538324ccf0ccffredc        }
13240f42037eb7b5118015c2caca635538324ccf0ccffredc
1325cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        public void onServiceDisconnected(ComponentName componentName) {
1326cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            // Called if we unexpectedly disconnect.
1327cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            String name = componentName.getClassName();
1328cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
13290f42037eb7b5118015c2caca635538324ccf0ccffredc            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
1330cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
1331ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                msg.arg1 = SERVICE_IBLUETOOTH;
1332cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
1333ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                msg.arg1 = SERVICE_IBLUETOOTHGATT;
1334ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            } else {
1335cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                Slog.e(TAG, "Unknown service disconnected: " + name);
1336ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return;
1337ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
13380f42037eb7b5118015c2caca635538324ccf0ccffredc            mHandler.sendMessage(msg);
13390f42037eb7b5118015c2caca635538324ccf0ccffredc        }
13400f42037eb7b5118015c2caca635538324ccf0ccffredc    }
13410f42037eb7b5118015c2caca635538324ccf0ccffredc
13420f42037eb7b5118015c2caca635538324ccf0ccffredc    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
13430f42037eb7b5118015c2caca635538324ccf0ccffredc
134440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private class BluetoothHandler extends Handler {
13454bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker        boolean mGetNameAddressOnly = false;
13464bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker
134740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        public BluetoothHandler(Looper looper) {
134840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            super(looper);
134940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
135040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
13510f42037eb7b5118015c2caca635538324ccf0ccffredc        @Override
13520f42037eb7b5118015c2caca635538324ccf0ccffredc        public void handleMessage(Message msg) {
13530f42037eb7b5118015c2caca635538324ccf0ccffredc            switch (msg.what) {
13544bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                case MESSAGE_GET_NAME_AND_ADDRESS:
13554bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                    if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
1356eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    try {
1357eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        mBluetoothLock.writeLock().lock();
13584bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                        if ((mBluetooth == null) && (!mBinding)) {
13594bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            if (DBG) Slog.d(TAG, "Binding to service to get name and address");
13604bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            mGetNameAddressOnly = true;
13614bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
13624bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
13634bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            Intent i = new Intent(IBluetooth.class.getName());
13644bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            if (!doBind(i, mConnection,
13654bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
13664bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                UserHandle.CURRENT)) {
13674bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
13684bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            } else {
13694bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                mBinding = true;
13704bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            }
13714bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                        } else if (mBluetooth != null) {
13724bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            try {
13734bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                storeNameAndAddress(mBluetooth.getName(),
13744bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                                    mBluetooth.getAddress());
13754bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            } catch (RemoteException re) {
13764bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                Slog.e(TAG, "Unable to grab names", re);
13774bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            }
13784bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            if (mGetNameAddressOnly && !mEnable) {
13794bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                                unbindAndFinish();
13804bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            }
13814bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            mGetNameAddressOnly = false;
13824bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                        }
1383eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    } finally {
1384eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        mBluetoothLock.writeLock().unlock();
13854bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                    }
13864bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                    break;
13874bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker
1388cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                case MESSAGE_ENABLE:
1389f24588615efa6c781ad963f1a5bbdf47359e1b53fredc                    if (DBG) {
1390cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                        Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
1391649fe497cea2f19e937f84218d1080bdcefe47f2fredc                    }
139240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
139340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mEnable = true;
1394a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On
1395a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    // Use service interface to get the exact state
1396a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    try {
1397a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        mBluetoothLock.readLock().lock();
1398a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        if (mBluetooth != null) {
1399a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            int state = mBluetooth.getState();
1400a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            if (state == BluetoothAdapter.STATE_BLE_ON) {
1401e0bfa2efa24ad273d8b23061cad9b3b7dcdbf5b0Marie Janssen                                Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
1402a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                                mBluetooth.onLeServiceUp();
1403e0bfa2efa24ad273d8b23061cad9b3b7dcdbf5b0Marie Janssen                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
1404a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                                break;
1405a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            }
1406a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        }
1407a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    } catch (RemoteException e) {
1408a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        Slog.e(TAG, "", e);
1409a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    } finally {
1410a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        mBluetoothLock.readLock().unlock();
1411a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    }
1412a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On
1413a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    mQuietEnable = (msg.arg1 == 1);
1414e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                    if (mBluetooth == null) {
1415a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        handleEnable(mQuietEnable);
1416e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                    } else {
1417e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        //
1418e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // We need to wait until transitioned to STATE_OFF and
1419e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // the previous Bluetooth process has exited. The
1420e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // waiting period has three components:
1421e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // (a) Wait until the local state is STATE_OFF. This
1422e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        //     is accomplished by "waitForOnOff(false, true)".
1423e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // (b) Wait until the STATE_OFF state is updated to
1424e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        //     all components.
1425e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // (c) Wait until the Bluetooth process exits, and
1426e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        //     ActivityManager detects it.
1427e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // The waiting for (b) and (c) is accomplished by
1428e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
1429e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // message. On slower devices, that delay needs to be
1430e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        // on the order of (2 * SERVICE_RESTART_TIME_MS).
1431e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        //
1432e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        waitForOnOff(false, true);
1433e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        Message restartMsg = mHandler.obtainMessage(
1434e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                                MESSAGE_RESTART_BLUETOOTH_SERVICE);
1435e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                        mHandler.sendMessageDelayed(restartMsg,
1436e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                                2 * SERVICE_RESTART_TIME_MS);
1437e47ec14318f64c29bf16b5a6bb662bc19206d6b0Pavlin Radoslavov                    }
1438649fe497cea2f19e937f84218d1080bdcefe47f2fredc                    break;
14390f42037eb7b5118015c2caca635538324ccf0ccffredc
1440cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                case MESSAGE_DISABLE:
1441cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    if (DBG) Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
144240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
144340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    if (mEnable && mBluetooth != null) {
144440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        waitForOnOff(true, false);
144540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        mEnable = false;
1446401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                        handleDisable();
144740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        waitForOnOff(false, false);
144840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    } else {
144940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        mEnable = false;
1450401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                        handleDisable();
145140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    }
14520f42037eb7b5118015c2caca635538324ccf0ccffredc                    break;
1453cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie
1454873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                case MESSAGE_RESTORE_USER_SETTING:
1455873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    try {
1456873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                        if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
1457873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                            if (DBG) Slog.d(TAG, "Restore Bluetooth state to disabled");
1458873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                            disable(REASON_RESTORE_USER_SETTING, true);
1459873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                        } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
1460873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                            if (DBG) Slog.d(TAG, "Restore Bluetooth state to enabled");
1461873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                            enable(REASON_RESTORE_USER_SETTING);
1462873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                        }
1463873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    } catch (RemoteException e) {
1464873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                        Slog.e(TAG,"Unable to change Bluetooth On setting", e);
1465873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    }
1466873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng                    break;
1467873b5708d14460360d32cfc98ee48cf62f1ebfa6Stanley Tng
14680f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_REGISTER_ADAPTER:
14690f42037eb7b5118015c2caca635538324ccf0ccffredc                {
14700f42037eb7b5118015c2caca635538324ccf0ccffredc                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
1471cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mCallbacks.register(callback);
14720f42037eb7b5118015c2caca635538324ccf0ccffredc                    break;
1473cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                }
14740f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_UNREGISTER_ADAPTER:
14750f42037eb7b5118015c2caca635538324ccf0ccffredc                {
14760f42037eb7b5118015c2caca635538324ccf0ccffredc                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
1477cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mCallbacks.unregister(callback);
14780f42037eb7b5118015c2caca635538324ccf0ccffredc                    break;
1479cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
14800f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
14810f42037eb7b5118015c2caca635538324ccf0ccffredc                {
14820f42037eb7b5118015c2caca635538324ccf0ccffredc                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
1483cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mStateChangeCallbacks.register(callback);
14840f42037eb7b5118015c2caca635538324ccf0ccffredc                    break;
1485cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
14860f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
14870f42037eb7b5118015c2caca635538324ccf0ccffredc                {
14880f42037eb7b5118015c2caca635538324ccf0ccffredc                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
1489cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mStateChangeCallbacks.unregister(callback);
14900f42037eb7b5118015c2caca635538324ccf0ccffredc                    break;
1491cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
1492e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                case MESSAGE_ADD_PROXY_DELAYED:
1493e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                {
1494e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    ProfileServiceConnections psc = mProfileServices.get(
1495e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                            new Integer(msg.arg1));
1496e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    if (psc == null) {
1497e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                        break;
1498e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    }
1499e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    IBluetoothProfileServiceConnection proxy =
1500e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                            (IBluetoothProfileServiceConnection) msg.obj;
1501e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    psc.addProxy(proxy);
1502e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    break;
1503e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
1504e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                case MESSAGE_BIND_PROFILE_SERVICE:
1505e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                {
1506e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
1507e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
1508e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    if (psc == null) {
1509e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                        break;
1510e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    }
1511e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    psc.bindService();
1512e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    break;
1513e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                }
15140f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
15150f42037eb7b5118015c2caca635538324ccf0ccffredc                {
151667609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
15170f42037eb7b5118015c2caca635538324ccf0ccffredc
15180f42037eb7b5118015c2caca635538324ccf0ccffredc                    IBinder service = (IBinder) msg.obj;
1519eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    try {
1520eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        mBluetoothLock.writeLock().lock();
1521ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
15220a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey                            mBluetoothGatt = IBluetoothGatt.Stub
15230a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey                                    .asInterface(Binder.allowBlocking(service));
1524d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                            onBluetoothGattServiceUp();
1525ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            break;
1526ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        } // else must be SERVICE_IBLUETOOTH
1527ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
1528ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        //Remove timeout
1529af5971ef27557f02f93b399c92d7e67106d825feZhihai Xu                        mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
1530ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
15310f42037eb7b5118015c2caca635538324ccf0ccffredc                        mBinding = false;
15329db28ebea5e435ae6eb016358f5109e718d9aeccMarie Janssen                        mBluetoothBinder = service;
15330a17db1cc5942ea000ca87bb72853de57a15ec64Jeff Sharkey                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
15340f42037eb7b5118015c2caca635538324ccf0ccffredc
15354bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                        if (!isNameAndAddressSet()) {
15364bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
15374bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            mHandler.sendMessage(getMsg);
15384bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                            if (mGetNameAddressOnly) return;
15394bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker                        }
15404bb4830b758ce0fadff33d993c4e7e8aca880cadAjay Panicker
1541cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                        //Register callback object
1542cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                        try {
1543cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                            mBluetooth.registerCallback(mBluetoothCallback);
1544cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                        } catch (RemoteException re) {
154567609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                            Slog.e(TAG, "Unable to register BluetoothCallback",re);
1546cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                        }
1547cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                        //Inform BluetoothAdapter instances that service is up
154840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        sendBluetoothServiceUpCallback();
154940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1550cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                        //Do enable request
1551bf072a712f584ae1c01022835b0de21c40513d06fredc                        try {
1552fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                            if (mQuietEnable == false) {
1553cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                                if (!mBluetooth.enable()) {
155467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                                    Slog.e(TAG,"IBluetooth.enable() returned false");
1555fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                                }
1556cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                            } else {
1557cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                                if (!mBluetooth.enableNoAutoConnect()) {
155867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                                    Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
1559fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                                }
1560cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                            }
1561bf072a712f584ae1c01022835b0de21c40513d06fredc                        } catch (RemoteException e) {
156267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                            Slog.e(TAG,"Unable to call enable()",e);
15630f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
1564eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    } finally {
1565eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        mBluetoothLock.writeLock().unlock();
1566bf072a712f584ae1c01022835b0de21c40513d06fredc                    }
156740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
156840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    if (!mEnable) {
156940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        waitForOnOff(true, false);
1570401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                        handleDisable();
157140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        waitForOnOff(false, false);
157240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    }
1573649fe497cea2f19e937f84218d1080bdcefe47f2fredc                    break;
1574cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
1575bf072a712f584ae1c01022835b0de21c40513d06fredc                case MESSAGE_BLUETOOTH_STATE_CHANGE:
15760f42037eb7b5118015c2caca635538324ccf0ccffredc                {
1577bf072a712f584ae1c01022835b0de21c40513d06fredc                    int prevState = msg.arg1;
1578bf072a712f584ae1c01022835b0de21c40513d06fredc                    int newState = msg.arg2;
1579cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    if (DBG) {
1580cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                      Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(prevState) + " > " +
1581cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                        BluetoothAdapter.nameForState(newState));
1582cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    }
158340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mState = newState;
158440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    bluetoothStateChangeHandler(prevState, newState);
1585dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                    // handle error state transition case from TURNING_ON to OFF
1586dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                    // unbind and rebind bluetooth service and enable bluetooth
1587d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) &&
1588a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            (newState == BluetoothAdapter.STATE_OFF) &&
1589a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            (mBluetooth != null) && mEnable) {
15902977c3e372070a540330a6761fbadd201822fff1Marie Janssen                        recoverBluetoothServiceFromError(false);
1591dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                    }
1592d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                    if ((prevState == BluetoothAdapter.STATE_TURNING_ON) &&
1593a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            (newState == BluetoothAdapter.STATE_BLE_ON) &&
1594a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            (mBluetooth != null) && mEnable) {
15952977c3e372070a540330a6761fbadd201822fff1Marie Janssen                        recoverBluetoothServiceFromError(true);
1596d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                    }
1597a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    // If we tried to enable BT while BT was in the process of shutting down,
1598a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    // wait for the BT process to fully tear down and then force a restart
1599a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    // here.  This is a bit of a hack (b/29363429).
1600a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) &&
1601a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            (newState == BluetoothAdapter.STATE_OFF)) {
1602a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        if (mEnable) {
1603a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
1604a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            waitForOnOff(false, true);
1605a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            Message restartMsg = mHandler.obtainMessage(
1606a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                                    MESSAGE_RESTART_BLUETOOTH_SERVICE);
1607a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
1608a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                        }
1609a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                    }
1610d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                    if (newState == BluetoothAdapter.STATE_ON ||
1611a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            newState == BluetoothAdapter.STATE_BLE_ON) {
1612dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                        // bluetooth is working, reset the counter
1613dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                        if (mErrorRecoveryRetryCounter != 0) {
161467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                            Slog.w(TAG, "bluetooth is recovered from error");
1615dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                            mErrorRecoveryRetryCounter = 0;
1616dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                        }
1617dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                    }
1618649fe497cea2f19e937f84218d1080bdcefe47f2fredc                    break;
1619cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
16200f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
16210f42037eb7b5118015c2caca635538324ccf0ccffredc                {
1622cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
1623eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    try {
1624eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        mBluetoothLock.writeLock().lock();
1625ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        if (msg.arg1 == SERVICE_IBLUETOOTH) {
1626ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            // if service is unbinded already, do nothing and return
1627ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            if (mBluetooth == null) break;
1628ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            mBluetooth = null;
1629ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
1630ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            mBluetoothGatt = null;
1631ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            break;
1632ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        } else {
1633cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                            Slog.e(TAG, "Unknown argument for service disconnect!");
1634ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                            break;
1635ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        }
1636eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    } finally {
1637eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        mBluetoothLock.writeLock().unlock();
16381223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                    }
163940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1640e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                    // log the unexpected crash
1641e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                    addCrashLog();
1642e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                    addActiveLog(REASON_UNEXPECTED, false);
164340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    if (mEnable) {
164440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        mEnable = false;
164540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        // Send a Bluetooth Restart message
164640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        Message restartMsg = mHandler.obtainMessage(
164740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                            MESSAGE_RESTART_BLUETOOTH_SERVICE);
164840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        mHandler.sendMessageDelayed(restartMsg,
164940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                            SERVICE_RESTART_TIME_MS);
165040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    }
165140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1652305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    sendBluetoothServiceDownCallback();
165340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1654305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    // Send BT state broadcast to update
1655305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    // the BT icon correctly
1656305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    if ((mState == BluetoothAdapter.STATE_TURNING_ON) ||
1657a0b91d77d62020652b7f003326ffe11c7e4d87c2Calvin On                            (mState == BluetoothAdapter.STATE_ON)) {
1658305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
1659305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                                                    BluetoothAdapter.STATE_TURNING_OFF);
1660305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                        mState = BluetoothAdapter.STATE_TURNING_OFF;
166140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    }
1662305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
1663305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
1664305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                                                    BluetoothAdapter.STATE_OFF);
1665305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    }
1666305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach
1667305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
1668305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach                    mState = BluetoothAdapter.STATE_OFF;
1669649fe497cea2f19e937f84218d1080bdcefe47f2fredc                    break;
1670cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
16711223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                case MESSAGE_RESTART_BLUETOOTH_SERVICE:
16721223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                {
1673cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE");
16741223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                    /* Enable without persisting the setting as
16751223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                     it doesnt change when IBluetooth
16761223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                     service restarts */
167740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mEnable = true;
1678e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                    addActiveLog(REASON_RESTARTED, true);
1679401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                    handleEnable(mQuietEnable);
16801223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                    break;
16811223e5a3115e825567972da26e38c0016bdfa268Syed Ibrahim M                }
1682cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                case MESSAGE_TIMEOUT_BIND: {
1683cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
1684cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mBluetoothLock.writeLock().lock();
1685cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mBinding = false;
1686cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    mBluetoothLock.writeLock().unlock();
1687cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    break;
1688cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                }
16890f42037eb7b5118015c2caca635538324ccf0ccffredc                case MESSAGE_TIMEOUT_UNBIND:
16900f42037eb7b5118015c2caca635538324ccf0ccffredc                {
169167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
1692eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    mBluetoothLock.writeLock().lock();
1693eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    mUnbinding = false;
1694eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    mBluetoothLock.writeLock().unlock();
1695649fe497cea2f19e937f84218d1080bdcefe47f2fredc                    break;
1696cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
169740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1698aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                case MESSAGE_USER_SWITCHED: {
1699aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                    if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED");
170040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
1701aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey
170240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    /* disable and enable BT when detect a user switch */
170388256d1a8a18ffc9f106da373dbe4891d5a72e7aRam Periathiruvadi                    if (mBluetooth != null && isEnabled()) {
1704eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        try {
1705eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                            mBluetoothLock.readLock().lock();
170640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                            if (mBluetooth != null) {
1707eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                                mBluetooth.unregisterCallback(mBluetoothCallback);
170840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                            }
1709eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        } catch (RemoteException re) {
1710eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                            Slog.e(TAG, "Unable to unregister", re);
1711eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        } finally {
1712eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                            mBluetoothLock.readLock().unlock();
171340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        }
17144e22ad35045dc5861193526afe1565d52f983698Zhihai Xu
17154e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
17164e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                            // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
17174e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
17184e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                            mState = BluetoothAdapter.STATE_OFF;
17194e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        }
17204e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        if (mState == BluetoothAdapter.STATE_OFF) {
17214e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
17224e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                            mState = BluetoothAdapter.STATE_TURNING_ON;
17234e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        }
172440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
172540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        waitForOnOff(true, false);
172640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
17274e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        if (mState == BluetoothAdapter.STATE_TURNING_ON) {
17284e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                            bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
17294e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        }
173040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1731e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                        unbindAllBluetoothProfileServices();
173240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        // disable
1733e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                        addActiveLog(REASON_USER_SWITCH, false);
1734401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                        handleDisable();
17354e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        // Pbap service need receive STATE_TURNING_OFF intent to close
17364e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
17374e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                                                    BluetoothAdapter.STATE_TURNING_OFF);
173840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1739414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        boolean didDisableTimeout = !waitForOnOff(false, true);
174040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
17414e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
174240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                                                    BluetoothAdapter.STATE_OFF);
174340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        sendBluetoothServiceDownCallback();
1744eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov
1745e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                        try {
1746e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                            mBluetoothLock.writeLock().lock();
1747e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                            if (mBluetooth != null) {
1748e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                                mBluetooth = null;
1749e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                                // Unbind
1750e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                                mContext.unbindService(mConnection);
1751e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                            }
1752e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                            mBluetoothGatt = null;
1753e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                        } finally {
1754e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                            mBluetoothLock.writeLock().unlock();
175540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        }
1756eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov
1757414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        //
1758414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        // If disabling Bluetooth times out, wait for an
1759414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        // additional amount of time to ensure the process is
1760414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        // shut down completely before attempting to restart.
1761414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        //
1762414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        if (didDisableTimeout) {
1763414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                            SystemClock.sleep(3000);
1764414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        } else {
1765414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                            SystemClock.sleep(100);
1766414011116777e66bb3364fa86b856aa3574edbfaPavlin Radoslavov                        }
176740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
17684e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
17694e22ad35045dc5861193526afe1565d52f983698Zhihai Xu                        mState = BluetoothAdapter.STATE_OFF;
177040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        // enable
1771e54b42237f749f37f0d920c89f52977871c07004Marie Janssen                        addActiveLog(REASON_USER_SWITCH, true);
177288256d1a8a18ffc9f106da373dbe4891d5a72e7aRam Periathiruvadi                        // mEnable flag could have been reset on disableBLE. Reenable it.
177388256d1a8a18ffc9f106da373dbe4891d5a72e7aRam Periathiruvadi                        mEnable = true;
1774401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                        handleEnable(mQuietEnable);
17758a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock                    } else if (mBinding || mBluetooth != null) {
177640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
177740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        userMsg.arg2 = 1 + msg.arg2;
1778cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                        // if user is switched when service is binding retry after a delay
177940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
178040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        if (DBG) {
1781cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                            Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
178240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                        }
17838a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock                    }
178440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    break;
178540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                }
1786aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                case MESSAGE_USER_UNLOCKED: {
1787aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                    if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
1788aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
1789aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey
1790eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    if (mEnable && !mBinding && (mBluetooth == null)) {
1791eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        // We should be connected, but we gave up for some
1792eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        // reason; maybe the Bluetooth service wasn't encryption
1793eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        // aware, so try binding again.
1794eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock");
1795eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                        handleEnable(mQuietEnable);
1796aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                    }
1797aacb89e929e4b36327df46c07a5afb6bd8e68479Jeff Sharkey                }
17980f42037eb7b5118015c2caca635538324ccf0ccffredc            }
17990f42037eb7b5118015c2caca635538324ccf0ccffredc        }
180040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    }
1801cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie
1802401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private void handleEnable(boolean quietMode) {
1803fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta        mQuietEnable = quietMode;
1804fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta
1805eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
1806eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.writeLock().lock();
180740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            if ((mBluetooth == null) && (!mBinding)) {
1808cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                //Start bind timeout and bind
1809cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
1810cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
1811cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                Intent i = new Intent(IBluetooth.class.getName());
1812ce09f5a53c8408d995c116a4430c000574d9875aDianne Hackborn                if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
1813ce09f5a53c8408d995c116a4430c000574d9875aDianne Hackborn                        UserHandle.CURRENT)) {
1814cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
181540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                } else {
181640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    mBinding = true;
1817cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
181840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            } else if (mBluetooth != null) {
1819cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                //Enable bluetooth
1820cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                try {
1821fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                    if (!mQuietEnable) {
1822fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                        if(!mBluetooth.enable()) {
182367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                            Slog.e(TAG,"IBluetooth.enable() returned false");
1824fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                        }
1825fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                    }
1826fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                    else {
1827fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                        if(!mBluetooth.enableNoAutoConnect()) {
182867609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                            Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
1829fffa86ba834d37684238c83c0dd081133324984dGanesh Ganapathi Batta                        }
1830cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                    }
1831cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                } catch (RemoteException e) {
183267609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                    Slog.e(TAG,"Unable to call enable()",e);
1833cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
1834cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie            }
1835eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
1836eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.writeLock().unlock();
1837cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        }
1838cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie    }
1839cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie
1840221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
1841221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
1842221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        intent.setComponent(comp);
1843221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
184467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey            Slog.e(TAG, "Fail to bind to: " + intent);
1845221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            return false;
1846221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        }
1847221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        return true;
1848221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    }
1849221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn
1850401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    private void handleDisable() {
1851eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
1852eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().lock();
1853305fdabfd0638a306c9366d79620d23e335cc0e0Andre Eisenbach            if (mBluetooth != null) {
185467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                if (DBG) Slog.d(TAG,"Sending off request.");
1855eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                if (!mBluetooth.disable()) {
1856eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    Slog.e(TAG,"IBluetooth.disable() returned false");
1857cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie                }
1858cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie            }
1859eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } catch (RemoteException e) {
1860eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            Slog.e(TAG,"Unable to call disable()",e);
1861eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
1862eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().unlock();
1863cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie        }
1864cdce0b9897183f8aef08fe200feb4027fac56290Matthew Xie    }
186540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
186640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private boolean checkIfCallerIsForegroundUser() {
186740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        int foregroundUser;
186840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        int callingUser = UserHandle.getCallingUserId();
18698385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen        int callingUid = Binder.getCallingUid();
187040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        long callingIdentity = Binder.clearCallingIdentity();
1871e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1872e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        UserInfo ui = um.getProfileParent(callingUser);
1873e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz        int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
18748385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen        int callingAppId = UserHandle.getAppId(callingUid);
187540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        boolean valid = false;
187640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        try {
187740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            foregroundUser = ActivityManager.getCurrentUser();
18788385c5afbd92da5f2e8bc13d153114bc3a7cb0f5Martijn Coenen            valid = (callingUser == foregroundUser) ||
1879e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    parentUser == foregroundUser    ||
1880bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos                    callingAppId == Process.NFC_UID ||
1881bd9a9a53ed09ca355eb0911d2aeee526b964aa7bAdrian Roos                    callingAppId == mSystemUiUid;
1882cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (DBG && !valid) {
188367609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey                Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
188440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    + " callingUser=" + callingUser
1885e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz                    + " parentUser=" + parentUser
188640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                    + " foregroundUser=" + foregroundUser);
188740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            }
188840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        } finally {
188940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            Binder.restoreCallingIdentity(callingIdentity);
189040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
189140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        return valid;
189240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    }
189340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1894d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    private void sendBleStateChanged(int prevState, int newState) {
1895cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        if (DBG) Slog.d(TAG,"Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) +
1896cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            " > " + BluetoothAdapter.nameForState(newState));
1897d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        // Send broadcast message to everyone else
1898d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
1899d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
1900d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
1901d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1902d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
1903d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora    }
1904d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
190540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private void bluetoothStateChangeHandler(int prevState, int newState) {
1906d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora        boolean isStandardBroadcast = true;
1907cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        if (prevState == newState) { // No change. Nothing to do.
1908cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            return;
1909cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        }
1910cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        // Notify all proxy objects first of adapter state change
1911cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        if (newState == BluetoothAdapter.STATE_BLE_ON ||
1912cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                newState == BluetoothAdapter.STATE_OFF) {
1913cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
1914cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen               && newState == BluetoothAdapter.STATE_BLE_ON);
1915cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen
1916cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (newState == BluetoothAdapter.STATE_OFF) {
1917cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                // If Bluetooth is off, send service down event to proxy objects, and unbind
1918cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down");
1919cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                sendBluetoothServiceDownCallback();
1920cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                unbindAndFinish();
1921d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                sendBleStateChanged(prevState, newState);
1922cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                // Don't broadcast as it has already been broadcast before
1923cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                isStandardBroadcast = false;
1924d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
1925cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            } else if (!intermediate_off) {
1926cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                // connect to GattService
1927cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode");
1928cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                if (mBluetoothGatt != null) {
1929cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp");
1930cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    onBluetoothGattServiceUp();
1931cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                } else {
1932cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service");
1933cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    if (mContext.getPackageManager().hasSystemFeature(
1934cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                                                    PackageManager.FEATURE_BLUETOOTH_LE)) {
1935cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                        Intent i = new Intent(IBluetoothGatt.class.getName());
1936cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                        doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT);
1937cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                    }
1938cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                }
1939d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                sendBleStateChanged(prevState, newState);
1940cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                //Don't broadcase this as std intent
1941d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                isStandardBroadcast = false;
1942d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora
1943cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            } else if (intermediate_off) {
1944cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode");
1945cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                // For LE only mode, broadcast as is
1946d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora                sendBleStateChanged(prevState, newState);
1947cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                sendBluetoothStateCallback(false); // BT is OFF for general users
1948cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                // Broadcast as STATE_OFF
1949cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                newState = BluetoothAdapter.STATE_OFF;
1950cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                sendBrEdrDownCallback();
195140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            }
1952cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        } else if (newState == BluetoothAdapter.STATE_ON) {
1953cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            boolean isUp = (newState == BluetoothAdapter.STATE_ON);
1954cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            sendBluetoothStateCallback(isUp);
1955cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            sendBleStateChanged(prevState, newState);
195640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
1957cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON ||
1958cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
1959cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            sendBleStateChanged(prevState, newState);
1960cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            isStandardBroadcast = false;
1961cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen
1962cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        } else if (newState == BluetoothAdapter.STATE_TURNING_ON ||
1963cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                newState == BluetoothAdapter.STATE_TURNING_OFF) {
1964cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            sendBleStateChanged(prevState, newState);
1965cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        }
1966cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen
1967cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen        if (isStandardBroadcast) {
1968cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            if (prevState == BluetoothAdapter.STATE_BLE_ON) {
1969cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                // Show prevState of BLE_ON as OFF to standard users
1970cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen                prevState = BluetoothAdapter.STATE_OFF;
1971d055adbe2c1c65d9346e65209fa8790190bc239eNitin Arora            }
1972cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
1973cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
1974cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
1975cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1976cb21ad71ed805968c43d3f5911107632a20fcf53Marie Janssen            mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
197740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
197840874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    }
197940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu
198040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    /**
198140874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu     *  if on is true, wait for state become ON
198240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu     *  if off is true, wait for state become OFF
198340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu     *  if both on and off are false, wait for state not ON
198440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu     */
198540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    private boolean waitForOnOff(boolean on, boolean off) {
198640874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        int i = 0;
198740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        while (i < 10) {
1988eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            try {
1989eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                mBluetoothLock.readLock().lock();
1990eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                if (mBluetooth == null) break;
1991eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                if (on) {
1992eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
1993eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                } else if (off) {
1994eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
1995eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                } else {
1996eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                    if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
199740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                }
1998eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            } catch (RemoteException e) {
1999eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                Slog.e(TAG, "getState()", e);
2000eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                break;
2001eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            } finally {
2002eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                mBluetoothLock.readLock().unlock();
200340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            }
200440874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            if (on || off) {
200540874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                SystemClock.sleep(300);
2006665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            } else {
200740874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu                SystemClock.sleep(50);
2008665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            }
200940874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu            i++;
201040874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        }
201167609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        Slog.e(TAG,"waitForOnOff time out");
201240874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu        return false;
201340874a096ba6448ebffea4b17486dbfbc957c0dfZhihai Xu    }
2014681ae7fc5e36f8da0c6975b316c93834c0d7b8a3Zhihai Xu
20155980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private void sendDisableMsg(String packageName) {
2016401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
20175980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        addActiveLog(packageName, false);
2018401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    }
2019401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu
20205980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private void sendEnableMsg(boolean quietMode, String packageName) {
2021401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
2022401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu                             quietMode ? 1 : 0, 0));
20235980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        addActiveLog(packageName, true);
20245980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    }
20255980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
20265980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen    private void addActiveLog(String packageName, boolean enable) {
20275980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        synchronized (mActiveLogs) {
2028e54b42237f749f37f0d920c89f52977871c07004Marie Janssen            if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
20295980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                mActiveLogs.remove();
20305980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            }
20315980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
20325980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
2033401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu    }
2034401202b5fe3d67bdf2ae6991fc451f444ecd6989Zhihai Xu
2035e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    private void addCrashLog() {
2036e54b42237f749f37f0d920c89f52977871c07004Marie Janssen      synchronized (mCrashTimestamps) {
2037e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) mCrashTimestamps.removeFirst();
2038e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        mCrashTimestamps.add(System.currentTimeMillis());
2039e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        mCrashes++;
2040e54b42237f749f37f0d920c89f52977871c07004Marie Janssen      }
2041e54b42237f749f37f0d920c89f52977871c07004Marie Janssen    }
2042e54b42237f749f37f0d920c89f52977871c07004Marie Janssen
20432977c3e372070a540330a6761fbadd201822fff1Marie Janssen    private void recoverBluetoothServiceFromError(boolean clearBle) {
204467609c75702df7178e2df6d9afa1b61c00cb2a43Jeff Sharkey        Slog.e(TAG,"recoverBluetoothServiceFromError");
2045eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        try {
2046eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().lock();
2047dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu            if (mBluetooth != null) {
2048dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                //Unregister callback object
2049eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov                mBluetooth.unregisterCallback(mBluetoothCallback);
2050dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu            }
2051eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } catch (RemoteException re) {
2052eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            Slog.e(TAG, "Unable to unregister", re);
2053eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov        } finally {
2054eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov            mBluetoothLock.readLock().unlock();
2055dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        }
2056dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
2057dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        SystemClock.sleep(500);
2058dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
2059dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        // disable
2060e54b42237f749f37f0d920c89f52977871c07004Marie Janssen        addActiveLog(REASON_START_CRASH, false);
2061dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        handleDisable();
2062dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
2063dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        waitForOnOff(false, true);
2064dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
2065dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        sendBluetoothServiceDownCallback();
2066eb50a39e98acb78d16465041bb5c172aa1637e97Pavlin Radoslavov
2067e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov        try {
2068e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov            mBluetoothLock.writeLock().lock();
2069e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov            if (mBluetooth != null) {
2070e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                mBluetooth = null;
2071e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                // Unbind
2072e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov                mContext.unbindService(mConnection);
2073e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov            }
2074e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov            mBluetoothGatt = null;
2075e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov        } finally {
2076e957a8a0b4100d001f79c866e7904d2426ac8da0Pavlin Radoslavov            mBluetoothLock.writeLock().unlock();
2077dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        }
2078dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
2079dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
2080dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        mState = BluetoothAdapter.STATE_OFF;
2081dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
20822977c3e372070a540330a6761fbadd201822fff1Marie Janssen        if (clearBle) {
20832977c3e372070a540330a6761fbadd201822fff1Marie Janssen          clearBleApps();
20842977c3e372070a540330a6761fbadd201822fff1Marie Janssen        }
20852977c3e372070a540330a6761fbadd201822fff1Marie Janssen
2086dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        mEnable = false;
2087dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu
2088dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) {
2089dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu            // Send a Bluetooth Restart message to reenable bluetooth
2090dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu            Message restartMsg = mHandler.obtainMessage(
2091dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu                             MESSAGE_RESTART_BLUETOOTH_SERVICE);
2092dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu            mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
2093dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        } else {
2094dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu            // todo: notify user to power down and power up phone to make bluetooth work.
2095dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu        }
2096dd9d17d45836bc1cc00136e088445fbca9244e0eZhihai Xu    }
2097726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood
209863d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova    private boolean isBluetoothDisallowed() {
209963d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        long callingIdentity = Binder.clearCallingIdentity();
210063d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        try {
210163d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            return mContext.getSystemService(UserManager.class)
210263d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova                    .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
210363d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        } finally {
210463d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova            Binder.restoreCallingIdentity(callingIdentity);
210563d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova        }
210663d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova    }
210763d5e4a7491b707235654cb081d2fc9074a5a65aLenka Trochtova
2108c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova    /**
2109c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova     * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
21104f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov     * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
21114f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov     * state if Bluetooth is not disallowed.
2112c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova     *
21134f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov     * @param userId user to disable bluetooth sharing for.
21144f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov     * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
2115c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova     */
21164f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov    private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
2117c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova        final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
2118c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova                "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
21194f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov        final int newState = bluetoothSharingDisallowed
2120c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova                ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
2121c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova                : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2122c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova        try {
21234f4f6f83c20162814e95e9ca0654eee89a818bdePavel Grafov            final IPackageManager imp = AppGlobals.getPackageManager();
21247c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson            imp.setComponentEnabledSetting(oppLauncherComponent, newState,
21257c3d2845f2e0e1a25da7f6c30769a467305a17f5Myles Watson                    PackageManager.DONT_KILL_APP, userId);
2126c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova        } catch (Exception e) {
2127c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova            // The component was not found, do nothing.
2128c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova        }
2129c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova    }
2130c6f0e23fa01ddfffae11d7b2f091d9c44fc039a4Lenka Trochtova
2131726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    @Override
21326e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2133fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
21346e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov        String errorMsg = null;
21355980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
21365980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
21375980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
21385980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        if (!protoOut) {
21395980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            writer.println("Bluetooth Status");
21405980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            writer.println("  enabled: " + isEnabled());
21415980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            writer.println("  state: " + BluetoothAdapter.nameForState(mState));
21425980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            writer.println("  address: " + mAddress);
21435980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            writer.println("  name: " + mName);
21445980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            if (mEnable) {
21455980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                long onDuration = System.currentTimeMillis() - mActiveLogs.getLast().getTime();
21465980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                String onDurationString = String.format("%02d:%02d:%02d.%03d",
21475980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                                          (int)(onDuration / (1000 * 60 * 60)),
21485980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                                          (int)((onDuration / (1000 * 60)) % 60),
21495980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                                          (int)((onDuration / 1000) % 60),
21505980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                                          (int)(onDuration % 1000));
21515980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                writer.println("  time since enabled: " + onDurationString + "\n");
21525980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            }
21535980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
2154a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            if (mActiveLogs.size() == 0) {
2155a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                writer.println("Bluetooth never enabled!");
2156a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            } else {
2157a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                writer.println("Enable log:");
2158a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                for (ActiveLog log : mActiveLogs) {
2159a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                    writer.println("  " + log);
2160a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                }
21615980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            }
21625980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
2163e54b42237f749f37f0d920c89f52977871c07004Marie Janssen            writer.println("Bluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
2164e54b42237f749f37f0d920c89f52977871c07004Marie Janssen            if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
2165e54b42237f749f37f0d920c89f52977871c07004Marie Janssen            for (Long time : mCrashTimestamps) {
2166e54b42237f749f37f0d920c89f52977871c07004Marie Janssen              writer.println("  " + timeToLog(time.longValue()));
2167e54b42237f749f37f0d920c89f52977871c07004Marie Janssen            }
2168e54b42237f749f37f0d920c89f52977871c07004Marie Janssen
2169a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            String bleAppString = "No BLE Apps registered.";
2170a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            if (mBleApps.size() == 1) {
2171a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                bleAppString = "1 BLE App registered:";
2172a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            } else if (mBleApps.size() > 1) {
2173a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                bleAppString = mBleApps.size() + " BLE Apps registered:";
2174a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            }
2175a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            writer.println("\n" + bleAppString);
21765980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            for (ClientDeathRecipient app : mBleApps.values()) {
2177a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                writer.println("  " + app.getPackageName());
21785980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            }
21795980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
2180a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen            writer.println("");
21815980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            writer.flush();
2182f5ec538f27eb47e545ef06c376078d8ee3f35a72Marie Janssen            if (args.length == 0) {
2183a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                // Add arg to produce output
2184a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                args = new String[1];
2185a95924da5706c25156c5c1cd56cf7beb537d025aMarie Janssen                args[0] = "--print";
2186f5ec538f27eb47e545ef06c376078d8ee3f35a72Marie Janssen            }
21875980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen        }
21885980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen
21896e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov        if (mBluetoothBinder == null) {
21906e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov            errorMsg = "Bluetooth Service not connected";
21916e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov        } else {
21926e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov            try {
21936e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov                mBluetoothBinder.dump(fd, args);
21946e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov            } catch (RemoteException re) {
21955980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen                errorMsg = "RemoteException while dumping Bluetooth Service";
21966e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov            }
21976e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov        }
21986e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov        if (errorMsg != null) {
21996e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov            // Silently return if we are extracting metrics in Protobuf format
22005980456040217f330289e3fa59df4efaafb1c6c5Marie Janssen            if (protoOut) return;
22016e8fafff7731e6a2c13342eebc9b5078b7d5021fPavlin Radoslavov            writer.println(errorMsg);
2202726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood        }
2203726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    }
22040f42037eb7b5118015c2caca635538324ccf0ccffredc}
2205