Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[android] Use new FileSourceManager interface
Browse files Browse the repository at this point in the history
Use new interface for Android classes:

- FileSource
- OfflineRegion
- OfflineManager
  • Loading branch information
alexshalamov committed Oct 14, 2019
1 parent e965761 commit bb2c870
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.util.concurrent.locks.ReentrantLock;

/**
* Holds a central reference to the core's DefaultFileSource for as long as
* Holds a central reference to the core's FileSource instances for as long as
* there are active mapviews / offline managers
*/
public class FileSource {
Expand Down
1 change: 1 addition & 0 deletions platform/android/filesource-files.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"platform/android/src/offline/offline_region_definition.cpp",
"platform/android/src/offline/offline_region_error.cpp",
"platform/android/src/offline/offline_region_status.cpp",
"platform/default/src/mbgl/storage/file_source_manager.cpp",
"platform/default/src/mbgl/storage/sqlite3.cpp"
],
"public_headers": {},
Expand Down
7 changes: 6 additions & 1 deletion platform/android/src/asset_manager_file_source.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include "asset_manager_file_source.hpp"

#include <mbgl/storage/file_source_request.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/url.hpp>
#include <mbgl/util/util.hpp>

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
Expand Down Expand Up @@ -54,4 +55,8 @@ std::unique_ptr<AsyncRequest> 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
1 change: 1 addition & 0 deletions platform/android/src/asset_manager_file_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class AssetManagerFileSource : public FileSource {
~AssetManagerFileSource() override;

std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
bool canRequest(const Resource&) const override;

private:
class Impl;
Expand Down
124 changes: 85 additions & 39 deletions platform/android/src/file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/logging.hpp>
Expand All @@ -14,21 +15,6 @@
#include "asset_manager_file_source.hpp"

namespace mbgl {

std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) {
auto env{android::AttachEnv()};
std::shared_ptr<DefaultFileSource> fileSource;
if (android::Mapbox::hasInstance(*env)) {
auto assetManager = android::Mapbox::getAssetManager(*env);
fileSource = std::make_shared<DefaultFileSource>(options.cachePath(),
std::make_unique<AssetManagerFileSource>(*env, assetManager));
} else {
fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), options.assetPath());
}
fileSource->setAccessToken(options.accessToken());
return fileSource;
}

namespace android {

// FileSource //
Expand All @@ -37,53 +23,99 @@ FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const
std::string path = jni::Make<std::string>(_env, _cachePath);
mapbox::sqlite::setTempPath(path);

mbgl::FileSourceManager::get()->registerFileSourceFactory(
mbgl::FileSourceType::Asset, [](const mbgl::ResourceOptions&) {
auto env{android::AttachEnv()};
std::unique_ptr<mbgl::FileSource> assetFileSource;
if (android::Mapbox::hasInstance(*env)) {

This comment has been minimized.

Copy link
@LukasPaczos

LukasPaczos Oct 21, 2019

Member

Should we throw if this condition is not met?

com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException would be a good candidate.

auto assetManager = android::Mapbox::getAssetManager(*env);
assetFileSource = std::make_unique<AssetManagerFileSource>(*env, assetManager);
}
return assetFileSource;
});

resourceOptions.withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "")
.withCachePath(path + DATABASE_FILE);

// Create a core default file source
fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(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::DatabaseFileSource>(
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Database, resourceOptions));
onlineSource = std::static_pointer_cast<mbgl::OnlineFileSource>(
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Network, resourceOptions));
}

FileSource::~FileSource() {
}

jni::Local<jni::String> FileSource::getAccessToken(jni::JNIEnv& env) {
return jni::Make<jni::String>(env, fileSource->getAccessToken());
if (auto* token = onlineSource->getProperty("access-token").getString()) {
return jni::Make<jni::String>(env, *token);
}

ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
return jni::Make<jni::String>(env, "");
}

void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) {
fileSource->setAccessToken(token ? jni::Make<std::string>(env, token) : "");
if (onlineSource) {
onlineSource->setProperty("access-token", token ? jni::Make<std::string>(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<std::string>(env, url));
if (onlineSource) {
onlineSource->setProperty("api-base-url", jni::Make<std::string>(env, url));
} else {
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
}
}

void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& 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<jni::EnvAttachingDeleter>(env, transformCallback);
resourceTransform = std::make_unique<Actor<ResourceTransform>>(
resourceTransform = std::make_unique<Actor<ResourceTransform::TransformCallback>>(
*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<decltype(global)>(std::move(global))](mbgl::Resource::Kind kind,
const std::string& url_) {
[callback = std::make_shared<decltype(global)>(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<FileSource::ResourcesCachePathChangeCallback>& _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<jni::String>(env, "Another resources cache path change is in progress"));
return;
Expand All @@ -93,33 +125,42 @@ void FileSource::setResourceCachePath(jni::JNIEnv& env, const jni::String& path,
mapbox::sqlite::setTempPath(newPath);

auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, _callback);
pathChangeCallback = std::make_unique<Actor<PathChangeCallback>>(*Scheduler::GetCurrent(),
[this, callback = std::make_shared<decltype(global)>(std::move(global)), newPath] {
android::UniqueEnv _env = android::AttachEnv();
FileSource::ResourcesCachePathChangeCallback::onSuccess(*_env, *callback, jni::Make<jni::String>(*_env, newPath));
pathChangeCallback.reset();
});
pathChangeCallback = Scheduler::GetCurrent()->bindOnce(
[this, callback = std::make_shared<decltype(global)>(std::move(global)), newPath] {
android::UniqueEnv _env = android::AttachEnv();
FileSource::ResourcesCachePathChangeCallback::onSuccess(
*_env, *callback, jni::Make<jni::String>(*_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<int>(1) ;
return;
}

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();
}
}
}
Expand All @@ -137,10 +178,15 @@ FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSo
return reinterpret_cast<FileSource *>(jFileSource.Get(env, field));
}

mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env,
const jni::Object<FileSource>& 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 //
Expand Down
18 changes: 10 additions & 8 deletions platform/android/src/file_source.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/database_file_source.hpp>
#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/resource_transform.hpp>

#include "asset_manager.hpp"

Expand All @@ -10,13 +12,12 @@
namespace mbgl {

template <typename T> 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:
Expand Down Expand Up @@ -71,11 +72,12 @@ class FileSource {
const std::string DATABASE_FILE = "/mbgl-offline.db";
optional<int> activationCounter;
mbgl::ResourceOptions resourceOptions;
std::unique_ptr<Actor<ResourceTransform>> resourceTransform;
std::unique_ptr<Actor<PathChangeCallback>> pathChangeCallback;
std::shared_ptr<mbgl::DefaultFileSource> fileSource;
std::unique_ptr<Actor<ResourceTransform::TransformCallback>> resourceTransform;
std::function<void()> pathChangeCallback;
std::shared_ptr<mbgl::DatabaseFileSource> databaseSource;
std::shared_ptr<mbgl::OnlineFileSource> onlineSource;
std::shared_ptr<mbgl::FileSource> resourceLoader;
};


} // namespace android
} // namespace mbgl
5 changes: 3 additions & 2 deletions platform/android/src/http_file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
#include <mbgl/storage/response.hpp>
#include <mbgl/util/logging.hpp>

#include <mbgl/util/async_request.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/http_header.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/util.hpp>

#include <jni/jni.hpp>
#include "attach_env.hpp"
Expand Down
2 changes: 1 addition & 1 deletion platform/android/src/jni_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
9 changes: 8 additions & 1 deletion platform/android/src/offline/offline_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "offline_manager.hpp"

#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/util/string.hpp>

#include "../attach_env.hpp"
Expand All @@ -10,7 +12,12 @@ namespace android {
// OfflineManager //

OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource)
: fileSource(std::static_pointer_cast<DefaultFileSource>(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {}
: fileSource(std::static_pointer_cast<mbgl::DatabaseFileSource>(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() {}

Expand Down
4 changes: 1 addition & 3 deletions platform/android/src/offline/offline_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

namespace mbgl {

class DefaultFileSource;

namespace android {

class OfflineManager {
Expand Down Expand Up @@ -102,7 +100,7 @@ class OfflineManager {
void setMaximumAmbientCacheSize(jni::JNIEnv&, const jni::jlong size, const jni::Object<FileSourceCallback>& callback_);

private:
std::shared_ptr<mbgl::DefaultFileSource> fileSource;
std::shared_ptr<mbgl::DatabaseFileSource> fileSource;
};

} // namespace android
Expand Down
Loading

0 comments on commit bb2c870

Please sign in to comment.