From ddbb3c7f89d0c1625ef6f80b588c5c2dcf929ca3 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Mon, 19 Nov 2018 04:22:19 -0800 Subject: [PATCH] Make android sdk crashless Summary: This diff wraps all the important places where the java code is called in a try-catch block in order to avoid flipper bringing down an app. Reviewed By: jknoxville Differential Revision: D12839504 fbshipit-source-id: 4711bccbe6d50094d76ed7ecd1eb652cefc2a090 --- android/src/main/cpp/sonar.cpp | 192 +++++++++++++++++++++++++-------- 1 file changed, 147 insertions(+), 45 deletions(-) diff --git a/android/src/main/cpp/sonar.cpp b/android/src/main/cpp/sonar.cpp index aba01c0e8..977268ac0 100644 --- a/android/src/main/cpp/sonar.cpp +++ b/android/src/main/cpp/sonar.cpp @@ -1,11 +1,10 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) Facebook, Inc. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. * */ - #include #ifdef FLIPPER_OSS @@ -30,6 +29,14 @@ using namespace facebook::flipper; namespace { +void handleException(const std::exception& e) { + // TODO: T35898390, report and log the exception in scribe + // TODO: T35898500, send flipper notification + std::string message = "Exception caught in C++ and suppressed: "; + message += e.what(); + __android_log_write(ANDROID_LOG_ERROR, "FLIPPER", message.c_str()); +} + class JEventBase : public jni::HybridClass { public: constexpr static auto kJavaDescriptor = "Lcom/facebook/flipper/android/EventBase;"; @@ -186,22 +193,45 @@ class JFlipperPlugin : public jni::JavaClass { std::string identifier() const { static const auto method = javaClassStatic()->getMethod("getId"); - return method(self())->toStdString(); + try { + return method(self())->toStdString(); + + } catch (const std::exception& e) { + handleException(e); + return ""; + } } void didConnect(std::shared_ptr conn) { - static const auto method = javaClassStatic()->getMethod)>("onConnect"); - method(self(), JFlipperConnectionImpl::newObjectCxxArgs(conn)); + auto method = + javaClassStatic() + ->getMethod)>( + "onConnect"); + try { + method(self(), JFlipperConnectionImpl::newObjectCxxArgs(conn)); + } catch (const std::exception& e) { + handleException(e); + } } void didDisconnect() { static const auto method = javaClassStatic()->getMethod("onDisconnect"); - method(self()); + try { + method(self()); + } catch (const std::exception& e) { + handleException(e); + } } bool runInBackground() { - static const auto method = javaClassStatic()->getMethod("runInBackground"); + static const auto method = + javaClassStatic()->getMethod("runInBackground"); + try { return method(self()) == JNI_TRUE; + } catch (const std::exception& e) { + handleException(e); + return false; + } } }; @@ -210,20 +240,41 @@ class JFlipperStateUpdateListener : public jni::JavaClassgetMethod("onUpdate"); - method(self()); + try { + static const auto method = + javaClassStatic()->getMethod("onUpdate"); + method(self()); + } catch (const std::exception& e) { + handleException(e); + } } void onStepStarted(std::string step) { - static const auto method = javaClassStatic()->getMethod("onStepStarted"); - method(self(), step); + try { + static const auto method = + javaClassStatic()->getMethod("onStepStarted"); + method(self(), step); + } catch (const std::exception& e) { + handleException(e); + } } void onStepSuccess(std::string step) { - static const auto method = javaClassStatic()->getMethod("onStepSuccess"); - method(self(), step); + try { + static const auto method = + javaClassStatic()->getMethod("onStepSuccess"); + method(self(), step); + } catch (const std::exception& e) { + handleException(e); + } } void onStepFailed(std::string step, std::string errorMessage) { - static const auto method = javaClassStatic()->getMethod("onStepFailed"); - method(self(), step, errorMessage); + try { + static const auto method = + javaClassStatic()->getMethod( + "onStepFailed"); + method(self(), step, errorMessage); + } catch (const std::exception& e) { + handleException(e); + } } }; @@ -295,65 +346,116 @@ class JFlipperClient : public jni::HybridClass { } static jni::alias_ref getInstance(jni::alias_ref) { - static auto client = make_global(newObjectCxxArgs()); - return client; + try { + static auto client = make_global(newObjectCxxArgs()); + return client; + } catch (const std::exception& e) { + return nullptr; + } } void start() { - FlipperClient::instance()->start(); + try { + FlipperClient::instance()->start(); + } catch (const std::exception& e) { + handleException(e); + } } void stop() { - FlipperClient::instance()->stop(); + try { + FlipperClient::instance()->stop(); + } catch (const std::exception& e) { + handleException(e); + } } void addPlugin(jni::alias_ref plugin) { - auto wrapper = std::make_shared(make_global(plugin)); - FlipperClient::instance()->addPlugin(wrapper); + try { + auto wrapper = + std::make_shared(make_global(plugin)); + FlipperClient::instance()->addPlugin(wrapper); + } catch (const std::exception& e) { + handleException(e); + } } void removePlugin(jni::alias_ref plugin) { - auto client = FlipperClient::instance(); - client->removePlugin(client->getPlugin(plugin->identifier())); + try { + auto client = FlipperClient::instance(); + client->removePlugin(client->getPlugin(plugin->identifier())); + } catch (const std::exception& e) { + handleException(e); + } } void subscribeForUpdates(jni::alias_ref stateListener) { - auto client = FlipperClient::instance(); - mStateListener = std::make_shared(stateListener); - client->setStateListener(mStateListener); + try { + auto client = FlipperClient::instance(); + mStateListener = + std::make_shared(stateListener); + client->setStateListener(mStateListener); + } catch (const std::exception& e) { + handleException(e); + } } void unsubscribe() { - auto client = FlipperClient::instance(); - mStateListener = nullptr; - client->setStateListener(nullptr); + try { + auto client = FlipperClient::instance(); + mStateListener = nullptr; + client->setStateListener(nullptr); + } catch (const std::exception& e) { + handleException(e); + } } std::string getState() { - return FlipperClient::instance()->getState(); + try { + return FlipperClient::instance()->getState(); + } catch (const std::exception& e) { + handleException(e); + return ""; + } } jni::global_ref getStateSummary() { - auto summary = jni::make_global(JStateSummary::create()); - auto elements = FlipperClient::instance()->getStateElements(); - for (auto&& element : elements) { - std::string status; - switch (element.state_) { - case State::in_progress: status = "IN_PROGRESS"; break; - case State::failed: status = "FAILED"; break; - case State::success: status = "SUCCESS"; break; + try { + auto summary = jni::make_global(JStateSummary::create()); + auto elements = FlipperClient::instance()->getStateElements(); + for (auto&& element : elements) { + std::string status; + switch (element.state_) { + case State::in_progress: + status = "IN_PROGRESS"; + break; + case State::failed: + status = "FAILED"; + break; + case State::success: + status = "SUCCESS"; + break; + } + summary->addEntry(element.name_, status); } - summary->addEntry(element.name_, status); + return summary; + } catch (const std::exception& e) { + handleException(e); + return nullptr; } - return summary; } jni::alias_ref getPlugin(const std::string& identifier) { - auto plugin = FlipperClient::instance()->getPlugin(identifier); - if (plugin) { - auto wrapper = std::static_pointer_cast(plugin); - return wrapper->jplugin; - } else { + try { + auto plugin = FlipperClient::instance()->getPlugin(identifier); + if (plugin) { + auto wrapper = std::static_pointer_cast(plugin); + return wrapper->jplugin; + } else { + return nullptr; + } + } catch (const std::exception& e) { + handleException(e); return nullptr; } }