diff --git a/apps/android/check.py b/apps/android/check.py index 65a6fecb80d5dcf8b18d96be8d47b9e91e9d37f2..e22e264651715af29fb6d0670456de4eb544437d 100644 --- a/apps/android/check.py +++ b/apps/android/check.py @@ -6,12 +6,14 @@ the caller starts and stops: It types a token into the page, waits until the section reports it saved, force-stops the app, turns the network off, starts it again and screenshots the page, then reads the section file -back with onestore's inspect example and looks for the token in it. +back with onestore's inspect example and looks for the token in it. The page must have drawn +where the keyboard was, which GL on Android 8 once left black. """ import argparse import json from pathlib import Path import secrets +import struct import subprocess import time @@ -70,6 +72,11 @@ def main(): adb('shell', 'cmd', 'connectivity', 'airplane-mode', 'enable') launch() (output / 'reopened.png').write_bytes(adb('exec-out', 'screencap', '-p', binary=True)) + # A raw capture: width and height, then RGBA rows after a header whose size varies by release. + screen = adb('exec-out', 'screencap', binary=True) + columns, rows = struct.unpack_from('<2I', screen) + pixel = len(screen) - columns * rows * 4 + (rows * 3 // 4 * columns + columns // 2) * 4 + drawn = any(screen[pixel:pixel + 3]) section = output / 'section.one' section.write_bytes(adb('exec-out', 'run-as', PACKAGE, 'cat', SECTION, binary=True)) (output / 'logcat.txt').write_text(adb('logcat', '-d')) @@ -84,11 +91,14 @@ def main(): 'intact': inspected.endswith(' 0 checksum mismatches'), # Text is stored as UTF-16, or as single bytes where it fits them. 'tokenInSection': token.encode('utf-16-le') in data or token.encode() in data, + 'drawn': drawn, } (output / 'result.json').write_text(json.dumps(result, indent=2) + '\n') print(json.dumps(result, indent=2)) if not (result['intact'] and result['tokenInSection']): raise SystemExit('The edit did not survive') + if not drawn: + raise SystemExit('The reopened page left the screen black') if __name__ == '__main__': diff --git a/crates/mobile/src/lib.rs b/crates/mobile/src/lib.rs index 900c39c986467f458b3c0fadf3794d73d390a393..65174163422e4acbb2a57844052bde4de088a525 100644 --- a/crates/mobile/src/lib.rs +++ b/crates/mobile/src/lib.rs @@ -1167,8 +1167,8 @@ pub unsafe extern "C" fn sb_view_free(view: *mut View) { #[unsafe(no_mangle)] pub extern "C" fn sb_view_resize(view: &mut View, width: f32, height: f32, scale: f32) { - let gpu = gpu(); - let Some(gpu) = gpu.as_ref() else { return }; + let guard = gpu(); + let Some(gpu) = guard.as_ref() else { return }; let Some(pixels) = report(view_pixels( [width, height], scale, @@ -1182,6 +1182,22 @@ pub extern "C" fn sb_view_resize(view: &mut View, width: f32, height: f32, scale let _ = report(canvas.page.scale_factor_changed(scale)); } let _ = report(canvas.page.resized(pixels)); + #[cfg(target_os = "android")] + if gpu.adapter.get_info().backend == wgpu::Backend::Gl + && let Some(Presentation { + surface, + _window: window, + .. + }) = view.presentation.take() + { + // The emulator's EGL takes a window's new size late, so GL makes a new surface, as + // GLSurfaceView does. + drop(surface); + drop(guard); + // SAFETY: `window` holds a reference until the new presentation has acquired its own. + view.presentation = report(unsafe { Presentation::new(window.0.as_ptr(), pixels) }); + return; + } if let Some(presentation) = &mut view.presentation { presentation.config.width = pixels[0]; presentation.config.height = pixels[1];