summaryrefslogtreecommitdiffstats
path: root/content/public/android
diff options
context:
space:
mode:
Diffstat (limited to 'content/public/android')
-rw-r--r--content/public/android/OWNERS4
-rw-r--r--content/public/android/java/content.xml1
-rw-r--r--content/public/android/java/org/chromium/content/browser/LocationProvider.java232
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);
+}