diff --git a/android/app/src/main/cpp/app/organicmaps/Framework.cpp b/android/app/src/main/cpp/app/organicmaps/Framework.cpp index 4fd22617f4..9b8a1c1bbe 100644 --- a/android/app/src/main/cpp/app/organicmaps/Framework.cpp +++ b/android/app/src/main/cpp/app/organicmaps/Framework.cpp @@ -108,11 +108,11 @@ enum MultiTouchAction MULTITOUCH_CANCEL = 0x00000004 }; -Framework::Framework() - : m_lastCompass(0.0) - , m_isSurfaceDestroyed(false) - , m_isChoosePositionMode(false) +Framework::Framework(std::function && afterMapsLoaded) +: m_work({} /* params */, false /* loadMaps */) { + m_work.LoadMapsAsync(std::move(afterMapsLoaded)); + m_work.GetTrafficManager().SetStateListener(bind(&Framework::TrafficStateChanged, this, _1)); m_work.GetTransitManager().SetStateListener(bind(&Framework::TransitSchemeStateChanged, this, _1)); m_work.GetIsolinesManager().SetStateListener(bind(&Framework::IsolinesSchemeStateChanged, this, _1)); @@ -1351,9 +1351,8 @@ JNIEXPORT void JNICALL Java_app_organicmaps_Framework_nativeSetRoutingListener(JNIEnv * env, jclass, jobject listener) { CHECK(g_framework, ("Framework isn't created yet!")); - auto rf = jni::make_global_ref(listener); frm()->GetRoutingManager().SetRouteBuildingListener( - [rf](routing::RouterResultCode e, storage::CountriesSet const & countries) { + [rf = jni::make_global_ref(listener)](routing::RouterResultCode e, storage::CountriesSet const & countries) { CallRoutingListener(rf, static_cast(e), countries); }); } diff --git a/android/app/src/main/cpp/app/organicmaps/Framework.hpp b/android/app/src/main/cpp/app/organicmaps/Framework.hpp index 02edd66368..e493ba61eb 100644 --- a/android/app/src/main/cpp/app/organicmaps/Framework.hpp +++ b/android/app/src/main/cpp/app/organicmaps/Framework.hpp @@ -57,12 +57,10 @@ namespace android ::Framework m_work; math::LowPassVector m_sensors[2]; - double m_lastCompass; + double m_lastCompass = 0; std::string m_searchQuery; - bool m_isSurfaceDestroyed; - std::map m_guiPositions; void TrafficStateChanged(TrafficManager::TrafficState state); @@ -77,10 +75,11 @@ namespace android TransitReadManager::TransitStateChangedFn m_onTransitStateChangedFn; IsolinesManager::IsolinesStateChangedFn m_onIsolinesStateChangedFn; - bool m_isChoosePositionMode; + bool m_isChoosePositionMode = false; + bool m_isSurfaceDestroyed = false; public: - Framework(); + Framework(std::function && afterMapsLoaded); storage::Storage & GetStorage(); DataSource const & GetDataSource(); diff --git a/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp b/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp index 3643c5f5cf..3c1b501326 100644 --- a/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp +++ b/android/app/src/main/cpp/app/organicmaps/MwmApplication.cpp @@ -29,10 +29,17 @@ extern "C" // static void nativeInitFramework(); JNIEXPORT void JNICALL - Java_app_organicmaps_MwmApplication_nativeInitFramework(JNIEnv * env, jclass clazz) + Java_app_organicmaps_MwmApplication_nativeInitFramework(JNIEnv * env, jclass clazz, jobject listener) { if (!g_framework) - g_framework = std::make_unique(); + { + g_framework = std::make_unique([listener = jni::make_global_ref(listener)]() + { + JNIEnv * env = jni::GetEnv(); + jmethodID const methodId = jni::GetMethodID(env, *listener, "processNavigation", "()V"); + env->CallVoidMethod(*listener, methodId); + }); + } } // static void nativeProcessTask(long taskPointer); diff --git a/android/app/src/main/java/app/organicmaps/MwmApplication.java b/android/app/src/main/java/app/organicmaps/MwmApplication.java index 2ba2e362c8..cfff380844 100644 --- a/android/app/src/main/java/app/organicmaps/MwmApplication.java +++ b/android/app/src/main/java/app/organicmaps/MwmApplication.java @@ -153,10 +153,10 @@ public class MwmApplication extends Application implements Application.ActivityL * @throws IOException - if failed to create directories. Caller must handle * the exception and do nothing with native code if initialization is failed. */ - public void init() throws IOException + public boolean init(SplashActivity listener) throws IOException { initNativePlatform(); - initNativeFramework(); + return initNativeFramework(listener); } private void initNativePlatform() throws IOException @@ -203,12 +203,12 @@ public class MwmApplication extends Application implements Application.ActivityL StorageUtils.requireDirectory(tempPath); } - private void initNativeFramework() + private boolean initNativeFramework(SplashActivity listener) { if (mFrameworkInitialized) - return; + return false; - nativeInitFramework(); + nativeInitFramework(listener); MapManager.nativeSubscribe(mStorageCallbacks); @@ -223,10 +223,11 @@ public class MwmApplication extends Application implements Application.ActivityL TrafficManager.INSTANCE.initialize(null); SubwayManager.from(this).initialize(null); IsolinesManager.from(this).initialize(null); + ProcessLifecycleOwner.get().getLifecycle().addObserver(mProcessLifecycleObserver); Logger.i(TAG, "Framework initialized"); mFrameworkInitialized = true; - ProcessLifecycleOwner.get().getLifecycle().addObserver(mProcessLifecycleObserver); + return true; } private void initNativeStrings() @@ -274,7 +275,7 @@ public class MwmApplication extends Application implements Application.ActivityL private native void nativeInitPlatform(String apkPath, String writablePath, String privatePath, String tmpPath, String flavorName, String buildType, boolean isTablet); - private static native void nativeInitFramework(); + private static native void nativeInitFramework(SplashActivity listener); private static native void nativeProcessTask(long taskPointer); private static native void nativeAddLocalization(String name, String value); private static native void nativeOnTransit(boolean foreground); diff --git a/android/app/src/main/java/app/organicmaps/SplashActivity.java b/android/app/src/main/java/app/organicmaps/SplashActivity.java index 21bab2d548..d2bd87f3f4 100644 --- a/android/app/src/main/java/app/organicmaps/SplashActivity.java +++ b/android/app/src/main/java/app/organicmaps/SplashActivity.java @@ -142,9 +142,10 @@ public class SplashActivity extends AppCompatActivity private void init() { MwmApplication app = MwmApplication.from(this); + boolean asyncContinue = false; try { - app.init(); + asyncContinue = app.init(this); } catch (IOException e) { showFatalErrorDialog(R.string.dialog_error_storage_title, R.string.dialog_error_storage_message); @@ -160,11 +161,13 @@ public class SplashActivity extends AppCompatActivity LocationHelper.INSTANCE.start(); } - processNavigation(); + if (!asyncContinue) + processNavigation(); } - @SuppressWarnings("unchecked") - private void processNavigation() + // Called from MwmApplication::nativeInitFramework like callback. + @SuppressWarnings({"unused", "unchecked"}) + public void processNavigation() { Intent input = getIntent(); Intent result = new Intent(this, DownloadResourcesLegacyActivity.class); diff --git a/map/framework.cpp b/map/framework.cpp index dc04388bd1..c2eef7a96b 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -271,7 +271,7 @@ void Framework::OnViewportChanged(ScreenBase const & screen) m_viewportChangedFn(screen); } -Framework::Framework(FrameworkParams const & params) +Framework::Framework(FrameworkParams const & params, bool loadMaps) : m_enabledDiffs(params.m_enableDiffs) , m_isRenderingEnabled(true) , m_transitManager(m_featuresFetcher.GetDataSource(), @@ -333,7 +333,7 @@ Framework::Framework(FrameworkParams const & params) LOG(LDEBUG, ("Country info getter initialized")); InitSearchAPI(params.m_numSearchAPIThreads); - LOG(LDEBUG, ("Search API initialized")); + LOG(LDEBUG, ("Search API initialized, part 1")); m_bmManager = make_unique(BookmarkManager::Callbacks( [this]() -> StringsBundle const & { return m_stringsBundle; }, @@ -358,29 +358,15 @@ Framework::Framework(FrameworkParams const & params) m_storage.SetDownloadingPolicy(&m_storageDownloadingPolicy); m_storage.SetStartDownloadingCallback([this]() { UpdatePlacePageInfoForCurrentSelection(); }); - LOG(LDEBUG, ("Storage initialized")); - - RegisterAllMaps(); - LOG(LDEBUG, ("Maps initialized")); - - // Perform real initialization after World was loaded. - GetSearchAPI().InitAfterWorldLoaded(); m_routingManager.SetRouterImpl(RouterType::Vehicle); UpdateMinBuildingsTapZoom(); - LOG(LDEBUG, ("Routing engine initialized")); - LOG(LINFO, ("System languages:", languages::GetPreferred())); editor.SetDelegate(make_unique(m_featuresFetcher.GetDataSource())); editor.SetInvalidateFn([this](){ InvalidateRect(GetCurrentViewport()); }); - editor.LoadEdits(); - - m_featuresFetcher.GetDataSource().AddObserver(editor); - - LOG(LDEBUG, ("Editor initialized")); m_trafficManager.SetCurrentDataVersion(m_storage.GetCurrentDataVersion()); m_trafficManager.SetSimplifiedColorScheme(LoadTrafficSimplifiedColors()); @@ -391,8 +377,12 @@ Framework::Framework(FrameworkParams const & params) InitTransliteration(); LOG(LDEBUG, ("Transliterators initialized")); + /// @todo No any real config loading here for now. GetPowerManager().Subscribe(this); GetPowerManager().Load(); + + if (loadMaps) + LoadMapsSync(); } Framework::~Framework() @@ -503,12 +493,50 @@ bool Framework::HasUnsavedEdits(storage::CountryId const & countryId) return hasUnsavedChanges; } +// Small copy-paste with LoadMapsAsync, but I don't have a better solution. +void Framework::LoadMapsSync() +{ + RegisterAllMaps(); + LOG(LDEBUG, ("Maps initialized")); + + GetSearchAPI().InitAfterWorldLoaded(); + LOG(LDEBUG, ("Search API initialized, part 2, after World was loaded")); + + osm::Editor & editor = osm::Editor::Instance(); + editor.LoadEdits(); + m_featuresFetcher.GetDataSource().AddObserver(editor); + LOG(LDEBUG, ("Editor initialized")); + + GetStorage().RestoreDownloadQueue(); +} + +// Small copy-paste with LoadMapsSync, but I don't have a better solution. +void Framework::LoadMapsAsync(std::function && callback) +{ + osm::Editor & editor = osm::Editor::Instance(); + threads::SimpleThread([this, &editor, callback = std::move(callback)]() + { + RegisterAllMaps(); + LOG(LDEBUG, ("Maps initialized")); + + GetSearchAPI().InitAfterWorldLoaded(); + LOG(LDEBUG, ("Search API initialized, part 2, after World was loaded")); + + GetPlatform().RunTask(Platform::Thread::Gui, [this, &editor, callback = std::move(callback)]() + { + editor.LoadEdits(); + m_featuresFetcher.GetDataSource().AddObserver(editor); + LOG(LDEBUG, ("Editor initialized")); + + GetStorage().RestoreDownloadQueue(); + + callback(); + }); + }).detach(); +} + void Framework::RegisterAllMaps() { - ASSERT(!m_storage.IsDownloadInProgress(), - ("Registering maps while map downloading leads to removing downloading maps from " - "ActiveMapsListener::m_items.")); - m_storage.RegisterAllLocalMaps(m_enabledDiffs); vector> maps; diff --git a/map/framework.hpp b/map/framework.hpp index 62b963dc55..afcf2035e5 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -210,7 +210,7 @@ protected: void InitTransliteration(); public: - explicit Framework(FrameworkParams const & params = {}); + explicit Framework(FrameworkParams const & params = {}, bool loadMaps = true); virtual ~Framework() override; df::DrapeApi & GetDrapeApi() { return m_drapeApi; } @@ -219,6 +219,9 @@ public: /// \note It works for group and leaf node. bool HasUnsavedEdits(storage::CountryId const & countryId); + void LoadMapsSync(); + void LoadMapsAsync(std::function && callback); + /// Registers all local map files in internal indexes. void RegisterAllMaps(); diff --git a/storage/storage.cpp b/storage/storage.cpp index 382790fd75..4f8605bd01 100644 --- a/storage/storage.cpp +++ b/storage/storage.cpp @@ -283,7 +283,8 @@ Storage::WorldStatus Storage::GetForceDownloadWorlds(std::vector & maps) const { - CHECK_THREAD_CHECKER(m_threadChecker, ()); + //CHECK_THREAD_CHECKER(m_threadChecker, ()); for (auto const & p : m_localFiles) maps.push_back(GetLatestLocalFile(p.first)); @@ -424,7 +420,7 @@ LocalFilePtr Storage::GetLatestLocalFile(CountryFile const & countryFile) const LocalFilePtr Storage::GetLatestLocalFile(CountryId const & countryId) const { - CHECK_THREAD_CHECKER(m_threadChecker, ()); + //CHECK_THREAD_CHECKER(m_threadChecker, ()); auto const it = m_localFiles.find(countryId); if (it == m_localFiles.end() || it->second.empty()) diff --git a/storage/storage.hpp b/storage/storage.hpp index d32b14a784..992b016172 100644 --- a/storage/storage.hpp +++ b/storage/storage.hpp @@ -580,6 +580,8 @@ public: std::string GetFilePath(CountryId const & countryId, MapFileType file) const; + void RestoreDownloadQueue(); + protected: void OnFinishDownloading(); @@ -587,7 +589,6 @@ private: friend struct storage_tests::UnitClass_StorageTest_DeleteCountry; void SaveDownloadQueue(); - void RestoreDownloadQueue(); // Returns true when country is in the downloader's queue. bool IsCountryInQueue(CountryId const & countryId) const;