ReviewOS

also looking at this

craft-native/craft

feat(android): setKeepAwake through the trampoline — ratchet 70 → 69

#174
Merged glennmichael123 wants to merge feat/android-keep-awake into main
7 files +140 -13
packages/zig/src/android_main_thread.zigmodified+45-0
Changes to packages/zig/src/android_main_thread.zig
@@ -48,6 +48,8 @@ const jobject = jni.jobject;
4848pub const Task = union(enum) {
4949 /// `activity.setRequestedOrientation(mode)`.
5050 set_requested_orientation: i32,
51 /// `activity.window.addFlags(flags)` or `clearFlags(flags)`.
52 set_window_flags: struct { flags: i32, add: bool },
5153};
5254
5355const slot_count = 32;
@@ -160,9 +162,36 @@ pub fn run(j: Jni, activity: jobject, token: u64) void {
160162 const task = claim(token) orelse return;
161163 switch (task) {
162164 .set_requested_orientation => |mode| setRequestedOrientation(j, activity, mode) catch {},
165 .set_window_flags => |request| setWindowFlags(j, activity, request.flags, request.add) catch {},
163166 }
164167}
165168
169/// Which `Window` method a request names.
170///
171/// Split out because it is the one place the two directions can be swapped,
172/// and swapping them turns the screen timeout back on while reporting success.
173pub fn windowFlagMethod(add: bool) [:0]const u8 {
174 return if (add) "addFlags" else "clearFlags";
175}
176
177/// `activity.window.addFlags(flags)` / `clearFlags(flags)`.
178fn setWindowFlags(j: Jni, activity: jobject, flags: i32, add: bool) !void {
179 try j.pushLocalFrame(8);
180 defer _ = j.popLocalFrame(null);
181
182 const window = try j.callObjectMethod(
183 activity,
184 try j.methodId(try j.objectClass(activity), "getWindow", "()Landroid/view/Window;"),
185 );
186
187 const window_cls = try j.objectClass(window);
188 try j.callVoidMethodA(
189 window,
190 try j.methodId(window_cls, windowFlagMethod(add), "(I)V"),
191 &.{.{ .i = flags }},
192 );
193}
194
166195fn setRequestedOrientation(j: Jni, activity: jobject, mode: i32) !void {
167196 try j.pushLocalFrame(4);
168197 defer _ = j.popLocalFrame(null);
@@ -257,6 +286,22 @@ test "releasing a token a caller could not schedule frees its slot" {
257286 }
258287}
259288
289test "a window-flag task carries both halves of the request" {
290 clearTable();
291
292 const token = try reserve(.{ .set_window_flags = .{ .flags = 128, .add = true } });
293 const claimed = claim(token).?;
294 try testing.expectEqual(@as(i32, 128), claimed.set_window_flags.flags);
295 try testing.expect(claimed.set_window_flags.add);
296}
297
298test "adding and clearing name different Window methods" {
299 // The swap that would leave the screen timing out while every layer
300 // reported success.
301 try testing.expectEqualStrings("addFlags", windowFlagMethod(true));
302 try testing.expectEqualStrings("clearFlags", windowFlagMethod(false));
303}
304
260305test "the holder class is the fixed one, not the templated bridge" {
261306 // A `{{` here would mean the library had been made app-specific, which is
262307 // the thing RegisterNatives exists to avoid.