From 4e73963c5c85b32f1aa1f45a78f37ba671bcf987 Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Mon, 13 Nov 2017 16:06:26 -0800 Subject: [android] Reuse Java Source objects by holding on to a strong reference in the C++ peer. --- .../com/mapbox/mapboxsdk/maps/NativeMapView.java | 13 ++- platform/android/config.cmake | 2 - platform/android/src/jni.cpp | 4 +- platform/android/src/native_map_view.cpp | 28 ++--- platform/android/src/native_map_view.hpp | 6 +- .../src/style/sources/custom_geometry_source.cpp | 10 +- .../src/style/sources/custom_geometry_source.hpp | 5 +- .../android/src/style/sources/geojson_source.cpp | 10 +- .../android/src/style/sources/geojson_source.hpp | 5 +- .../android/src/style/sources/image_source.cpp | 10 +- .../android/src/style/sources/image_source.hpp | 5 +- .../android/src/style/sources/raster_source.cpp | 10 +- .../android/src/style/sources/raster_source.hpp | 5 +- platform/android/src/style/sources/source.cpp | 117 +++++++++++++++++---- platform/android/src/style/sources/source.hpp | 36 +++---- platform/android/src/style/sources/sources.cpp | 62 ----------- platform/android/src/style/sources/sources.hpp | 18 ---- .../android/src/style/sources/unknown_source.cpp | 10 +- .../android/src/style/sources/unknown_source.hpp | 5 +- .../android/src/style/sources/vector_source.cpp | 10 +- .../android/src/style/sources/vector_source.hpp | 5 +- 21 files changed, 183 insertions(+), 193 deletions(-) delete mode 100644 platform/android/src/style/sources/sources.cpp delete mode 100644 platform/android/src/style/sources/sources.hpp diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index e8eb7e8718..f1635c898f 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -733,7 +733,7 @@ final class NativeMapView { if (isDestroyedOn("addSource")) { return; } - nativeAddSource(source.getNativePtr()); + nativeAddSource(source, source.getNativePtr()); } @Nullable @@ -741,14 +741,15 @@ final class NativeMapView { if (isDestroyedOn("removeSource")) { return null; } - return nativeRemoveSourceById(sourceId); + Source source = getSource(sourceId); + return removeSource(source); } public Source removeSource(@NonNull Source source) { if (isDestroyedOn("removeSource")) { return null; } - nativeRemoveSource(source.getNativePtr()); + nativeRemoveSource(source, source.getNativePtr()); return source; } @@ -1027,11 +1028,9 @@ final class NativeMapView { private native Source nativeGetSource(String sourceId); - private native void nativeAddSource(long nativeSourcePtr) throws CannotAddSourceException; + private native void nativeAddSource(Source source, long sourcePtr) throws CannotAddSourceException; - private native Source nativeRemoveSourceById(String sourceId); - - private native void nativeRemoveSource(long sourcePtr); + private native void nativeRemoveSource(Source source, long sourcePtr); private native void nativeAddImage(String name, int width, int height, float pixelRatio, byte[] array); diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 0102d405d7..0175fa7ca6 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -181,8 +181,6 @@ add_library(mbgl-android STATIC platform/android/src/style/sources/custom_geometry_source.hpp platform/android/src/style/sources/source.cpp platform/android/src/style/sources/source.hpp - platform/android/src/style/sources/sources.cpp - platform/android/src/style/sources/sources.hpp platform/android/src/style/sources/raster_source.cpp platform/android/src/style/sources/raster_source.hpp platform/android/src/style/sources/unknown_source.cpp diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index f4e5734861..63566e1772 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -47,7 +47,7 @@ #include "style/functions/interval_stops.hpp" #include "style/functions/stop.hpp" #include "style/layers/layers.hpp" -#include "style/sources/sources.hpp" +#include "style/sources/source.hpp" #include "style/light.hpp" #include "snapshotter/map_snapshotter.hpp" #include "snapshotter/map_snapshot.hpp" @@ -161,7 +161,7 @@ void registerNatives(JavaVM *vm) { // Style TransitionOptions::registerNative(env); registerNativeLayers(env); - registerNativeSources(env); + Source::registerNative(env); Light::registerNative(env); Position::registerNative(env); Stop::registerNative(env); diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 04cbb21927..36a73fee35 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -856,9 +856,7 @@ jni::Array> NativeMapView::getSources(JNIEnv& env) { jni::Array> jSources = jni::Array>::New(env, sources.size(), Source::javaClass); int index = 0; for (auto source : sources) { - auto jSource = jni::Object(createJavaSourcePeer(env, *rendererFrontend, *source)); - jSources.Set(env, index, jSource); - jni::DeleteLocalRef(env, jSource); + jSources.Set(env, index, Source::peerForCoreSource(env, *source, *rendererFrontend)); index++; } @@ -874,38 +872,25 @@ jni::Object NativeMapView::getSource(JNIEnv& env, jni::String sourceId) } // Create and return the source's native peer - return jni::Object(createJavaSourcePeer(env, *rendererFrontend, *coreSource)); + return Source::peerForCoreSource(env, *coreSource, *rendererFrontend); } -void NativeMapView::addSource(JNIEnv& env, jni::jlong sourcePtr) { +void NativeMapView::addSource(JNIEnv& env, jni::Object obj, jlong sourcePtr) { assert(sourcePtr != 0); Source *source = reinterpret_cast(sourcePtr); try { - source->addToMap(*map); - source->setRendererFrontend(*rendererFrontend); + source->addToMap(env, obj, *map, *rendererFrontend); } catch (const std::runtime_error& error) { jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/sources/CannotAddSourceException"), error.what()); } } -jni::Object NativeMapView::removeSourceById(JNIEnv& env, jni::String id) { - std::unique_ptr coreSource = map->getStyle().removeSource(jni::Make(env, id)); - if (coreSource) { - return jni::Object(createJavaSourcePeer(env, *rendererFrontend, *coreSource)); - } else { - return jni::Object(); - } -} - -void NativeMapView::removeSource(JNIEnv&, jlong sourcePtr) { +void NativeMapView::removeSource(JNIEnv& env, jni::Object obj, jlong sourcePtr) { assert(sourcePtr != 0); mbgl::android::Source *source = reinterpret_cast(sourcePtr); - std::unique_ptr coreSource = map->getStyle().removeSource(source->get().getID()); - if (coreSource) { - source->setSource(std::move(coreSource)); - } + source->removeFromMap(env, obj, *map); } void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::jint w, jni::jint h, jni::jfloat scale, jni::Array pixels) { @@ -1048,7 +1033,6 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::getSources, "nativeGetSources"), METHOD(&NativeMapView::getSource, "nativeGetSource"), METHOD(&NativeMapView::addSource, "nativeAddSource"), - METHOD(&NativeMapView::removeSourceById, "nativeRemoveSourceById"), METHOD(&NativeMapView::removeSource, "nativeRemoveSource"), METHOD(&NativeMapView::addImage, "nativeAddImage"), METHOD(&NativeMapView::addImages, "nativeAddImages"), diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index d7e3b17b99..507d77ac5f 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -19,7 +19,7 @@ #include "geometry/lat_lng.hpp" #include "geometry/projected_meters.hpp" #include "style/layers/layers.hpp" -#include "style/sources/sources.hpp" +#include "style/sources/source.hpp" #include "geometry/lat_lng_bounds.hpp" #include "map/camera_position.hpp" #include "map/image.hpp" @@ -230,11 +230,11 @@ public: jni::Object getSource(JNIEnv&, jni::String); - void addSource(JNIEnv&, jni::jlong); + void addSource(JNIEnv&, jni::Object, jlong nativePtr); jni::Object removeSourceById(JNIEnv&, jni::String); - void removeSource(JNIEnv&, jlong); + void removeSource(JNIEnv&, jni::Object, jlong nativePtr); void addImage(JNIEnv&, jni::String, jni::jint, jni::jint, jni::jfloat, jni::Array); diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp index e647975e4d..205fe55ed9 100644 --- a/platform/android/src/style/sources/custom_geometry_source.cpp +++ b/platform/android/src/style/sources/custom_geometry_source.cpp @@ -46,6 +46,12 @@ namespace android { javaPeer(_obj.NewGlobalRef(env)) { } + CustomGeometrySource::CustomGeometrySource(jni::JNIEnv& env, + mbgl::style::Source& coreSource, + AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend) { + } + CustomGeometrySource::~CustomGeometrySource() = default; void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) { @@ -94,9 +100,9 @@ namespace android { jni::Class CustomGeometrySource::javaClass; - jni::jobject* CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { + jni::Object CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { static auto constructor = CustomGeometrySource::javaClass.template GetConstructor(env); - return CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast(this)); + return jni::Object(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void CustomGeometrySource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/custom_geometry_source.hpp b/platform/android/src/style/sources/custom_geometry_source.hpp index 50ced9298a..00d8dc918f 100644 --- a/platform/android/src/style/sources/custom_geometry_source.hpp +++ b/platform/android/src/style/sources/custom_geometry_source.hpp @@ -27,6 +27,8 @@ public: jni::String, jni::Object<>); + CustomGeometrySource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); + ~CustomGeometrySource(); void fetchTile(const mbgl::CanonicalTileID& tileID); @@ -39,7 +41,8 @@ public: jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array> ); - jni::jobject* createJavaPeer(jni::JNIEnv&); +private: + jni::Object createJavaPeer(jni::JNIEnv&); jni::UniqueObject javaPeer; }; // class CustomGeometrySource diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index 4468b453f3..6d9ab9e22c 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -43,8 +43,10 @@ namespace android { ) { } - GeoJSONSource::GeoJSONSource(mbgl::style::GeoJSONSource& coreSource) - : Source(coreSource) { + GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, + mbgl::style::Source& coreSource, + AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend) { } GeoJSONSource::~GeoJSONSource() = default; @@ -118,9 +120,9 @@ namespace android { jni::Class GeoJSONSource::javaClass; - jni::jobject* GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { + jni::Object GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { static auto constructor = GeoJSONSource::javaClass.template GetConstructor(env); - return GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast(this)); + return jni::Object(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void GeoJSONSource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 52dd632bfa..c46519b04a 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -21,7 +21,7 @@ public: GeoJSONSource(jni::JNIEnv&, jni::String, jni::Object<>); - GeoJSONSource(mbgl::style::GeoJSONSource&); + GeoJSONSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); ~GeoJSONSource(); @@ -40,7 +40,8 @@ public: jni::String getURL(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); +private: + jni::Object createJavaPeer(jni::JNIEnv&); }; // class GeoJSONSource diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp index d46b367c53..0cd6995969 100644 --- a/platform/android/src/style/sources/image_source.cpp +++ b/platform/android/src/style/sources/image_source.cpp @@ -23,8 +23,10 @@ namespace android { ) { } - ImageSource::ImageSource(mbgl::style::ImageSource& coreSource) - : Source(coreSource) { + ImageSource::ImageSource(jni::JNIEnv& env, + mbgl::style::Source& coreSource, + AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend) { } ImageSource::~ImageSource() = default; @@ -45,9 +47,9 @@ namespace android { jni::Class ImageSource::javaClass; - jni::jobject* ImageSource::createJavaPeer(jni::JNIEnv& env) { + jni::Object ImageSource::createJavaPeer(jni::JNIEnv& env) { static auto constructor = ImageSource::javaClass.template GetConstructor(env); - return ImageSource::javaClass.New(env, constructor, reinterpret_cast(this)); + return jni::Object(ImageSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void ImageSource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp index 9787a7294f..f0af28d357 100644 --- a/platform/android/src/style/sources/image_source.hpp +++ b/platform/android/src/style/sources/image_source.hpp @@ -21,7 +21,7 @@ public: ImageSource(jni::JNIEnv&, jni::String, jni::Object); - ImageSource(mbgl::style::ImageSource&); + ImageSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); ~ImageSource(); @@ -30,7 +30,8 @@ public: void setImage(jni::JNIEnv&, jni::Object); - jni::jobject* createJavaPeer(jni::JNIEnv&); +private: + jni::Object createJavaPeer(jni::JNIEnv&); }; // class ImageSource diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp index d45342a1ad..33223a5b69 100644 --- a/platform/android/src/style/sources/raster_source.cpp +++ b/platform/android/src/style/sources/raster_source.cpp @@ -22,8 +22,10 @@ namespace android { ) { } - RasterSource::RasterSource(mbgl::style::RasterSource& coreSource) - : Source(coreSource) { + RasterSource::RasterSource(jni::JNIEnv& env, + mbgl::style::Source& coreSource, + AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend) { } RasterSource::~RasterSource() = default; @@ -35,9 +37,9 @@ namespace android { jni::Class RasterSource::javaClass; - jni::jobject* RasterSource::createJavaPeer(jni::JNIEnv& env) { + jni::Object RasterSource::createJavaPeer(jni::JNIEnv& env) { static auto constructor = RasterSource::javaClass.template GetConstructor(env); - return RasterSource::javaClass.New(env, constructor, reinterpret_cast(this)); + return jni::Object(RasterSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void RasterSource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/raster_source.hpp b/platform/android/src/style/sources/raster_source.hpp index 84c49d7381..a1da22f40d 100644 --- a/platform/android/src/style/sources/raster_source.hpp +++ b/platform/android/src/style/sources/raster_source.hpp @@ -18,13 +18,14 @@ public: RasterSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - RasterSource(mbgl::style::RasterSource&); + RasterSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); ~RasterSource(); jni::String getURL(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); +private: + jni::Object createJavaPeer(jni::JNIEnv&); }; // class RasterSource diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp index 447b13019d..3b89b25d7d 100644 --- a/platform/android/src/style/sources/source.cpp +++ b/platform/android/src/style/sources/source.cpp @@ -15,29 +15,70 @@ #include +// Core Sources +#include +#include +#include +#include + +// Android Source peers +#include "geojson_source.hpp" +#include "image_source.hpp" +#include "raster_source.hpp" +#include "unknown_source.hpp" +#include "vector_source.hpp" +#include "custom_geometry_source.hpp" + namespace mbgl { namespace android { - /** - * Invoked when the construction is initiated from the jvm through a subclass - */ - Source::Source(jni::JNIEnv&, std::unique_ptr coreSource) - : ownedSource(std::move(coreSource)) - , source(*ownedSource) { + static std::unique_ptr createSourcePeer(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) { + if (coreSource.is()) { + return std::make_unique(env, *coreSource.as(), frontend); + } else if (coreSource.is()) { + return std::make_unique(env, *coreSource.as(), frontend); + } else if (coreSource.is()) { + return std::make_unique(env, *coreSource.as(), frontend); + } else if (coreSource.is()) { + return std::make_unique(env, *coreSource.as(), frontend); + } else { + return std::make_unique(env, coreSource, frontend); + } } - Source::Source(mbgl::style::Source& coreSource) - : source(coreSource) { + jni::Object Source::peerForCoreSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) { + if (!coreSource.peer.has_value()) { + coreSource.peer = createSourcePeer(env, coreSource, frontend); + } + return *mbgl::util::any_cast>(&coreSource.peer)->get()->javaPeer; } - Source::~Source() = default; + Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, jni::Object obj, AndroidRendererFrontend& frontend) + : source(coreSource) + , javaPeer(obj.NewGlobalRef(env)) + , rendererFrontend(&frontend) { + } - style::Source& Source::get() { - return source; + Source::Source(jni::JNIEnv&, std::unique_ptr coreSource) + : ownedSource(std::move(coreSource)) + , source(*ownedSource) { } - void Source::setSource(std::unique_ptr coreSource) { - this->ownedSource = std::move(coreSource); + Source::~Source() { + // Before being added to a map, the Java peer owns this C++ peer and cleans + // up after itself correctly through the jni native peer bindings. + // After being added to the map, the ownership is flipped and the C++ peer has a strong reference + // to it's Java peer, preventing the Java peer from being GC'ed. + // 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) { + // Manually clear the java peer + android::UniqueEnv env = android::AttachEnv(); + static auto nativePtrField = javaClass.GetField(*env, "nativePtr"); + javaPeer->Set(*env, nativePtrField, (jlong) 0); + javaPeer.reset(); + } } jni::String Source::getId(jni::JNIEnv& env) { @@ -49,23 +90,48 @@ namespace android { return attribution ? jni::Make(env, attribution.value()) : jni::Make(env,""); } - void Source::addToMap(mbgl::Map& _map) { + void Source::addToMap(JNIEnv& env, jni::Object obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { // Check to see if we own the source first if (!ownedSource) { throw std::runtime_error("Cannot add source twice"); } - // Add source to map - _map.getStyle().addSource(releaseCoreSource()); - } + // Add source to map and release ownership + map.getStyle().addSource(std::move(ownedSource)); + + // Add peer to core source + source.peer = std::unique_ptr(this); + + // Add strong reference to java source + javaPeer = obj.NewGlobalRef(env); - void Source::setRendererFrontend(AndroidRendererFrontend& frontend_) { - rendererFrontend = &frontend_; + rendererFrontend = &frontend; } - std::unique_ptr Source::releaseCoreSource() { - assert(ownedSource != nullptr); - return std::move(ownedSource); + void Source::removeFromMap(JNIEnv&, jni::Object, mbgl::Map& map) { + // Cannot remove if not attached yet + 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()); + + // The source may not be removed if any layers still reference it + 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()); + util::any_cast>(&(ownedSource->peer))->release(); + ownedSource->peer.reset(); + + // Release the strong reference to the java peer + assert(javaPeer); + javaPeer.release(); + + rendererFrontend = nullptr; } jni::Class Source::javaClass; @@ -82,6 +148,13 @@ namespace android { METHOD(&Source::getAttribution, "nativeGetAttribution") ); + // Register subclasses + GeoJSONSource::registerNative(env); + ImageSource::registerNative(env); + RasterSource::registerNative(env); + UnknownSource::registerNative(env); + VectorSource::registerNative(env); + CustomGeometrySource::registerNative(env); } } // namespace android diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp index 383017b66f..718f60b381 100644 --- a/platform/android/src/style/sources/source.hpp +++ b/platform/android/src/style/sources/source.hpp @@ -21,48 +21,40 @@ public: static void registerNative(jni::JNIEnv&); + static jni::Object peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); + /* - * Called when a Java object is created on the c++ side + * Called when a Java object is created for a core source that belongs to a map. */ - Source(mbgl::style::Source&); + Source(jni::JNIEnv&, mbgl::style::Source&, jni::Object, AndroidRendererFrontend&); /* - * Called when a Java object was created from the jvm side + * Called when a Java object is created for a new core source that does not belong to a map. */ Source(jni::JNIEnv&, std::unique_ptr); virtual ~Source(); - /** - * Set core source (ie return ownership after remove) - */ - void setSource(std::unique_ptr); - - style::Source& get(); - - void addToMap(mbgl::Map&); + void addToMap(JNIEnv&, jni::Object, mbgl::Map&, AndroidRendererFrontend&); - void setRendererFrontend(AndroidRendererFrontend&); - - virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0; + void removeFromMap(JNIEnv&, jni::Object, mbgl::Map&); jni::String getId(jni::JNIEnv&); jni::String getAttribution(jni::JNIEnv&); protected: - // Release the owned view and return it - std::unique_ptr releaseCoreSource(); - - // Set on newly created sources until added to the map + // Set on newly created sources until added to the map. std::unique_ptr ownedSource; - // Raw pointer that is valid until the source is removed from the map + // Raw pointer that is valid at all times. mbgl::style::Source& source; - // RendererFrontend pointer is valid only when - // added to the map - AndroidRendererFrontend* rendererFrontend; + // Set when the source is added to a map. + jni::UniqueObject javaPeer; + + // RendererFrontend pointer is valid only when added to the map. + AndroidRendererFrontend* rendererFrontend { nullptr }; }; } // namespace android diff --git a/platform/android/src/style/sources/sources.cpp b/platform/android/src/style/sources/sources.cpp deleted file mode 100644 index 72d7bcda8c..0000000000 --- a/platform/android/src/style/sources/sources.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "sources.hpp" - -#include -#include -#include -#include -#include - -#include "source.hpp" -#include "geojson_source.hpp" -#include "image_source.hpp" -#include "raster_source.hpp" -#include "unknown_source.hpp" -#include "vector_source.hpp" -#include "custom_geometry_source.hpp" - -namespace { - - using namespace mbgl::android; - - Source* initializeSourcePeer(mbgl::style::Source& coreSource) { - Source* source; - if (coreSource.is()) { - source = new VectorSource(*coreSource.as()); - } else if (coreSource.is()) { - source = new RasterSource(*coreSource.as()); - } else if (coreSource.is()) { - source = new GeoJSONSource(*coreSource.as()); - } else if (coreSource.is()) { - source = new ImageSource(*coreSource.as()); - } else { - source = new UnknownSource(coreSource); - } - - return source; - } -} // namespace - -namespace mbgl { -namespace android { - - -jni::jobject* createJavaSourcePeer(jni::JNIEnv& env, AndroidRendererFrontend& frontend, mbgl::style::Source& coreSource) { - std::unique_ptr peerSource = std::unique_ptr(initializeSourcePeer(coreSource)); - peerSource->setRendererFrontend(frontend); - jni::jobject* result = peerSource->createJavaPeer(env); - peerSource.release(); - return result; -} - -void registerNativeSources(jni::JNIEnv& env) { - Source::registerNative(env); - GeoJSONSource::registerNative(env); - ImageSource::registerNative(env); - RasterSource::registerNative(env); - UnknownSource::registerNative(env); - VectorSource::registerNative(env); - CustomGeometrySource::registerNative(env); -} - -} -} diff --git a/platform/android/src/style/sources/sources.hpp b/platform/android/src/style/sources/sources.hpp deleted file mode 100644 index c7b36818b2..0000000000 --- a/platform/android/src/style/sources/sources.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -#include "source.hpp" -#include "../../android_renderer_frontend.hpp" - -#include - -namespace mbgl { -namespace android { - - jni::jobject* createJavaSourcePeer(jni::JNIEnv&, AndroidRendererFrontend&, mbgl::style::Source&); - - void registerNativeSources(jni::JNIEnv&); - -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/style/sources/unknown_source.cpp b/platform/android/src/style/sources/unknown_source.cpp index 79f27bdfbf..4b5510c1db 100644 --- a/platform/android/src/style/sources/unknown_source.cpp +++ b/platform/android/src/style/sources/unknown_source.cpp @@ -12,15 +12,17 @@ namespace { namespace mbgl { namespace android { - UnknownSource::UnknownSource(mbgl::style::Source& coreSource) - : Source(coreSource) { + UnknownSource::UnknownSource(jni::JNIEnv& env, + mbgl::style::Source& coreSource, + AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend) { } jni::Class UnknownSource::javaClass; - jni::jobject* UnknownSource::createJavaPeer(jni::JNIEnv& env) { + jni::Object UnknownSource::createJavaPeer(jni::JNIEnv& env) { static auto constructor = UnknownSource::javaClass.template GetConstructor(env); - return UnknownSource::javaClass.New(env, constructor, reinterpret_cast(this)); + return jni::Object(UnknownSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void UnknownSource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/unknown_source.hpp b/platform/android/src/style/sources/unknown_source.hpp index 4a003c9a7f..414d420c61 100644 --- a/platform/android/src/style/sources/unknown_source.hpp +++ b/platform/android/src/style/sources/unknown_source.hpp @@ -16,11 +16,12 @@ public: static void registerNative(jni::JNIEnv&); - UnknownSource(mbgl::style::Source&); + UnknownSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); ~UnknownSource() = default; - jni::jobject* createJavaPeer(jni::JNIEnv&); +private: + jni::Object createJavaPeer(jni::JNIEnv&); }; // class UnknownSource diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index 7fe45441bd..9a9548d283 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -30,8 +30,10 @@ namespace android { ) { } - VectorSource::VectorSource(mbgl::style::VectorSource& coreSource) - : Source(coreSource) { + VectorSource::VectorSource(jni::JNIEnv& env, + mbgl::style::Source& coreSource, + AndroidRendererFrontend& frontend) + : Source(env, coreSource, createJavaPeer(env), frontend) { } VectorSource::~VectorSource() = default; @@ -56,9 +58,9 @@ namespace android { jni::Class VectorSource::javaClass; - jni::jobject* VectorSource::createJavaPeer(jni::JNIEnv& env) { + jni::Object VectorSource::createJavaPeer(jni::JNIEnv& env) { static auto constructor = VectorSource::javaClass.template GetConstructor(env); - return VectorSource::javaClass.New(env, constructor, reinterpret_cast(this)); + return jni::Object(VectorSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void VectorSource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index 509fe068d1..16049f5c77 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -19,7 +19,7 @@ public: VectorSource(jni::JNIEnv&, jni::String, jni::Object<>); - VectorSource(mbgl::style::VectorSource&); + VectorSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); ~VectorSource(); @@ -28,7 +28,8 @@ public: jni::String getURL(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); +private: + jni::Object createJavaPeer(jni::JNIEnv&); }; // class VectorSource -- cgit v1.2.1