Merge "add bootchart and systrace support to bootanalyze" into oc-dev
diff --git a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
index 072e2d6..4cdb640 100644
--- a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
+++ b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
@@ -652,6 +652,9 @@
// profile. When unpaired, we remove the device from all of the profiles' device list.
if (bondState == BluetoothDevice.BOND_NONE) {
for (Integer profile : mProfilesToConnect) {
+ if (DBG) {
+ Log.d(TAG, "Removing " + device + " from profile: " + profile);
+ }
removeDeviceFromProfile(device, profile);
}
}
@@ -1071,6 +1074,8 @@
}
for (BluetoothDevicesInfo devInfo : mProfileToConnectableDevicesMap.values()) {
writer.print("Profile: " + devInfo.getProfileLocked() + "\t");
+ writer.print(
+ "Num of Paired devices: " + devInfo.getNumberOfPairedDevicesLocked() + "\t");
writer.print("Active Connections: " + devInfo.getNumberOfActiveConnectionsLocked());
writer.println();
List<BluetoothDevicesInfo.DeviceInfo> deviceInfoList = devInfo.getDeviceInfoList();
diff --git a/service/src/com/android/car/BluetoothDevicesInfo.java b/service/src/com/android/car/BluetoothDevicesInfo.java
index eb77aad..a383f04 100644
--- a/service/src/com/android/car/BluetoothDevicesInfo.java
+++ b/service/src/com/android/car/BluetoothDevicesInfo.java
@@ -16,6 +16,7 @@
package com.android.car;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
@@ -27,7 +28,7 @@
/**
* BluetoothDevicesInfo contains all the information pertinent to connection on a Bluetooth Profile.
* It holds
- * 1. a list of devices {@link #mDeviceList} that has previously paired and connected on this
+ * 1. a list of devices {@link #mDeviceInfoList} that has previously paired and connected on this
* profile.
* 2. a Connection Info object {@link #mConnectionInfo} that has following book keeping information:
* a) profile
@@ -46,7 +47,6 @@
private static final String TAG = "CarBluetoothDevicesInfo";
private static final boolean DBG = false;
private final int DEVICE_NOT_FOUND = -1;
-
// The device list and the connection state information together have all the information
// that is required to know which device(s) to connect to, when we need to connect/
private List<DeviceInfo> mDeviceInfoList;
@@ -56,14 +56,20 @@
* This class holds on to information regarding this bluetooth profile's connection state.
*/
private class ConnectionInfo {
-
- int mProfile; // which bluetooth profile this Device Info is for
- boolean mDeviceAvailableToConnect; // known devices available to connect on this profile.
- int mDeviceIndex; // position of this device in the device List.
- int mNumPairedDevices; // Number of paired & connected devices for this profile
- int mRetryAttempt; // Connection Retry counter
- int mNumActiveConnections; // Current number of active connections on this profile
- int mNumConnectionsSupported; // number of concurrent active connections supported.
+ // which bluetooth profile this Device Info is for
+ private int mProfile;
+ // are there any devices available to connect. It is false either if
+ // 1. no device has been paired to connect on this profile
+ // 2. all paired devices have been tried to connect to, but unsuccessful (not in range etc)
+ private boolean mDeviceAvailableToConnect;
+ // index of device in the mDeviceInfoList that the next connection attempt should be made
+ private int mDeviceIndex;
+ // Connection Retry counter
+ private int mRetryAttempt;
+ // Current number of active connections on this profile
+ private int mNumActiveConnections;
+ // number of concurrent active connections supported.
+ private int mNumConnectionsSupported;
public ConnectionInfo(int profile) {
// Default the number of concurrent active connections supported to 1.
@@ -79,7 +85,6 @@
private void initConnectionInfo() {
mDeviceAvailableToConnect = true;
mDeviceIndex = 0;
- mNumPairedDevices = 0;
mRetryAttempt = 0;
mNumActiveConnections = 0;
}
@@ -164,6 +169,17 @@
return isPresent;
}
+ private DeviceInfo findDeviceInfoInListLocked(@Nullable BluetoothDevice device) {
+ if (device == null) {
+ return null;
+ }
+ for (DeviceInfo devInfo : mDeviceInfoList) {
+ if (devInfo.mBluetoothDevice.getAddress().equals(device.getAddress())) {
+ return devInfo;
+ }
+ }
+ return null;
+ }
/**
* Get the current list of connectable devices for this profile.
*
@@ -198,7 +214,7 @@
// Check if this device is already in the device list
if (checkDeviceInListLocked(dev)) {
if (DBG) {
- Log.d(TAG, "Device " + dev.getName() + "already in list. Not adding");
+ Log.d(TAG, "Device " + dev + " already in list. Not adding");
}
return;
}
@@ -211,14 +227,6 @@
Log.d(TAG, "Device List is null");
}
}
- // Increment the number of paired devices for this profile.
- if (mConnectionInfo != null) {
- mConnectionInfo.mNumPairedDevices++;
- } else {
- if (DBG) {
- Log.d(TAG, "Unexpected: ConnectionInfo is null");
- }
- }
}
/**
@@ -239,7 +247,7 @@
}
if (dev.getAddress().equals(device.getAddress())) {
if (DBG) {
- Log.d(TAG, "Setting " + dev.getName() + " state to " + state);
+ Log.d(TAG, "Setting " + dev + " state to " + state);
}
devInfo.setConnectionState(state);
break;
@@ -280,19 +288,22 @@
*/
public void removeDeviceLocked(BluetoothDevice dev) {
if (mDeviceInfoList != null) {
- mDeviceInfoList.remove(dev);
+ DeviceInfo devInfo = findDeviceInfoInListLocked(dev);
+ if (devInfo != null) {
+ mDeviceInfoList.remove(devInfo);
+ // If the device was connected when it was unpaired, we wouldn't have received the
+ // Profile disconnected intents. Hence check if the device was connected and if it
+ // was, then decrement the number of active connections.
+ if (devInfo.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {
+ mConnectionInfo.mNumActiveConnections--;
+ }
+ }
} else {
if (DBG) {
Log.d(TAG, "Device List is null");
}
}
- if (mConnectionInfo != null) {
- mConnectionInfo.mNumPairedDevices--;
- } else {
- if (DBG) {
- Log.d(TAG, "ConnectionInfo is null");
- }
- }
+ Log.d(TAG, "Device List size: " + mDeviceInfoList.size());
}
public void clearDeviceListLocked() {
@@ -310,21 +321,34 @@
*/
public BluetoothDevice getNextDeviceInQueueLocked() {
BluetoothDevice device = null;
- if (mConnectionInfo.mDeviceIndex >= mConnectionInfo.mNumPairedDevices) {
+ int numberOfPairedDevices = getNumberOfPairedDevicesLocked();
+ if (mConnectionInfo.mDeviceIndex >= numberOfPairedDevices) {
if (DBG) {
Log.d(TAG,
"No device available for profile "
+ mConnectionInfo.mProfile + " "
+ mConnectionInfo.mDeviceIndex + "/"
- + mConnectionInfo.mNumPairedDevices);
+ + numberOfPairedDevices);
}
- mConnectionInfo.mDeviceIndex = 0; //reset the index
+ // mDeviceIndex is the index of the device in the mDeviceInfoList, that the next
+ // connection attempt would be made on. It is moved ahead on
+ // updateConnectionStatusLocked() so it always holds the index of the next device to
+ // connect to. But here, when we get the next device to connect to, if we see that
+ // the index is greater than the number of devices in the list, then we move the index
+ // back to the first device in the list and don't return anything.
+ // The reason why this is reset is to imply that connection attempts on this profile has
+ // been exhausted and if you want to retry connecting on this profile, we will start
+ // from the first device.
+ // The reason to reset here rather than in updateConnectionStatusLocked() is to make
+ // sure we have the latest view of the numberOfPairedDevices before we say we have
+ // exhausted the list.
+ mConnectionInfo.mDeviceIndex = 0;
return null;
}
device = mDeviceInfoList.get(mConnectionInfo.mDeviceIndex).mBluetoothDevice;
if (DBG) {
Log.d(TAG, "Getting device " + mConnectionInfo.mDeviceIndex + " from list: "
- + device.getName());
+ + device);
}
return device;
}
@@ -347,18 +371,18 @@
}
if (success) {
if (DBG) {
- Log.d(TAG, mConnectionInfo.mProfile + " connected to " + device.getName());
+ Log.d(TAG, mConnectionInfo.mProfile + " connected to " + device);
}
// b/34722344 - TODO
// Get the position of this device in the device list maintained for this profile.
int positionInQ = getPositionInListLocked(device);
if (DBG) {
- Log.d(TAG, "Position of " + device.getName() + " in Q: " + positionInQ);
+ Log.d(TAG, "Position of " + device + " in Q: " + positionInQ);
}
// If the device that connected is not in the list, it could be because it is being
// paired and getting added to the device list for this profile for the first time.
if (positionInQ == DEVICE_NOT_FOUND) {
- Log.d(TAG, "Connected device not in Q: " + device.getName());
+ Log.d(TAG, "Connected device not in Q: " + device);
addDeviceLocked(device);
positionInQ = mDeviceInfoList.size() - 1;
} else if (positionInQ != mConnectionInfo.mDeviceIndex) {
@@ -370,7 +394,8 @@
// to remember which devices connected on which profile (regardless of the origin
// of the connection request) so it knows which device to connect the next time.
if (DBG) {
- Log.d(TAG, "Different device connected: " + device.getName());
+ Log.d(TAG, "Different device connected: " + device + " CurrIndex: "
+ + mConnectionInfo.mDeviceIndex);
}
}
@@ -450,8 +475,8 @@
*
* @return number of paired devices on this profile.
*/
- public Integer getNumberOfPairedDevicesLocked() {
- return mConnectionInfo.mNumPairedDevices;
+ public int getNumberOfPairedDevicesLocked() {
+ return mDeviceInfoList.size();
}
/**
@@ -521,13 +546,17 @@
mConnectionInfo.mDeviceIndex = 0;
mConnectionInfo.mRetryAttempt = 0;
mConnectionInfo.mDeviceAvailableToConnect = true;
+ for (DeviceInfo info : mDeviceInfoList) {
+ setConnectionStateLocked(info.getBluetoothDevice(),
+ BluetoothProfile.STATE_DISCONNECTED);
+ }
}
public void resetDeviceListLocked() {
if (mDeviceInfoList != null) {
mDeviceInfoList.clear();
- mConnectionInfo.mNumPairedDevices = 0;
}
resetConnectionInfoLocked();
}
+
}
diff --git a/service/src/com/android/car/PerUserCarServiceHelper.java b/service/src/com/android/car/PerUserCarServiceHelper.java
index db6a10c..73e41cf 100644
--- a/service/src/com/android/car/PerUserCarServiceHelper.java
+++ b/service/src/com/android/car/PerUserCarServiceHelper.java
@@ -27,6 +27,8 @@
import android.os.UserHandle;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.List;
import java.util.ArrayList;
@@ -47,6 +49,9 @@
private UserSwitchBroadcastReceiver mReceiver;
private IntentFilter mUserSwitchFilter;
private static final String EXTRA_USER_HANDLE = "android.intent.extra.user_handle";
+ private final Object mServiceBindLock = new Object();
+ @GuardedBy("mServiceBindLock")
+ private boolean mBound = false;
public PerUserCarServiceHelper(Context context) {
mContext = context;
@@ -164,11 +169,15 @@
Log.d(TAG, "Binding to User service");
}
Intent startIntent = new Intent(mContext, PerUserCarService.class);
- // Try binding - if valid connection not obtained, unbind
- if (!mContext.bindServiceAsUser(startIntent, mUserServiceConnection,
- mContext.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
- Log.e(TAG, "bindToPerUserCarService() failed to get valid connection");
- unbindFromPerUserCarService();
+ synchronized (mServiceBindLock) {
+ mBound = true;
+ boolean bindSuccess = mContext.bindServiceAsUser(startIntent, mUserServiceConnection,
+ mContext.BIND_AUTO_CREATE, UserHandle.CURRENT);
+ // If valid connection not obtained, unbind
+ if (!bindSuccess) {
+ Log.e(TAG, "bindToPerUserCarService() failed to get valid connection");
+ unbindFromPerUserCarService();
+ }
}
}
@@ -176,10 +185,16 @@
* Unbind from the {@link PerUserCarService} running as the Current user.
*/
private void unbindFromPerUserCarService() {
- if (DBG) {
- Log.d(TAG, "Unbinding from User Service");
+ synchronized (mServiceBindLock) {
+ // mBound flag makes sure we are unbinding only when the service is bound.
+ if (mBound) {
+ if (DBG) {
+ Log.d(TAG, "Unbinding from User Service");
+ }
+ mContext.unbindService(mUserServiceConnection);
+ mBound = false;
+ }
}
- mContext.unbindService(mUserServiceConnection);
}
/**