Add MapRenderer dangling reference check (#3541)
Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
@@ -9,8 +9,10 @@
|
||||
#include <mbgl/util/instrumentation.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include "android_renderer_backend.hpp"
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
@@ -91,23 +93,38 @@ private:
|
||||
ActorRef<RendererObserver> delegate;
|
||||
};
|
||||
|
||||
AndroidRendererFrontend::AndroidRendererFrontend(Private, MapRenderer& mapRenderer_)
|
||||
: mapRenderer(mapRenderer_),
|
||||
AndroidRendererFrontend::AndroidRendererFrontend(Private,
|
||||
jni::JNIEnv& env,
|
||||
const jni::Object<MapRenderer>& mapRendererObj)
|
||||
: mapRenderer(MapRenderer::getNativePeer(env, mapRendererObj)),
|
||||
mapRunLoop(util::RunLoop::Get()) {}
|
||||
|
||||
std::shared_ptr<AndroidRendererFrontend> AndroidRendererFrontend::create(MapRenderer& mapRenderer) {
|
||||
auto ptr = std::make_shared<AndroidRendererFrontend>(Private(), mapRenderer);
|
||||
ptr->init();
|
||||
std::shared_ptr<AndroidRendererFrontend> AndroidRendererFrontend::create(
|
||||
jni::JNIEnv& env, const jni::Object<MapRenderer>& mapRendererObj) {
|
||||
auto ptr = std::make_shared<AndroidRendererFrontend>(Private(), env, mapRendererObj);
|
||||
ptr->init(env, mapRendererObj);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::init() {
|
||||
updateAsyncTask = std::make_unique<util::AsyncTask>([weakSelf = weak_from_this()]() {
|
||||
if (auto self = weakSelf.lock()) {
|
||||
self->mapRenderer.update(std::move(self->updateParams));
|
||||
self->mapRenderer.requestRender();
|
||||
}
|
||||
});
|
||||
void AndroidRendererFrontend::init(jni::JNIEnv& env, const jni::Object<MapRenderer>& mapRendererObj) {
|
||||
auto weakMapRenderer = std::make_shared<jni::WeakReference<jni::Object<MapRenderer>>>(env, mapRendererObj);
|
||||
|
||||
updateAsyncTask = std::make_unique<util::AsyncTask>(
|
||||
[weakSelf = weak_from_this(), weakMapRenderer = std::move(weakMapRenderer)]() {
|
||||
if (auto self = weakSelf.lock()) {
|
||||
try {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
auto mapRendererRef = weakMapRenderer->get(*_env);
|
||||
if (mapRendererRef) {
|
||||
self->mapRenderer.update(std::move(self->updateParams));
|
||||
self->mapRenderer.requestRender(*_env, mapRendererRef);
|
||||
}
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android,
|
||||
std::string("AndroidRendererFrontend::updateAsyncTask failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AndroidRendererFrontend::~AndroidRendererFrontend() = default;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class RenderedQueryOptions;
|
||||
@@ -33,10 +35,9 @@ class AndroidRendererFrontend : public RendererFrontend, public std::enable_shar
|
||||
};
|
||||
|
||||
public:
|
||||
AndroidRendererFrontend(Private, MapRenderer&);
|
||||
|
||||
static std::shared_ptr<AndroidRendererFrontend> create(MapRenderer&);
|
||||
void init();
|
||||
AndroidRendererFrontend(Private, jni::JNIEnv&, const jni::Object<MapRenderer>&);
|
||||
static std::shared_ptr<AndroidRendererFrontend> create(jni::JNIEnv&, const jni::Object<MapRenderer>&);
|
||||
void init(jni::JNIEnv&, const jni::Object<MapRenderer>&);
|
||||
|
||||
~AndroidRendererFrontend() override;
|
||||
|
||||
|
||||
@@ -138,6 +138,18 @@ void MapRenderer::requestRender() {
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::requestRender(JNIEnv& env, jni::Local<jni::Object<MapRenderer>>& ref) {
|
||||
try {
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
static auto onInvalidate = javaClass.GetMethod<void()>(env, "requestRender");
|
||||
if (ref) {
|
||||
ref.Call(env, onInvalidate);
|
||||
}
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, std::string("MapRenderer::requestRender failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::update(std::shared_ptr<UpdateParameters> params) {
|
||||
try {
|
||||
// Lock on the parameters
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
void waitForEmpty(const util::SimpleIdentity tag) override;
|
||||
|
||||
void requestRender();
|
||||
void requestRender(JNIEnv&, jni::Local<jni::Object<MapRenderer>>&);
|
||||
|
||||
// Snapshot - requires a RunLoop on the calling thread
|
||||
using SnapshotCallback = std::function<void(PremultipliedImage)>;
|
||||
|
||||
@@ -75,7 +75,7 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env,
|
||||
}
|
||||
|
||||
// Create a renderer frontend
|
||||
rendererFrontend = AndroidRendererFrontend::create(mapRenderer);
|
||||
rendererFrontend = AndroidRendererFrontend::create(_env, jMapRenderer);
|
||||
|
||||
// Create Map options
|
||||
MapOptions options;
|
||||
|
||||
Reference in New Issue
Block a user