Merge changes Ibf543273,Id56946b6
* changes: bootstat: allow kernel_panic,sysrq to propagate subreason bootstat: test error out only on first bad bootloader reason
This commit is contained in:
commit
7c681665f0
2 changed files with 72 additions and 38 deletions
|
@ -239,6 +239,8 @@ EXPECT_EQ() {
|
|||
return 0
|
||||
}
|
||||
|
||||
BAD_BOOTLOADER_REASON=
|
||||
|
||||
[ "USAGE: EXPECT_PROPERTY <prop> <value> [--allow_failure]
|
||||
|
||||
Returns true (0) if current return (regex) value is true and the result matches
|
||||
|
@ -249,9 +251,20 @@ EXPECT_PROPERTY() {
|
|||
value="${2}"
|
||||
shift 2
|
||||
val=`adb shell getprop ${property} 2>&1`
|
||||
EXPECT_EQ "${value}" "${val}" for Android property ${property} ||
|
||||
[ -n "${1}" ] ||
|
||||
save_ret=${?}
|
||||
EXPECT_EQ "${value}" "${val}" for Android property ${property}
|
||||
local_ret=${?}
|
||||
if [ 0 != ${local_ret} -a "ro.boot.bootreason" = "${property}" ]; then
|
||||
if [ -z "${BAD_BOOTLOADER_REASON}" ]; then
|
||||
BAD_BOOTLOADER_REASON=${val}
|
||||
elif [ X"${BAD_BOOTLOADER_REASON}" = X"${val}" ]; then
|
||||
local_ret=0
|
||||
fi
|
||||
fi
|
||||
if [ 0 != ${local_ret} ]; then
|
||||
if [ -z "${1}" ] ; then
|
||||
save_ret=${local_ret}
|
||||
fi
|
||||
fi
|
||||
return ${save_ret}
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,10 @@ const std::map<std::string, int32_t> kBootReasonMap = {
|
|||
{"software_master", 147},
|
||||
{"cold,charger", 148},
|
||||
{"cold,rtc", 149},
|
||||
{"cold,rtc,2sec", 150},
|
||||
{"reboot,tool", 151},
|
||||
{"reboot,wdt", 152},
|
||||
{"reboot,unknown", 153},
|
||||
};
|
||||
|
||||
// Converts a string value representing the reason the system booted to an
|
||||
|
@ -467,6 +471,8 @@ class pstoreConsole {
|
|||
}
|
||||
return std::string::npos;
|
||||
}
|
||||
|
||||
operator const std::string&() const { return console; }
|
||||
};
|
||||
|
||||
// If bit error match to needle, correct it.
|
||||
|
@ -503,12 +509,60 @@ bool correctForBitErrorOrUnderline(std::string& reason, const std::string& needl
|
|||
return corrected;
|
||||
}
|
||||
|
||||
// Converts a string value representing the reason the system booted to a
|
||||
// string complying with Android system standard reason.
|
||||
void transformReason(std::string& reason) {
|
||||
std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
|
||||
std::transform(reason.begin(), reason.end(), reason.begin(),
|
||||
[](char c) { return ::isblank(c) ? '_' : c; });
|
||||
std::transform(reason.begin(), reason.end(), reason.begin(),
|
||||
[](char c) { return ::isprint(c) ? c : '?'; });
|
||||
}
|
||||
|
||||
// Pull out and correct quoted (') subreason, pos just beyond first quote.
|
||||
// Check subreasons for reboot,<subreason> and kernel_panic,sysrq,<subreason>
|
||||
std::string getSubreason(const std::string& content, size_t pos) {
|
||||
static constexpr size_t max_reason_length = 256;
|
||||
|
||||
std::string subReason(content.substr(pos, max_reason_length));
|
||||
// Correct against any known strings that Bit Error Match
|
||||
for (const auto& s : knownReasons) {
|
||||
correctForBitErrorOrUnderline(subReason, s);
|
||||
}
|
||||
for (const auto& m : kBootReasonMap) {
|
||||
if (m.first.length() <= strlen("cold")) continue; // too short?
|
||||
if (correctForBitErrorOrUnderline(subReason, m.first + "'")) continue;
|
||||
if (m.first.length() <= strlen("reboot,cold")) continue; // short?
|
||||
if (android::base::StartsWith(m.first, "reboot,")) {
|
||||
correctForBitErrorOrUnderline(subReason, m.first.substr(strlen("reboot,")) + "'");
|
||||
} else if (android::base::StartsWith(m.first, "kernel_panic,sysrq,")) {
|
||||
correctForBitErrorOrUnderline(subReason, m.first.substr(strlen("kernel_panic,sysrq,")) + "'");
|
||||
}
|
||||
}
|
||||
for (pos = 0; pos < subReason.length(); ++pos) {
|
||||
char c = subReason[pos];
|
||||
// #, &, %, / are common single bit error for ' that we can block
|
||||
if (!::isprint(c) || (c == '\'') || (c == '#') || (c == '&') || (c == '%') || (c == '/')) {
|
||||
subReason.erase(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
transformReason(subReason);
|
||||
return subReason;
|
||||
}
|
||||
|
||||
bool addKernelPanicSubReason(const pstoreConsole& console, std::string& ret) {
|
||||
// Check for kernel panic types to refine information
|
||||
if ((console.rfind("SysRq : Trigger a crash") != std::string::npos) ||
|
||||
(console.rfind("PC is at sysrq_handle_crash+") != std::string::npos)) {
|
||||
// Can not happen, except on userdebug, during testing/debugging.
|
||||
ret = "kernel_panic,sysrq";
|
||||
// Invented for Android to allow daemons that specifically trigger sysrq
|
||||
// to communicate more accurate boot subreasons via last console messages.
|
||||
static constexpr char sysrqSubreason[] = "SysRq : Trigger a crash : '";
|
||||
auto pos = console.rfind(sysrqSubreason);
|
||||
if (pos != std::string::npos) {
|
||||
ret += "," + getSubreason(console, pos + strlen(sysrqSubreason));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (console.rfind("Unable to handle kernel NULL pointer dereference at virtual address") !=
|
||||
|
@ -527,24 +581,12 @@ bool addKernelPanicSubReason(const std::string& content, std::string& ret) {
|
|||
return addKernelPanicSubReason(pstoreConsole(content), ret);
|
||||
}
|
||||
|
||||
// Converts a string value representing the reason the system booted to a
|
||||
// string complying with Android system standard reason.
|
||||
void transformReason(std::string& reason) {
|
||||
std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
|
||||
std::transform(reason.begin(), reason.end(), reason.begin(),
|
||||
[](char c) { return ::isblank(c) ? '_' : c; });
|
||||
std::transform(reason.begin(), reason.end(), reason.begin(),
|
||||
[](char c) { return ::isprint(c) ? c : '?'; });
|
||||
}
|
||||
|
||||
const char system_reboot_reason_property[] = "sys.boot.reason";
|
||||
const char last_reboot_reason_property[] = LAST_REBOOT_REASON_PROPERTY;
|
||||
const char bootloader_reboot_reason_property[] = "ro.boot.bootreason";
|
||||
|
||||
// Scrub, Sanitize, Standardize and Enhance the boot reason string supplied.
|
||||
std::string BootReasonStrToReason(const std::string& boot_reason) {
|
||||
static const size_t max_reason_length = 256;
|
||||
|
||||
std::string ret(GetProperty(system_reboot_reason_property));
|
||||
std::string reason(boot_reason);
|
||||
// If sys.boot.reason == ro.boot.bootreason, let's re-evaluate
|
||||
|
@ -647,28 +689,7 @@ std::string BootReasonStrToReason(const std::string& boot_reason) {
|
|||
static const char cmd[] = "reboot: Restarting system with command '";
|
||||
size_t pos = console.rfind(cmd);
|
||||
if (pos != std::string::npos) {
|
||||
pos += strlen(cmd);
|
||||
std::string subReason(content.substr(pos, max_reason_length));
|
||||
// Correct against any known strings that Bit Error Match
|
||||
for (const auto& s : knownReasons) {
|
||||
correctForBitErrorOrUnderline(subReason, s);
|
||||
}
|
||||
for (const auto& m : kBootReasonMap) {
|
||||
if (m.first.length() <= strlen("cold")) continue; // too short?
|
||||
if (correctForBitErrorOrUnderline(subReason, m.first + "'")) continue;
|
||||
if (m.first.length() <= strlen("reboot,cold")) continue; // short?
|
||||
if (!android::base::StartsWith(m.first, "reboot,")) continue;
|
||||
correctForBitErrorOrUnderline(subReason, m.first.substr(strlen("reboot,")) + "'");
|
||||
}
|
||||
for (pos = 0; pos < subReason.length(); ++pos) {
|
||||
char c = subReason[pos];
|
||||
// #, &, %, / are common single bit error for ' that we can block
|
||||
if (!::isprint(c) || (c == '\'') || (c == '#') || (c == '&') || (c == '%') || (c == '/')) {
|
||||
subReason.erase(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
transformReason(subReason);
|
||||
std::string subReason(getSubreason(content, pos + strlen(cmd)));
|
||||
if (subReason != "") { // Will not land "reboot" as that is too blunt.
|
||||
if (isKernelRebootReason(subReason)) {
|
||||
ret = "reboot," + subReason; // User space can't talk kernel reasons.
|
||||
|
|
Loading…
Reference in a new issue