Index: content/browser/geolocation/location_api_adapter_android.cc |
diff --git a/content/browser/geolocation/location_api_adapter_android.cc b/content/browser/geolocation/location_api_adapter_android.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..980d1bda3ab95812b15173556f08c0e4885ea04a |
--- /dev/null |
+++ b/content/browser/geolocation/location_api_adapter_android.cc |
@@ -0,0 +1,172 @@ |
+// 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. |
+ |
+#include "content/browser/geolocation/location_api_adapter_android.h" |
+ |
+#include "base/android/context_utils.h" |
+#include "base/android/jni_android.h" |
+#include "base/android/jni_string.h" |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "base/threading/thread_task_runner_handle.h" |
+#include "content/browser/geolocation/location_provider_android.h" |
+#include "jni/LocationProviderAdapter_jni.h" |
+ |
+using base::android::AttachCurrentThread; |
+using base::android::CheckException; |
+using base::android::ClearException; |
+using content::AndroidLocationApiAdapter; |
+ |
+static void NewLocationAvailable(JNIEnv* env, |
+ const JavaParamRef<jclass>&, |
+ jdouble latitude, |
+ jdouble longitude, |
+ jdouble time_stamp, |
+ jboolean has_altitude, |
+ jdouble altitude, |
+ jboolean has_accuracy, |
+ jdouble accuracy, |
+ jboolean has_heading, |
+ jdouble heading, |
+ jboolean has_speed, |
+ jdouble speed) { |
+ AndroidLocationApiAdapter::OnNewLocationAvailable(latitude, longitude, |
+ time_stamp, has_altitude, altitude, has_accuracy, accuracy, |
+ has_heading, heading, has_speed, speed); |
+} |
+ |
+static void NewErrorAvailable(JNIEnv* env, |
+ const JavaParamRef<jclass>&, |
+ const JavaParamRef<jstring>& message) { |
+ AndroidLocationApiAdapter::OnNewErrorAvailable(env, message); |
+} |
+ |
+namespace content { |
+ |
+AndroidLocationApiAdapter::AndroidLocationApiAdapter() |
+ : location_provider_(NULL) { |
+} |
+ |
+AndroidLocationApiAdapter::~AndroidLocationApiAdapter() { |
+ CHECK(!location_provider_); |
+ CHECK(!task_runner_.get()); |
+ CHECK(java_location_provider_android_object_.is_null()); |
+} |
+ |
+bool AndroidLocationApiAdapter::Start( |
+ LocationProviderAndroid* location_provider, bool high_accuracy) { |
+ JNIEnv* env = AttachCurrentThread(); |
+ if (!location_provider_) { |
+ location_provider_ = location_provider; |
+ CHECK(java_location_provider_android_object_.is_null()); |
+ CreateJavaObject(env); |
+ { |
+ base::AutoLock lock(lock_); |
+ CHECK(!task_runner_.get()); |
+ task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
+ } |
+ } |
+ // At this point we should have all our pre-conditions ready, and they'd only |
+ // change in Stop() which must be called on the same thread as here. |
+ CHECK(location_provider_); |
+ CHECK(task_runner_.get()); |
+ CHECK(!java_location_provider_android_object_.is_null()); |
+ // We'll start receiving notifications from java in the main thread looper |
+ // until Stop() is called. |
+ return Java_LocationProviderAdapter_start(env, |
+ java_location_provider_android_object_.obj(), high_accuracy); |
+} |
+ |
+void AndroidLocationApiAdapter::Stop() { |
+ if (!location_provider_) { |
+ CHECK(!task_runner_.get()); |
+ CHECK(java_location_provider_android_object_.is_null()); |
+ return; |
+ } |
+ |
+ { |
+ base::AutoLock lock(lock_); |
+ task_runner_ = NULL; |
+ } |
+ |
+ location_provider_ = NULL; |
+ |
+ JNIEnv* env = AttachCurrentThread(); |
+ Java_LocationProviderAdapter_stop( |
+ env, java_location_provider_android_object_.obj()); |
+ java_location_provider_android_object_.Reset(); |
+} |
+ |
+// static |
+void AndroidLocationApiAdapter::NotifyProviderNewGeoposition( |
+ const Geoposition& geoposition) { |
+ // Called on the geolocation thread, safe to access location_provider_ here. |
+ if (GetInstance()->location_provider_) { |
+ CHECK(GetInstance()->task_runner_->BelongsToCurrentThread()); |
+ GetInstance()->location_provider_->NotifyNewGeoposition(geoposition); |
+ } |
+} |
+ |
+// static |
+void AndroidLocationApiAdapter::OnNewLocationAvailable( |
+ double latitude, double longitude, double time_stamp, |
+ bool has_altitude, double altitude, |
+ bool has_accuracy, double accuracy, |
+ bool has_heading, double heading, |
+ bool has_speed, double speed) { |
+ Geoposition position; |
+ position.latitude = latitude; |
+ position.longitude = longitude; |
+ position.timestamp = base::Time::FromDoubleT(time_stamp); |
+ if (has_altitude) |
+ position.altitude = altitude; |
+ if (has_accuracy) |
+ position.accuracy = accuracy; |
+ if (has_heading) |
+ position.heading = heading; |
+ if (has_speed) |
+ position.speed = speed; |
+ GetInstance()->OnNewGeopositionInternal(position); |
+} |
+ |
+// static |
+void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv* env, |
+ jstring message) { |
+ Geoposition position_error; |
+ position_error.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; |
+ position_error.error_message = |
+ base::android::ConvertJavaStringToUTF8(env, message); |
+ GetInstance()->OnNewGeopositionInternal(position_error); |
+} |
+ |
+// static |
+AndroidLocationApiAdapter* AndroidLocationApiAdapter::GetInstance() { |
+ return base::Singleton<AndroidLocationApiAdapter>::get(); |
+} |
+ |
+// static |
+bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) { |
+ return RegisterNativesImpl(env); |
+} |
+ |
+void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv* env) { |
+ // Create the Java LocationProviderAdapter object. |
+ java_location_provider_android_object_.Reset( |
+ Java_LocationProviderAdapter_create(env, |
+ base::android::GetApplicationContext())); |
+ CHECK(!java_location_provider_android_object_.is_null()); |
+} |
+ |
+void AndroidLocationApiAdapter::OnNewGeopositionInternal( |
+ const Geoposition& geoposition) { |
+ base::AutoLock lock(lock_); |
+ if (!task_runner_.get()) |
+ return; |
+ task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&AndroidLocationApiAdapter::NotifyProviderNewGeoposition, |
+ geoposition)); |
+} |
+ |
+} // namespace content |