Merge \"Fix unsafe concurrent access in LegacyTypeTracker\" into nyc-mr1-dev

am: 90b2c781ff

Change-Id: I6af8e185a165009f2b7b6efef764c883488bd7bf
This commit is contained in:
Hugo Benichi
2016-06-27 08:02:44 +00:00
committed by android-build-merger

View File

@@ -487,8 +487,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
* *
* The actual lists are populated when we scan the network types that * The actual lists are populated when we scan the network types that
* are supported on this device. * are supported on this device.
*
* Threading model:
* - addSupportedType() is only called in the constructor
* - add(), update(), remove() are only called from the ConnectivityService handler thread.
* They are therefore not thread-safe with respect to each other.
* - getNetworkForType() can be called at any time on binder threads. It is synchronized
* on mTypeLists to be thread-safe with respect to a concurrent remove call.
* - dump is thread-safe with respect to concurrent add and remove calls.
*/ */
private ArrayList<NetworkAgentInfo> mTypeLists[]; private final ArrayList<NetworkAgentInfo> mTypeLists[];
public LegacyTypeTracker() { public LegacyTypeTracker() {
mTypeLists = (ArrayList<NetworkAgentInfo>[]) mTypeLists = (ArrayList<NetworkAgentInfo>[])
@@ -508,11 +516,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
public NetworkAgentInfo getNetworkForType(int type) { public NetworkAgentInfo getNetworkForType(int type) {
if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) { synchronized (mTypeLists) {
return mTypeLists[type].get(0); if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
} else { return mTypeLists[type].get(0);
return null; }
} }
return null;
} }
private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
@@ -535,12 +544,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (list.contains(nai)) { if (list.contains(nai)) {
return; return;
} }
synchronized (mTypeLists) {
list.add(nai); list.add(nai);
}
// Send a broadcast if this is the first network of its type or if it's the default. // Send a broadcast if this is the first network of its type or if it's the default.
final boolean isDefaultNetwork = isDefaultNetwork(nai); final boolean isDefaultNetwork = isDefaultNetwork(nai);
if (list.size() == 1 || isDefaultNetwork) { if ((list.size() == 1) || isDefaultNetwork) {
maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork); maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type); sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
} }
@@ -552,11 +562,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (list == null || list.isEmpty()) { if (list == null || list.isEmpty()) {
return; return;
} }
final boolean wasFirstNetwork = list.get(0).equals(nai); final boolean wasFirstNetwork = list.get(0).equals(nai);
if (!list.remove(nai)) { synchronized (mTypeLists) {
return; if (!list.remove(nai)) {
return;
}
} }
final DetailedState state = DetailedState.DISCONNECTED; final DetailedState state = DetailedState.DISCONNECTED;
@@ -591,8 +602,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (int type = 0; type < mTypeLists.length; type++) { for (int type = 0; type < mTypeLists.length; type++) {
final ArrayList<NetworkAgentInfo> list = mTypeLists[type]; final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
final boolean contains = (list != null && list.contains(nai)); final boolean contains = (list != null && list.contains(nai));
final boolean isFirst = (list != null && list.size() > 0 && nai == list.get(0)); final boolean isFirst = contains && (nai == list.get(0));
if (isFirst || (contains && isDefault)) { if (isFirst || contains && isDefault) {
maybeLogBroadcast(nai, state, type, isDefault); maybeLogBroadcast(nai, state, type, isDefault);
sendLegacyNetworkBroadcast(nai, state, type); sendLegacyNetworkBroadcast(nai, state, type);
} }
@@ -617,10 +628,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println(); pw.println();
pw.println("Current state:"); pw.println("Current state:");
pw.increaseIndent(); pw.increaseIndent();
for (int type = 0; type < mTypeLists.length; type++) { synchronized (mTypeLists) {
if (mTypeLists[type] == null|| mTypeLists[type].size() == 0) continue; for (int type = 0; type < mTypeLists.length; type++) {
for (NetworkAgentInfo nai : mTypeLists[type]) { if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
pw.println(type + " " + naiToString(nai)); for (NetworkAgentInfo nai : mTypeLists[type]) {
pw.println(type + " " + naiToString(nai));
}
} }
} }
pw.decreaseIndent(); pw.decreaseIndent();