am 15e3d0f: location: Use ILocationProvider Binder interface for all loc

Merge commit '15e3d0f082d551f8819fbe4b0d502cc108627876'

* commit '15e3d0f082d551f8819fbe4b0d502cc108627876':
  location: Use ILocationProvider Binder interface for all location providers.
diff --git a/Android.mk b/Android.mk
index 20c93e6..954d1d6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,6 +119,7 @@
 	im/java/android/im/IImPlugin.aidl \
 	location/java/android/location/IGeocodeProvider.aidl \
 	location/java/android/location/IGpsStatusListener.aidl \
+	location/java/android/location/IGpsStatusProvider.aidl \
 	location/java/android/location/ILocationCollector.aidl \
 	location/java/android/location/ILocationListener.aidl \
 	location/java/android/location/ILocationManager.aidl \
diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/location/java/android/location/IGpsStatusProvider.aidl
new file mode 100644
index 0000000..cf277c8
--- /dev/null
+++ b/location/java/android/location/IGpsStatusProvider.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.location.IGpsStatusListener;
+
+/**
+ * An interface for location providers that provide GPS status information.
+ *
+ * {@hide}
+ */
+interface IGpsStatusProvider {
+    void addGpsStatusListener(IGpsStatusListener listener);
+    void removeGpsStatusListener(IGpsStatusListener listener);
+}
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
index 82533a5..e3e374d 100644
--- a/location/java/android/location/ILocationProvider.aidl
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -19,13 +19,11 @@
 import android.os.Bundle;
 
 /**
- * An interface for location providers implemented outside of the system process.
+ * Binder interface for location providers.
  *
  * {@hide}
  */
 interface ILocationProvider {
-
-    /* for LocationProvider */
     boolean requiresNetwork();
     boolean requiresSatellite();
     boolean requiresCell();
@@ -35,8 +33,6 @@
     boolean supportsBearing();
     int getPowerRequirement();
     int getAccuracy();
-
-    /* for LocationProviderImpl */
     void enable();
     void disable();
     boolean isEnabled();
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 57d3c53..693848b 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -22,7 +22,9 @@
 import android.content.IntentFilter;
 import android.location.Criteria;
 import android.location.IGpsStatusListener;
+import android.location.IGpsStatusProvider;
 import android.location.ILocationManager;
+import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
@@ -54,7 +56,7 @@
  *
  * {@hide}
  */
-public class GpsLocationProvider extends LocationProviderImpl {
+public class GpsLocationProvider extends ILocationProvider.Stub {
 
     private static final String TAG = "GpsLocationProvider";
     
@@ -142,7 +144,7 @@
     private int mLocationFlags = LOCATION_INVALID;
 
     // current status
-    private int mStatus = TEMPORARILY_UNAVAILABLE;
+    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
 
     // time for last status update
     private long mStatusUpdateTime = SystemClock.elapsedRealtime();
@@ -178,7 +180,8 @@
     private Properties mProperties;
     private String mNtpServer;
 
-    private Context mContext;
+    private final Context mContext;
+    private final ILocationManager mLocationManager;
     private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
     private Bundle mLocationExtras = new Bundle();
     private ArrayList<Listener> mListeners = new ArrayList<Listener>();
@@ -203,6 +206,57 @@
     // current setting - 5 minutes
     private static final long RETRY_INTERVAL = 5*60*1000; 
 
+    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
+        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
+            if (listener == null) {
+                throw new NullPointerException("listener is null in addGpsStatusListener");
+            }
+
+            synchronized(mListeners) {
+                IBinder binder = listener.asBinder();
+                int size = mListeners.size();
+                for (int i = 0; i < size; i++) {
+                    Listener test = mListeners.get(i);
+                    if (binder.equals(test.mListener.asBinder())) {
+                        // listener already added
+                        return;
+                    }
+                }
+
+                Listener l = new Listener(listener);
+                binder.linkToDeath(l, 0);
+                mListeners.add(l);
+            }
+        }
+
+        public void removeGpsStatusListener(IGpsStatusListener listener) {
+            if (listener == null) {
+                throw new NullPointerException("listener is null in addGpsStatusListener");
+            }
+
+            synchronized(mListeners) {
+                IBinder binder = listener.asBinder();
+                Listener l = null;
+                int size = mListeners.size();
+                for (int i = 0; i < size && l == null; i++) {
+                    Listener test = mListeners.get(i);
+                    if (binder.equals(test.mListener.asBinder())) {
+                        l = test;
+                    }
+                }
+
+                if (l != null) {
+                    mListeners.remove(l);
+                    binder.unlinkToDeath(l, 0);
+                }
+            }
+        }
+    };
+
+    public IGpsStatusProvider getGpsStatusProvider() {
+        return mGpsStatusProvider;
+    }
+
     private class TelephonyBroadcastReceiver extends BroadcastReceiver {
         @Override public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
@@ -231,8 +285,8 @@
     }
 
     public GpsLocationProvider(Context context, ILocationManager locationManager) {
-        super(LocationManager.GPS_PROVIDER, locationManager);
         mContext = context;
+        mLocationManager = locationManager;
 
         TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver();
         IntentFilter intentFilter = new IntentFilter();
@@ -270,7 +324,6 @@
      * Returns true if the provider requires access to a
      * data network (e.g., the Internet), false otherwise.
      */
-    @Override
     public boolean requiresNetwork() {
         // We want updateNetworkState() to get called when the network state changes
         // for XTRA and NTP time injection support.
@@ -295,7 +348,6 @@
      * satellite-based positioning system (e.g., GPS), false
      * otherwise.
      */
-    @Override
     public boolean requiresSatellite() {
         return true;
     }
@@ -305,7 +357,6 @@
      * cellular network (e.g., to make use of cell tower IDs), false
      * otherwise.
      */
-    @Override
     public boolean requiresCell() {
         return false;
     }
@@ -315,7 +366,6 @@
      * monetary charge to the user, false if use is free.  It is up to
      * each provider to give accurate information.
      */
-    @Override
     public boolean hasMonetaryCost() {
         return false;
     }
@@ -326,7 +376,6 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
-    @Override
     public boolean supportsAltitude() {
         return true;
     }
@@ -337,7 +386,6 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
-    @Override
     public boolean supportsSpeed() {
         return true;
     }
@@ -348,7 +396,6 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
-    @Override
     public boolean supportsBearing() {
         return true;
     }
@@ -359,7 +406,6 @@
      * @return the power requirement for this provider, as one of the
      * constants Criteria.POWER_REQUIREMENT_*.
      */
-    @Override
     public int getPowerRequirement() {
         return Criteria.POWER_HIGH;
     }
@@ -370,7 +416,6 @@
      * @return the accuracy of location from this provider, as one
      * of the constants Criteria.ACCURACY_*.
      */
-    @Override
     public int getAccuracy() {
         return Criteria.ACCURACY_FINE;
     }
@@ -380,7 +425,6 @@
      * must be handled.  Hardware may be started up
      * when the provider is enabled.
      */
-    @Override
     public synchronized void enable() {
         if (Config.LOGD) Log.d(TAG, "enable");
         if (mEnabled) return;
@@ -410,7 +454,6 @@
      * need not be handled.  Hardware may be shut
      * down while the provider is disabled.
      */
-    @Override
     public synchronized void disable() {
         if (Config.LOGD) Log.d(TAG, "disable");
         if (!mEnabled) return;
@@ -443,12 +486,10 @@
         native_cleanup();
     }
 
-    @Override
     public boolean isEnabled() {
         return mEnabled;
     }
 
-    @Override
     public int getStatus(Bundle extras) {
         if (extras != null) {
             extras.putInt("satellites", mSvCount);
@@ -465,14 +506,11 @@
         }
     }
 
-    @Override
     public long getStatusUpdateTime() {
         return mStatusUpdateTime;
     }
 
-    @Override
     public void enableLocationTracking(boolean enable) {
-        super.enableLocationTracking(enable);
         if (enable) {
             mFixRequestTime = System.currentTimeMillis();
             mTTFF = 0;
@@ -483,9 +521,7 @@
         }
     }
 
-    @Override
     public void setMinTime(long minTime) {
-        super.setMinTime(minTime);
         if (Config.LOGD) Log.d(TAG, "setMinTime " + minTime);
         
         if (minTime >= 0) {
@@ -516,48 +552,12 @@
         }
     }
 
-    public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {        
-        if (listener == null) throw new NullPointerException("listener is null in addGpsStatusListener");
-
-        synchronized(mListeners) {
-            IBinder binder = listener.asBinder();
-            int size = mListeners.size();
-            for (int i = 0; i < size; i++) {
-                Listener test = mListeners.get(i);
-                if (binder.equals(test.mListener.asBinder())) {
-                    // listener already added
-                    return;
-                }
-            }
-
-            Listener l = new Listener(listener);
-            binder.linkToDeath(l, 0);
-            mListeners.add(l);
-        }
-    }
-    
-    public void removeGpsStatusListener(IGpsStatusListener listener) {
-        if (listener == null) throw new NullPointerException("listener is null in addGpsStatusListener");
-
-        synchronized(mListeners) {        
-            IBinder binder = listener.asBinder();
-            Listener l = null;
-            int size = mListeners.size();
-            for (int i = 0; i < size && l == null; i++) {
-                Listener test = mListeners.get(i);
-                if (binder.equals(test.mListener.asBinder())) {
-                    l = test;
-                }
-            }
-
-            if (l != null) {
-                mListeners.remove(l);
-                binder.unlinkToDeath(l, 0);
-            }
-        }
+    public void wakeLockAcquired() {
     }
 
-    @Override
+    public void wakeLockReleased() {
+    }
+
     public void addListener(int uid) {
         mClientUids.put(uid, 0);
         if (mNavigating) {
@@ -569,7 +569,6 @@
         }
     }
 
-    @Override
     public void removeListener(int uid) {
         mClientUids.delete(uid);
         if (mNavigating) {
@@ -581,7 +580,6 @@
         }
     }
 
-    @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
         
         if ("delete_aiding_data".equals(command)) {
@@ -632,7 +630,7 @@
             }
 
             // reset SV count to zero
-            updateStatus(TEMPORARILY_UNAVAILABLE, 0);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
         }
     }
 
@@ -646,7 +644,7 @@
             mLocationFlags = LOCATION_INVALID;
 
             // reset SV count to zero
-            updateStatus(TEMPORARILY_UNAVAILABLE, 0);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
         }
     }
 
@@ -709,15 +707,19 @@
                 mLocation.removeAccuracy();
             }
 
-            reportLocationChanged(mLocation);
+            try {
+                mLocationManager.setLocation(mLocation);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException calling reportLocation");
+            }
         }
 
-        if (mStarted && mStatus != AVAILABLE) {
+        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
             // send an intent to notify that the GPS is receiving fixes.
             Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
             intent.putExtra(EXTRA_ENABLED, true);
             mContext.sendBroadcast(intent);
-            updateStatus(AVAILABLE, mSvCount);
+            updateStatus(LocationProvider.AVAILABLE, mSvCount);
         }
    }
 
@@ -812,13 +814,13 @@
 
         updateStatus(mStatus, svCount);
 
-        if (mNavigating && mStatus == AVAILABLE && mLastFixTime > 0 &&
+        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
             System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
             // send an intent to notify that the GPS is no longer receiving fixes.
             Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
             intent.putExtra(EXTRA_ENABLED, false);
             mContext.sendBroadcast(intent);
-            updateStatus(TEMPORARILY_UNAVAILABLE, mSvCount);
+            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
         }
     }
 
diff --git a/location/java/com/android/internal/location/LocationProviderImpl.java b/location/java/com/android/internal/location/LocationProviderImpl.java
deleted file mode 100644
index fc830f5..0000000
--- a/location/java/com/android/internal/location/LocationProviderImpl.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.location;
-
-import android.location.ILocationManager;
-import android.location.Location;
-import android.location.LocationProvider;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * An abstract superclass for location provider implementations.
- * Location provider implementations are typically instantiated by the
- * location manager service in the system process, and location
- * information is made available to implementations via the manager.
- *
- * {@hide}
- */
-public abstract class LocationProviderImpl extends LocationProvider {
-    private static final String TAG = "LocationProviderImpl";
-
-    private static ArrayList<LocationProviderImpl> sProviders =
-        new ArrayList<LocationProviderImpl>();
-    private static HashMap<String, LocationProviderImpl> sProvidersByName
-        = new HashMap<String, LocationProviderImpl>();
-
-    private final ILocationManager mLocationManager;
-    private boolean mLocationTracking = false;
-    private long mMinTime = 0;
-
-    protected LocationProviderImpl(String name, ILocationManager locationManager) {
-        super(name);
-        mLocationManager = locationManager;
-    }
-
-    public static void addProvider(LocationProviderImpl provider) {
-        sProviders.add(provider);
-        sProvidersByName.put(provider.getName(), provider);
-    }
-
-    public static void removeProvider(LocationProviderImpl provider) {
-        sProviders.remove(provider);
-        sProvidersByName.remove(provider.getName());
-    }
-
-    public static ArrayList<LocationProviderImpl> getProviders() {
-        return sProviders;
-    }
-
-    public static LocationProviderImpl getProvider(String name) {
-        return sProvidersByName.get(name);
-    }
-
-    public void reportLocationChanged(Location location) {
-        try {
-            mLocationManager.setLocation(location);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException calling ILocationManager.setLocation");
-        }
-    }
-    
-    /**
-     * Enables this provider.  When enabled, calls to {@link #getStatus()}
-     * must be handled.  Hardware may be started up
-     * when the provider is enabled.
-     */
-    public abstract void enable();
-
-    /**
-     * Disables this provider.  When disabled, calls to {@link #getStatus()}
-     * need not be handled.  Hardware may be shut
-     * down while the provider is disabled.
-     */
-    public abstract void disable();
-
-    /**
-     * Returns true if this provider is enabled, false otherwise;
-     */
-    public abstract boolean isEnabled();
-
-    /**
-     * Returns a information on the status of this provider.
-     * {@link #OUT_OF_SERVICE} is returned if the provider is
-     * out of service, and this is not expected to change in the near
-     * future; {@link #TEMPORARILY_UNAVAILABLE} is returned if
-     * the provider is temporarily unavailable but is expected to be
-     * available shortly; and {@link #AVAILABLE} is returned
-     * if the provider is currently available.
-     */
-    public int getStatus() {
-        return getStatus(null);
-    }
-
-    /**
-     * Returns a information on the status of this provider.
-     * {@link #OUT_OF_SERVICE} is returned if the provider is
-     * out of service, and this is not expected to change in the near
-     * future; {@link #TEMPORARILY_UNAVAILABLE} is returned if
-     * the provider is temporarily unavailable but is expected to be
-     * available shortly; and {@link #AVAILABLE} is returned
-     * if the provider is currently available.
-     *
-     * <p> If extras is non-null, additional status information may be
-     * added to it in the form of provider-specific key/value pairs.
-     */
-    public abstract int getStatus(Bundle extras);
-
-    /**
-     * Returns the time at which the status was last updated. It is the
-     * responsibility of the provider to appropriately set this value
-     * using {@link android.os.SystemClock.elapsedRealtime()} each time
-     * there is a status update that it wishes to broadcast to all its
-     * listeners. The provider should be careful not to broadcast
-     * the same status again.
-     *
-     * @return time of last status update in millis since last reboot
-     */
-    public long getStatusUpdateTime() {
-        return 0;
-    }
-
-    /**
-     * Notifies the location provider that clients are listening for locations.
-     * Called with enable set to true when the first client is added and
-     * called with enable set to false when the last client is removed.
-     * This allows the provider to prepare for receiving locations,
-     * and to shut down when no clients are remaining.
-     *
-     * @param enable true if location tracking should be enabled.
-     */
-    public void enableLocationTracking(boolean enable) {
-        mLocationTracking = enable;
-    }
-
-    /**
-     * Returns true if the provider has any listeners
-     *
-     * @return true if provider is being tracked
-     */
-    public boolean isLocationTracking() {
-        return mLocationTracking;
-    }
-
-    /**
-     * Notifies the location provider of the smallest minimum time between updates amongst
-     * all clients that are listening for locations.  This allows the provider to reduce
-     * the frequency of updates to match the requested frequency.
-     *
-     * @param minTime the smallest minTime value over all listeners for this provider.
-     */
-    public void setMinTime(long minTime) {
-        mMinTime = minTime;
-    }
-
-    /**
-     * Gets the smallest minimum time between updates amongst all the clients listening
-     * for locations. By default this value is 0 (as frqeuently as possible)
-     *
-     * @return the smallest minTime value over all listeners for this provider
-     */
-    public long getMinTime() {
-        return mMinTime;
-    }
-
-    /**
-     * Updates the network state for the given provider. This function must
-     * be overwritten if {@link #requiresNetwork} returns true. The state is
-     * {@link #TEMPORARILY_UNAVAILABLE} (disconnected), OR {@link #AVAILABLE}
-     * (connected or connecting).
-     *
-     * @param state data state
-     */
-    public void updateNetworkState(int state) {
-    }
-
-    /**
-     * Implements addditional location provider specific additional commands.
-     *
-     * @param command name of the command to send to the provider.
-     * @param extras optional arguments for the command (or null).
-     * The provider may optionally fill the extras Bundle with results from the command.
-     *
-     * @return true if the command succeeds. 
-     */
-    public boolean sendExtraCommand(String command, Bundle extras) {
-        return false;
-    }
-
-    /**
-     * Informs the location provider when a new client is listening for location information
-     *
-     * @param uid the uid of the client proces
-     */
-    public void addListener(int uid) {
-    }
-
-    /**
-     * Informs the location provider when a client is no longer listening for location information
-     *
-     * @param uid the uid of the client proces
-     */
-    public void removeListener(int uid) {
-    }
-
-    /**
-     * Informs the location provider when the location manager service has acquired its wake lock
-     */
-    public void wakeLockAcquired() {
-    }
-
-    /**
-     * Informs the location provider when the location manager service has released its wake lock
-     */
-    public void wakeLockReleased() {
-    }
-}
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index d3c86db..abca28f 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -17,7 +17,6 @@
 package com.android.internal.location;
 
 import android.location.Address;
-import android.location.ILocationManager;
 import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationManager;
@@ -32,19 +31,24 @@
  *
  * {@hide}
  */
-public class LocationProviderProxy extends LocationProviderImpl {
+public class LocationProviderProxy {
 
     private static final String TAG = "LocationProviderProxy";
 
+    private final String mName;
     private final ILocationProvider mProvider;
+    private boolean mLocationTracking = false;
+    private long mMinTime = 0;
 
-    public LocationProviderProxy(String name, ILocationManager locationManager,
-            ILocationProvider provider) {
-        super(name, locationManager);
+    public LocationProviderProxy(String name, ILocationProvider provider) {
+        mName = name;
         mProvider = provider;
     }
 
-    @Override
+    public String getName() {
+        return mName;
+    }
+
     public boolean requiresNetwork() {
         try {
             return mProvider.requiresNetwork();
@@ -54,7 +58,6 @@
         }
     }
 
-    @Override
     public boolean requiresSatellite() {
         try {
             return mProvider.requiresSatellite();
@@ -64,7 +67,6 @@
         }
     }
 
-    @Override
     public boolean requiresCell() {
         try {
             return mProvider.requiresCell();
@@ -74,7 +76,6 @@
         }
     }
 
-    @Override
     public boolean hasMonetaryCost() {
         try {
             return mProvider.hasMonetaryCost();
@@ -84,7 +85,6 @@
         }
     }
 
-    @Override
     public boolean supportsAltitude() {
         try {
             return mProvider.supportsAltitude();
@@ -94,7 +94,6 @@
         }
     }
 
-    @Override
     public boolean supportsSpeed() {
         try {
             return mProvider.supportsSpeed();
@@ -104,8 +103,7 @@
         }
     }
 
-     @Override
-    public boolean supportsBearing() {
+     public boolean supportsBearing() {
         try {
             return mProvider.supportsBearing();
         } catch (RemoteException e) {
@@ -114,7 +112,6 @@
         }
     }
 
-    @Override
     public int getPowerRequirement() {
         try {
             return mProvider.getPowerRequirement();
@@ -124,7 +121,6 @@
         }
     }
 
-    @Override
     public int getAccuracy() {
         try {
             return mProvider.getAccuracy();
@@ -134,7 +130,6 @@
         }
     }
 
-    @Override
     public void enable() {
         try {
             mProvider.enable();
@@ -143,7 +138,6 @@
         }
     }
 
-    @Override
     public void disable() {
         try {
             mProvider.disable();
@@ -152,7 +146,6 @@
         }
     }
 
-    @Override
     public boolean isEnabled() {
         try {
             return mProvider.isEnabled();
@@ -162,7 +155,6 @@
         }
     }
 
-    @Override
     public int getStatus(Bundle extras) {
         try {
             return mProvider.getStatus(extras);
@@ -172,7 +164,6 @@
         }
     }
 
-    @Override
     public long getStatusUpdateTime() {
         try {
             return mProvider.getStatusUpdateTime();
@@ -182,27 +173,32 @@
         }
     }
 
-    @Override
+    public boolean isLocationTracking() {
+        return mLocationTracking;
+    }
+
     public void enableLocationTracking(boolean enable) {
+        mLocationTracking = enable;
         try {
-            super.enableLocationTracking(enable);
             mProvider.enableLocationTracking(enable);
         } catch (RemoteException e) {
             Log.e(TAG, "enableLocationTracking failed", e);
         }
     }
 
-    @Override
+    public long getMinTime() {
+        return mMinTime;
+    }
+
     public void setMinTime(long minTime) {
+        mMinTime = minTime;
         try {
-            super.setMinTime(minTime);
             mProvider.setMinTime(minTime);
         } catch (RemoteException e) {
             Log.e(TAG, "setMinTime failed", e);
         }
     }
 
-    @Override
     public void updateNetworkState(int state) {
         try {
             mProvider.updateNetworkState(state);
@@ -211,7 +207,6 @@
         }
     }
 
-    @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
         try {
             return mProvider.sendExtraCommand(command, extras);
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 6336e2b..6fa2c29 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -17,8 +17,12 @@
 package com.android.internal.location;
 
 import android.location.ILocationManager;
+import android.location.ILocationProvider;
 import android.location.Location;
+import android.location.LocationProvider;
 import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
 import android.util.PrintWriterPrinter;
 
 import java.io.PrintWriter;
@@ -28,7 +32,9 @@
  *
  * {@hide}
  */
-public class MockProvider extends LocationProviderImpl {
+public class MockProvider extends ILocationProvider.Stub {
+    private final String mName;
+    private final ILocationManager mLocationManager;
     private final boolean mRequiresNetwork;
     private final boolean mRequiresSatellite;
     private final boolean mRequiresCell;
@@ -46,12 +52,14 @@
     private boolean mHasStatus;
     private boolean mEnabled;
 
+    private static final String TAG = "MockProvider";
+
     public MockProvider(String name,  ILocationManager locationManager,
         boolean requiresNetwork, boolean requiresSatellite,
         boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
-        super(name, locationManager);
-
+        mName = name;
+        mLocationManager = locationManager;
         mRequiresNetwork = requiresNetwork;
         mRequiresSatellite = requiresSatellite;
         mRequiresCell = requiresCell;
@@ -64,78 +72,64 @@
         mLocation = new Location(name);
     }
 
-    @Override
     public void disable() {
         mEnabled = false;
     }
 
-    @Override
     public void enable() {
         mEnabled = true;
     }
 
-    @Override
     public int getStatus(Bundle extras) {
         if (mHasStatus) {
             extras.clear();
             extras.putAll(mExtras);
             return mStatus;
         } else {
-            return AVAILABLE;
+            return LocationProvider.AVAILABLE;
         }
     }
 
-    @Override
     public long getStatusUpdateTime() {
         return mStatusUpdateTime;
     }
 
-    @Override
     public boolean isEnabled() {
         return mEnabled;
     }
 
-    @Override
     public int getAccuracy() {
         return mAccuracy;
     }
 
-    @Override
     public int getPowerRequirement() {
         return mPowerRequirement;
     }
 
-    @Override
     public boolean hasMonetaryCost() {
         return mHasMonetaryCost;
     }
 
-    @Override
     public boolean requiresCell() {
         return mRequiresCell;
     }
 
-    @Override
     public boolean requiresNetwork() {
         return mRequiresNetwork;
     }
 
-    @Override
     public boolean requiresSatellite() {
         return mRequiresSatellite;
     }
 
-    @Override
     public boolean supportsAltitude() {
         return mSupportsAltitude;
     }
 
-    @Override
     public boolean supportsBearing() {
         return mSupportsBearing;
     }
 
-    @Override
     public boolean supportsSpeed() {
         return mSupportsSpeed;
     }
@@ -143,7 +137,11 @@
     public void setLocation(Location l) {
         mLocation.set(l);
         mHasLocation = true;
-        reportLocationChanged(mLocation);
+        try {
+            mLocationManager.setLocation(mLocation);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling reportLocation");
+        }
     }
 
     public void clearLocation() {
@@ -165,8 +163,33 @@
         mStatusUpdateTime = 0;
     }
 
+    public void enableLocationTracking(boolean enable) {
+    }
+
+    public void setMinTime(long minTime) {
+    }
+
+    public void updateNetworkState(int state) {
+    }
+
+    public boolean sendExtraCommand(String command, Bundle extras) {
+        return false;
+    }
+
+    public void addListener(int uid) {
+    }
+
+    public void removeListener(int uid) {
+    }
+
+    public void wakeLockAcquired() {
+    }
+
+    public void wakeLockReleased() {
+    }
+
     public void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + getName());
+        pw.println(prefix + mName);
         pw.println(prefix + "mHasLocation=" + mHasLocation);
         pw.println(prefix + "mLocation:");
         mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 0e1e0d9..d44abaa 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -46,6 +46,7 @@
 import android.location.Address;
 import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
+import android.location.IGpsStatusProvider;
 import android.location.ILocationCollector;
 import android.location.ILocationListener;
 import android.location.ILocationManager;
@@ -72,7 +73,6 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.location.GpsLocationProvider;
-import com.android.internal.location.LocationProviderImpl;
 import com.android.internal.location.LocationProviderProxy;
 import com.android.internal.location.MockProvider;
 import com.android.server.am.BatteryStatsService;
@@ -119,9 +119,10 @@
     private static boolean sProvidersLoaded = false;
 
     private final Context mContext;
-    private GpsLocationProvider mGpsLocationProvider;
+    private LocationProviderProxy mGpsLocationProvider;
     private LocationProviderProxy mNetworkLocationProvider;
     private IGeocodeProvider mGeocodeProvider;
+    private IGpsStatusProvider mGpsStatusProvider;
     private LocationWorkerHandler mLocationHandler;
 
     // Handler messages
@@ -143,6 +144,15 @@
      */
     private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
 
+
+    /**
+     * List of location providers.
+     */
+    private final ArrayList<LocationProviderProxy> mProviders =
+        new ArrayList<LocationProviderProxy>();
+    private final HashMap<String, LocationProviderProxy> mProvidersByName
+        = new HashMap<String, LocationProviderProxy>();
+
     /**
      * Object used internally for synchronization
      */
@@ -502,6 +512,16 @@
         }
     }
 
+    private void addProvider(LocationProviderProxy provider) {
+        mProviders.add(provider);
+        mProvidersByName.put(provider.getName(), provider);
+    }
+
+    private void removeProvider(LocationProviderProxy provider) {
+        mProviders.remove(provider);
+        mProvidersByName.remove(provider.getName());
+    }
+
     /**
      * Load providers from /data/location/<provider_name>/
      *                                                          class
@@ -535,8 +555,11 @@
         // Attempt to load "real" providers first
         if (GpsLocationProvider.isSupported()) {
             // Create a gps location provider
-            mGpsLocationProvider = new GpsLocationProvider(mContext, this);
-            LocationProviderImpl.addProvider(mGpsLocationProvider);
+            GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
+            mGpsStatusProvider = provider.getGpsStatusProvider();
+            mGpsLocationProvider =
+                    new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
+            addProvider(mGpsLocationProvider);
         }
 
         updateProvidersLocked();
@@ -611,8 +634,8 @@
 
         synchronized (mLock) {
             mNetworkLocationProvider =
-                    new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, this, provider);
-            LocationProviderImpl.addProvider(mNetworkLocationProvider);
+                    new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, provider);
+            addProvider(mNetworkLocationProvider);
             updateProvidersLocked();
             
             // notify NetworkLocationProvider of any events it might have missed
@@ -703,10 +726,9 @@
         if (LOCAL_LOGV) {
             Log.v(TAG, "getAllProviders");
         }
-        ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-        ArrayList<String> out = new ArrayList<String>(providers.size());
-        for (int i = providers.size() - 1; i >= 0; i--) {
-            LocationProviderImpl p = providers.get(i);
+        ArrayList<String> out = new ArrayList<String>(mProviders.size());
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            LocationProviderProxy p = mProviders.get(i);
             out.add(p.getName());
         }
         return out;
@@ -729,10 +751,9 @@
         if (LOCAL_LOGV) {
             Log.v(TAG, "getProviders");
         }
-        ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-        ArrayList<String> out = new ArrayList<String>(providers.size());
-        for (int i = providers.size() - 1; i >= 0; i--) {
-            LocationProviderImpl p = providers.get(i);
+        ArrayList<String> out = new ArrayList<String>(mProviders.size());
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            LocationProviderProxy p = mProviders.get(i);
             String name = p.getName();
             if (isAllowedProviderSafe(name)) {
                 if (enabledOnly && !isAllowedBySettingsLocked(name)) {
@@ -745,9 +766,8 @@
     }
 
     private void updateProvidersLocked() {
-        ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-        for (int i = providers.size() - 1; i >= 0; i--) {
-            LocationProviderImpl p = providers.get(i);
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            LocationProviderProxy p = mProviders.get(i);
             boolean isEnabled = p.isEnabled();
             String name = p.getName();
             boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
@@ -764,7 +784,7 @@
     private void updateProviderListenersLocked(String provider, boolean enabled) {
         int listeners = 0;
 
-        LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+        LocationProviderProxy p = mProvidersByName.get(provider);
         if (p == null) {
             return;
         }
@@ -966,8 +986,8 @@
             Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
         }
 
-        LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
-        if (impl == null) {
+        LocationProviderProxy proxy = mProvidersByName.get(provider);
+        if (proxy == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
 
@@ -985,14 +1005,14 @@
             }
 
             if (newUid) {
-                impl.addListener(callingUid);
+                proxy.addListener(callingUid);
             }
 
             boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
             if (isProviderEnabled) {
                 long minTimeForProvider = getMinTimeLocked(provider);
-                impl.setMinTime(minTimeForProvider);
-                impl.enableLocationTracking(true);
+                proxy.setMinTime(minTimeForProvider);
+                proxy.enableLocationTracking(true);
                 updateWakelockStatusLocked();
             } else {
                 // Notify the listener that updates are currently disabled
@@ -1047,10 +1067,9 @@
                 // Call dispose() on the obsolete update records.
                 for (UpdateRecord record : oldRecords.values()) {
                     if (!providerHasListener(record.mProvider, callingUid, receiver)) {
-                        LocationProviderImpl impl =
-                                LocationProviderImpl.getProvider(record.mProvider);
-                        if (impl != null) {
-                            impl.removeListener(callingUid);
+                        LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
+                        if (proxy != null) {
+                            proxy.removeListener(callingUid);
                         }
                     }
                     record.disposeLocked();
@@ -1074,7 +1093,7 @@
                     hasOtherListener = true;
                 }
 
-                LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+                LocationProviderProxy p = mProvidersByName.get(provider);
                 if (p != null) {
                     if (hasOtherListener) {
                         p.setMinTime(getMinTimeLocked(provider));
@@ -1091,7 +1110,7 @@
     }
 
     public boolean addGpsStatusListener(IGpsStatusListener listener) {
-        if (mGpsLocationProvider == null) {
+        if (mGpsStatusProvider == null) {
             return false;
         }
         if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) !=
@@ -1100,9 +1119,9 @@
         }
 
         try {
-            mGpsLocationProvider.addGpsStatusListener(listener);
+            mGpsStatusProvider.addGpsStatusListener(listener);
         } catch (RemoteException e) {
-            Log.w(TAG, "RemoteException in addGpsStatusListener");
+            Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
             return false;
         }
         return true;
@@ -1110,7 +1129,11 @@
 
     public void removeGpsStatusListener(IGpsStatusListener listener) {
         synchronized (mLock) {
-            mGpsLocationProvider.removeGpsStatusListener(listener);
+            try {
+                mGpsStatusProvider.removeGpsStatusListener(listener);
+            } catch (Exception e) {
+                Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
+            }
         }
     }
 
@@ -1124,12 +1147,12 @@
         }
 
         synchronized (mLock) {
-            LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
+            LocationProviderProxy proxy = mProvidersByName.get(provider);
             if (provider == null) {
                 return false;
             }
     
-            return impl.sendExtraCommand(command, extras);
+            return proxy.sendExtraCommand(command, extras);
         }
     }
 
@@ -1359,14 +1382,12 @@
             mProximityListener = new ProximityListener();
             mProximityReceiver = new Receiver(mProximityListener);
 
-            LocationProvider provider = LocationProviderImpl.getProvider(
-                LocationManager.GPS_PROVIDER);
+            LocationProviderProxy provider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
             if (provider != null) {
                 requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
             }
 
-            provider =
-                LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER);
+            provider = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
             if (provider != null) {
                 requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
             }
@@ -1417,7 +1438,7 @@
     }
 
     private Bundle _getProviderInfoLocked(String provider) {
-        LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+        LocationProviderProxy p = mProvidersByName.get(provider);
         if (p == null) {
             return null;
         }
@@ -1460,7 +1481,7 @@
     private boolean _isProviderEnabledLocked(String provider) {
         checkPermissionsSafe(provider);
 
-        LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+        LocationProviderProxy p = mProvidersByName.get(provider);
         if (p == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
@@ -1483,7 +1504,7 @@
     private Location _getLastKnownLocationLocked(String provider) {
         checkPermissionsSafe(provider);
 
-        LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+        LocationProviderProxy p = mProvidersByName.get(provider);
         if (p == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
@@ -1534,7 +1555,7 @@
             return;
         }
 
-        LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
+        LocationProviderProxy p = mProvidersByName.get(provider);
         if (p == null) {
             return;
         }
@@ -1550,9 +1571,8 @@
 
         if (LocationManager.NETWORK_PROVIDER.equals(p.getName())) {
             mWakeLockNetworkReceived = true;
-        } else if (p instanceof GpsLocationProvider) {
-            // Gps location received signal is in NetworkStateBroadcastReceiver
         }
+        // Gps location received signal is in NetworkStateBroadcastReceiver
 
         // Fetch latest status update time
         long newStatusUpdateTime = p.getStatusUpdateTime();
@@ -1720,9 +1740,8 @@
 
                 // Notify location providers of current network state
                 synchronized (mLock) {
-                    ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-                    for (int i = providers.size() - 1; i >= 0; i--) {
-                        LocationProviderImpl provider = providers.get(i);
+                    for (int i = mProviders.size() - 1; i >= 0; i--) {
+                        LocationProviderProxy provider = mProviders.get(i);
                         if (provider.requiresNetwork()) {
                             provider.updateNetworkState(mNetworkState);
                         }
@@ -1930,10 +1949,10 @@
                 requiresNetwork, requiresSatellite,
                 requiresCell, hasMonetaryCost, supportsAltitude,
                 supportsSpeed, supportsBearing, powerRequirement, accuracy);
-            if (LocationProviderImpl.getProvider(name) != null) {
+            if (mProvidersByName.get(name) != null) {
                 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
             }
-            LocationProviderImpl.addProvider(provider);
+            addProvider(new LocationProviderProxy(name, provider));
             mMockProviders.put(name, provider);
             updateProvidersLocked();
         }
@@ -1946,7 +1965,7 @@
             if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
-            LocationProviderImpl.removeProvider(mockProvider);
+            removeProvider(mProvidersByName.get(provider));
             mMockProviders.remove(mockProvider);
             updateProvidersLocked();
         }
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index 0fc3d16..500786d 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -19,17 +19,19 @@
 
 import android.location.Criteria;
 import android.location.ILocationManager;
+import android.location.ILocationProvider;
 import android.location.Location;
+import android.location.LocationProvider;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.SystemClock;
-
-import com.android.internal.location.LocationProviderImpl;
+import android.util.Log;
 
 /**
  * @hide - This is part of a framework that is under development and should not be used for
  * active development.
  */
-public class TestLocationProvider extends LocationProviderImpl {
+public class TestLocationProvider extends ILocationProvider.Stub {
 
     public static final String PROVIDER_NAME = "test";
     public static final double LAT = 0;
@@ -37,9 +39,12 @@
     public static final double ALTITUDE = 10000;
     public static final float SPEED = 10;
     public static final float BEARING = 1;
-    public static final int STATUS = AVAILABLE;
+    public static final int STATUS = LocationProvider.AVAILABLE;
     private static final long LOCATION_INTERVAL = 1000;
 
+    private static final String TAG = "TestLocationProvider";
+
+    private final ILocationManager mLocationManager;
     private Location mLocation;
     private boolean mEnabled;
     private TestLocationProviderThread mThread;
@@ -75,59 +80,46 @@
     }
 
     public TestLocationProvider(ILocationManager locationManager) {
-        super(PROVIDER_NAME, locationManager);
+        mLocationManager = locationManager;
         mLocation = new Location(PROVIDER_NAME);
     }
 
-    //LocationProvider methods
-
-    @Override
     public int getAccuracy() {
         return Criteria.ACCURACY_COARSE;
     }
 
-    @Override
     public int getPowerRequirement() {
         return Criteria.NO_REQUIREMENT;
     }
 
-    @Override
     public boolean hasMonetaryCost() {
         return false;
     }
 
-    @Override
     public boolean requiresCell() {
         return false;
     }
 
-    @Override
     public boolean requiresNetwork() {
         return false;
     }
 
-    @Override
     public boolean requiresSatellite() {
         return false;
     }
 
-    @Override
     public boolean supportsAltitude() {
         return true;
     }
 
-    @Override
     public boolean supportsBearing() {
         return true;
     }
 
-    @Override
     public boolean supportsSpeed() {
         return true;
     }
 
-    //LocationProviderImpl methods
-    @Override
     public synchronized void disable() {
         mEnabled = false;
         if (mThread != null) {
@@ -140,23 +132,49 @@
         }
     }
 
-    @Override
     public synchronized void enable() {
        mEnabled = true;
         mThread = new TestLocationProviderThread();
         mThread.start();
     }
 
-    @Override
     public boolean isEnabled() {
         return mEnabled;
     }
 
-    @Override
     public int getStatus(Bundle extras) {
         return STATUS;
     }
 
+    public long getStatusUpdateTime() {
+        return 0;
+    }
+
+    public void enableLocationTracking(boolean enable) {
+    }
+
+    public void setMinTime(long minTime) {
+    }
+
+    public void updateNetworkState(int state) {
+    }
+
+    public boolean sendExtraCommand(String command, Bundle extras) {
+        return false;
+    }
+
+    public void addListener(int uid) {
+    }
+
+    public void removeListener(int uid) {
+    }
+
+    public void wakeLockAcquired() {
+    }
+
+    public void wakeLockReleased() {
+    }
+
     private void updateLocation() {
         long time = SystemClock.uptimeMillis();
         long multiplier = (time/5000)%500000;
@@ -170,7 +188,11 @@
         extras.putInt("extraTest", 24);
         mLocation.setExtras(extras);
         mLocation.setTime(time);
-        reportLocationChanged(mLocation);
+        try {
+            mLocationManager.setLocation(mLocation);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling updateLocation");
+        }
     }
 
 }