Chromium Code Reviews| 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..c29a1ab064ae90185cfca7d9b0c9e4a4b17a8b2c |
| --- /dev/null |
| +++ b/content/browser/geolocation/location_api_adapter_android.cc |
| @@ -0,0 +1,160 @@ |
| +// 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/jni_android.h" |
| +#include "base/android/jni_string.h" |
| +#include "base/bind.h" |
| +#include "base/location.h" |
| +#include "content/browser/geolocation/location_provider_android.h" |
| +#include "jni/location_provider_jni.h" |
| + |
| +using base::android::AttachCurrentThread; |
| +using base::android::CheckException; |
| +using base::android::ClearException; |
| +using base::android::GetMethodID; |
| + |
| +static void NewLocationAvailable(JNIEnv* env, jclass, |
| + jdouble latitude, |
| + jdouble longitude, |
| + jlong 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); |
|
bulach
2012/05/08 09:11:05
nit: indent+2 here and above
John Knottenbelt
2012/05/08 13:43:16
Done.
|
| +} |
| + |
| +static void NewErrorAvailable(JNIEnv* env, jclass, jstring message) { |
| + AndroidLocationApiAdapter::OnNewErrorAvailable(env, message); |
| +} |
| + |
| +AndroidLocationApiAdapter::AndroidLocationApiAdapter() |
| + : location_provider_(NULL) { |
| +} |
| + |
| +AndroidLocationApiAdapter::~AndroidLocationApiAdapter() { |
| + CHECK(!location_provider_); |
| + CHECK(!message_loop_); |
| + 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(!message_loop_.get()); |
| + message_loop_ = base::MessageLoopProxy::current(); |
| + } |
| + } |
| + // 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(message_loop_.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_LocationProvider_start(env, |
| + java_location_provider_android_object_.obj(), high_accuracy); |
| +} |
| + |
| +void AndroidLocationApiAdapter::Stop() { |
| + if (!location_provider_) { |
| + CHECK(!message_loop_.get()); |
| + CHECK(java_location_provider_android_object_.is_null()); |
| + return; |
| + } |
| + |
| + { |
| + base::AutoLock lock(lock_); |
| + message_loop_ = NULL; |
| + } |
| + |
| + location_provider_ = NULL; |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + Java_LocationProvider_stop(env, java_location_provider_android_object_.obj()); |
| + java_location_provider_android_object_.Reset(); |
| +} |
| + |
| +// static |
| +void AndroidLocationApiAdapter::NotifyProviderNewGeoposition( |
| + const content::Geoposition& geoposition) { |
| + // Called on the geolocation thread, safe to access location_provider_ here. |
| + if (GetInstance()->location_provider_) { |
| + CHECK(GetInstance()->message_loop_->BelongsToCurrentThread()); |
| + GetInstance()->location_provider_->NotifyNewGeoposition(geoposition); |
| + } |
| +} |
| + |
| +// static |
| +void AndroidLocationApiAdapter::OnNewLocationAvailable( |
| + double latitude, double longitude, long time_stamp, |
| + bool has_altitude, double altitude, |
| + bool has_accuracy, double accuracy, |
| + bool has_heading, double heading, |
| + bool has_speed, double speed) { |
| + content::Geoposition position; |
| + position.latitude = latitude; |
| + position.longitude = longitude; |
| + position.timestamp = base::Time::FromDoubleT(time_stamp / 1000.0); |
| + 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) { |
| + content::Geoposition position_error; |
| + position_error.error_code = |
| + content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; |
| + position_error.error_message = |
| + base::android::ConvertJavaStringToUTF8(env, message); |
| + GetInstance()->OnNewGeopositionInternal(position_error); |
| +} |
| + |
| +// static |
| +AndroidLocationApiAdapter* AndroidLocationApiAdapter::GetInstance() { |
| + return Singleton<AndroidLocationApiAdapter>::get(); |
| +} |
| + |
| +// static |
| +bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) { |
| + return RegisterNativesImpl(env); |
| +} |
| + |
| +void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv* env) { |
| + // Create the Java AndroidLocationProvider object. |
| + java_location_provider_android_object_.Reset( |
| + Java_LocationProvider_create(env, |
| + base::android::GetApplicationContext())); |
| + CHECK(!java_location_provider_android_object_.is_null()); |
| +} |
| + |
| +void AndroidLocationApiAdapter::OnNewGeopositionInternal( |
| + const content::Geoposition& geoposition) { |
| + base::AutoLock lock(lock_); |
| + if (!message_loop_) |
| + return; |
| + message_loop_->PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &AndroidLocationApiAdapter::NotifyProviderNewGeoposition, |
| + geoposition)); |
| +} |