From e1ed0632225bee5c6ce623434fbba2fe833d2d27 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 7 Oct 2019 15:43:09 +0300 Subject: [android] Use new FileSourceManager interface Use new interface for android jni adaptation classes. --- platform/android/src/asset_manager_file_source.cpp | 7 +- platform/android/src/asset_manager_file_source.hpp | 1 + platform/android/src/file_source.cpp | 124 ++++++++++++++------- platform/android/src/file_source.hpp | 18 +-- platform/android/src/http_file_source.cpp | 5 +- platform/android/src/jni_native.cpp | 2 +- platform/android/src/offline/offline_manager.cpp | 9 +- platform/android/src/offline/offline_manager.hpp | 4 +- platform/android/src/offline/offline_region.cpp | 26 +++-- platform/android/src/offline/offline_region.hpp | 2 +- 10 files changed, 133 insertions(+), 65 deletions(-) diff --git a/platform/android/src/asset_manager_file_source.cpp b/platform/android/src/asset_manager_file_source.cpp index b9150deef9..73ecec2b05 100644 --- a/platform/android/src/asset_manager_file_source.cpp +++ b/platform/android/src/asset_manager_file_source.cpp @@ -1,10 +1,11 @@ #include "asset_manager_file_source.hpp" #include +#include #include -#include #include #include +#include #include #include @@ -54,4 +55,8 @@ std::unique_ptr AssetManagerFileSource::request(const Resource& re return std::move(req); } +bool AssetManagerFileSource::canRequest(const Resource& resource) const { + return 0 == resource.url.rfind(mbgl::util::ASSET_PROTOCOL, 0); +} + } // namespace mbgl diff --git a/platform/android/src/asset_manager_file_source.hpp b/platform/android/src/asset_manager_file_source.hpp index 4ec5b4c30e..bcbc6f1e9d 100644 --- a/platform/android/src/asset_manager_file_source.hpp +++ b/platform/android/src/asset_manager_file_source.hpp @@ -18,6 +18,7 @@ public: ~AssetManagerFileSource() override; std::unique_ptr request(const Resource&, Callback) override; + bool canRequest(const Resource&) const override; private: class Impl; diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index a002d6616f..8bbe9acbd2 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -14,21 +15,6 @@ #include "asset_manager_file_source.hpp" namespace mbgl { - -std::shared_ptr FileSource::createPlatformFileSource(const ResourceOptions& options) { - auto env{android::AttachEnv()}; - std::shared_ptr fileSource; - if (android::Mapbox::hasInstance(*env)) { - auto assetManager = android::Mapbox::getAssetManager(*env); - fileSource = std::make_shared(options.cachePath(), - std::make_unique(*env, assetManager)); - } else { - fileSource = std::make_shared(options.cachePath(), options.assetPath()); - } - fileSource->setAccessToken(options.accessToken()); - return fileSource; -} - namespace android { // FileSource // @@ -37,53 +23,99 @@ FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const std::string path = jni::Make(_env, _cachePath); mapbox::sqlite::setTempPath(path); + mbgl::FileSourceManager::get()->registerFileSourceFactory( + mbgl::FileSourceType::Asset, [](const mbgl::ResourceOptions&) { + auto env{android::AttachEnv()}; + std::unique_ptr assetFileSource; + if (android::Mapbox::hasInstance(*env)) { + auto assetManager = android::Mapbox::getAssetManager(*env); + assetFileSource = std::make_unique(*env, assetManager); + } + return assetFileSource; + }); + resourceOptions.withAccessToken(accessToken ? jni::Make(_env, accessToken) : "") .withCachePath(path + DATABASE_FILE); - // Create a core default file source - fileSource = std::static_pointer_cast(mbgl::FileSource::getSharedFileSource(resourceOptions)); + // Create a core file sources + // TODO: Split Android FileSource API to smaller interfaces + resourceLoader = + mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::ResourceLoader, resourceOptions); + databaseSource = std::static_pointer_cast( + mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Database, resourceOptions)); + onlineSource = std::static_pointer_cast( + mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Network, resourceOptions)); } FileSource::~FileSource() { } jni::Local FileSource::getAccessToken(jni::JNIEnv& env) { - return jni::Make(env, fileSource->getAccessToken()); + if (auto* token = onlineSource->getProperty(mbgl::ACCESS_TOKEN_KEY).getString()) { + return jni::Make(env, *token); + } + + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled."); + return jni::Make(env, ""); } void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) { - fileSource->setAccessToken(token ? jni::Make(env, token) : ""); + if (onlineSource) { + onlineSource->setProperty(mbgl::ACCESS_TOKEN_KEY, token ? jni::Make(env, token) : ""); + } else { + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled."); + } } void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) { - fileSource->setAPIBaseURL(jni::Make(env, url)); + if (onlineSource) { + onlineSource->setProperty(mbgl::API_BASE_URL_KEY, jni::Make(env, url)); + } else { + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled."); + } } void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object& transformCallback) { + // Core could be built without support for network resource provider. + if (!onlineSource) { + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled."); + return; + } + if (transformCallback) { auto global = jni::NewGlobal(env, transformCallback); - resourceTransform = std::make_unique>( + resourceTransform = std::make_unique>( *Scheduler::GetCurrent(), // Capture the ResourceTransformCallback object as a managed global into // the lambda. It is released automatically when we're setting a new ResourceTransform in // a subsequent call. // Note: we're converting it to shared_ptr because this lambda is converted to a std::function, // which requires copyability of its captured variables. - [callback = std::make_shared(std::move(global))](mbgl::Resource::Kind kind, - const std::string& url_) { + [callback = std::make_shared(std::move(global))]( + mbgl::Resource::Kind kind, const std::string& url_, ResourceTransform::FinishedCallback cb) { android::UniqueEnv _env = android::AttachEnv(); - return FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_); + cb(FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_)); }); - fileSource->setResourceTransform(resourceTransform->self()); + onlineSource->setResourceTransform( + {[actorRef = resourceTransform->self()]( + Resource::Kind kind, const std::string& url, ResourceTransform::FinishedCallback cb) { + actorRef.invoke(&ResourceTransform::TransformCallback::operator(), kind, url, std::move(cb)); + }}); } else { // Reset the callback resourceTransform.reset(); - fileSource->setResourceTransform({}); + onlineSource->setResourceTransform({}); } } -void FileSource::setResourceCachePath(jni::JNIEnv& env, const jni::String& path, +void FileSource::setResourceCachePath(jni::JNIEnv& env, + const jni::String& path, const jni::Object& _callback) { + if (!databaseSource) { + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled."); + return; + } + if (pathChangeCallback) { FileSource::ResourcesCachePathChangeCallback::onError(env, _callback, jni::Make(env, "Another resources cache path change is in progress")); return; @@ -93,17 +125,22 @@ void FileSource::setResourceCachePath(jni::JNIEnv& env, const jni::String& path, mapbox::sqlite::setTempPath(newPath); auto global = jni::NewGlobal(env, _callback); - pathChangeCallback = std::make_unique>(*Scheduler::GetCurrent(), - [this, callback = std::make_shared(std::move(global)), newPath] { - android::UniqueEnv _env = android::AttachEnv(); - FileSource::ResourcesCachePathChangeCallback::onSuccess(*_env, *callback, jni::Make(*_env, newPath)); - pathChangeCallback.reset(); - }); + pathChangeCallback = Scheduler::GetCurrent()->bindOnce( + [this, callback = std::make_shared(std::move(global)), newPath] { + android::UniqueEnv _env = android::AttachEnv(); + FileSource::ResourcesCachePathChangeCallback::onSuccess( + *_env, *callback, jni::Make(*_env, newPath)); + pathChangeCallback = {}; + }); - fileSource->setResourceCachePath(newPath + DATABASE_FILE, pathChangeCallback->self()); + databaseSource->setDatabasePath(newPath + DATABASE_FILE, pathChangeCallback); } void FileSource::resume(jni::JNIEnv&) { + if (!resourceLoader) { + return; + } + if (!activationCounter) { activationCounter = optional(1) ; return; @@ -111,15 +148,19 @@ void FileSource::resume(jni::JNIEnv&) { activationCounter.value()++; if (activationCounter == 1) { - fileSource->resume(); + resourceLoader->resume(); } } void FileSource::pause(jni::JNIEnv&) { + if (!resourceLoader) { + return; + } + if (activationCounter) { activationCounter.value()--; if (activationCounter == 0) { - fileSource->pause(); + resourceLoader->pause(); } } } @@ -137,10 +178,15 @@ FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object(jFileSource.Get(env, field)); } -mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, const jni::Object& jFileSource) { +mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, + const jni::Object& jFileSource) { FileSource* fileSource = FileSource::getNativePeer(env, jFileSource); - assert(fileSource != nullptr); - return fileSource->resourceOptions.clone(); + // Core could be compiled without support for any sources. + if (fileSource) { + return fileSource->resourceOptions.clone(); + } + + return {}; } // FileSource::ResourcesCachePathChangeCallback // diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index 6a9190fa06..591bfbc93e 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -1,7 +1,9 @@ #pragma once -#include +#include +#include #include +#include #include "asset_manager.hpp" @@ -10,13 +12,12 @@ namespace mbgl { template class Actor; -class ResourceTransform; -using mbgl::PathChangeCallback; namespace android { /** - * Peer class for the Android FileSource holder. Ensures that a single DefaultFileSource is used + * Peer class for the Android FileSource holder. Ensures that a single core FileSource + * of a ResourceLoader type is used. */ class FileSource { public: @@ -71,11 +72,12 @@ private: const std::string DATABASE_FILE = "/mbgl-offline.db"; optional activationCounter; mbgl::ResourceOptions resourceOptions; - std::unique_ptr> resourceTransform; - std::unique_ptr> pathChangeCallback; - std::shared_ptr fileSource; + std::unique_ptr> resourceTransform; + std::function pathChangeCallback; + std::shared_ptr databaseSource; + std::shared_ptr onlineSource; + std::shared_ptr resourceLoader; }; - } // namespace android } // namespace mbgl diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index 7066918fef..37f7307373 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -3,10 +3,11 @@ #include #include +#include #include -#include -#include #include +#include +#include #include #include "attach_env.hpp" diff --git a/platform/android/src/jni_native.cpp b/platform/android/src/jni_native.cpp index bcbdfcf484..d6b03d981e 100644 --- a/platform/android/src/jni_native.cpp +++ b/platform/android/src/jni_native.cpp @@ -66,7 +66,7 @@ void registerNatives(JavaVM *vm) { jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6); - // For the DefaultFileSource + // For the FileSource static mbgl::util::RunLoop mainRunLoop; FileSource::registerNative(env); diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index be864e18aa..98f2b88a7f 100644 --- a/platform/android/src/offline/offline_manager.cpp +++ b/platform/android/src/offline/offline_manager.cpp @@ -1,5 +1,7 @@ #include "offline_manager.hpp" +#include +#include #include #include "../attach_env.hpp" @@ -23,7 +25,12 @@ void handleException(std::exception_ptr exception, // OfflineManager // OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object& jFileSource) - : fileSource(std::static_pointer_cast(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {} + : fileSource(std::static_pointer_cast(mbgl::FileSourceManager::get()->getFileSource( + mbgl::FileSourceType::Database, FileSource::getSharedResourceOptions(env, jFileSource)))) { + if (!fileSource) { + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled."); + } +} OfflineManager::~OfflineManager() {} diff --git a/platform/android/src/offline/offline_manager.hpp b/platform/android/src/offline/offline_manager.hpp index 0af92f8115..84111a7423 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -12,8 +12,6 @@ namespace mbgl { -class DefaultFileSource; - namespace android { class OfflineManager { @@ -106,7 +104,7 @@ public: void runPackDatabaseAutomatically(jni::JNIEnv&, jboolean autopack); private: - std::shared_ptr fileSource; + std::shared_ptr fileSource; }; } // namespace android diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 4276ce8f45..4ee835bab3 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -1,5 +1,6 @@ #include "offline_region.hpp" +#include #include #include @@ -14,8 +15,13 @@ namespace android { // OfflineRegion // OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object& jFileSource) - : region(reinterpret_cast(offlineRegionPtr)) - , fileSource(std::static_pointer_cast(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {} + : region(reinterpret_cast(offlineRegionPtr)), + fileSource(std::static_pointer_cast(mbgl::FileSourceManager::get()->getFileSource( + mbgl::FileSourceType::Database, FileSource::getSharedResourceOptions(env, jFileSource)))) { + if (!fileSource) { + ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled."); + } +} OfflineRegion::~OfflineRegion() {} @@ -159,15 +165,17 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Ar }); } -jni::Local> OfflineRegion::New(jni::JNIEnv& env, const jni::Object& jFileSource, mbgl::OfflineRegion region) { - +jni::Local> OfflineRegion::New(jni::JNIEnv& env, + const jni::Object& jFileSource, + mbgl::OfflineRegion region) { // Definition auto definition = region.getDefinition().match( - [&](const mbgl::OfflineTilePyramidRegionDefinition def) { - return OfflineTilePyramidRegionDefinition::New(env, def); - }, [&](const mbgl::OfflineGeometryRegionDefinition def) { - return OfflineGeometryRegionDefinition::New(env, def); - }); + [&](const mbgl::OfflineTilePyramidRegionDefinition def) { + return OfflineTilePyramidRegionDefinition::New(env, def); + }, + [&](const mbgl::OfflineGeometryRegionDefinition def) { + return OfflineGeometryRegionDefinition::New(env, def); + }); // Create region java object static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/offline/offline_region.hpp b/platform/android/src/offline/offline_region.hpp index dda253469e..6844008bb4 100644 --- a/platform/android/src/offline/offline_region.hpp +++ b/platform/android/src/offline/offline_region.hpp @@ -85,7 +85,7 @@ public: private: std::unique_ptr region; - std::shared_ptr fileSource; + std::shared_ptr fileSource; }; } // namespace android -- cgit v1.2.1