Home | History | Annotate | Download | only in webkit
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.webkit;
     18 
     19 import android.app.ActivityThread;
     20 import android.content.Context;
     21 import android.location.Location;
     22 import android.location.LocationListener;
     23 import android.location.LocationManager;
     24 import android.location.LocationProvider;
     25 import android.os.Bundle;
     26 import android.util.Log;
     27 import android.webkit.WebView;
     28 import android.webkit.WebViewCore;
     29 
     30 
     31 /**
     32  * Implements the Java side of GeolocationServiceAndroid.
     33  */
     34 final class GeolocationService implements LocationListener {
     35 
     36     // Log tag
     37     private static final String TAG = "geolocationService";
     38 
     39     private long mNativeObject;
     40     private LocationManager mLocationManager;
     41     private boolean mIsGpsEnabled;
     42     private boolean mIsRunning;
     43     private boolean mIsNetworkProviderAvailable;
     44     private boolean mIsGpsProviderAvailable;
     45 
     46     /**
     47      * Constructor
     48      * @param nativeObject The native object to which this object will report position updates and
     49      *     errors.
     50      */
     51     public GeolocationService(long nativeObject) {
     52         mNativeObject = nativeObject;
     53         // Register newLocationAvailable with platform service.
     54         ActivityThread thread = ActivityThread.systemMain();
     55         Context context = thread.getApplication();
     56         mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
     57         if (mLocationManager == null) {
     58             Log.e(TAG, "Could not get location manager.");
     59         }
     60      }
     61 
     62     /**
     63      * Start listening for location updates.
     64      */
     65     public void start() {
     66         registerForLocationUpdates();
     67         mIsRunning = true;
     68     }
     69 
     70     /**
     71      * Stop listening for location updates.
     72      */
     73     public void stop() {
     74         unregisterFromLocationUpdates();
     75         mIsRunning = false;
     76     }
     77 
     78     /**
     79      * Sets whether to use the GPS.
     80      * @param enable Whether to use the GPS.
     81      */
     82     public void setEnableGps(boolean enable) {
     83         if (mIsGpsEnabled != enable) {
     84             mIsGpsEnabled = enable;
     85             if (mIsRunning) {
     86                 // There's no way to unregister from a single provider, so we can
     87                 // only unregister from all, then reregister with all but the GPS.
     88                 unregisterFromLocationUpdates();
     89                 registerForLocationUpdates();
     90             }
     91         }
     92     }
     93 
     94     /**
     95      * LocationListener implementation.
     96      * Called when the location has changed.
     97      * @param location The new location, as a Location object.
     98      */
     99     public void onLocationChanged(Location location) {
    100         // Callbacks from the system location sevice are queued to this thread, so it's possible
    101         // that we receive callbacks after unregistering. At this point, the native object will no
    102         // longer exist.
    103         if (mIsRunning) {
    104             nativeNewLocationAvailable(mNativeObject, location);
    105         }
    106     }
    107 
    108     /**
    109      * LocationListener implementation.
    110      * Called when the provider status changes.
    111      * @param provider The name of the provider.
    112      * @param status The new status of the provider.
    113      * @param extras an optional Bundle with provider specific data.
    114      */
    115     public void onStatusChanged(String providerName, int status, Bundle extras) {
    116         boolean isAvailable = (status == LocationProvider.AVAILABLE);
    117         if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
    118             mIsNetworkProviderAvailable = isAvailable;
    119         } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
    120             mIsGpsProviderAvailable = isAvailable;
    121         }
    122         maybeReportError("The last location provider is no longer available");
    123     }
    124 
    125     /**
    126      * LocationListener implementation.
    127      * Called when the provider is enabled.
    128      * @param provider The name of the location provider that is now enabled.
    129      */
    130     public void onProviderEnabled(String providerName) {
    131         // No need to notify the native side. It's enough to start sending
    132         // valid position fixes again.
    133         if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
    134             mIsNetworkProviderAvailable = true;
    135         } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
    136             mIsGpsProviderAvailable = true;
    137         }
    138     }
    139 
    140     /**
    141      * LocationListener implementation.
    142      * Called when the provider is disabled.
    143      * @param provider The name of the location provider that is now disabled.
    144      */
    145     public void onProviderDisabled(String providerName) {
    146         if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
    147             mIsNetworkProviderAvailable = false;
    148         } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
    149             mIsGpsProviderAvailable = false;
    150         }
    151         maybeReportError("The last location provider was disabled");
    152     }
    153 
    154     /**
    155      * Registers this object with the location service.
    156      */
    157     private void registerForLocationUpdates() {
    158         try {
    159             mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
    160             mIsNetworkProviderAvailable = true;
    161             if (mIsGpsEnabled) {
    162                 mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    163                 mIsGpsProviderAvailable = true;
    164             }
    165         } catch(SecurityException e) {
    166             Log.e(TAG, "Caught security exception registering for location updates from system. " +
    167                 "This should only happen in DumpRenderTree.");
    168         }
    169     }
    170 
    171     /**
    172      * Unregisters this object from the location service.
    173      */
    174     private void unregisterFromLocationUpdates() {
    175         mLocationManager.removeUpdates(this);
    176     }
    177 
    178     /**
    179      * Reports an error if neither the network nor the GPS provider is available.
    180      */
    181     private void maybeReportError(String message) {
    182         // Callbacks from the system location sevice are queued to this thread, so it's possible
    183         // that we receive callbacks after unregistering. At this point, the native object will no
    184         // longer exist.
    185         if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) {
    186             nativeNewErrorAvailable(mNativeObject, message);
    187         }
    188     }
    189 
    190     // Native functions
    191     private static native void nativeNewLocationAvailable(long nativeObject, Location location);
    192     private static native void nativeNewErrorAvailable(long nativeObject, String message);
    193 }
    194