Merge "Remove calls to set_process_name."
diff --git a/api/current.txt b/api/current.txt
index adb39af..9f7e642 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -51033,6 +51033,7 @@
     method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
     method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
@@ -51044,6 +51045,7 @@
     method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
@@ -51112,6 +51114,7 @@
     method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel disconnect() throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public abstract boolean isConnected();
     method public static java.nio.channels.DatagramChannel open() throws java.io.IOException;
@@ -51347,6 +51350,7 @@
     method public abstract java.nio.channels.SocketChannel accept() throws java.io.IOException;
     method public final java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.ServerSocketChannel open() throws java.io.IOException;
     method public abstract java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.ServerSocket socket();
@@ -51362,6 +51366,7 @@
     method public abstract java.nio.channels.SocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract boolean connect(java.net.SocketAddress) throws java.io.IOException;
     method public abstract boolean finishConnect() throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public abstract boolean isConnected();
     method public abstract boolean isConnectionPending();
diff --git a/api/system-current.txt b/api/system-current.txt
index bafcfe8..a097edb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -53651,6 +53651,7 @@
     method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
     method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
     method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
@@ -53662,6 +53663,7 @@
     method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
     method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
     method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
@@ -53730,6 +53732,7 @@
     method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel disconnect() throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public abstract boolean isConnected();
     method public static java.nio.channels.DatagramChannel open() throws java.io.IOException;
@@ -53965,6 +53968,7 @@
     method public abstract java.nio.channels.SocketChannel accept() throws java.io.IOException;
     method public final java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public static java.nio.channels.ServerSocketChannel open() throws java.io.IOException;
     method public abstract java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public abstract java.net.ServerSocket socket();
@@ -53980,6 +53984,7 @@
     method public abstract java.nio.channels.SocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract boolean connect(java.net.SocketAddress) throws java.io.IOException;
     method public abstract boolean finishConnect() throws java.io.IOException;
+    method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
     method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
     method public abstract boolean isConnected();
     method public abstract boolean isConnectionPending();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 327fb8a..7e5cc12 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -468,8 +468,16 @@
          *
          * 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 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 @@
             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 @@
             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 @@
             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 @@
             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();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7ea9038..abc1dc9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13330,8 +13330,9 @@
                 for (int curUser : users) {
                     long timeout = SystemClock.uptimeMillis() + 5000;
                     synchronized (conn) {
-                        long now = SystemClock.uptimeMillis();
-                        while (conn.mContainerService == null && now < timeout) {
+                        long now;
+                        while (conn.mContainerService == null &&
+                                (now = SystemClock.uptimeMillis()) < timeout) {
                             try {
                                 conn.wait(timeout - now);
                             } catch (InterruptedException e) {