eclair snapshot
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 3f268c9..bbb43d7 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -16,12 +16,7 @@
 
 package com.android.server;
 
-import java.io.BufferedReader;
-import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -31,7 +26,6 @@
 import java.util.Observable;
 import java.util.Observer;
 import java.util.Set;
-import java.util.regex.Pattern;
 
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -49,10 +43,12 @@
 import android.location.ILocationListener;
 import android.location.ILocationManager;
 import android.location.ILocationProvider;
+import android.location.INetInitiatedListener;
 import android.location.Location;
 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;
@@ -63,7 +59,6 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
@@ -71,6 +66,7 @@
 import com.android.internal.location.GpsLocationProvider;
 import com.android.internal.location.LocationProviderProxy;
 import com.android.internal.location.MockProvider;
+import com.android.internal.location.GpsNetInitiatedHandler;
 
 /**
  * The service class that manages LocationProviders and issues location
@@ -82,17 +78,9 @@
     private static final String TAG = "LocationManagerService";
     private static final boolean LOCAL_LOGV = false;
 
-    // Minimum time interval between last known location writes, in milliseconds.
-    private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L;
-
-    // Max time to hold wake lock for, in milliseconds.
-    private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L;
-
     // The last time a location was written, by provider name.
     private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
 
-    private static final Pattern PATTERN_COMMA = Pattern.compile(",");
-
     private static final String ACCESS_FINE_LOCATION =
         android.Manifest.permission.ACCESS_FINE_LOCATION;
     private static final String ACCESS_COARSE_LOCATION =
@@ -118,6 +106,7 @@
     private final Context mContext;
     private IGeocodeProvider mGeocodeProvider;
     private IGpsStatusProvider mGpsStatusProvider;
+    private INetInitiatedListener mNetInitiatedListener;
     private LocationWorkerHandler mLocationHandler;
 
     // Cache the real providers for use in addTestProvider() and removeTestProvider()
@@ -394,7 +383,12 @@
     }
 
     public void locationCallbackFinished(ILocationListener listener) {
-        Receiver receiver = getReceiver(listener);
+        //Do not use getReceiver here as that will add the ILocationListener to
+        //the receiver list if it is not found.  If it is not found then the
+        //LocationListener was removed when it had a pending broadcast and should
+        //not be added back.
+        IBinder binder = listener.asBinder();
+        Receiver receiver = mReceivers.get(binder);
         if (receiver != null) {
             synchronized (receiver) {
                 // so wakelock calls will succeed
@@ -413,97 +407,6 @@
         }
     }
 
-    private Location readLastKnownLocationLocked(String provider) {
-        Location location = null;
-        String s = null;
-        try {
-            File f = new File(LocationManager.SYSTEM_DIR + "/location."
-                    + provider);
-            if (!f.exists()) {
-                return null;
-            }
-            BufferedReader reader = new BufferedReader(new FileReader(f), 256);
-            s = reader.readLine();
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to read last known location", e);
-        }
-
-        if (s == null) {
-            return null;
-        }
-        try {
-            String[] tokens = PATTERN_COMMA.split(s);
-            int idx = 0;
-            long time = Long.parseLong(tokens[idx++]);
-            double latitude = Double.parseDouble(tokens[idx++]);
-            double longitude = Double.parseDouble(tokens[idx++]);
-            double altitude = Double.parseDouble(tokens[idx++]);
-            float bearing = Float.parseFloat(tokens[idx++]);
-            float speed = Float.parseFloat(tokens[idx++]);
-
-            location = new Location(provider);
-            location.setTime(time);
-            location.setLatitude(latitude);
-            location.setLongitude(longitude);
-            location.setAltitude(altitude);
-            location.setBearing(bearing);
-            location.setSpeed(speed);
-        } catch (NumberFormatException nfe) {
-            Log.e(TAG, "NumberFormatException reading last known location", nfe);
-            return null;
-        }
-
-        return location;
-    }
-
-    private void writeLastKnownLocationLocked(String provider,
-        Location location) {
-        long now = SystemClock.elapsedRealtime();
-        Long last = mLastWriteTime.get(provider);
-        if ((last != null)
-            && (now - last.longValue() < MIN_LAST_KNOWN_LOCATION_TIME)) {
-            return;
-        }
-        mLastWriteTime.put(provider, now);
-
-        StringBuilder sb = new StringBuilder(100);
-        sb.append(location.getTime());
-        sb.append(',');
-        sb.append(location.getLatitude());
-        sb.append(',');
-        sb.append(location.getLongitude());
-        sb.append(',');
-        sb.append(location.getAltitude());
-        sb.append(',');
-        sb.append(location.getBearing());
-        sb.append(',');
-        sb.append(location.getSpeed());
-
-        FileWriter writer = null;
-        try {
-            File d = new File(LocationManager.SYSTEM_DIR);
-            if (!d.exists()) {
-                if (!d.mkdirs()) {
-                    Log.w(TAG, "Unable to create directory to write location");
-                    return;
-                }
-            }
-            File f = new File(LocationManager.SYSTEM_DIR + "/location." + provider);
-            writer = new FileWriter(f);
-            writer.write(sb.toString());
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to write location", e);
-        } finally {
-            if (writer != null) {
-                try {
-                writer.close();
-                } catch (IOException e) {
-                    Log.w(TAG, "Exception closing file", e);
-                }
-            }
-        }
-    }
-
     private void addProvider(LocationProviderProxy provider) {
         mProviders.add(provider);
         mProvidersByName.put(provider.getName(), provider);
@@ -541,6 +444,7 @@
             // Create a gps location provider
             GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
             mGpsStatusProvider = provider.getGpsStatusProvider();
+            mNetInitiatedListener = provider.getNetInitiatedListener();
             LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
             addProvider(proxy);
             mGpsLocationProvider = proxy;
@@ -626,7 +530,7 @@
             }
 
             // notify provider of current network state
-            proxy.updateNetworkState(mNetworkState);
+            proxy.updateNetworkState(mNetworkState, null);
         }
     }
 
@@ -850,7 +754,9 @@
          */
         void disposeLocked() {
             ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
-            records.remove(this);
+            if (records != null) {
+                records.remove(this);
+            }
         }
 
         @Override
@@ -869,15 +775,6 @@
             mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
             pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
         }
-        
-        /**
-         * Calls dispose().
-         */
-        @Override protected void finalize() {
-            synchronized (mLock) {
-                disposeLocked();
-            }
-        }
     }
 
     private Receiver getReceiver(ILocationListener listener) {
@@ -1030,6 +927,12 @@
         try {
             if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
                 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
+                synchronized(receiver) {
+                    if(receiver.mPendingBroadcasts > 0) {
+                        decrementPendingBroadcasts();
+                        receiver.mPendingBroadcasts = 0;
+                    }
+                }
             }
 
             // Record which providers were associated with this listener
@@ -1108,6 +1011,11 @@
     }
 
     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
+        if (provider == null) {
+            // throw NullPointerException to remain compatible with previous implementation
+            throw new NullPointerException();
+        }
+
         // first check for permission to the provider
         checkPermissionsSafe(provider);
         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
@@ -1118,7 +1026,7 @@
 
         synchronized (mLock) {
             LocationProviderProxy proxy = mProvidersByName.get(provider);
-            if (provider == null) {
+            if (proxy == null) {
                 return false;
             }
     
@@ -1126,6 +1034,22 @@
         }
     }
 
+    public boolean sendNiResponse(int notifId, int userResponse)
+    {
+        if (Binder.getCallingUid() != Process.myUid()) {
+            throw new SecurityException(
+                    "calling sendNiResponse from outside of the system is not allowed");
+        }
+        try {
+            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
+        }
+        catch (RemoteException e)
+        {
+            Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
+            return false;
+        }
+    }
+
     class ProximityAlert {
         final int  mUid;
         final double mLatitude;
@@ -1157,13 +1081,13 @@
             return mIntent;
         }
 
-        boolean isInProximity(double latitude, double longitude) {
+        boolean isInProximity(double latitude, double longitude, float accuracy) {
             Location loc = new Location("");
             loc.setLatitude(latitude);
             loc.setLongitude(longitude);
 
             double radius = loc.distanceTo(mLocation);
-            return radius <= mRadius;
+            return radius <= Math.max(mRadius,accuracy);
         }
         
         @Override
@@ -1203,6 +1127,7 @@
             long now = System.currentTimeMillis();
             double latitude = loc.getLatitude();
             double longitude = loc.getLongitude();
+            float accuracy = loc.getAccuracy();
             ArrayList<PendingIntent> intentsToRemove = null;
 
             for (ProximityAlert alert : mProximityAlerts.values()) {
@@ -1212,7 +1137,7 @@
                 if ((expiration == -1) || (now <= expiration)) {
                     boolean entered = mProximitiesEntered.contains(alert);
                     boolean inProximity =
-                        alert.isInProximity(latitude, longitude);
+                        alert.isInProximity(latitude, longitude, accuracy);
                     if (!entered && inProximity) {
                         if (LOCAL_LOGV) {
                             Log.v(TAG, "Entered alert");
@@ -1487,16 +1412,7 @@
             return null;
         }
 
-        Location location = mLastKnownLocation.get(provider);
-        if (location == null) {
-            // Get the persistent last known location for the provider
-            location = readLastKnownLocationLocked(provider);
-            if (location != null) {
-                mLastKnownLocation.put(provider, location);
-            }
-        }
-
-        return location;
+        return mLastKnownLocation.get(provider);
     }
 
     private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
@@ -1541,7 +1457,6 @@
         } else {
             lastLocation.set(location);
         }
-        writeLastKnownLocationLocked(provider, location);
 
         // Fetch latest status update time
         long newStatusUpdateTime = p.getStatusUpdateTime();
@@ -1686,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);
                         }
                     }
                 }
@@ -1792,6 +1709,7 @@
         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
         checkMockPermissionsSafe();
 
+        long identity = Binder.clearCallingIdentity();
         synchronized (mLock) {
             MockProvider provider = new MockProvider(name, this,
                 requiresNetwork, requiresSatellite,
@@ -1814,6 +1732,7 @@
             mLastKnownLocation.put(name, null);
             updateProvidersLocked();
         }
+        Binder.restoreCallingIdentity(identity);
     }
 
     public void removeTestProvider(String provider) {
@@ -1823,6 +1742,7 @@
             if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
+            long identity = Binder.clearCallingIdentity();
             removeProvider(mProvidersByName.get(provider));
             mMockProviders.remove(mockProvider);
             // reinstall real provider if we were mocking GPS or network provider
@@ -1835,6 +1755,7 @@
             }
             mLastKnownLocation.put(provider, null);
             updateProvidersLocked();
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -1870,6 +1791,7 @@
             if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
+            long identity = Binder.clearCallingIdentity();
             if (enabled) {
                 mockProvider.enable();
                 mEnabledProviders.add(provider);
@@ -1880,6 +1802,7 @@
                 mDisabledProviders.add(provider);
             }
             updateProvidersLocked();
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -1890,9 +1813,11 @@
             if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
+            long identity = Binder.clearCallingIdentity();
             mEnabledProviders.remove(provider);
             mDisabledProviders.remove(provider);
             updateProvidersLocked();
+            Binder.restoreCallingIdentity(identity);
         }
     }