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