summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Tarasov <igor.tarasov@mapbox.com>2019-09-16 23:37:50 +0300
committerIgor Tarasov <igor.tarasov@mapbox.com>2019-09-16 23:37:50 +0300
commitf4f7283515690ed0a24828745b6a407fa67929a0 (patch)
tree4994e87d72ba24c3181a2e07e734da2554373ac7
parent2eed5486ffd4986331b8cd78d6181eb6478fb552 (diff)
downloadqtlocation-mapboxgl-f4f7283515690ed0a24828745b6a407fa67929a0.tar.gz
[android] Style sources - handle invalidated core source.
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.cpp10
-rw-r--r--platform/android/src/style/sources/geojson_source.cpp14
-rw-r--r--platform/android/src/style/sources/image_source.cpp8
-rw-r--r--platform/android/src/style/sources/raster_dem_source.cpp2
-rw-r--r--platform/android/src/style/sources/raster_source.cpp2
-rw-r--r--platform/android/src/style/sources/source.cpp37
-rw-r--r--platform/android/src/style/sources/source.hpp28
-rw-r--r--platform/android/src/style/sources/vector_source.cpp4
8 files changed, 62 insertions, 43 deletions
diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp
index 8a6d409158..da696e82b5 100644
--- a/platform/android/src/style/sources/custom_geometry_source.cpp
+++ b/platform/android/src/style/sources/custom_geometry_source.cpp
@@ -143,17 +143,17 @@ namespace android {
// Update the core source if not cancelled
if (!isCancelled(z, x ,y)) {
- source->as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::setTileData(CanonicalTileID(z, x, y), GeoJSON(geometry));
+ source(env)->as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::setTileData(CanonicalTileID(z, x, y), GeoJSON(geometry));
}
}
- void CustomGeometrySource::invalidateTile(jni::JNIEnv&, jni::jint z, jni::jint x, jni::jint y) {
- source->as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateTile(CanonicalTileID(z, x, y));
+ void CustomGeometrySource::invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y) {
+ source(env)->as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateTile(CanonicalTileID(z, x, y));
}
void CustomGeometrySource::invalidateBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& jBounds) {
auto bounds = LatLngBounds::getLatLngBounds(env, jBounds);
- source->as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateRegion(bounds);
+ source(env)->as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateRegion(bounds);
}
jni::Local<jni::Array<jni::Object<geojson::Feature>>> CustomGeometrySource::querySourceFeatures(jni::JNIEnv& env,
@@ -163,7 +163,7 @@ namespace android {
std::vector<mbgl::Feature> features;
if (rendererFrontend) {
- features = rendererFrontend->querySourceFeatures(source->getID(), { {}, toFilter(env, jfilter) });
+ features = rendererFrontend->querySourceFeatures(source(env)->getID(), { {}, toFilter(env, jfilter) });
}
return Feature::convert(env, features);
}
diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp
index 40e94efd97..aa05f9c912 100644
--- a/platform/android/src/style/sources/geojson_source.cpp
+++ b/platform/android/src/style/sources/geojson_source.cpp
@@ -84,11 +84,11 @@ namespace android {
void GeoJSONSource::setURL(jni::JNIEnv& env, const jni::String& url) {
// Update the core source
- source->as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url));
+ source(env)->as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url));
}
jni::Local<jni::String> GeoJSONSource::getURL(jni::JNIEnv& env) {
- optional<std::string> url = source->as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getURL();
+ optional<std::string> url = source(env)->as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getURL();
return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>();
}
@@ -99,7 +99,7 @@ namespace android {
std::vector<mbgl::Feature> features;
if (rendererFrontend) {
- features = rendererFrontend->querySourceFeatures(source->getID(),
+ features = rendererFrontend->querySourceFeatures(source(env)->getID(),
{ {}, toFilter(env, jfilter) });
}
return Feature::convert(env, features);
@@ -112,7 +112,7 @@ namespace android {
if (rendererFrontend) {
mbgl::Feature _feature = Feature::convert(env, feature);
_feature.properties["cluster_id"] = static_cast<uint64_t>(_feature.properties["cluster_id"].get<double>());
- const auto featureExtension = rendererFrontend->queryFeatureExtensions(source->getID(), _feature, "supercluster", "children", {});
+ const auto featureExtension = rendererFrontend->queryFeatureExtensions(source(env)->getID(), _feature, "supercluster", "children", {});
if (featureExtension.is<mbgl::FeatureCollection>()) {
return Feature::convert(env, featureExtension.get<mbgl::FeatureCollection>());
}
@@ -129,7 +129,7 @@ namespace android {
_feature.properties["cluster_id"] = static_cast<uint64_t>(_feature.properties["cluster_id"].get<double>());
const std::map<std::string, mbgl::Value> options = { {"limit", static_cast<uint64_t>(limit)},
{"offset", static_cast<uint64_t>(offset)} };
- auto featureExtension = rendererFrontend->queryFeatureExtensions(source->getID(), _feature, "supercluster", "leaves", options);
+ auto featureExtension = rendererFrontend->queryFeatureExtensions(source(env)->getID(), _feature, "supercluster", "leaves", options);
if (featureExtension.is<mbgl::FeatureCollection>()) {
return Feature::convert(env, featureExtension.get<mbgl::FeatureCollection>());
}
@@ -144,7 +144,7 @@ namespace android {
if (rendererFrontend) {
mbgl::Feature _feature = Feature::convert(env, feature);
_feature.properties["cluster_id"] = static_cast<uint64_t>(_feature.properties["cluster_id"].get<double>());
- auto featureExtension = rendererFrontend->queryFeatureExtensions(source->getID(), _feature, "supercluster", "expansion-zoom", {});
+ auto featureExtension = rendererFrontend->queryFeatureExtensions(source(env)->getID(), _feature, "supercluster", "expansion-zoom", {});
if (featureExtension.is<mbgl::Value>()) {
auto value = featureExtension.get<mbgl::Value>();
if (value.is<uint64_t>()) {
@@ -183,7 +183,7 @@ namespace android {
android::UniqueEnv _env = android::AttachEnv();
// Update the core source
- source->as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(geoJSON);
+ source(*_env)->as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(geoJSON);
// if there is an awaiting update, execute it, otherwise, release resources
if (awaitingUpdate) {
diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp
index 0986f74b35..b107fc94f2 100644
--- a/platform/android/src/style/sources/image_source.cpp
+++ b/platform/android/src/style/sources/image_source.cpp
@@ -33,20 +33,20 @@ namespace android {
void ImageSource::setURL(jni::JNIEnv& env, const jni::String& url) {
// Update the core source
- source->as<mbgl::style::ImageSource>()->ImageSource::setURL(jni::Make<std::string>(env, url));
+ source(env)->as<mbgl::style::ImageSource>()->ImageSource::setURL(jni::Make<std::string>(env, url));
}
jni::Local<jni::String> ImageSource::getURL(jni::JNIEnv& env) {
- optional<std::string> url = source->as<mbgl::style::ImageSource>()->ImageSource::getURL();
+ optional<std::string> url = source(env)->as<mbgl::style::ImageSource>()->ImageSource::getURL();
return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>();
}
void ImageSource::setImage(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) {
- source->as<mbgl::style::ImageSource>()->setImage(Bitmap::GetImage(env, bitmap));
+ source(env)->as<mbgl::style::ImageSource>()->setImage(Bitmap::GetImage(env, bitmap));
}
void ImageSource::setCoordinates(jni::JNIEnv& env, const jni::Object<LatLngQuad>& coordinatesObject) {
- source->as<mbgl::style::ImageSource>()->setCoordinates(
+ source(env)->as<mbgl::style::ImageSource>()->setCoordinates(
LatLngQuad::getLatLngArray(env, coordinatesObject));
}
diff --git a/platform/android/src/style/sources/raster_dem_source.cpp b/platform/android/src/style/sources/raster_dem_source.cpp
index dd98925d22..950fdde341 100644
--- a/platform/android/src/style/sources/raster_dem_source.cpp
+++ b/platform/android/src/style/sources/raster_dem_source.cpp
@@ -32,7 +32,7 @@ namespace android {
RasterDEMSource::~RasterDEMSource() = default;
jni::Local<jni::String> RasterDEMSource::getURL(jni::JNIEnv& env) {
- optional<std::string> url = source->as<mbgl::style::RasterDEMSource>()->RasterDEMSource::getURL();
+ optional<std::string> url = source(env)->as<mbgl::style::RasterDEMSource>()->RasterDEMSource::getURL();
return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>();
}
diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp
index d643b8ac71..425e37c3da 100644
--- a/platform/android/src/style/sources/raster_source.cpp
+++ b/platform/android/src/style/sources/raster_source.cpp
@@ -31,7 +31,7 @@ namespace android {
RasterSource::~RasterSource() = default;
jni::Local<jni::String> RasterSource::getURL(jni::JNIEnv& env) {
- optional<std::string> url = source->as<mbgl::style::RasterSource>()->RasterSource::getURL();
+ optional<std::string> url = source(env)->as<mbgl::style::RasterSource>()->RasterSource::getURL();
return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>();
}
diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp
index 6af30f2922..8f4e631e9a 100644
--- a/platform/android/src/style/sources/source.cpp
+++ b/platform/android/src/style/sources/source.cpp
@@ -56,14 +56,13 @@ namespace android {
}
Source::Source(jni::JNIEnv& env, mbgl::style::Source* coreSource, const jni::Object<Source>& obj, AndroidRendererFrontend& frontend)
- : source(coreSource)
- , javaPeer(jni::NewGlobal(env, obj))
+ : javaPeer(jni::NewGlobal(env, obj))
, rendererFrontend(&frontend) {
+ source(coreSource);
}
- Source::Source(jni::JNIEnv&, std::unique_ptr<mbgl::style::Source> coreSource)
- : ownedSource(std::move(coreSource))
- , source(ownedSource.get()) {
+ Source::Source(jni::JNIEnv&, std::unique_ptr<mbgl::style::Source> coreSource) {
+ source(std::move(coreSource));
}
Source::~Source() {
@@ -74,7 +73,7 @@ namespace android {
// In this case, the core source initiates the destruction, which requires releasing the Java peer,
// while also resetting it's nativePtr to 0 to prevent the subsequent GC of the Java peer from
// re-entering this dtor.
- if (ownedSource.get() == nullptr && javaPeer.get() != nullptr) {
+ if (ownedSource_ == nullptr && javaPeer.get() != nullptr) {
// Manually clear the java peer
android::UniqueEnv env = android::AttachEnv();
static auto& javaClass = jni::Class<Source>::Singleton(*env);
@@ -85,25 +84,25 @@ namespace android {
}
jni::Local<jni::String> Source::getId(jni::JNIEnv& env) {
- return jni::Make<jni::String>(env, source->getID());
+ return jni::Make<jni::String>(env, source(env)->getID());
}
jni::Local<jni::String> Source::getAttribution(jni::JNIEnv& env) {
- auto attribution = source->getAttribution();
+ auto attribution = source(env)->getAttribution();
return attribution ? jni::Make<jni::String>(env, attribution.value()) : jni::Make<jni::String>(env,"");
}
void Source::addToMap(JNIEnv& env, const jni::Object<Source>& obj, mbgl::Map& map, AndroidRendererFrontend& frontend) {
// Check to see if we own the source first
- if (!ownedSource) {
+ if (!ownedSource_) {
throw std::runtime_error("Cannot add source twice");
}
// Add source to map and release ownership
- map.getStyle().addSource(std::move(ownedSource));
+ map.getStyle().addSource(std::move(ownedSource_));
// Add peer to core source
- source->peer = std::unique_ptr<Source>(this);
+ source(env)->peer = std::unique_ptr<Source>(this);
// Add strong reference to java source
javaPeer = jni::NewGlobal(env, obj);
@@ -111,29 +110,29 @@ namespace android {
rendererFrontend = &frontend;
}
- bool Source::removeFromMap(JNIEnv&, const jni::Object<Source>&, mbgl::Map& map) {
+ bool Source::removeFromMap(JNIEnv& env, const jni::Object<Source>&, mbgl::Map& map) {
// Cannot remove if not attached yet
- if (ownedSource) {
+ if (ownedSource_) {
throw std::runtime_error("Cannot remove detached source");
}
// Remove the source from the map and take ownership
- ownedSource = map.getStyle().removeSource(source->getID());
+ source(map.getStyle().removeSource(source(env)->getID()));
// The source may not be removed if any layers still reference it
- return ownedSource != nullptr;
+ return ownedSource_ != nullptr;
}
void Source::releaseJavaPeer() {
// We can't release the peer if the source was not removed from the map
- if (!ownedSource) {
+ if (!ownedSource_) {
return;
}
// Release the peer relationships. These will be re-established when the source is added to a map
- assert(ownedSource->peer.has_value());
- ownedSource->peer.get<std::unique_ptr<Source>>().release();
- ownedSource->peer = mapbox::base::TypeWrapper();
+ assert(ownedSource_->peer.has_value());
+ ownedSource_->peer.get<std::unique_ptr<Source>>().release();
+ ownedSource_->peer = mapbox::base::TypeWrapper();
// Release the strong reference to the java peer
assert(javaPeer);
diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp
index 127de0bb9d..6217b909f3 100644
--- a/platform/android/src/style/sources/source.hpp
+++ b/platform/android/src/style/sources/source.hpp
@@ -7,6 +7,8 @@
#include "../value.hpp"
#include "../../android_renderer_frontend.hpp"
+#include <mapbox/weak.hpp>
+
#include <jni/jni.hpp>
namespace mbgl {
@@ -44,17 +46,35 @@ public:
jni::Local<jni::String> getAttribution(jni::JNIEnv&);
protected:
- // Set on newly created sources until added to the map.
- std::unique_ptr<mbgl::style::Source> ownedSource;
- // Raw pointer that is valid at all times.
- mbgl::style::Source *source;
+ inline void source(std::unique_ptr<mbgl::style::Source> ownedSource) noexcept {
+ ownedSource_ = std::move(ownedSource);
+ }
+
+ inline void source(mbgl::style::Source *coreSource) noexcept {
+ coreSource_ = coreSource->makeWeakPtr();
+ }
+
+ inline mbgl::style::Source *source(jni::JNIEnv& env) {
+ if (ownedSource_) return ownedSource_.get();
+ if (!coreSource_) {
+ jni::ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"),
+ "This source got invalidated after the style change");
+ }
+ return coreSource_.get();
+ }
// Set when the source is added to a map.
jni::Global<jni::Object<Source>> javaPeer;
// RendererFrontend pointer is valid only when added to the map.
AndroidRendererFrontend* rendererFrontend { nullptr };
+
+private:
+ // Set on newly created sources until added to the map.
+ std::unique_ptr<mbgl::style::Source> ownedSource_;
+
+ mapbox::base::WeakPtr<mbgl::style::Source> coreSource_;
};
} // namespace android
diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp
index 04952c456e..bc66b2e318 100644
--- a/platform/android/src/style/sources/vector_source.cpp
+++ b/platform/android/src/style/sources/vector_source.cpp
@@ -39,7 +39,7 @@ namespace android {
VectorSource::~VectorSource() = default;
jni::Local<jni::String> VectorSource::getURL(jni::JNIEnv& env) {
- optional<std::string> url = source->as<mbgl::style::VectorSource>()->VectorSource::getURL();
+ optional<std::string> url = source(env)->as<mbgl::style::VectorSource>()->VectorSource::getURL();
return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>();
}
@@ -51,7 +51,7 @@ namespace android {
std::vector<mbgl::Feature> features;
if (rendererFrontend) {
- features = rendererFrontend->querySourceFeatures(source->getID(),
+ features = rendererFrontend->querySourceFeatures(source(env)->getID(),
{ toVector(env, jSourceLayerIds), toFilter(env, jfilter) });
}
return Feature::convert(env, features);