blob: 03d878f7b02a6eae6c1c2580440c4c7c8ca9ee1b [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "minios/screens/screen_log.h"
#include <utility>
#include <base/logging.h>
#include "minios/draw_utils.h"
#include "minios/utils.h"
namespace minios {
namespace {
// Default log constants.
const int kLogCharPerLine = 111;
const int kLogLinesPerPage = 20;
// Scaled down log constants when frecon canvas size is not big enough to
// support `log_area_border_large`.
const int kSmallLogCharPerLine = 79;
const int kSmallLogLinesPerPage = 13;
// y-coord of the upper edge of the log area, 16px below title.
const int kLogAreaY = 196;
const char kLogPath[] = "/var/log/messages";
} // namespace
ScreenLog::ScreenLog(std::shared_ptr<DrawInterface> draw_utils,
ScreenControllerInterface* screen_controller)
: ScreenBase(
/*button_count=*/4, /*index_=*/1, draw_utils, screen_controller),
log_path_(base::FilePath(kLogPath)),
log_offset_idx_(0),
log_offsets_({0}) {}
void ScreenLog::Show() {
draw_utils_->MessageBaseScreen();
int frecon_size = draw_utils_->GetFreconCanvasSize();
const int kXOffset = (-frecon_size / 2) + (720 / 2);
draw_utils_->ShowMessage("title_message_log", kXOffset,
-frecon_size / 2 + 162);
ShowButtons();
UpdateLogArea();
}
void ScreenLog::ShowButtons() {
draw_utils_->ShowLanguageMenu(index_ == 0);
int frecon_size = draw_utils_->GetFreconCanvasSize();
int lines_per_page = (frecon_size < kSmallCanvasSize) ? kSmallLogLinesPerPage
: kLogLinesPerPage;
auto y_offset = -frecon_size / 2 + kLogAreaY +
(kMonospaceGlyphHeight * lines_per_page) + 16 +
kButtonHeight / 2;
auto y_offset_step = kButtonHeight + kButtonMargin;
int default_btn_width = draw_utils_->GetDefaultButtonWidth();
draw_utils_->ShowButton("btn_page_up", y_offset, index_ == 1,
default_btn_width, false);
draw_utils_->ShowButton("btn_page_down", y_offset + y_offset_step,
index_ == 2, default_btn_width, false);
draw_utils_->ShowButton("btn_back", y_offset + 2 * y_offset_step, index_ == 3,
default_btn_width, false);
}
void ScreenLog::UpdateLogArea() {
int frecon_size = draw_utils_->GetFreconCanvasSize();
bool is_small_canvas = (frecon_size < kSmallCanvasSize);
int lines_per_page =
is_small_canvas ? kSmallLogLinesPerPage : kLogLinesPerPage;
int char_per_line = is_small_canvas ? kSmallLogCharPerLine : kLogCharPerLine;
auto screen_path = draw_utils_->GetScreenPath();
auto image_path = is_small_canvas
? screen_path.Append("log_area_border.png")
: screen_path.Append("log_area_border_large.png");
draw_utils_->ShowImage(
image_path,
-frecon_size / 2 + ((kMonospaceGlyphWidth * char_per_line) + 10) / 2,
-frecon_size / 2 + kLogAreaY +
(kMonospaceGlyphHeight * lines_per_page) / 2);
std::string content;
// If the offsets into the file are already calculated, use the start and end
// byte offsets into the file to quickly index.
if (log_offset_idx_ + 1 < log_offsets_.size()) {
auto start_offset = log_offsets_[log_offset_idx_],
end_offset = log_offsets_[log_offset_idx_ + 1];
auto [success, content_local] = ReadFileContentWithinRange(
log_path_, start_offset, end_offset, char_per_line);
content = std::move(content_local);
if (!success) {
PLOG(ERROR) << "Failed to read content from " << log_path_.value()
<< " between offsets " << start_offset << " and "
<< end_offset;
}
} else {
// Otherwise, the new end offset must be calculated based off the number of
// lines and columns to read.
auto start_offset = log_offsets_[log_offset_idx_];
auto [success, content_local, bytes_read] =
ReadFileContent(log_path_, start_offset, lines_per_page, char_per_line);
content = std::move(content_local);
if (!success) {
PLOG(ERROR) << "Failed to read content from " << log_path_.value()
<< " starting ad offset " << start_offset;
} else if (bytes_read != 0) {
log_offsets_.push_back(start_offset + bytes_read);
}
}
draw_utils_->ShowText(
content, (-frecon_size / 2) + kMonospaceGlyphWidth,
-frecon_size / 2 + kLogAreaY + kMonospaceGlyphHeight / 2, "white");
}
void ScreenLog::OnKeyPress(int key_changed) {
bool enter = false;
UpdateButtonsIndex(key_changed, &enter);
if (enter) {
switch (index_) {
case 0:
screen_controller_->SwitchLocale(this);
break;
case 1:
if (log_offset_idx_ > 0) {
--log_offset_idx_;
UpdateLogArea();
}
break;
case 2:
if (log_offset_idx_ < log_offsets_.size() - 1) {
++log_offset_idx_;
UpdateLogArea();
}
break;
case 3:
// Back to debug options screen.
screen_controller_->OnBackward(this);
break;
default:
LOG(FATAL) << "Index " << index_ << " is not valid.";
}
} else {
ShowButtons();
}
}
void ScreenLog::Reset() {}
ScreenType ScreenLog::GetType() {
return ScreenType::kLogScreen;
}
std::string ScreenLog::GetName() {
return "ScreenLog";
}
} // namespace minios