resolve merge conflicts of c816141 to nyc-mr1-dev-plus-aosp

am: 07e590a574

Change-Id: I49fd2c3ed7ac5cbdf102ec289235b1fb12bee39a
This commit is contained in:
Marie Janssen
2016-12-29 23:45:39 +00:00
committed by android-build-merger
3 changed files with 160 additions and 124 deletions

View File

@@ -680,30 +680,7 @@ public final class BluetoothAdapter {
} }
/** /**
* Performs action based on user action to turn BT ON * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
* 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().
* *
* <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
* to STATE_OFF and completely shut-down Bluetooth * to STATE_OFF and completely shut-down Bluetooth
@@ -733,61 +710,50 @@ public final class BluetoothAdapter {
if (!isBleScanAlwaysAvailable()) return false; if (!isBleScanAlwaysAvailable()) return false;
int state = getLeState(); int state = getLeState();
if (state == BluetoothAdapter.STATE_ON) { if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
if (DBG) Log.d (TAG, "STATE_ON: shouldn't disable"); String packageName = ActivityThread.currentPackageName();
if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName);
try { try {
mManagerService.updateBleAppCount(mToken, false); mManagerService.updateBleAppCount(mToken, false, packageName);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); Log.e(TAG, "", e);
} }
return true; 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; return false;
} }
/** /**
* Special Applications who want to only turn on Bluetooth Low Energy (BLE) would * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
* 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.
* *
* <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} * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
* to be notified of subsequent adapter state changes. If this call returns * to be notified of adapter state changes.
* true, then the adapter state will immediately transition from {@link *
* #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, and some time * If this call returns * true, then the adapter state is either in a mode where
* later transition to either {@link #STATE_OFF} or {@link * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
* #STATE_BLE_ON}. If this call returns false then there was an * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
* immediate problem that will prevent the adapter from being turned on - *
* such as Airplane mode, or the adapter is already turned on. * If this call returns false then there was an immediate problem that prevents the
* (@link #ACTION_BLE_STATE_CHANGED) returns the Bluetooth Adapter's various * 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 * states, It includes all the classic Bluetooth Adapter states along with
* internal BLE only states * 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 * immediate error
* @hide * @hide
*/ */
@@ -796,13 +762,14 @@ public final class BluetoothAdapter {
if (!isBleScanAlwaysAvailable()) return false; if (!isBleScanAlwaysAvailable()) return false;
try { try {
mManagerService.updateBleAppCount(mToken, true); String packageName = ActivityThread.currentPackageName();
mManagerService.updateBleAppCount(mToken, true, packageName);
if (isLeEnabled()) { if (isLeEnabled()) {
if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled"); if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled");
return true; return true;
} }
if (DBG) Log.d(TAG, "enableBLE(): Calling enable"); if (DBG) Log.d(TAG, "enableBLE(): Calling enable");
return mManagerService.enable(ActivityThread.currentPackageName()); return mManagerService.enable(packageName);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); Log.e(TAG, "", e);
} }
@@ -1940,9 +1907,6 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.MAP_CLIENT) { } else if (profile == BluetoothProfile.MAP_CLIENT) {
BluetoothMapClient mapClient = new BluetoothMapClient(context, listener); BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
return true; return true;
} else if (profile == BluetoothProfile.INPUT_HOST) {
BluetoothInputHost iHost = new BluetoothInputHost(context, listener);
return true;
} else { } else {
return false; return false;
} }
@@ -2019,10 +1983,6 @@ public final class BluetoothAdapter {
BluetoothMapClient mapClient = (BluetoothMapClient)proxy; BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
mapClient.close(); mapClient.close();
break; break;
case BluetoothProfile.INPUT_HOST:
BluetoothInputHost iHost = (BluetoothInputHost) proxy;
iHost.close();
break;
} }
} }
@@ -2094,7 +2054,7 @@ public final class BluetoothAdapter {
return true; return true;
} }
try { try {
return mManagerService.enableNoAutoConnect(); return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);} } catch (RemoteException e) {Log.e(TAG, "", e);}
return false; return false;
} }

View File

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

View File

@@ -57,14 +57,16 @@ import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException;
import android.util.Slog; import android.util.Slog;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map; import java.util.Map;
class BluetoothManagerService extends IBluetoothManager.Stub { class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService"; private static final String TAG = "BluetoothManagerService";
private static final boolean DBG = true; private static final boolean DBG = true;
@@ -137,16 +139,46 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
new ReentrantReadWriteLock(); new ReentrantReadWriteLock();
private boolean mBinding; private boolean mBinding;
private boolean mUnbinding; private boolean mUnbinding;
// used inside handler thread // used inside handler thread
private boolean mQuietEnable = false; 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. // synchronize with broadcast receiver.
private boolean mQuietEnableExternal; private boolean mQuietEnableExternal;
// configuarion from external IBinder call which is used to
// synchronize with broadcast receiver.
private boolean mEnableExternal; 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 int mState;
private final BluetoothHandler mHandler; private final BluetoothHandler mHandler;
private int mErrorRecoveryRetryCounter; private int mErrorRecoveryRetryCounter;
@@ -172,7 +204,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} }
} }
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
@Override @Override
public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
@@ -252,12 +284,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} else if (st == BluetoothAdapter.STATE_ON){ } else if (st == BluetoothAdapter.STATE_ON){
// disable without persisting the setting // disable without persisting the setting
Slog.d(TAG, "Calling disable"); Slog.d(TAG, "Calling disable");
sendDisableMsg(); sendDisableMsg("airplane mode");
} }
} else if (mEnableExternal) { } else if (mEnableExternal) {
// enable without persisting the setting // enable without persisting the setting
Slog.d(TAG, "Calling enable"); Slog.d(TAG, "Calling enable");
sendEnableMsg(mQuietEnableExternal); sendEnableMsg(mQuietEnableExternal, "airplane mode");
} }
} }
} }
@@ -273,6 +305,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|| context.getResources().getBoolean( || context.getResources().getBoolean(
com.android.internal.R.bool.config_permissionReviewRequired); com.android.internal.R.bool.config_permissionReviewRequired);
mActiveLogs = new LinkedList<ActiveLog>();
mBluetooth = null; mBluetooth = null;
mBluetoothBinder = null; mBluetoothBinder = null;
mBluetoothGatt = null; mBluetoothGatt = null;
@@ -300,15 +333,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mEnableExternal = true; mEnableExternal = true;
} }
int sysUiUid = -1; int systemUiUid = -1;
try { try {
sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
// Some platforms, such as wearables do not have a system ui. // Some platforms, such as wearables do not have a system ui.
Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
} }
mSystemUiUid = sysUiUid; mSystemUiUid = systemUiUid;
} }
/** /**
@@ -488,8 +521,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} }
class ClientDeathRecipient implements IBinder.DeathRecipient { class ClientDeathRecipient implements IBinder.DeathRecipient {
private String mPackageName;
public ClientDeathRecipient(String packageName) {
mPackageName = packageName;
}
public void binderDied() { 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()) { if (isBleAppPresent()) {
// Nothing to do, another app is here. // Nothing to do, another app is here.
return; return;
@@ -508,10 +547,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mBluetoothLock.readLock().unlock(); mBluetoothLock.readLock().unlock();
} }
} }
}
/** Internal death rec list */ public String getPackageName() {
Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>(); return mPackageName;
}
}
@Override @Override
public boolean isBleScanAlwaysAvailable() { public boolean isBleScanAlwaysAvailable() {
@@ -569,28 +609,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} }
} }
public int updateBleAppCount(IBinder token, boolean enable) { public int updateBleAppCount(IBinder token, boolean enable, String packageName) {
if (enable) { ClientDeathRecipient r = mBleApps.get(token);
ClientDeathRecipient r = mBleApps.get(token); if (r == null && enable) {
if (r == null) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
ClientDeathRecipient deathRec = new ClientDeathRecipient(); try {
try { token.linkToDeath(deathRec, 0);
token.linkToDeath(deathRec, 0); } catch (RemoteException ex) {
} catch (RemoteException ex) { throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
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");
} }
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(); int appCount = mBleApps.size();
if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); if (DBG) Slog.d(TAG, appCount + " registered Ble Apps");
@@ -605,7 +639,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mBleApps.clear(); mBleApps.clear();
} }
/** @hide*/ /** @hide */
public boolean isBleAppPresent() { public boolean isBleAppPresent() {
if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
return mBleApps.size() > 0; return mBleApps.size() > 0;
@@ -671,7 +705,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} }
} }
public boolean enableNoAutoConnect() public boolean enableNoAutoConnect(String packageName)
{ {
if (isBluetoothDisallowed()) { if (isBluetoothDisallowed()) {
if (DBG) { if (DBG) {
@@ -696,7 +730,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
synchronized(mReceiver) { synchronized(mReceiver) {
mQuietEnableExternal = true; mQuietEnableExternal = true;
mEnableExternal = true; mEnableExternal = true;
sendEnableMsg(true); sendEnableMsg(true, packageName);
} }
return true; return true;
} }
@@ -729,7 +763,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} }
if (DBG) { if (DBG) {
Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + Slog.d(TAG,"enable(" + packageName + "): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding + " mState = " + " mBinding = " + mBinding + " mState = " +
BluetoothAdapter.nameForState(mState)); BluetoothAdapter.nameForState(mState));
} }
@@ -738,7 +772,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mQuietEnableExternal = false; mQuietEnableExternal = false;
mEnableExternal = true; mEnableExternal = true;
// waive WRITE_SECURE_SETTINGS permission check // waive WRITE_SECURE_SETTINGS permission check
sendEnableMsg(false); sendEnableMsg(false, packageName);
} }
if (DBG) Slog.d(TAG, "enable returning"); if (DBG) Slog.d(TAG, "enable returning");
return true; return true;
@@ -774,7 +808,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
persistBluetoothSetting(BLUETOOTH_OFF); persistBluetoothSetting(BLUETOOTH_OFF);
} }
mEnableExternal = false; mEnableExternal = false;
sendDisableMsg(); sendDisableMsg(packageName);
} }
return true; return true;
} }
@@ -919,7 +953,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} }
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal); sendEnableMsg(mQuietEnableExternal, "system boot");
} else if (!isNameAndAddressSet()) { } else if (!isNameAndAddressSet()) {
if (DBG) Slog.d(TAG, "Getting adapter name and address"); if (DBG) Slog.d(TAG, "Getting adapter name and address");
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
@@ -1887,13 +1921,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
return false; return false;
} }
private void sendDisableMsg() { private void sendDisableMsg(String packageName) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 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, mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0)); 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) { private void recoverBluetoothServiceFromError(boolean clearBle) {
@@ -1964,19 +2009,50 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
String errorMsg = null; 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) { if (mBluetoothBinder == null) {
errorMsg = "Bluetooth Service not connected"; errorMsg = "Bluetooth Service not connected";
} else { } else {
try { try {
mBluetoothBinder.dump(fd, args); mBluetoothBinder.dump(fd, args);
} catch (RemoteException re) { } catch (RemoteException re) {
errorMsg = "RemoteException while calling Bluetooth Service"; errorMsg = "RemoteException while dumping Bluetooth Service";
} }
} }
if (errorMsg != null) { if (errorMsg != null) {
// Silently return if we are extracting metrics in Protobuf format // Silently return if we are extracting metrics in Protobuf format
if ((args.length > 0) && args[0].startsWith("--proto")) if (protoOut) return;
return;
writer.println(errorMsg); writer.println(errorMsg);
} }
} }