summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2016-07-12 13:08:20 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2016-07-12 13:08:21 +0000
commitee4c8fb9ebfd014fc6bc0fd2cc24ada2c078455e (patch)
treeb9d70ffd007e07b3a52c3703b5549a68ccc4eba3
parent9a3fbe116209a6d44a5f9672a3a249cb8932e3d2 (diff)
parent5224f00b5110e37a288692a3449387aa199a1fc3 (diff)
downloadbase-ee4c8fb9ebfd014fc6bc0fd2cc24ada2c078455e.tar.gz
Merge "Fix unsafe concurrent access in LegacyTypeTracker"
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java47
1 files changed, 30 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 327fb8a7ef2d..7e5cc1231875 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -468,8 +468,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
*
* The actual lists are populated when we scan the network types that
* 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() {
mTypeLists = (ArrayList<NetworkAgentInfo>[])
@@ -489,11 +497,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
public NetworkAgentInfo getNetworkForType(int type) {
- if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
- return mTypeLists[type].get(0);
- } else {
- return null;
+ synchronized (mTypeLists) {
+ if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
+ return mTypeLists[type].get(0);
+ }
}
+ return null;
}
private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
@@ -516,12 +525,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (list.contains(nai)) {
return;
}
-
- list.add(nai);
+ synchronized (mTypeLists) {
+ list.add(nai);
+ }
// Send a broadcast if this is the first network of its type or if it's the default.
final boolean isDefaultNetwork = isDefaultNetwork(nai);
- if (list.size() == 1 || isDefaultNetwork) {
+ if ((list.size() == 1) || isDefaultNetwork) {
maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
}
@@ -533,11 +543,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (list == null || list.isEmpty()) {
return;
}
-
final boolean wasFirstNetwork = list.get(0).equals(nai);
- if (!list.remove(nai)) {
- return;
+ synchronized (mTypeLists) {
+ if (!list.remove(nai)) {
+ return;
+ }
}
final DetailedState state = DetailedState.DISCONNECTED;
@@ -572,8 +583,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (int type = 0; type < mTypeLists.length; type++) {
final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
final boolean contains = (list != null && list.contains(nai));
- final boolean isFirst = (list != null && list.size() > 0 && nai == list.get(0));
- if (isFirst || (contains && isDefault)) {
+ final boolean isFirst = contains && (nai == list.get(0));
+ if (isFirst || contains && isDefault) {
maybeLogBroadcast(nai, state, type, isDefault);
sendLegacyNetworkBroadcast(nai, state, type);
}
@@ -598,10 +609,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println();
pw.println("Current state:");
pw.increaseIndent();
- for (int type = 0; type < mTypeLists.length; type++) {
- if (mTypeLists[type] == null|| mTypeLists[type].size() == 0) continue;
- for (NetworkAgentInfo nai : mTypeLists[type]) {
- pw.println(type + " " + naiToString(nai));
+ synchronized (mTypeLists) {
+ for (int type = 0; type < mTypeLists.length; type++) {
+ if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
+ for (NetworkAgentInfo nai : mTypeLists[type]) {
+ pw.println(type + " " + naiToString(nai));
+ }
}
}
pw.decreaseIndent();