Say the app is starting before there is anything to say it with
Nothing from our own code reached logcat on the tablet: 284 lines from the app's PID during a launch, every one of them from Hwaps, BlockMonitor, InputEventReceiver or nativeloader, and not even the version banner android_main emits three statements in. I could not find the fault in our wiring, and this commit does not claim to fix it. What it does is make the next launch say which side is at fault, and close a hole that is real whatever the answer turns out to be. What reading rules out, so nobody repeats it: install does call log::set_max_level. The Config carries an explicit tag and an explicit max level, and its env_filter is None, so android_logger's enabled() and filter_matches() both pass an Info record. Tee::enabled delegates to the console and gates nothing else. set_boxed_logger cannot have failed — its Err path drops the Tee, taking the LogFile with it, and the file on the device has content. And Tee::log calls console.log() unconditionally *before* the file write, which is itself gated on console.enabled(), so every line that reached the file proves the AndroidLogger was handed the same record. Nothing else in the graph installs a logger; android-activity and Slint's backend do not. The diff that introduced this changed the level, the tag and the Config not at all — init_once and set_boxed_logger leave the same logger installed at the same level. That leaves below __android_log_write, which no amount of reading this file can reach. So: the console logger is now built first, and one line goes through it directly, before the state directory and before the log file. Two things follow. Everything between android_main's first statement and install returning — external_data_path, create_dir_all and an open on a FUSE volume the system may still be mounting — currently has no surface at all to fail on; that window is what logcat is for, and it now has a line in it. And when the log is silent, that line separates the two cases: present with the log::info! lines below it missing is the facade, absent along with them is liblog not delivering this process's records. It goes through Log::log rather than log::info!, which is not a style choice: the facade's maximum level is Off until install sets it, so a log::info! there compiles and emits nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,9 +31,50 @@ mod intents;
|
||||
/// Android application entry point, called by android-activity's glue.
|
||||
#[no_mangle]
|
||||
fn android_main(app: slint::android::AndroidApp) {
|
||||
// Before the logger, because the logger needs somewhere to write, and
|
||||
// before any `log::` call at all, because records emitted before this line
|
||||
// reach nothing.
|
||||
// **The first statement in the process, and it has to be.** Everything
|
||||
// between here and `install` returning runs with no logger installed at
|
||||
// all: asking the activity for its external directory, `create_dir_all`
|
||||
// and an `open` on a FUSE-backed volume the system may still be mounting.
|
||||
// A failure or a stall in any of it is invisible on every surface there
|
||||
// is — no file yet, and nothing in logcat either — which is precisely the
|
||||
// kind of launch logcat exists to debug.
|
||||
//
|
||||
// `AndroidLogger` rather than `init_once`, so logcat can be *teed* rather
|
||||
// than replaced: `init_once` installs itself as the global logger and
|
||||
// there is only one of those. Everything that reached logcat before the
|
||||
// file existed still reaches it, at the same level and under the same tag;
|
||||
// the file is strictly additional.
|
||||
let console = android_logger::AndroidLogger::new(
|
||||
android_logger::Config::default()
|
||||
.with_max_level(log::LevelFilter::Info)
|
||||
.with_tag("DarkRoom"),
|
||||
);
|
||||
|
||||
// Handed to the logger directly, and **not** written as `log::info!`,
|
||||
// which here would compile and emit nothing: the facade's maximum level is
|
||||
// `Off` until `diagnostics::install` sets it, and the macro tests that
|
||||
// before it reaches any logger at all. This call skips the facade and
|
||||
// reaches `__android_log_write` with nothing in between.
|
||||
//
|
||||
// That independence is the second reason for it. When the log is silent,
|
||||
// this line is what says which half is at fault: present here and absent
|
||||
// below means the `log` wiring, absent in both means liblog is not
|
||||
// delivering this process's records — a question about the device, which
|
||||
// no amount of reading this file can answer.
|
||||
log::Log::log(
|
||||
&console,
|
||||
&log::Record::builder()
|
||||
.level(log::Level::Info)
|
||||
.target(module_path!())
|
||||
.module_path(Some(module_path!()))
|
||||
.args(format_args!(
|
||||
"DarkRoom v{} starting; logcat only until the log file opens",
|
||||
env!("CARGO_PKG_VERSION")
|
||||
))
|
||||
.build(),
|
||||
);
|
||||
|
||||
// Before the file logger, because it needs somewhere to write.
|
||||
//
|
||||
// **The external directory, not the internal one, and the difference is
|
||||
// the entire point of the file.** Both are app-private and both survive
|
||||
@@ -53,16 +94,6 @@ fn android_main(app: slint::android::AndroidApp) {
|
||||
dr_plat::set_state_dir(dir);
|
||||
}
|
||||
|
||||
// `AndroidLogger` rather than `init_once`, so logcat can be *teed* rather
|
||||
// than replaced: `init_once` installs itself as the global logger and
|
||||
// there is only one of those. Everything that reached logcat before this
|
||||
// change still reaches it, at the same level and under the same tag; the
|
||||
// file is strictly additional.
|
||||
let console = android_logger::AndroidLogger::new(
|
||||
android_logger::Config::default()
|
||||
.with_max_level(log::LevelFilter::Info)
|
||||
.with_tag("DarkRoom"),
|
||||
);
|
||||
let logging = dr_plat::diagnostics::install(Box::new(console), log::LevelFilter::Info);
|
||||
|
||||
// Panics go to stderr, and Android discards stderr. Without this hook a
|
||||
|
||||
Reference in New Issue
Block a user