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
,
21 const JavaParamRef
<jclass
>&,
25 jboolean has_altitude
,
27 jboolean has_accuracy
,
33 AndroidLocationApiAdapter::OnNewLocationAvailable(latitude
, longitude
,
34 time_stamp
, has_altitude
, altitude
, has_accuracy
, accuracy
,
35 has_heading
, heading
, has_speed
, speed
);
38 static void NewErrorAvailable(JNIEnv
* env
,
39 const JavaParamRef
<jclass
>&,
40 const JavaParamRef
<jstring
>& message
) {
41 AndroidLocationApiAdapter::OnNewErrorAvailable(env
, message
);
46 AndroidLocationApiAdapter::AndroidLocationApiAdapter()
47 : location_provider_(NULL
) {
50 AndroidLocationApiAdapter::~AndroidLocationApiAdapter() {
51 CHECK(!location_provider_
);
52 CHECK(!task_runner_
.get());
53 CHECK(java_location_provider_android_object_
.is_null());
56 bool AndroidLocationApiAdapter::Start(
57 LocationProviderAndroid
* location_provider
, bool high_accuracy
) {
58 JNIEnv
* env
= AttachCurrentThread();
59 if (!location_provider_
) {
60 location_provider_
= location_provider
;
61 CHECK(java_location_provider_android_object_
.is_null());
62 CreateJavaObject(env
);
64 base::AutoLock
lock(lock_
);
65 CHECK(!task_runner_
.get());
66 task_runner_
= base::ThreadTaskRunnerHandle::Get();
69 // At this point we should have all our pre-conditions ready, and they'd only
70 // change in Stop() which must be called on the same thread as here.
71 CHECK(location_provider_
);
72 CHECK(task_runner_
.get());
73 CHECK(!java_location_provider_android_object_
.is_null());
74 // We'll start receiving notifications from java in the main thread looper
75 // until Stop() is called.
76 return Java_LocationProviderAdapter_start(env
,
77 java_location_provider_android_object_
.obj(), high_accuracy
);
80 void AndroidLocationApiAdapter::Stop() {
81 if (!location_provider_
) {
82 CHECK(!task_runner_
.get());
83 CHECK(java_location_provider_android_object_
.is_null());
88 base::AutoLock
lock(lock_
);
92 location_provider_
= NULL
;
94 JNIEnv
* env
= AttachCurrentThread();
95 Java_LocationProviderAdapter_stop(
96 env
, java_location_provider_android_object_
.obj());
97 java_location_provider_android_object_
.Reset();
101 void AndroidLocationApiAdapter::NotifyProviderNewGeoposition(
102 const Geoposition
& geoposition
) {
103 // Called on the geolocation thread, safe to access location_provider_ here.
104 if (GetInstance()->location_provider_
) {
105 CHECK(GetInstance()->task_runner_
->BelongsToCurrentThread());
106 GetInstance()->location_provider_
->NotifyNewGeoposition(geoposition
);
111 void AndroidLocationApiAdapter::OnNewLocationAvailable(
112 double latitude
, double longitude
, double time_stamp
,
113 bool has_altitude
, double altitude
,
114 bool has_accuracy
, double accuracy
,
115 bool has_heading
, double heading
,
116 bool has_speed
, double speed
) {
117 Geoposition position
;
118 position
.latitude
= latitude
;
119 position
.longitude
= longitude
;
120 position
.timestamp
= base::Time::FromDoubleT(time_stamp
);
122 position
.altitude
= altitude
;
124 position
.accuracy
= accuracy
;
126 position
.heading
= heading
;
128 position
.speed
= speed
;
129 GetInstance()->OnNewGeopositionInternal(position
);
133 void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv
* env
,
135 Geoposition position_error
;
136 position_error
.error_code
= Geoposition::ERROR_CODE_POSITION_UNAVAILABLE
;
137 position_error
.error_message
=
138 base::android::ConvertJavaStringToUTF8(env
, message
);
139 GetInstance()->OnNewGeopositionInternal(position_error
);
143 AndroidLocationApiAdapter
* AndroidLocationApiAdapter::GetInstance() {
144 return base::Singleton
<AndroidLocationApiAdapter
>::get();
148 bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv
* env
) {
149 return RegisterNativesImpl(env
);
152 void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv
* env
) {
153 // Create the Java AndroidLocationProvider object.
154 java_location_provider_android_object_
.Reset(
155 Java_LocationProviderAdapter_create(env
,
156 base::android::GetApplicationContext()));
157 CHECK(!java_location_provider_android_object_
.is_null());
160 void AndroidLocationApiAdapter::OnNewGeopositionInternal(
161 const Geoposition
& geoposition
) {
162 base::AutoLock
lock(lock_
);
163 if (!task_runner_
.get())
165 task_runner_
->PostTask(
167 base::Bind(&AndroidLocationApiAdapter::NotifyProviderNewGeoposition
,
171 } // namespace content