diff --git a/apps/darkroom-android/src/lib.rs b/apps/darkroom-android/src/lib.rs index 7a18205..7ce71bc 100644 --- a/apps/darkroom-android/src/lib.rs +++ b/apps/darkroom-android/src/lib.rs @@ -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