15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/location_api_adapter_android.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_android.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_string.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/location_provider_android.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "jni/LocationProviderAdapter_jni.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::AttachCurrentThread; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::CheckException; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ClearException; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::AndroidLocationApiAdapter; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NewLocationAvailable(JNIEnv* env, jclass, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jdouble latitude, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jdouble longitude, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jdouble time_stamp, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jboolean has_altitude, jdouble altitude, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jboolean has_accuracy, jdouble accuracy, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jboolean has_heading, jdouble heading, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jboolean has_speed, jdouble speed) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AndroidLocationApiAdapter::OnNewLocationAvailable(latitude, longitude, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_stamp, has_altitude, altitude, has_accuracy, accuracy, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_heading, heading, has_speed, speed); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NewErrorAvailable(JNIEnv* env, jclass, jstring message) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AndroidLocationApiAdapter::OnNewErrorAvailable(env, message); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AndroidLocationApiAdapter::AndroidLocationApiAdapter() 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : location_provider_(NULL) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AndroidLocationApiAdapter::~AndroidLocationApiAdapter() { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!location_provider_); 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CHECK(!message_loop_.get()); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(java_location_provider_android_object_.is_null()); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AndroidLocationApiAdapter::Start( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocationProviderAndroid* location_provider, bool high_accuracy) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!location_provider_) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_provider_ = location_provider; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(java_location_provider_android_object_.is_null()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateJavaObject(env); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!message_loop_.get()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_ = base::MessageLoopProxy::current(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At this point we should have all our pre-conditions ready, and they'd only 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change in Stop() which must be called on the same thread as here. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(location_provider_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(message_loop_.get()); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!java_location_provider_android_object_.is_null()); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll start receiving notifications from java in the main thread looper 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // until Stop() is called. 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Java_LocationProviderAdapter_start(env, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_location_provider_android_object_.obj(), high_accuracy); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AndroidLocationApiAdapter::Stop() { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!location_provider_) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!message_loop_.get()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(java_location_provider_android_object_.is_null()); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_ = NULL; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_provider_ = NULL; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Java_LocationProviderAdapter_stop( 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) env, java_location_provider_android_object_.obj()); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_location_provider_android_object_.Reset(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AndroidLocationApiAdapter::NotifyProviderNewGeoposition( 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Geoposition& geoposition) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the geolocation thread, safe to access location_provider_ here. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetInstance()->location_provider_) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(GetInstance()->message_loop_->BelongsToCurrentThread()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetInstance()->location_provider_->NotifyNewGeoposition(geoposition); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AndroidLocationApiAdapter::OnNewLocationAvailable( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double latitude, double longitude, double time_stamp, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_altitude, double altitude, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_accuracy, double accuracy, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_heading, double heading, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_speed, double speed) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Geoposition position; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.latitude = latitude; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.longitude = longitude; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.timestamp = base::Time::FromDoubleT(time_stamp); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_altitude) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.altitude = altitude; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_accuracy) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.accuracy = accuracy; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_heading) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.heading = heading; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_speed) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.speed = speed; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetInstance()->OnNewGeopositionInternal(position); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AndroidLocationApiAdapter::OnNewErrorAvailable(JNIEnv* env, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jstring message) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Geoposition position_error; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_error.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_error.error_message = 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::android::ConvertJavaStringToUTF8(env, message); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetInstance()->OnNewGeopositionInternal(position_error); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AndroidLocationApiAdapter* AndroidLocationApiAdapter::GetInstance() { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<AndroidLocationApiAdapter>::get(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RegisterNativesImpl(env); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv* env) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the Java AndroidLocationProvider object. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_location_provider_android_object_.Reset( 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Java_LocationProviderAdapter_create(env, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::android::GetApplicationContext())); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!java_location_provider_android_object_.is_null()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AndroidLocationApiAdapter::OnNewGeopositionInternal( 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Geoposition& geoposition) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!message_loop_.get()) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_->PostTask( 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &AndroidLocationApiAdapter::NotifyProviderNewGeoposition, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) geoposition)); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 165