1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/geolocation/location_api_adapter_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
10 #include "base/location.h"
11 #include "content/browser/geolocation/location_provider_android.h"
12 #include "jni/LocationProviderAdapter_jni.h"
14 using base::android::AttachCurrentThread
;
15 using base::android::CheckException
;
16 using base::android::ClearException
;
17 using content::AndroidLocationApiAdapter
;
19 static void NewLocationAvailable(JNIEnv
* env
, jclass
,
23 jboolean has_altitude
, jdouble altitude
,
24 jboolean has_accuracy
, jdouble accuracy
,
25 jboolean has_heading
, jdouble heading
,
26 jboolean has_speed
, jdouble speed
) {
27 AndroidLocationApiAdapter::OnNewLocationAvailable(latitude
, longitude
,
28 time_stamp
, has_altitude
, altitude
, has_accuracy
, accuracy
,
29 has_heading
, heading
, has_speed
, speed
);
32 static void NewErrorAvailable(JNIEnv
* env
, jclass
, jstring message
) {
33 AndroidLocationApiAdapter::OnNewErrorAvailable(env
, message
);
38 AndroidLocationApiAdapter::AndroidLocationApiAdapter()
39 : location_provider_(NULL
) {
42 AndroidLocationApiAdapter::~AndroidLocationApiAdapter() {
43 CHECK(!location_provider_
);
44 CHECK(!message_loop_
.get());
45 CHECK(java_location_provider_android_object_
.is_null());
48 bool AndroidLocationApiAdapter::Start(
49 LocationProviderAndroid
* location_provider
, bool high_accuracy
) {
50 JNIEnv
* env
= AttachCurrentThread();
51 if (!location_provider_
) {
52 location_provider_
= location_provider
;
53 CHECK(java_location_provider_android_object_
.is_null());
54 CreateJavaObject(env
);
56 base::AutoLock
lock(lock_
);
57 CHECK(!message_loop_
.get());
58 message_loop_
= base::MessageLoopProxy::current();
61 // At this point we should have all our pre-conditions ready, and they'd only
62 // change in Stop() which must be called on the same thread as here.
63 CHECK(location_provider_
);
64 CHECK(message_loop_
.get());
65 CHECK(!java_location_provider_android_object_
.is_null());
66 // We'll start receiving notifications from java in the main thread looper
67 // until Stop() is called.
68 return Java_LocationProviderAdapter_start(env
,
69 java_location_provider_android_object_
.obj(), high_accuracy
);
72 void AndroidLocationApiAdapter::Stop() {
73 if (!location_provider_
) {
74 CHECK(!message_loop_
.get());
75 CHECK(java_location_provider_android_object_
.is_null());
80 base::AutoLock
lock(lock_
);
84 location_provider_
= NULL
;
86 JNIEnv
* env
= AttachCurrentThread();
87 Java_LocationProviderAdapter_stop(
88 env
, java_location_provider_android_object_
.obj());
89 java_location_provider_android_object_
.Reset();
93 void AndroidLocationApiAdapter::NotifyProviderNewGeoposition(
94 const Geoposition
& geoposition
) {
95 // Called on the geolocation thread, safe to access location_provider_ here.
96 if (GetInstance()->location_provider_
) {
97 CHECK(GetInstance()->message_loop_
->BelongsToCurrentThread());
98 GetInstance()->location_provider_
->NotifyNewGeoposition(geoposition
);
103 void AndroidLocationApiAdapter::OnNewLocationAvailable(
104 double latitude
, double longitude
, double time_stamp
,
105 bool has_altitude
, double altitude
,
106 bool has_accuracy
, double accuracy
,
107 bool has_heading
, double heading
,
108 bool has_speed
, double speed
) {
109 Geoposition position
;
110 position
.latitude
= latitude
;
111 position
.longitude
= longitude
;
112 position
.timestamp
= base::Time::FromDoubleT(time_stamp
);
114 position
.altitude
= altitude
;
116 position
.accuracy
= accuracy
;
118 position
.heading
= heading
;
120 position
.speed
= speed
;
121 GetInstance()->OnNewGeopositionInternal(position
);
125 void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv
* env
,
127 Geoposition position_error
;
128 position_error
.error_code
= Geoposition::ERROR_CODE_POSITION_UNAVAILABLE
;
129 position_error
.error_message
=
130 base::android::ConvertJavaStringToUTF8(env
, message
);
131 GetInstance()->OnNewGeopositionInternal(position_error
);
135 AndroidLocationApiAdapter
* AndroidLocationApiAdapter::GetInstance() {
136 return Singleton
<AndroidLocationApiAdapter
>::get();
140 bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv
* env
) {
141 return RegisterNativesImpl(env
);
144 void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv
* env
) {
145 // Create the Java AndroidLocationProvider object.
146 java_location_provider_android_object_
.Reset(
147 Java_LocationProviderAdapter_create(env
,
148 base::android::GetApplicationContext()));
149 CHECK(!java_location_provider_android_object_
.is_null());
152 void AndroidLocationApiAdapter::OnNewGeopositionInternal(
153 const Geoposition
& geoposition
) {
154 base::AutoLock
lock(lock_
);
155 if (!message_loop_
.get())
157 message_loop_
->PostTask(
160 &AndroidLocationApiAdapter::NotifyProviderNewGeoposition
,
164 } // namespace content