Merge branch 'eclair-plus-aosp' of ssh://android-git.corp.google.com:29418/platform/frameworks/base into eclair-mr2-plus-aosp
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 9c2becf..ca8660c 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -56,6 +56,8 @@
         EXEC_XBIN("procrank");
         PRINT("------ VIRTUAL MEMORY STATS ------");
         DUMP("/proc/vmstat");
+        PRINT("------ VMALLOC INFO ------");
+        DUMP("/proc/vmallocinfo");
         PRINT("------ SLAB INFO ------");
         DUMP("/proc/slabinfo");
         PRINT("------ ZONEINFO ------");
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index cc35b7d..ff48583 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -46,7 +46,7 @@
  */
 public final class BluetoothAdapter {
     private static final String TAG = "BluetoothAdapter";
-    private static final boolean DBG = true;  //STOPSHIP: Remove excess logging
+    private static final boolean DBG = false;
 
     /**
      * Sentinel error value for this class. Guaranteed to not equal any other
@@ -569,6 +569,7 @@
      * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
      * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
      * starts or completes.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
      *
      * @return true if discovering
      */
@@ -582,6 +583,7 @@
     /**
      * Return the set of {@link BluetoothDevice} objects that are bonded
      * (paired) to the local adapter.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
      *
      * @return unmodifiable set of {@link BluetoothDevice}, or null on error
      */
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 39a74ac..849e6c7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -513,6 +513,7 @@
 
     /**
      * Get trust state of a remote device.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
      * @hide
      */
     public boolean getTrustState() {
@@ -526,6 +527,7 @@
 
     /**
      * Set trust state for a remote device.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
      * @param value the trust state value (true or false)
      * @hide
      */
@@ -657,6 +659,8 @@
      * Call #connect on the returned #BluetoothSocket to begin the connection.
      * The remote device will not be authenticated and communication on this
      * socket will not be encrypted.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     *
      * @param port    remote port
      * @return An RFCOMM BluetoothSocket
      * @throws IOException On error, for example Bluetooth not available, or
@@ -671,6 +675,8 @@
     /**
      * Construct a SCO socket ready to start an outgoing connection.
      * Call #connect on the returned #BluetoothSocket to begin the connection.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     *
      * @return a SCO BluetoothSocket
      * @throws IOException on error, for example Bluetooth not available, or
      *                     insufficient permissions.
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index e5e6db9..538e51a 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -48,6 +48,7 @@
     private ITelephony mPhoneService;
 
     private String mApnType;
+    private String mApnName;
     private boolean mEnabled;
     private BroadcastReceiver mStateReceiver;
 
@@ -139,6 +140,7 @@
                     String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
                     String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
                     String apnTypeList = intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);
+                    mApnName = apnName;
 
                     boolean unavailable = intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,
                             false);
@@ -339,6 +341,7 @@
                 intent.putExtra(Phone.STATE_KEY, Phone.DataState.CONNECTED.toString());
                 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, Phone.REASON_APN_CHANGED);
                 intent.putExtra(Phone.DATA_APN_TYPES_KEY, mApnType);
+                intent.putExtra(Phone.DATA_APN_KEY, mApnName);
                 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, mInterfaceName);
                 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, false);
                 if (mStateReceiver != null) mStateReceiver.onReceive(mContext, intent);
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index b73e53f..9a2d6d9 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -72,6 +72,8 @@
     private final AudioManager mAudioManager;
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
+    private boolean mSuspending;
+    private boolean mResuming;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -149,6 +151,8 @@
 
         if (mBluetoothService.isEnabled())
             onBluetoothEnable();
+        mSuspending = false;
+        mResuming = false;
     }
 
     @Override
@@ -241,6 +245,7 @@
                 }
         }
         mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
+        mAudioManager.setParameters("A2dpSuspended=false");
     }
 
     private synchronized void onBluetoothDisable() {
@@ -336,7 +341,10 @@
     public synchronized boolean suspendSink(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                             "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("suspendSink(" + device + ")");
+        if (DBG) log("suspendSink(" + device + "), mSuspending: "+mSuspending+", mResuming: "+mResuming);
+        if (mSuspending) {
+            return true;
+        }
         if (device == null || mAudioDevices == null) {
             return false;
         }
@@ -347,9 +355,14 @@
         }
         switch (state.intValue()) {
         case BluetoothA2dp.STATE_CONNECTED:
+            if (mResuming) {
+                mSuspending = true;
+            }
             return true;
         case BluetoothA2dp.STATE_PLAYING:
-            return suspendSinkNative(path);
+            mAudioManager.setParameters("A2dpSuspended=true");
+            mSuspending = suspendSinkNative(path);
+            return mSuspending;
         default:
             return false;
         }
@@ -358,7 +371,10 @@
     public synchronized boolean resumeSink(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                             "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("resumeSink(" + device + ")");
+        if (DBG) log("resumeSink(" + device + "), mResuming: "+mResuming+", mSuspending: "+mSuspending);
+        if (mResuming) {
+            return true;
+        }
         if (device == null || mAudioDevices == null) {
             return false;
         }
@@ -369,9 +385,14 @@
         }
         switch (state.intValue()) {
         case BluetoothA2dp.STATE_PLAYING:
+            if (mSuspending) {
+                mResuming = true;
+            }
             return true;
         case BluetoothA2dp.STATE_CONNECTED:
-            return resumeSinkNative(path);
+            mResuming = resumeSinkNative(path);
+            mAudioManager.setParameters("A2dpSuspended=false");
+            return mResuming;
         default:
             return false;
         }
@@ -437,6 +458,10 @@
     }
 
     private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
+        if (state == BluetoothA2dp.STATE_DISCONNECTED) {
+            mSuspending = false;
+            mResuming = false;
+        }
         if (state != prevState) {
             if (state == BluetoothA2dp.STATE_DISCONNECTED ||
                     state == BluetoothA2dp.STATE_DISCONNECTING) {
@@ -452,6 +477,29 @@
             }
             mAudioDevices.put(device, state);
 
+            if (state == BluetoothA2dp.STATE_CONNECTED && prevState == BluetoothA2dp.STATE_PLAYING) {
+                if (DBG) log("handleSinkStateChange() STATE_PLAYING -> STATE_CONNECTED: mSuspending: "
+                        +mSuspending+", mResuming: "+mResuming);
+                if (mSuspending) {
+                    mSuspending = false;
+                    if (mResuming) {
+                        mResuming = false;
+                        resumeSink(device);
+                    }
+                }
+            }
+            if (state == BluetoothA2dp.STATE_PLAYING && prevState == BluetoothA2dp.STATE_CONNECTED) {
+                if (DBG) log("handleSinkStateChange() STATE_CONNECTED -> STATE_PLAYING: mSuspending: "
+                        +mSuspending+", mResuming: "+mResuming);
+
+                if (mResuming) {
+                    mResuming = false;
+                    if (mSuspending) {
+                        mSuspending = false;
+                        suspendSink(device);
+                    }
+                }
+            }
             Intent intent = new Intent(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
             intent.putExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, prevState);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 7ebd91d..5c8c7cc 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -61,7 +61,7 @@
 
 public class BluetoothService extends IBluetooth.Stub {
     private static final String TAG = "BluetoothService";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private int mNativeData;
     private BluetoothEventLoop mEventLoop;
@@ -191,10 +191,10 @@
     /**
      * Bring down bluetooth. Returns true on success.
      *
-     * @param saveSetting If true, disable BT in settings
+     * @param saveSetting If true, persist the new setting
      */
     public synchronized boolean disable(boolean saveSetting) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
 
         switch (mBluetoothState) {
         case BluetoothAdapter.STATE_OFF:
@@ -1013,7 +1013,8 @@
      */
     public synchronized boolean setTrust(String address, boolean value) {
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                    "Need BLUETOOTH_ADMIN permission");
             return false;
         }
 
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index 57a29f2..351815b 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -16,7 +16,7 @@
 
 #include <math.h>
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "A2dpAudioInterface"
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -40,7 +40,7 @@
 //}
 
 A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
-    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true)
+    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
 {
 }
 
@@ -78,6 +78,7 @@
     if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
         mOutput = out;
         mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        mOutput->setSuspended(mSuspended);
     } else {
         delete out;
     }
@@ -142,6 +143,14 @@
         }
         param.remove(key);
     }
+    key = String8("A2dpSuspended");
+    if (param.get(key, value) == NO_ERROR) {
+        mSuspended = (value == "true");
+        if (mOutput) {
+            mOutput->setSuspended(mSuspended);
+        }
+        param.remove(key);
+    }
 
     if (param.size()) {
         status_t hwStatus = mHardwareInterface->setParameters(param.toString());
@@ -166,6 +175,12 @@
         a2dpParam.add(key, value);
         param.remove(key);
     }
+    key = "A2dpSuspended";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mSuspended ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
 
     String8 keyValuePairs  = a2dpParam.toString();
 
@@ -204,7 +219,7 @@
     mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
     // assume BT enabled to start, this is safe because its only the
     // enabled->disabled transition we are worried about
-    mBluetoothEnabled(true), mDevice(0), mClosing(false)
+    mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
 {
     // use any address by default
     strcpy(mA2dpAddress, "00:00:00:00:00:00");
@@ -258,8 +273,10 @@
     size_t remaining = bytes;
     status_t status = -1;
 
-    if (!mBluetoothEnabled || mClosing) {
-        LOGW("A2dpAudioStreamOut::write(), but bluetooth disabled");
+    if (!mBluetoothEnabled || mClosing || mSuspended) {
+        LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+               mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+                mBluetoothEnabled, mClosing, mSuspended);
         goto Error;
     }
 
@@ -408,6 +425,14 @@
     return NO_ERROR;
 }
 
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
+{
+    LOGV("setSuspended %d", onOff);
+    mSuspended = onOff;
+    standby();
+    return NO_ERROR;
+}
+
 status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
 {
     Mutex::Autolock lock(mLock);
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 35a6e11..530e432 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -101,6 +101,7 @@
                 status_t    close_l();
                 status_t    setAddress(const char* address);
                 status_t    setBluetoothEnabled(bool enabled);
+                status_t    setSuspended(bool onOff);
 
     private:
                 int         mFd;
@@ -113,6 +114,7 @@
                 bool        mBluetoothEnabled;
                 uint32_t    mDevice;
                 bool        mClosing;
+                bool        mSuspended;
     };
 
     friend class A2dpAudioStreamOut;
@@ -121,6 +123,7 @@
     AudioHardwareInterface  *mHardwareInterface;
     char        mA2dpAddress[20];
     bool        mBluetoothEnabled;
+    bool        mSuspended;
 };
 
 
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
index 4fe0494..7da16e4 100644
--- a/location/java/android/location/ILocationProvider.aidl
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -17,6 +17,7 @@
 package android.location;
 
 import android.location.Location;
+import android.net.NetworkInfo;
 import android.os.Bundle;
 
 /**
@@ -41,7 +42,7 @@
     long getStatusUpdateTime();
     void enableLocationTracking(boolean enable);
     void setMinTime(long minTime);
-    void updateNetworkState(int state);
+    void updateNetworkState(int state, in NetworkInfo info);
     void updateLocation(in Location location);
     boolean sendExtraCommand(String command, inout Bundle extras);
     void addListener(int uid);
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index bfa0671..cd62ed1 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -32,6 +32,7 @@
 import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
 import android.net.SntpClient;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -46,7 +47,6 @@
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.location.GpsNetInitiatedHandler;
 import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
 
@@ -303,22 +303,6 @@
             } else if (action.equals(ALARM_TIMEOUT)) {
                 if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
                 hibernate();
-            } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
-                String state = intent.getStringExtra(Phone.STATE_KEY);
-                String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
-                String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
-
-                if (Config.LOGD) {
-                    Log.d(TAG, "state: " + state +  " apnName: " + apnName + " reason: " + reason);
-                }
-                // FIXME - might not have an APN on CDMA
-                if ("CONNECTED".equals(state) && apnName != null && apnName.length() > 0) {
-                    mAGpsApn = apnName;
-                    if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
-                        native_agps_data_conn_open(mAGpsApn);
-                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
-                    }
-                }
             }
         }
     };
@@ -343,7 +327,6 @@
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(ALARM_WAKEUP);
         intentFilter.addAction(ALARM_TIMEOUT);
-        intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
         context.registerReceiver(mBroadcastReciever, intentFilter);
 
         mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -391,13 +374,30 @@
         return true;
     }
 
-    public void updateNetworkState(int state) {
+    public void updateNetworkState(int state, NetworkInfo info) {
         mNetworkAvailable = (state == LocationProvider.AVAILABLE);
 
         if (Config.LOGD) {
-            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable"));
+            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
+                + " info: " + info);
         }
-        
+
+        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
+                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
+            String apnName = info.getExtraInfo();
+            if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
+                mAGpsApn = apnName;
+                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
+                native_agps_data_conn_open(apnName);
+                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
+            } else {
+                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
+                mAGpsApn = null;
+                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
+                native_agps_data_conn_failed();
+            }
+        }
+
         if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
             // signal the network thread when the network becomes available
             mNetworkThread.signal();
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index 4ae424a..89337b3 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -20,6 +20,7 @@
 import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationManager;
+import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -217,9 +218,9 @@
         }
     }
 
-    public void updateNetworkState(int state) {
+    public void updateNetworkState(int state, NetworkInfo info) {
         try {
-            mProvider.updateNetworkState(state);
+            mProvider.updateNetworkState(state, info);
         } catch (RemoteException e) {
             Log.e(TAG, "updateNetworkState failed", e);
         }
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index e2e0562..2614f82 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -20,6 +20,7 @@
 import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationProvider;
+import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
@@ -169,7 +170,7 @@
     public void setMinTime(long minTime) {
     }
 
-    public void updateNetworkState(int state) {
+    public void updateNetworkState(int state, NetworkInfo info) {
     }
 
     public void updateLocation(Location location) {
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 3204d9a..1e4c136 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -31,6 +31,9 @@
 
 using namespace android;
 
+// set this to 1 for crude GL debugging
+#define CHECK_FOR_GL_ERRORS     0
+
 // ----------------------------------------------------------------------------
 // extensions for the framework
 // ----------------------------------------------------------------------------
@@ -71,7 +74,7 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
-#if USE_FAST_TLS_KEY
+#if USE_FAST_TLS_KEY && !CHECK_FOR_GL_ERRORS
 
     #define API_ENTRY(_api) __attribute__((naked)) _api
 
@@ -95,12 +98,27 @@
 
 #else
 
+    #if CHECK_FOR_GL_ERRORS
+    
+        #define CHECK_GL_ERRORS(_api) \
+            do { GLint err = glGetError(); \
+                LOGE_IF(err != GL_NO_ERROR, "%s failed (0x%04X)", #_api, err); \
+            } while(false);
+
+    #else
+
+        #define CHECK_GL_ERRORS(_api) do { } while(false);
+
+    #endif
+
+
     #define API_ENTRY(_api) _api
 
     #define CALL_GL_API(_api, ...)                                      \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
-        _c->_api(__VA_ARGS__)
-    
+        _c->_api(__VA_ARGS__);                                          \
+        CHECK_GL_ERRORS(_api)
+
     #define CALL_GL_API_RETURN(_api, ...)                               \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
         return _c->_api(__VA_ARGS__)
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index c8fa4c3..d1b3bd0 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -48,6 +48,7 @@
 import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -529,7 +530,7 @@
             }
 
             // notify provider of current network state
-            proxy.updateNetworkState(mNetworkState);
+            proxy.updateNetworkState(mNetworkState, null);
         }
     }
 
@@ -1600,13 +1601,15 @@
                 } else {
                     mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
                 }
+                NetworkInfo info =
+                        (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
 
                 // Notify location providers of current network state
                 synchronized (mLock) {
                     for (int i = mProviders.size() - 1; i >= 0; i--) {
                         LocationProviderProxy provider = mProviders.get(i);
                         if (provider.requiresNetwork()) {
-                            provider.updateNetworkState(mNetworkState);
+                            provider.updateNetworkState(mNetworkState, info);
                         }
                     }
                 }
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index 2ea020e..dc07585 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -22,6 +22,7 @@
 import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationProvider;
+import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -156,7 +157,7 @@
     public void setMinTime(long minTime) {
     }
 
-    public void updateNetworkState(int state) {
+    public void updateNetworkState(int state, NetworkInfo info) {
     }
 
     public void updateLocation(Location location) {