blob: 07cddbae69cd17a683a265efdbac02f839383f00 [file] [log] [blame] [edit]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "activity_lifecycle_state.h"
#include <android/api-level.h>
#include <stdlib.h>
#include <cstdio>
#include <fstream>
#include <sstream>
#include "Log.h"
#include "jni/jni_wrap.h"
#include "system_utils.h"
#include "tuningfork_utils.h"
namespace tuningfork {
ActivityLifecycleState::ActivityLifecycleState() {
std::stringstream lifecycle_path_builder;
lifecycle_path_builder << DefaultTuningForkSaveDirectory();
file_utils::CheckAndCreateDir(lifecycle_path_builder.str());
lifecycle_path_builder << "/lifecycle.bin";
tf_lifecycle_path_str_ = lifecycle_path_builder.str();
ALOGV("Path to lifecycle file: %s", tf_lifecycle_path_str_.c_str());
std::stringstream crash_info_path_builder;
crash_info_path_builder << DefaultTuningForkSaveDirectory()
<< "/crash_info.bin";
tf_crash_info_file_ = crash_info_path_builder.str();
ALOGV("Path to crash info file: %s", tf_crash_info_file_.c_str());
}
ActivityLifecycleState::~ActivityLifecycleState() {}
bool ActivityLifecycleState::SetNewState(TuningFork_LifecycleState new_state) {
current_state_ = new_state;
if (current_state_ == TUNINGFORK_STATE_ONSTART)
app_on_foreground_ = true;
else if (current_state_ == TUNINGFORK_STATE_ONSTOP)
app_on_foreground_ = false;
TuningFork_LifecycleState saved_state = GetStoredState();
StoreStateToDisk(current_state_);
ALOGV(
"New lifecycle state recorded: %s, app on foreground: %d, saved state: "
"%s",
GetStateName(current_state_), app_on_foreground_,
GetStateName(saved_state));
return !(current_state_ == TUNINGFORK_STATE_ONCREATE &&
saved_state == TUNINGFORK_STATE_ONSTART);
}
const char* ActivityLifecycleState::GetStateName(
TuningFork_LifecycleState state) {
switch (state) {
case TUNINGFORK_STATE_UNINITIALIZED:
return "uninitialized";
case TUNINGFORK_STATE_ONCREATE:
return "onCreate";
case TUNINGFORK_STATE_ONSTART:
return "onStart";
case TUNINGFORK_STATE_ONSTOP:
return "onStop";
case TUNINGFORK_STATE_ONDESTROY:
return "onDestroy";
}
}
TuningFork_LifecycleState ActivityLifecycleState::GetStateFromString(
const std::string& name) {
if (name == "onCreate") {
return TUNINGFORK_STATE_ONCREATE;
} else if (name == "onStart") {
return TUNINGFORK_STATE_ONSTART;
} else if (name == "onStop") {
return TUNINGFORK_STATE_ONSTOP;
} else if (name == "onDestroy") {
return TUNINGFORK_STATE_ONDESTROY;
} else {
return TUNINGFORK_STATE_UNINITIALIZED;
}
}
TuningFork_LifecycleState ActivityLifecycleState::GetStoredState() {
if (!file_utils::FileExists(tf_lifecycle_path_str_)) {
return TUNINGFORK_STATE_UNINITIALIZED;
}
std::ifstream file(tf_lifecycle_path_str_);
std::string state_name;
file >> state_name;
return GetStateFromString(state_name);
}
void ActivityLifecycleState::StoreStateToDisk(TuningFork_LifecycleState state) {
std::ofstream file(tf_lifecycle_path_str_);
if (file.is_open()) {
file << GetStateName(state);
} else {
ALOGE_ONCE("Lifecycle state couldn't be stored.");
}
}
TuningFork_LifecycleState ActivityLifecycleState::GetCurrentState() {
return current_state_;
}
bool ActivityLifecycleState::IsAppOnForeground() { return app_on_foreground_; }
CrashReason ActivityLifecycleState::GetLatestCrashReason() {
if (!file_utils::FileExists(tf_crash_info_file_)) {
return GetReasonFromActivityManager();
} else {
std::ifstream file(tf_crash_info_file_);
int signal;
file >> signal;
file.close();
if (remove(tf_crash_info_file_.c_str())) {
ALOGE_ONCE("Failed to delete the crash info file.");
}
return ConvertSignalToCrashReason(signal);
}
}
CrashReason ActivityLifecycleState::ConvertSignalToCrashReason(int signal) {
switch (signal) {
case SIGFPE:
return FLOATING_POINT_ERROR;
case SIGSEGV:
return SEGMENTATION_FAULT;
case SIGBUS:
return BUS_ERROR;
default:
return CRASH_REASON_UNSPECIFIED;
}
}
CrashReason ActivityLifecycleState::GetReasonFromActivityManager() {
if (gamesdk::GetSystemPropAsInt("ro.build.version.sdk") >= 30) {
using namespace gamesdk::jni;
auto app_context = AppContext();
auto pm = app_context.getPackageManager();
CHECK_FOR_JNI_EXCEPTION_AND_RETURN(CRASH_REASON_UNSPECIFIED);
std::string package_name = app_context.getPackageName().C();
CHECK_FOR_JNI_EXCEPTION_AND_RETURN(CRASH_REASON_UNSPECIFIED);
java::Object obj = app_context.getSystemService(
android::content::Context::ACTIVITY_SERVICE);
CHECK_FOR_JNI_EXCEPTION_AND_RETURN(CRASH_REASON_UNSPECIFIED);
if (!obj.IsNull()) {
android::app::ActivityManager activity_manager(std::move(obj));
java::util::List reasons =
activity_manager.getHistoricalProcessExitReasons(package_name,
0, 0);
CHECK_FOR_JNI_EXCEPTION_AND_RETURN(CRASH_REASON_UNSPECIFIED);
if (!reasons.isEmpty()) {
android::app::ApplicationExitInfo exit_info(
std::move(reasons.get(0)));
int reason = exit_info.getReason();
if (reason ==
android::app::ApplicationExitInfo::REASON_LOW_MEMORY) {
return LOW_MEMORY;
}
}
}
}
return CRASH_REASON_UNSPECIFIED;
}
} // namespace tuningfork