resolve merge conflicts of 9cc7ebe to stage-aosp-master

Change-Id: Ia1cdf49d77a574c38ed5cc33c31d5cf930103484
This commit is contained in:
Marie Janssen
2016-12-29 12:16:34 -08:00
4 changed files with 265 additions and 145 deletions

View File

@@ -23,6 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
@@ -271,6 +272,29 @@ public final class BluetoothAdapter {
public static final String ACTION_REQUEST_ENABLE =
"android.bluetooth.adapter.action.REQUEST_ENABLE";
/**
* Activity Action: Show a system activity that allows the user to turn off
* Bluetooth. This is used only if permission review is enabled which is for
* apps targeting API less than 23 require a permission review before any of
* the app's components can run.
* <p>This system activity will return once Bluetooth has completed turning
* off, or the user has decided not to turn Bluetooth off.
* <p>Notification of the result of this activity is posted using the
* {@link android.app.Activity#onActivityResult} callback. The
* <code>resultCode</code>
* will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
* turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
* has rejected the request or an error has occurred.
* <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
* for global notification whenever Bluetooth is turned on or off.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_REQUEST_DISABLE =
"android.bluetooth.adapter.action.REQUEST_DISABLE";
/**
* Activity Action: Show a system activity that allows user to enable BLE scans even when
* Bluetooth is turned off.<p>
@@ -656,30 +680,7 @@ public final class BluetoothAdapter {
}
/**
* Performs action based on user action to turn BT ON
* or OFF if BT is in BLE_ON state
*/
private void notifyUserAction(boolean enable) {
try {
mServiceLock.readLock().lock();
if (mService == null) {
Log.e(TAG, "mService is null");
return;
}
if (enable) {
mService.onLeServiceUp(); //NA:TODO implementation pending
} else {
mService.onBrEdrDown(); //NA:TODO implementation pending
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
} finally {
mServiceLock.readLock().unlock();
}
}
/**
* Turns off Bluetooth LE which was earlier turned on by calling EnableBLE().
* Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
*
* <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
* to STATE_OFF and completely shut-down Bluetooth
@@ -709,61 +710,50 @@ public final class BluetoothAdapter {
if (!isBleScanAlwaysAvailable()) return false;
int state = getLeState();
if (state == BluetoothAdapter.STATE_ON) {
if (DBG) Log.d (TAG, "STATE_ON: shouldn't disable");
if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
String packageName = ActivityThread.currentPackageName();
if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName);
try {
mManagerService.updateBleAppCount(mToken, false);
mManagerService.updateBleAppCount(mToken, false, packageName);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return true;
} else if (state == BluetoothAdapter.STATE_BLE_ON) {
if (DBG) Log.d (TAG, "STATE_BLE_ON");
int bleAppCnt = 0;
try {
bleAppCnt = mManagerService.updateBleAppCount(mToken, false);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
if (bleAppCnt == 0) {
// Disable only if there are no other clients
notifyUserAction(false);
}
return true;
}
if (DBG) Log.d (TAG, "STATE_OFF: Already disabled");
if (DBG) Log.d (TAG, "disableBLE(): Already disabled");
return false;
}
/**
* Special Applications who want to only turn on Bluetooth Low Energy (BLE) would
* EnableBLE, EnableBLE brings-up Bluetooth so that application can access
* only LE related feature (Bluetooth GATT layers interfaces using the respective class)
* EnableBLE in turn registers the existance of a special App which wants to
* turn on Bluetooth Low enrgy part without making it visible at the settings UI
* as Bluetooth ON.
* <p>Invoking EnableBLE when Bluetooth is already in ON state, would just registers
* the existance of special Application and doesn't do anything to current BT state.
* when user turn OFF Bluetooth from UI, if there is an existance of special app, Bluetooth
* would stay in BLE_ON state so that LE features are still acessible to the special
* Applications.
* Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
*
* <p>This is an asynchronous call: it will return immediately, and
* enableBLE registers the existence of an app using only LE functions.
*
* enableBLE may enable Bluetooth to an LE only mode so that an app can use
* LE related features (BluetoothGatt or BluetoothGattServer classes)
*
* If the user disables Bluetooth while an app is registered to use LE only features,
* Bluetooth will remain on in LE only mode for the app.
*
* When Bluetooth is in LE only mode, it is not shown as ON to the UI.
*
* <p>This is an asynchronous call: it returns immediately, and
* clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
* to be notified of subsequent adapter state changes. If this call returns
* true, then the adapter state will immediately transition from {@link
* #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, and some time
* later transition to either {@link #STATE_OFF} or {@link
* #STATE_BLE_ON}. If this call returns false then there was an
* immediate problem that will prevent the adapter from being turned on -
* such as Airplane mode, or the adapter is already turned on.
* (@link #ACTION_BLE_STATE_CHANGED) returns the Bluetooth Adapter's various
* to be notified of adapter state changes.
*
* If this call returns * true, then the adapter state is either in a mode where
* LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
* and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
*
* If this call returns false then there was an immediate problem that prevents the
* adapter from being turned on - such as Airplane mode.
*
* {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
* states, It includes all the classic Bluetooth Adapter states along with
* internal BLE only states
*
* @return true to indicate Bluetooth LE start-up has begun, or false on
* @return true to indicate Bluetooth LE will be available, or false on
* immediate error
* @hide
*/
@@ -772,13 +762,14 @@ public final class BluetoothAdapter {
if (!isBleScanAlwaysAvailable()) return false;
try {
mManagerService.updateBleAppCount(mToken, true);
String packageName = ActivityThread.currentPackageName();
mManagerService.updateBleAppCount(mToken, true, packageName);
if (isLeEnabled()) {
if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled");
return true;
}
if (DBG) Log.d(TAG, "enableBLE(): Calling enable");
return mManagerService.enable();
return mManagerService.enable(packageName);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -905,7 +896,7 @@ public final class BluetoothAdapter {
return true;
}
try {
return mManagerService.enable();
return mManagerService.enable(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -937,7 +928,7 @@ public final class BluetoothAdapter {
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean disable() {
try {
return mManagerService.disable(true);
return mManagerService.disable(ActivityThread.currentPackageName(), true);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -955,7 +946,7 @@ public final class BluetoothAdapter {
public boolean disable(boolean persist) {
try {
return mManagerService.disable(persist);
return mManagerService.disable(ActivityThread.currentPackageName(), persist);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -1916,9 +1907,6 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.MAP_CLIENT) {
BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
return true;
} else if (profile == BluetoothProfile.INPUT_HOST) {
BluetoothInputHost iHost = new BluetoothInputHost(context, listener);
return true;
} else {
return false;
}
@@ -1995,10 +1983,6 @@ public final class BluetoothAdapter {
BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
mapClient.close();
break;
case BluetoothProfile.INPUT_HOST:
BluetoothInputHost iHost = (BluetoothInputHost) proxy;
iHost.close();
break;
}
}
@@ -2070,7 +2054,7 @@ public final class BluetoothAdapter {
return true;
}
try {
return mManagerService.enableNoAutoConnect();
return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}

View File

@@ -34,9 +34,9 @@ interface IBluetoothManager
void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
boolean isEnabled();
boolean enable();
boolean enableNoAutoConnect();
boolean disable(boolean persist);
boolean enable(String packageName);
boolean enableNoAutoConnect(String packageName);
boolean disable(String packageName, boolean persist);
int getState();
IBluetoothGatt getBluetoothGatt();
@@ -47,6 +47,6 @@ interface IBluetoothManager
String getName();
boolean isBleScanAlwaysAvailable();
int updateBleAppCount(IBinder b, boolean enable);
int updateBleAppCount(IBinder b, boolean enable, String packageName);
boolean isBleAppPresent();
}

View File

@@ -35,11 +35,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Bundle;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -55,14 +57,16 @@ import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService";
private static final boolean DBG = true;
@@ -135,16 +139,46 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
new ReentrantReadWriteLock();
private boolean mBinding;
private boolean mUnbinding;
// used inside handler thread
private boolean mQuietEnable = false;
// configuarion from external IBinder call which is used to
private boolean mEnable;
/**
* Used for tracking apps that enabled / disabled Bluetooth.
*/
private class ActiveLog {
private String mPackageName;
private boolean mEnable;
private long mTimestamp;
public ActiveLog(String packageName, boolean enable, long timestamp) {
mPackageName = packageName;
mEnable = enable;
mTimestamp = timestamp;
}
public long getTime() {
return mTimestamp;
}
public String toString() {
return android.text.format.DateFormat.format("MM-dd hh:mm:ss ", mTimestamp) +
(mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName;
}
}
private LinkedList<ActiveLog> mActiveLogs;
// configuration from external IBinder call which is used to
// synchronize with broadcast receiver.
private boolean mQuietEnableExternal;
// configuarion from external IBinder call which is used to
// synchronize with broadcast receiver.
private boolean mEnableExternal;
// used inside handler thread
private boolean mEnable;
// Map of apps registered to keep BLE scanning on.
private Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
private int mState;
private final BluetoothHandler mHandler;
private int mErrorRecoveryRetryCounter;
@@ -155,6 +189,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private final Map <Integer, ProfileServiceConnections> mProfileServices =
new HashMap <Integer, ProfileServiceConnections>();
private final boolean mPermissionReviewRequired;
private void registerForAirplaneMode(IntentFilter filter) {
final ContentResolver resolver = mContext.getContentResolver();
final String airplaneModeRadios = Settings.Global.getString(resolver,
@@ -168,7 +204,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
}
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
@Override
public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
@@ -184,7 +220,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
final boolean bluetoothDisallowed =
newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
if ((mEnable || mEnableExternal) && bluetoothDisallowed) {
disable(true);
try {
disable("android.os.UserManagerInternal", true);
} catch (RemoteException e) {
// Shouldn't happen: startConsentUiIfNeeded not called
// when from system.
}
}
}
};
@@ -242,12 +283,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} else if (st == BluetoothAdapter.STATE_ON){
// disable without persisting the setting
Slog.d(TAG, "Calling disable");
sendDisableMsg();
sendDisableMsg("airplane mode");
}
} else if (mEnableExternal) {
// enable without persisting the setting
Slog.d(TAG, "Calling enable");
sendEnableMsg(mQuietEnableExternal);
sendEnableMsg(mQuietEnableExternal, "airplane mode");
}
}
}
@@ -258,6 +299,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mHandler = new BluetoothHandler(IoThread.get().getLooper());
mContext = context;
mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED
|| context.getResources().getBoolean(
com.android.internal.R.bool.config_permissionReviewRequired);
mActiveLogs = new LinkedList<ActiveLog>();
mBluetooth = null;
mBluetoothBinder = null;
mBluetoothGatt = null;
@@ -284,15 +331,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mEnableExternal = true;
}
int sysUiUid = -1;
int systemUiUid = -1;
try {
sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
} catch (PackageManager.NameNotFoundException e) {
// Some platforms, such as wearables do not have a system ui.
Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
}
mSystemUiUid = sysUiUid;
mSystemUiUid = systemUiUid;
}
/**
@@ -470,8 +517,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
class ClientDeathRecipient implements IBinder.DeathRecipient {
private String mPackageName;
public ClientDeathRecipient(String packageName) {
mPackageName = packageName;
}
public void binderDied() {
if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App");
if (DBG) Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
if (isBleAppPresent()) {
// Nothing to do, another app is here.
return;
@@ -490,10 +543,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mBluetoothLock.readLock().unlock();
}
}
}
/** Internal death rec list */
Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
public String getPackageName() {
return mPackageName;
}
}
@Override
public boolean isBleScanAlwaysAvailable() {
@@ -551,28 +605,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
}
public int updateBleAppCount(IBinder token, boolean enable) {
if (enable) {
ClientDeathRecipient r = mBleApps.get(token);
if (r == null) {
ClientDeathRecipient deathRec = new ClientDeathRecipient();
try {
token.linkToDeath(deathRec, 0);
} catch (RemoteException ex) {
throw new IllegalArgumentException("Wake lock is already dead.");
}
mBleApps.put(token, deathRec);
if (DBG) Slog.d(TAG, "Registered for death Notification");
}
} else {
ClientDeathRecipient r = mBleApps.get(token);
if (r != null) {
// Unregister death recipient as the app goes away.
token.unlinkToDeath(r, 0);
mBleApps.remove(token);
if (DBG) Slog.d(TAG, "Unregistered for death Notification");
public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
ClientDeathRecipient r = mBleApps.get(token);
if (r == null && enable) {
ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
try {
token.linkToDeath(deathRec, 0);
} catch (RemoteException ex) {
throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
}
mBleApps.put(token, deathRec);
if (DBG) Slog.d(TAG, "Registered for death of " + packageName);
} else if (!enable && r != null) {
// Unregister death recipient as the app goes away.
token.unlinkToDeath(r, 0);
mBleApps.remove(token);
if (DBG) Slog.d(TAG, "Unregistered for death of " + packageName);
}
int appCount = mBleApps.size();
if (DBG) Slog.d(TAG, appCount + " registered Ble Apps");
@@ -587,7 +635,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mBleApps.clear();
}
/** @hide*/
/** @hide */
public boolean isBleAppPresent() {
if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
return mBleApps.size() > 0;
@@ -653,7 +701,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
}
public boolean enableNoAutoConnect()
public boolean enableNoAutoConnect(String packageName)
{
if (isBluetoothDisallowed()) {
if (DBG) {
@@ -678,12 +726,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
synchronized(mReceiver) {
mQuietEnableExternal = true;
mEnableExternal = true;
sendEnableMsg(true);
sendEnableMsg(true, packageName);
}
return true;
}
public boolean enable() {
public boolean enable(String packageName) throws RemoteException {
if (isBluetoothDisallowed()) {
if (DBG) {
Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
@@ -691,16 +739,27 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
return false;
}
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
Slog.w(TAG,"enable(): not allowed for non-active and non system user");
return false;
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
Slog.w(TAG, "enable(): not allowed for non-active and non system user");
return false;
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (!isEnabled() && mPermissionReviewRequired
&& startConsentUiIfNeeded(packageName, callingUid,
BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
return false;
}
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (DBG) {
Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth +
Slog.d(TAG,"enable(" + packageName + "): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding + " mState = " +
BluetoothAdapter.nameForState(mState));
}
@@ -709,20 +768,30 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mQuietEnableExternal = false;
mEnableExternal = true;
// waive WRITE_SECURE_SETTINGS permission check
sendEnableMsg(false);
sendEnableMsg(false, packageName);
}
if (DBG) Slog.d(TAG, "enable returning");
return true;
}
public boolean disable(boolean persist) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
public boolean disable(String packageName, boolean persist) throws RemoteException {
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
Slog.w(TAG,"disable(): not allowed for non-active and non system user");
return false;
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
Slog.w(TAG, "disable(): not allowed for non-active and non system user");
return false;
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (isEnabled() && mPermissionReviewRequired
&& startConsentUiIfNeeded(packageName, callingUid,
BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
return false;
}
}
if (DBG) {
@@ -735,11 +804,36 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
persistBluetoothSetting(BLUETOOTH_OFF);
}
mEnableExternal = false;
sendDisableMsg();
sendDisableMsg(packageName);
}
return true;
}
private boolean startConsentUiIfNeeded(String packageName,
int callingUid, String intentAction) throws RemoteException {
try {
// Validate the package only if we are going to use it
ApplicationInfo applicationInfo = mContext.getPackageManager()
.getApplicationInfoAsUser(packageName,
PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.getUserId(callingUid));
if (applicationInfo.uid != callingUid) {
throw new SecurityException("Package " + callingUid
+ " not in uid " + callingUid);
}
// Legacy apps in permission review mode trigger a user prompt
if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
Intent intent = new Intent(intentAction);
mContext.startActivity(intent);
return true;
}
} catch (PackageManager.NameNotFoundException e) {
throw new RemoteException(e.getMessage());
}
return false;
}
public void unbindAndFinish() {
if (DBG) {
Slog.d(TAG,"unbindAndFinish(): " + mBluetooth +
@@ -855,7 +949,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal);
sendEnableMsg(mQuietEnableExternal, "system boot");
} else if (!isNameAndAddressSet()) {
if (DBG) Slog.d(TAG, "Getting adapter name and address");
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
@@ -1823,13 +1917,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
return false;
}
private void sendDisableMsg() {
private void sendDisableMsg(String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
addActiveLog(packageName, false);
}
private void sendEnableMsg(boolean quietMode) {
private void sendEnableMsg(boolean quietMode, String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0));
addActiveLog(packageName, true);
}
private void addActiveLog(String packageName, boolean enable) {
synchronized (mActiveLogs) {
if (mActiveLogs.size() > 10) {
mActiveLogs.remove();
}
mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
}
}
private void recoverBluetoothServiceFromError(boolean clearBle) {
@@ -1900,19 +2005,50 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
String errorMsg = null;
boolean protoOut = (args.length > 0) && args[0].startsWith("--proto");
if (!protoOut) {
writer.println("Bluetooth Status");
writer.println(" enabled: " + isEnabled());
writer.println(" state: " + BluetoothAdapter.nameForState(mState));
writer.println(" address: " + mAddress);
writer.println(" name: " + mName);
if (mEnable) {
long onDuration = System.currentTimeMillis() - mActiveLogs.getLast().getTime();
String onDurationString = String.format("%02d:%02d:%02d.%03d",
(int)(onDuration / (1000 * 60 * 60)),
(int)((onDuration / (1000 * 60)) % 60),
(int)((onDuration / 1000) % 60),
(int)(onDuration % 1000));
writer.println(" time since enabled: " + onDurationString + "\n");
}
writer.println("Enable log:");
for (ActiveLog log : mActiveLogs) {
writer.println(log);
}
writer.println("\n" + mBleApps.size() + " BLE Apps registered:");
for (ClientDeathRecipient app : mBleApps.values()) {
writer.println(app.getPackageName());
}
writer.flush();
}
if (mBluetoothBinder == null) {
errorMsg = "Bluetooth Service not connected";
} else {
try {
mBluetoothBinder.dump(fd, args);
} catch (RemoteException re) {
errorMsg = "RemoteException while calling Bluetooth Service";
errorMsg = "RemoteException while dumping Bluetooth Service";
}
}
if (errorMsg != null) {
// Silently return if we are extracting metrics in Protobuf format
if ((args.length > 0) && args[0].startsWith("--proto"))
return;
if (protoOut) return;
writer.println(errorMsg);
}
}

View File

@@ -547,7 +547,7 @@ public final class ShutdownThread extends Thread {
bluetooth.getState() == BluetoothAdapter.STATE_OFF;
if (!bluetoothOff) {
Log.w(TAG, "Disabling Bluetooth...");
bluetooth.disable(false); // disable but don't persist new state
bluetooth.disable(mContext.getPackageName(), false); // disable but don't persist new state
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during bluetooth shutdown", ex);