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
This commit is contained in:
Pritesh Nandgaonkar
2018-11-19 04:22:19 -08:00
committed by Facebook Github Bot
parent bcf6479a5e
commit ddbb3c7f89

View File

@@ -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 <memory>
#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<JEventBase> {
public:
constexpr static auto kJavaDescriptor = "Lcom/facebook/flipper/android/EventBase;";
@@ -186,22 +193,45 @@ class JFlipperPlugin : public jni::JavaClass<JFlipperPlugin> {
std::string identifier() const {
static const auto method = javaClassStatic()->getMethod<std::string()>("getId");
return method(self())->toStdString();
try {
return method(self())->toStdString();
} catch (const std::exception& e) {
handleException(e);
return "";
}
}
void didConnect(std::shared_ptr<FlipperConnection> conn) {
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JFlipperConnection::javaobject>)>("onConnect");
method(self(), JFlipperConnectionImpl::newObjectCxxArgs(conn));
auto method =
javaClassStatic()
->getMethod<void(jni::alias_ref<JFlipperConnection::javaobject>)>(
"onConnect");
try {
method(self(), JFlipperConnectionImpl::newObjectCxxArgs(conn));
} catch (const std::exception& e) {
handleException(e);
}
}
void didDisconnect() {
static const auto method = javaClassStatic()->getMethod<void()>("onDisconnect");
method(self());
try {
method(self());
} catch (const std::exception& e) {
handleException(e);
}
}
bool runInBackground() {
static const auto method = javaClassStatic()->getMethod<jboolean()>("runInBackground");
static const auto method =
javaClassStatic()->getMethod<jboolean()>("runInBackground");
try {
return method(self()) == JNI_TRUE;
} catch (const std::exception& e) {
handleException(e);
return false;
}
}
};
@@ -210,20 +240,41 @@ class JFlipperStateUpdateListener : public jni::JavaClass<JFlipperStateUpdateLis
constexpr static auto kJavaDescriptor = "Lcom/facebook/flipper/core/FlipperStateUpdateListener;";
void onUpdate() {
static const auto method = javaClassStatic()->getMethod<void()>("onUpdate");
method(self());
try {
static const auto method =
javaClassStatic()->getMethod<void()>("onUpdate");
method(self());
} catch (const std::exception& e) {
handleException(e);
}
}
void onStepStarted(std::string step) {
static const auto method = javaClassStatic()->getMethod<void(std::string)>("onStepStarted");
method(self(), step);
try {
static const auto method =
javaClassStatic()->getMethod<void(std::string)>("onStepStarted");
method(self(), step);
} catch (const std::exception& e) {
handleException(e);
}
}
void onStepSuccess(std::string step) {
static const auto method = javaClassStatic()->getMethod<void(std::string)>("onStepSuccess");
method(self(), step);
try {
static const auto method =
javaClassStatic()->getMethod<void(std::string)>("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<void(std::string, std::string)>("onStepFailed");
method(self(), step, errorMessage);
try {
static const auto method =
javaClassStatic()->getMethod<void(std::string, std::string)>(
"onStepFailed");
method(self(), step, errorMessage);
} catch (const std::exception& e) {
handleException(e);
}
}
};
@@ -295,65 +346,116 @@ class JFlipperClient : public jni::HybridClass<JFlipperClient> {
}
static jni::alias_ref<JFlipperClient::javaobject> getInstance(jni::alias_ref<jclass>) {
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<JFlipperPlugin> plugin) {
auto wrapper = std::make_shared<JFlipperPluginWrapper>(make_global(plugin));
FlipperClient::instance()->addPlugin(wrapper);
try {
auto wrapper =
std::make_shared<JFlipperPluginWrapper>(make_global(plugin));
FlipperClient::instance()->addPlugin(wrapper);
} catch (const std::exception& e) {
handleException(e);
}
}
void removePlugin(jni::alias_ref<JFlipperPlugin> 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<JFlipperStateUpdateListener> stateListener) {
auto client = FlipperClient::instance();
mStateListener = std::make_shared<AndroidFlipperStateUpdateListener>(stateListener);
client->setStateListener(mStateListener);
try {
auto client = FlipperClient::instance();
mStateListener =
std::make_shared<AndroidFlipperStateUpdateListener>(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<JStateSummary::javaobject> 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<JFlipperPlugin> getPlugin(const std::string& identifier) {
auto plugin = FlipperClient::instance()->getPlugin(identifier);
if (plugin) {
auto wrapper = std::static_pointer_cast<JFlipperPluginWrapper>(plugin);
return wrapper->jplugin;
} else {
try {
auto plugin = FlipperClient::instance()->getPlugin(identifier);
if (plugin) {
auto wrapper = std::static_pointer_cast<JFlipperPluginWrapper>(plugin);
return wrapper->jplugin;
} else {
return nullptr;
}
} catch (const std::exception& e) {
handleException(e);
return nullptr;
}
}