Snap for 7579381 from 0a51c9643809a8d6d1ee853683836b18b9cba26b to sc-release

Change-Id: I26d11abcd59232949cf1469a8c7ecdae6dbee619
diff --git a/src/com/google/android/iwlan/IwlanDataService.java b/src/com/google/android/iwlan/IwlanDataService.java
index 5d81556..3537776 100644
--- a/src/com/google/android/iwlan/IwlanDataService.java
+++ b/src/com/google/android/iwlan/IwlanDataService.java
@@ -1117,20 +1117,35 @@
 
     @VisibleForTesting
     /* Note: this api should have valid transport if networkConnected==true */
-    static synchronized void setNetworkConnected(
+    // Only synchronize on IwlanDataService.class for changes being made to static variables
+    // Calls to DataServiceProvider object methods (or any objects in the future) should
+    // not be made within synchronized block protected by IwlanDataService.class
+    static void setNetworkConnected(
             boolean networkConnected, Network network, Transport transport) {
+
         boolean hasNetworkChanged = false;
-        sNetworkConnected = networkConnected;
-        if (!network.equals(sNetwork)) {
-            Log.e(TAG, "setNetworkConnected NW changed from: " + sNetwork + " TO: " + network);
-            sNetwork = network;
-            hasNetworkChanged = true;
-        }
-        if (networkConnected) {
-            if (transport == Transport.UNSPECIFIED_NETWORK) {
+        boolean hasTransportChanged = false;
+        boolean hasNetworkConnectedChanged = false;
+
+        synchronized (IwlanDataService.class) {
+            if (sNetworkConnected == networkConnected
+                    && network.equals(sNetwork)
+                    && sDefaultDataTransport == transport) {
+                // Nothing changed
+                return;
+            }
+
+            // safety check
+            if (networkConnected && transport == Transport.UNSPECIFIED_NETWORK) {
                 Log.e(TAG, "setNetworkConnected: Network connected but transport unspecified");
                 return;
             }
+
+            if (!network.equals(sNetwork)) {
+                Log.e(TAG, "setNetworkConnected NW changed from: " + sNetwork + " TO: " + network);
+                hasNetworkChanged = true;
+            }
+
             if (transport != sDefaultDataTransport) {
                 Log.d(
                         TAG,
@@ -1138,37 +1153,55 @@
                                 + sDefaultDataTransport.name()
                                 + " to "
                                 + transport.name());
+                hasTransportChanged = true;
+            }
+
+            if (sNetworkConnected != networkConnected) {
+                Log.d(
+                        TAG,
+                        "Network connected state change from "
+                                + sNetworkConnected
+                                + " to "
+                                + networkConnected);
+                hasNetworkConnectedChanged = true;
+            }
+
+            sNetworkConnected = networkConnected;
+            sDefaultDataTransport = transport;
+            sNetwork = network;
+            if (!networkConnected) {
+                //reset link protocol type
+                sLinkProtocolType = LinkProtocolType.UNKNOWN;
+            }
+        }
+
+        if (networkConnected) {
+            if (hasTransportChanged) {
                 // Perform forceClose for tunnels in bringdown.
                 // let framework handle explicit teardown
                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviderList) {
                     dp.forceCloseTunnelsInDeactivatingState();
                 }
             }
-        }
-        sDefaultDataTransport = transport;
 
-        if (!networkConnected) {
-            sLinkProtocolType = LinkProtocolType.UNKNOWN;
+            if (transport == Transport.WIFI && hasNetworkConnectedChanged) {
+                IwlanEventListener.onWifiConnected(mContext);
+            }
+            // only prefetch dns and updateNetwork if Network has changed
+            if (hasNetworkChanged) {
+                for (IwlanDataServiceProvider dp : sIwlanDataServiceProviderList) {
+                    dp.dnsPrefetchCheck();
+                    dp.updateNetwork(sNetwork);
+                }
+            }
+        } else {
             for (IwlanDataServiceProvider dp : sIwlanDataServiceProviderList) {
-                // once network is disconnect, even NAT KA offload fails
+                // once network is disconnected, even NAT KA offload fails
                 // But we should still let framework do an explicit teardown
                 // so as to not affect an ongoing handover
                 // only force close tunnels in bring down state
                 dp.forceCloseTunnelsInDeactivatingState();
             }
-        } else {
-            if (transport == Transport.WIFI) {
-                IwlanEventListener.onWifiConnected(mContext);
-            }
-            for (IwlanDataServiceProvider dp : sIwlanDataServiceProviderList) {
-                dp.dnsPrefetchCheck();
-            }
-
-            if (hasNetworkChanged) {
-                for (IwlanDataServiceProvider dp : sIwlanDataServiceProviderList) {
-                    dp.updateNetwork(sNetwork);
-                }
-            }
         }
     }