also looking at this
feat(android): setKeepAwake through the trampoline — ratchet 70 → 69
#174
7 files
+140
-13
| @@ -48,6 +48,8 @@ const jobject = jni.jobject; | ||
| 48 | 48 | pub const Task = union(enum) { |
| 49 | 49 | /// `activity.setRequestedOrientation(mode)`. |
| 50 | 50 | set_requested_orientation: i32, |
| 51 | /// `activity.window.addFlags(flags)` or `clearFlags(flags)`. | |
| 52 | set_window_flags: struct { flags: i32, add: bool }, | |
| 51 | 53 | }; |
| 52 | 54 | |
| 53 | 55 | const slot_count = 32; |
| @@ -160,9 +162,36 @@ pub fn run(j: Jni, activity: jobject, token: u64) void { | ||
| 160 | 162 | const task = claim(token) orelse return; |
| 161 | 163 | switch (task) { |
| 162 | 164 | .set_requested_orientation => |mode| setRequestedOrientation(j, activity, mode) catch {}, |
| 165 | .set_window_flags => |request| setWindowFlags(j, activity, request.flags, request.add) catch {}, | |
| 163 | 166 | } |
| 164 | 167 | } |
| 165 | 168 | |
| 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. | |
| 173 | pub fn windowFlagMethod(add: bool) [:0]const u8 { | |
| 174 | return if (add) "addFlags" else "clearFlags"; | |
| 175 | } | |
| 176 | ||
| 177 | /// `activity.window.addFlags(flags)` / `clearFlags(flags)`. | |
| 178 | fn 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 | ||
| 166 | 195 | fn setRequestedOrientation(j: Jni, activity: jobject, mode: i32) !void { |
| 167 | 196 | try j.pushLocalFrame(4); |
| 168 | 197 | defer _ = j.popLocalFrame(null); |
| @@ -257,6 +286,22 @@ test "releasing a token a caller could not schedule frees its slot" { | ||
| 257 | 286 | } |
| 258 | 287 | } |
| 259 | 288 | |
| 289 | test "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 | ||
| 298 | test "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 | ||
| 260 | 305 | test "the holder class is the fixed one, not the templated bridge" { |
| 261 | 306 | // A `{{` here would mean the library had been made app-specific, which is |
| 262 | 307 | // the thing RegisterNatives exists to avoid. |