• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/browser/geolocation/location_api_adapter_android.h"
6 
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "content/browser/geolocation/location_provider_android.h"
12 #include "jni/LocationProviderAdapter_jni.h"
13 
14 using base::android::AttachCurrentThread;
15 using base::android::CheckException;
16 using base::android::ClearException;
17 using content::AndroidLocationApiAdapter;
18 
NewLocationAvailable(JNIEnv * env,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)19 static void NewLocationAvailable(JNIEnv* env, jclass,
20                                  jdouble latitude,
21                                  jdouble longitude,
22                                  jdouble time_stamp,
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);
30 }
31 
NewErrorAvailable(JNIEnv * env,jclass,jstring message)32 static void NewErrorAvailable(JNIEnv* env, jclass, jstring message) {
33   AndroidLocationApiAdapter::OnNewErrorAvailable(env, message);
34 }
35 
36 namespace content {
37 
AndroidLocationApiAdapter()38 AndroidLocationApiAdapter::AndroidLocationApiAdapter()
39     : location_provider_(NULL) {
40 }
41 
~AndroidLocationApiAdapter()42 AndroidLocationApiAdapter::~AndroidLocationApiAdapter() {
43   CHECK(!location_provider_);
44   CHECK(!message_loop_.get());
45   CHECK(java_location_provider_android_object_.is_null());
46 }
47 
Start(LocationProviderAndroid * location_provider,bool high_accuracy)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);
55     {
56       base::AutoLock lock(lock_);
57       CHECK(!message_loop_.get());
58       message_loop_ = base::MessageLoopProxy::current();
59     }
60   }
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);
70 }
71 
Stop()72 void AndroidLocationApiAdapter::Stop() {
73   if (!location_provider_) {
74     CHECK(!message_loop_.get());
75     CHECK(java_location_provider_android_object_.is_null());
76     return;
77   }
78 
79   {
80     base::AutoLock lock(lock_);
81     message_loop_ = NULL;
82   }
83 
84   location_provider_ = NULL;
85 
86   JNIEnv* env = AttachCurrentThread();
87   Java_LocationProviderAdapter_stop(
88       env, java_location_provider_android_object_.obj());
89   java_location_provider_android_object_.Reset();
90 }
91 
92 // static
NotifyProviderNewGeoposition(const Geoposition & geoposition)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);
99   }
100 }
101 
102 // static
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)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);
113   if (has_altitude)
114     position.altitude = altitude;
115   if (has_accuracy)
116     position.accuracy = accuracy;
117   if (has_heading)
118     position.heading = heading;
119   if (has_speed)
120     position.speed = speed;
121   GetInstance()->OnNewGeopositionInternal(position);
122 }
123 
124 // static
OnNewErrorAvailable(JNIEnv * env,jstring message)125 void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv* env,
126                                                     jstring message) {
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);
132 }
133 
134 // static
GetInstance()135 AndroidLocationApiAdapter* AndroidLocationApiAdapter::GetInstance() {
136   return Singleton<AndroidLocationApiAdapter>::get();
137 }
138 
139 // static
RegisterGeolocationService(JNIEnv * env)140 bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) {
141   return RegisterNativesImpl(env);
142 }
143 
CreateJavaObject(JNIEnv * 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());
150 }
151 
OnNewGeopositionInternal(const Geoposition & geoposition)152 void AndroidLocationApiAdapter::OnNewGeopositionInternal(
153     const Geoposition& geoposition) {
154   base::AutoLock lock(lock_);
155   if (!message_loop_.get())
156     return;
157   message_loop_->PostTask(
158       FROM_HERE,
159       base::Bind(
160           &AndroidLocationApiAdapter::NotifyProviderNewGeoposition,
161           geoposition));
162 }
163 
164 }  // namespace content
165