diff options
author | Łukasz Paczos <lukas.paczos@gmail.com> | 2019-05-14 14:55:17 +0200 |
---|---|---|
committer | Łukasz Paczos <lukasz.paczos@mapbox.com> | 2019-05-24 15:03:55 +0200 |
commit | 1bef3b7d1d877c67db051b33e0516b36acee700d (patch) | |
tree | b8c60eeb7ddc1c4aefb1cbb1cfd86740fd1a75bd /platform | |
parent | 46ef2d86d2065aaaa63e8c83c750e46c74932777 (diff) | |
download | qtlocation-mapboxgl-1bef3b7d1d877c67db051b33e0516b36acee700d.tar.gz |
[android] resume file source and wait for result to complete resources cache path change
Diffstat (limited to 'platform')
5 files changed, 141 insertions, 30 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index 1301c103f4..b3b7b61831 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java @@ -312,8 +312,7 @@ public class FileSource { Context.MODE_PRIVATE).edit(); editor.putString(MAPBOX_SHARED_PREFERENCE_RESOURCES_CACHE_PATH, path); editor.apply(); - setResourcesCachePath(applicationContext, path); - callback.onSuccess(path); + internalSetResourcesCachePath(applicationContext, path, callback); } @Override @@ -326,11 +325,26 @@ public class FileSource { } } - private static void setResourcesCachePath(@NonNull Context context, @NonNull String path) { - resourcesCachePathLoaderLock.lock(); - resourcesCachePath = path; - resourcesCachePathLoaderLock.unlock(); - getInstance(context).setResourceCachePath(path); + private static void internalSetResourcesCachePath(@NonNull Context context, @NonNull String path, + @NonNull final ResourcesCachePathChangeCallback callback) { + final FileSource fileSource = getInstance(context); + fileSource.setResourceCachePath(path, new ResourcesCachePathChangeCallback() { + @Override + public void onSuccess(@NonNull String path) { + fileSource.deactivate(); + resourcesCachePathLoaderLock.lock(); + resourcesCachePath = path; + resourcesCachePathLoaderLock.unlock(); + callback.onSuccess(path); + } + + @Override + public void onError(@NonNull String message) { + fileSource.deactivate(); + callback.onError(message); + } + }); + fileSource.activate(); } private static boolean isPathWritable(String path) { @@ -388,7 +402,7 @@ public class FileSource { public native void setResourceTransform(final ResourceTransformCallback callback); @Keep - private native void setResourceCachePath(String path); + private native void setResourceCachePath(String path, ResourcesCachePathChangeCallback callback); @Keep private native void initialize(String accessToken, String cachePath, AssetManager assetManager); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt index 91b3922f47..08a15b0c54 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt @@ -1,6 +1,5 @@ package com.mapbox.mapboxsdk.testapp.storage -import android.os.Handler import android.support.test.annotation.UiThreadTest import android.support.test.rule.ActivityTestRule import android.support.test.runner.AndroidJUnit4 @@ -10,6 +9,7 @@ import org.junit.* import org.junit.rules.TestName import org.junit.runner.RunWith import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit @RunWith(AndroidJUnit4::class) class FileSourceStandaloneTest { @@ -55,19 +55,57 @@ class FileSourceStandaloneTest { fileSourceTestUtils.changePath(fileSourceTestUtils.testPath) Assert.assertEquals(fileSourceTestUtils.testPath, FileSource.getResourcesCachePath(rule.activity)) - // workaround for https://github.com/mapbox/mapbox-gl-native/issues/14334 - val latch = CountDownLatch(1) + fileSourceTestUtils.changePath(fileSourceTestUtils.originalPath) + Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity)) + } + + @Test + fun overridePathChangeCallTest() { + val firstLatch = CountDownLatch(1) + val secondLatch = CountDownLatch(1) rule.activity.runOnUiThread { - fileSource.activate() - Handler().postDelayed({ + FileSource.setResourcesCachePath( + fileSourceTestUtils.testPath, + object : FileSource.ResourcesCachePathChangeCallback { + override fun onSuccess(path: String) { + Assert.assertEquals(fileSourceTestUtils.testPath, path) + firstLatch.countDown() + } + + override fun onError(message: String) { + Assert.fail("First attempt should succeed.") + } + }) + + FileSource.setResourcesCachePath( + fileSourceTestUtils.testPath2, + object : FileSource.ResourcesCachePathChangeCallback { + override fun onSuccess(path: String) { + Assert.fail("Second attempt should fail because first one is in progress.") + } + + override fun onError(message: String) { + Assert.assertEquals("Another resources cache path change is in progress", message) + secondLatch.countDown() + } + }) + } + + if (!secondLatch.await(5, TimeUnit.SECONDS)) { + rule.runOnUiThread { + // if we fail to call a callback, the file source is not going to be deactivated fileSource.deactivate() - latch.countDown() - }, 2000) + } + Assert.fail("Second attempt should fail.") } - latch.await() - fileSourceTestUtils.changePath(fileSourceTestUtils.originalPath) - Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity)) + if (!firstLatch.await(5, TimeUnit.SECONDS)) { + rule.runOnUiThread { + // if we fail to call a callback, the file source is not going to be deactivated + fileSource.deactivate() + } + Assert.fail("First attempt should succeed.") + } } @After diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt index c69321581a..c79d3b2752 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt @@ -10,10 +10,15 @@ import java.util.concurrent.CountDownLatch class FileSourceTestUtils(private val activity: Activity) { val originalPath = FileSource.getResourcesCachePath(activity) val testPath = "$originalPath/test" + val testPath2 = "$originalPath/test2" + + private val paths = listOf(testPath, testPath2) fun setup() { - val testFile = File(testPath) - testFile.mkdirs() + for (path in paths) { + val testFile = File(path) + testFile.mkdirs() + } } @WorkerThread @@ -22,25 +27,29 @@ class FileSourceTestUtils(private val activity: Activity) { if (currentPath != originalPath) { changePath(originalPath) } - val testFile = File(testPath) - if (testFile.exists()) { - testFile.deleteRecursively() + + for (path in paths) { + val testFile = File(path) + if (testFile.exists()) { + testFile.deleteRecursively() + } } } @WorkerThread - fun changePath(path: String) { + fun changePath(requestedPath: String) { val latch = CountDownLatch(1) activity.runOnUiThread { FileSource.setResourcesCachePath( - path, + requestedPath, object : FileSource.ResourcesCachePathChangeCallback { override fun onSuccess(path: String) { + Assert.assertEquals(requestedPath, path) latch.countDown() } override fun onError(message: String) { - Assert.fail("Resource path change failed - path: $path, message: $message") + Assert.fail("Resource path change failed - path: $requestedPath, message: $message") } }) } diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 41081cd0fb..ba5f18dbc4 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -77,10 +77,25 @@ void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object<FileSo } } -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 (pathChangeCallback) { + FileSource::ResourcesCachePathChangeCallback::onError(env, _callback, jni::Make<jni::String>(env, "Another resources cache path change is in progress")); + return; + } + std::string newPath = jni::Make<std::string>(env, path); mapbox::sqlite::setTempPath(newPath); - fileSource->setResourceCachePath(newPath + DATABASE_FILE); + + 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(); + }); + + fileSource->setResourceCachePath(newPath + DATABASE_FILE, pathChangeCallback->self()); } void FileSource::resume(jni::JNIEnv&) { @@ -123,11 +138,32 @@ mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, con return fileSource->resourceOptions.clone(); } +// FileSource::ResourcesCachePathChangeCallback // + +void FileSource::ResourcesCachePathChangeCallback::onSuccess(jni::JNIEnv& env, + const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback, + const jni::String& path) { + static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env); + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onSuccess"); + + callback.Call(env, method, path); +} + +void FileSource::ResourcesCachePathChangeCallback::onError(jni::JNIEnv& env, + const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback, + const jni::String& message) { + static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env); + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); + + callback.Call(env, method, message); +} + void FileSource::registerNative(jni::JNIEnv& env) { - // Ensure the class for ResourceTransformCallback is cached. If it's requested for the + // Ensure the classes are cached. If they're requested for the // first time on a background thread, Android's class loader heuristics will fail. // https://developer.android.com/training/articles/perf-jni#faq_FindClass jni::Class<ResourceTransformCallback>::Singleton(env); + jni::Class<ResourcesCachePathChangeCallback>::Singleton(env); static auto& javaClass = jni::Class<FileSource>::Singleton(env); diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index 3001a5e0f0..f3ad33eb31 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -11,6 +11,7 @@ namespace mbgl { template <typename T> class Actor; class ResourceTransform; +using mbgl::PathChangeCallback; namespace android { @@ -28,6 +29,18 @@ public: static std::string onURL(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&, int, std::string); }; + struct ResourcesCachePathChangeCallback { + static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourcesCachePathChangeCallback";} + + static void onSuccess(jni::JNIEnv&, + const jni::Object<FileSource::ResourcesCachePathChangeCallback>&, + const jni::String&); + + static void onError(jni::JNIEnv&, + const jni::Object<FileSource::ResourcesCachePathChangeCallback>&, + const jni::String&); + }; + FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object<AssetManager>&); ~FileSource(); @@ -40,7 +53,7 @@ public: void setResourceTransform(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&); - void setResourceCachePath(jni::JNIEnv&, const jni::String&); + void setResourceCachePath(jni::JNIEnv&, const jni::String&, const jni::Object<FileSource::ResourcesCachePathChangeCallback>&); void resume(jni::JNIEnv&); @@ -59,6 +72,7 @@ private: optional<int> activationCounter; mbgl::ResourceOptions resourceOptions; std::unique_ptr<Actor<ResourceTransform>> resourceTransform; + std::unique_ptr<Actor<PathChangeCallback>> pathChangeCallback; std::shared_ptr<mbgl::DefaultFileSource> fileSource; }; |