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 "base/thread_task_runner_handle.h"
12 #include "content/browser/geolocation/location_provider_android.h"
13 #include "jni/LocationProviderAdapter_jni.h"
15 using base::android::AttachCurrentThread
;
16 using base::android::CheckException
;
17 using base::android::ClearException
;
18 using content::AndroidLocationApiAdapter
;
20 static void NewLocationAvailable(JNIEnv
* env
, jclass
,
24 jboolean has_altitude
, jdouble altitude
,
25 jboolean has_accuracy
, jdouble accuracy
,
26 jboolean has_heading
, jdouble heading
,
27 jboolean has_speed
, jdouble speed
) {
28 AndroidLocationApiAdapter::OnNewLocationAvailable(latitude
, longitude
,
29 time_stamp
, has_altitude
, altitude
, has_accuracy
, accuracy
,
30 has_heading
, heading
, has_speed
, speed
);
33 static void NewErrorAvailable(JNIEnv
* env
, jclass
, jstring message
) {
34 AndroidLocationApiAdapter::OnNewErrorAvailable(env
, message
);
39 AndroidLocationApiAdapter::AndroidLocationApiAdapter()
40 : location_provider_(NULL
) {
43 AndroidLocationApiAdapter::~AndroidLocationApiAdapter() {
44 CHECK(!location_provider_
);
45 CHECK(!task_runner_
.get());
46 CHECK(java_location_provider_android_object_
.is_null());
49 bool AndroidLocationApiAdapter::Start(
50 LocationProviderAndroid
* location_provider
, bool high_accuracy
) {
51 JNIEnv
* env
= AttachCurrentThread();
52 if (!location_provider_
) {
53 location_provider_
= location_provider
;
54 CHECK(java_location_provider_android_object_
.is_null());
55 CreateJavaObject(env
);
57 base::AutoLock
lock(lock_
);
58 CHECK(!task_runner_
.get());
59 task_runner_
= base::ThreadTaskRunnerHandle::Get();
62 // At this point we should have all our pre-conditions ready, and they'd only
63 // change in Stop() which must be called on the same thread as here.
64 CHECK(location_provider_
);
65 CHECK(task_runner_
.get());
66 CHECK(!java_location_provider_android_object_
.is_null());
67 // We'll start receiving notifications from java in the main thread looper
68 // until Stop() is called.
69 return Java_LocationProviderAdapter_start(env
,
70 java_location_provider_android_object_
.obj(), high_accuracy
);
73 void AndroidLocationApiAdapter::Stop() {
74 if (!location_provider_
) {
75 CHECK(!task_runner_
.get());
76 CHECK(java_location_provider_android_object_
.is_null());
81 base::AutoLock
lock(lock_
);
85 location_provider_
= NULL
;
87 JNIEnv
* env
= AttachCurrentThread();
88 Java_LocationProviderAdapter_stop(
89 env
, java_location_provider_android_object_
.obj());
90 java_location_provider_android_object_
.Reset();
94 void AndroidLocationApiAdapter::NotifyProviderNewGeoposition(
95 const Geoposition
& geoposition
) {
96 // Called on the geolocation thread, safe to access location_provider_ here.
97 if (GetInstance()->location_provider_
) {
98 CHECK(GetInstance()->task_runner_
->BelongsToCurrentThread());
99 GetInstance()->location_provider_
->NotifyNewGeoposition(geoposition
);
104 void AndroidLocationApiAdapter::OnNewLocationAvailable(
105 double latitude
, double longitude
, double time_stamp
,
106 bool has_altitude
, double altitude
,
107 bool has_accuracy
, double accuracy
,
108 bool has_heading
, double heading
,
109 bool has_speed
, double speed
) {
110 Geoposition position
;
111 position
.latitude
= latitude
;
112 position
.longitude
= longitude
;
113 position
.timestamp
= base::Time::FromDoubleT(time_stamp
);
115 position
.altitude
= altitude
;
117 position
.accuracy
= accuracy
;
119 position
.heading
= heading
;
121 position
.speed
= speed
;
122 GetInstance()->OnNewGeopositionInternal(position
);
126 void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv
* env
,
128 Geoposition position_error
;
129 position_error
.error_code
= Geoposition::ERROR_CODE_POSITION_UNAVAILABLE
;
130 position_error
.error_message
=
131 base::android::ConvertJavaStringToUTF8(env
, message
);
132 GetInstance()->OnNewGeopositionInternal(position_error
);
136 AndroidLocationApiAdapter
* AndroidLocationApiAdapter::GetInstance() {
137 return Singleton
<AndroidLocationApiAdapter
>::get();
141 bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv
* env
) {
142 return RegisterNativesImpl(env
);
145 void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv
* env
) {
146 // Create the Java AndroidLocationProvider object.
147 java_location_provider_android_object_
.Reset(
148 Java_LocationProviderAdapter_create(env
,
149 base::android::GetApplicationContext()));
150 CHECK(!java_location_provider_android_object_
.is_null());
153 void AndroidLocationApiAdapter::OnNewGeopositionInternal(
154 const Geoposition
& geoposition
) {
155 base::AutoLock
lock(lock_
);
156 if (!task_runner_
.get())
158 task_runner_
->PostTask(
160 base::Bind(&AndroidLocationApiAdapter::NotifyProviderNewGeoposition
,
164 } // namespace content