diff options
Diffstat (limited to 'content/public/android')
-rw-r--r-- | content/public/android/OWNERS | 4 | ||||
-rw-r--r-- | content/public/android/java/content.xml | 1 | ||||
-rw-r--r-- | content/public/android/java/org/chromium/content/browser/LocationProvider.java | 232 |
3 files changed, 237 insertions, 0 deletions
diff --git a/content/public/android/OWNERS b/content/public/android/OWNERS new file mode 100644 index 0000000..a35ceee --- /dev/null +++ b/content/public/android/OWNERS @@ -0,0 +1,4 @@ +satish@chromium.org +bulach@chromium.org +jrg@chromium.org +yfriedman@chromium.org diff --git a/content/public/android/java/content.xml b/content/public/android/java/content.xml index a00a4e5..435cbab 100644 --- a/content/public/android/java/content.xml +++ b/content/public/android/java/content.xml @@ -40,6 +40,7 @@ <javac srcdir="${src}" destdir="${classes.dir}"> <classpath> <path location="${location.base}/android.jar"/> + <path location="${PRODUCT_DIR}/chromium_base.jar"/> </classpath> </javac> </target> diff --git a/content/public/android/java/org/chromium/content/browser/LocationProvider.java b/content/public/android/java/org/chromium/content/browser/LocationProvider.java new file mode 100644 index 0000000..6a89eef --- /dev/null +++ b/content/public/android/java/org/chromium/content/browser/LocationProvider.java @@ -0,0 +1,232 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser; + +import android.content.Context; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.Looper; +import android.util.Log; + +import org.chromium.base.ActivityStatus; +import org.chromium.base.CalledByNative; +import org.chromium.base.ThreadUtils; + +import java.util.concurrent.FutureTask; + +/** + * Implements the Java side of LocationProviderAndroid. + * Delegates all real functionality to the inner class. + * See detailed documentation on + * content/browser/geolocation/android_location_api_adapter.h. + * Based on android.webkit.GeolocationService.java + */ +class LocationProvider { + + // Log tag + private static final String TAG = "LocationProvider"; + + /** + * This is the core of android location provider. It is a separate class for clarity + * so that it can manage all processing completely in the UI thread. The container class + * ensures that the start/stop calls into this class are done in the UI thread. + */ + private static class LocationProviderImpl + implements LocationListener, ActivityStatus.Listener { + + private Context mContext; + private LocationManager mLocationManager; + private boolean mIsRunning; + private boolean mShouldRunAfterActivityResume; + private boolean mIsGpsEnabled; + + LocationProviderImpl(Context context) { + mContext = context; + } + + public void onActivityStatusChanged(boolean isPaused) { + if (isPaused) { + mShouldRunAfterActivityResume = mIsRunning; + unregisterFromLocationUpdates(); + } else { + assert !mIsRunning; + if (mShouldRunAfterActivityResume) { + registerForLocationUpdates(); + } + } + } + + /** + * Start listening for location updates. + * @param gpsEnabled Whether or not we're interested in high accuracy GPS. + */ + private void start(boolean gpsEnabled) { + if (!mIsRunning && !mShouldRunAfterActivityResume) { + // Currently idle so start listening to activity status changes. + ActivityStatus.getInstance().registerListener(this); + } + mIsGpsEnabled = gpsEnabled; + if (ActivityStatus.getInstance().isPaused()) { + mShouldRunAfterActivityResume = true; + } else { + unregisterFromLocationUpdates(); + registerForLocationUpdates(); + } + } + + /** + * Stop listening for location updates. + */ + private void stop() { + unregisterFromLocationUpdates(); + ActivityStatus.getInstance().unregisterListener(this); + mShouldRunAfterActivityResume = false; + } + + /** + * Returns true if we are currently listening for location updates, false if not. + */ + private boolean isRunning() { + return mIsRunning; + } + + @Override + public void onLocationChanged(Location location) { + // Callbacks from the system location sevice are queued to this thread, so it's + // possible that we receive callbacks after unregistering. At this point, the + // native object will no longer exist. + if (mIsRunning) { + nativeNewLocationAvailable(location.getLatitude(), location.getLongitude(), + location.getTime(), location.hasAltitude(), location.getAltitude(), + location.hasAccuracy(), location.getAccuracy(), + location.hasBearing(), location.getBearing(), + location.hasSpeed(), location.getSpeed()); + } + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + + @Override + public void onProviderEnabled(String provider) { + } + + @Override + public void onProviderDisabled(String provider) { + } + + private void ensureLocationManagerCreated() { + if (mLocationManager != null) return; + mLocationManager = (LocationManager) mContext.getSystemService( + Context.LOCATION_SERVICE); + if (mLocationManager == null) { + Log.e(TAG, "Could not get location manager."); + } + } + + /** + * Registers this object with the location service. + */ + private void registerForLocationUpdates() { + ensureLocationManagerCreated(); + + assert !mIsRunning; + mIsRunning = true; + + // We're running on the main thread. The C++ side is responsible to + // bounce notifications to the Geolocation thread as they arrive in the mainLooper. + try { + Criteria criteria = new Criteria(); + mLocationManager.requestLocationUpdates(0, 0, criteria, this, + Looper.getMainLooper()); + if (mIsGpsEnabled) { + criteria.setAccuracy(Criteria.ACCURACY_FINE); + mLocationManager.requestLocationUpdates(0, 0, criteria, this, + Looper.getMainLooper()); + } + } catch(SecurityException e) { + Log.e(TAG, "Caught security exception registering for location updates from " + + "system. This should only happen in DumpRenderTree."); + } catch(IllegalArgumentException e) { + Log.e(TAG, "Caught IllegalArgumentException registering for location updates."); + } + } + + /** + * Unregisters this object from the location service. + */ + private void unregisterFromLocationUpdates() { + if (mIsRunning) { + mIsRunning = false; + mLocationManager.removeUpdates(this); + } + } + } + + // Delegate handling the real work in the main thread. + private LocationProviderImpl mImpl; + + private LocationProvider(Context context) { + mImpl = new LocationProviderImpl(context); + } + + @CalledByNative + static LocationProvider create(Context context) { + return new LocationProvider(context); + } + + /** + * Start listening for location updates until we're told to quit. May be + * called in any thread. + * @param gpsEnabled Whether or not we're interested in high accuracy GPS. + */ + @CalledByNative + public boolean start(final boolean gpsEnabled) { + FutureTask<Void> task = new FutureTask<Void>(new Runnable() { + @Override + public void run() { + mImpl.start(gpsEnabled); + } + }, null); + ThreadUtils.runOnUiThread(task); + return true; + } + + /** + * Stop listening for location updates. May be called in any thread. + */ + @CalledByNative + public void stop() { + FutureTask<Void> task = new FutureTask<Void>(new Runnable() { + @Override + public void run() { + mImpl.stop(); + } + }, null); + ThreadUtils.runOnUiThread(task); + } + + /** + * Returns true if we are currently listening for location updates, false if not. + * Must be called only in the UI thread. + */ + public boolean isRunning() { + assert Looper.myLooper() == Looper.getMainLooper(); + return mImpl.isRunning(); + } + + // Native functions + public static native void nativeNewLocationAvailable( + double latitude, double longitude, long timeStamp, + boolean hasAltitude, double altitude, + boolean hasAccuracy, double accuracy, + boolean hasHeading, double heading, + boolean hasSpeed, double speed); + public static native void nativeNewErrorAvailable(String message); +} |