Skip to content

Commit 4fa6963

Browse files
committed
Fixed on_platform_message not firing.
Added platform task loop.
1 parent 2349c3a commit 4fa6963

File tree

3 files changed

+181
-38
lines changed

3 files changed

+181
-38
lines changed

src/flutter-pi.c

Lines changed: 158 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <features.h>
12
#include <dlfcn.h>
23
#include <fcntl.h>
34
#include <stdio.h>
@@ -10,6 +11,9 @@
1011
#include <EGL/eglext.h>
1112
#include <GLES/gl.h>
1213
#include <linux/input.h>
14+
#include <pthread.h>
15+
#include <signal.h>
16+
#include <errno.h>
1317

1418
#include <math.h>
1519
#include <limits.h>
@@ -20,8 +24,6 @@
2024
#include "flutter-pi.h"
2125
#include "methodchannel.h"
2226

23-
#define PATH_EXISTS(path) (access((path),R_OK)==0)
24-
2527

2628
char* usage = "Flutter Raspberry Pi\n\nUsage:\n flutter-pi <asset_bundle_path> <flutter_flags>\n";
2729

@@ -47,26 +49,34 @@ double mouse_x = 0;
4749
double mouse_y = 0;
4850
uint8_t button = 0;
4951

52+
pthread_t io_thread_id;
53+
pthread_t platform_thread_id;
54+
struct LinkedTaskListElement task_list_head_sentinel
55+
= {.next = NULL, .target_time = 0, .task = {.runner = NULL, .task = 0}};
56+
pthread_mutex_t task_list_lock;
57+
bool should_notify_platform_thread = false;
58+
sigset_t sigusr1_set;
59+
5060
/*********************
5161
* FLUTTER CALLBACKS *
5262
*********************/
53-
bool make_current(void* userdata) {
63+
bool make_current(void* userdata) {
5464
if (eglMakeCurrent(display, surface, surface, context) != EGL_TRUE) {
5565
fprintf(stderr, "Could not make the context current.\n");
5666
return false;
5767
}
5868

5969
return true;
6070
}
61-
bool clear_current(void* userdata) {
71+
bool clear_current(void* userdata) {
6272
if (eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
6373
fprintf(stderr, "Could not clear the current context.\n");
6474
return false;
6575
}
6676

6777
return true;
6878
}
69-
bool present(void* userdata) {
79+
bool present(void* userdata) {
7080
if (eglSwapBuffers(display, surface) != EGL_TRUE) {
7181
fprintf(stderr, "Could not swap buffers to present the screen.\n");
7282
return false;
@@ -82,7 +92,7 @@ bool present(void* userdata) {
8292
uint32_t fbo_callback(void* userdata) {
8393
return 0;
8494
}
85-
void* proc_resolver(void* userdata, const char* name) {
95+
void* proc_resolver(void* userdata, const char* name) {
8696
if (name == NULL) return NULL;
8797

8898
printf("calling proc_resolver with %s\n", name);
@@ -94,23 +104,118 @@ void* proc_resolver(void* userdata, const char* name) {
94104

95105
return NULL;
96106
}
97-
void on_platform_message(const FlutterPlatformMessage* message, void* userdata) {
98-
printf("Got Platform Message on Channel: %s\n", message->channel);
99-
107+
void on_platform_message(const FlutterPlatformMessage* message, void* userdata) {
100108
struct MethodCall methodcall;
101109
if (!MethodChannel_decode(message->message_size, (uint8_t*) (message->message), &methodcall)) {
102110
fprintf(stderr, "Decoding method call failed\n");
103111
return;
104112
}
105113
printf("MethodCall: method name: %s argument type: %d\n", methodcall.method, methodcall.argument.type);
106114

115+
if (strcmp(methodcall.method, "counter") == 0) {
116+
printf("method \"counter\" was called with argument %d\n", methodcall.argument.value.int_value);
117+
}
118+
107119
MethodChannel_freeMethodCall(&methodcall);
108120
}
109121

122+
/************************
123+
* PLATFORM TASK-RUNNER *
124+
************************/
125+
void handle_signal(int _) {}
126+
bool init_message_loop() {
127+
platform_thread_id = pthread_self();
128+
129+
// first, initialize the task heap mutex
130+
if (pthread_mutex_init(&task_list_lock, NULL) != 0) {
131+
fprintf(stderr, "Could not initialize task list mutex\n");
132+
return false;
133+
}
134+
135+
sigemptyset(&sigusr1_set);
136+
sigaddset(&sigusr1_set, SIGUSR1);
137+
138+
sigaction(SIGUSR1, &(struct sigaction) {.sa_handler = &handle_signal}, NULL);
139+
pthread_sigmask(SIG_UNBLOCK, &sigusr1_set, NULL);
140+
141+
return true;
142+
}
143+
bool message_loop(void) {
144+
should_notify_platform_thread = true;
145+
146+
while (true) {
147+
pthread_mutex_lock(&task_list_lock);
148+
if (task_list_head_sentinel.next == NULL) {
149+
pthread_mutex_unlock(&task_list_lock);
150+
151+
sigwaitinfo(&sigusr1_set, NULL);
152+
} else {
153+
uint64_t target_time = task_list_head_sentinel.next->target_time;
154+
uint64_t current_time = FlutterEngineGetCurrentTime();
155+
156+
if (target_time > current_time) {
157+
uint64_t diff = target_time - current_time;
158+
159+
struct timespec target_timespec = {
160+
.tv_sec = (uint64_t) (diff / 1000000000l),
161+
.tv_nsec = (uint64_t) (diff % 1000000000l)
162+
};
163+
164+
pthread_mutex_unlock(&task_list_lock);
165+
166+
int result = sigtimedwait(&sigusr1_set, NULL, &target_timespec);
167+
if (result == EINTR) continue;
168+
} else {
169+
pthread_mutex_unlock(&task_list_lock);
170+
}
171+
}
172+
173+
pthread_mutex_lock(&task_list_lock);
174+
FlutterTask task = task_list_head_sentinel.next->task;
175+
176+
struct LinkedTaskListElement* new_first = task_list_head_sentinel.next->next;
177+
free(task_list_head_sentinel.next);
178+
task_list_head_sentinel.next = new_first;
179+
pthread_mutex_unlock(&task_list_lock);
180+
181+
if (FlutterEngineRunTask(engine, &task) != kSuccess) {
182+
fprintf(stderr, "Error running platform task\n");
183+
return false;
184+
};
185+
}
186+
187+
return true;
188+
}
189+
void post_platform_task(FlutterTask task, uint64_t target_time, void* userdata) {
190+
struct LinkedTaskListElement* to_insert = malloc(sizeof(struct LinkedTaskListElement));
191+
to_insert->next = NULL;
192+
to_insert->task = task;
193+
to_insert->target_time = target_time;
194+
195+
pthread_mutex_lock(&task_list_lock);
196+
struct LinkedTaskListElement* this = &task_list_head_sentinel;
197+
while ((this->next) != NULL && (target_time > this->next->target_time))
198+
this = this->next;
199+
200+
to_insert->next = this->next;
201+
this->next = to_insert;
202+
pthread_mutex_unlock(&task_list_lock);
203+
204+
if (should_notify_platform_thread) {
205+
pthread_kill(platform_thread_id, SIGUSR1);
206+
}
207+
}
208+
bool runs_platform_tasks_on_current_thread(void* userdata) {
209+
return pthread_equal(pthread_self(), platform_thread_id) != 0;
210+
}
211+
212+
110213
/******************
111214
* INITIALIZATION *
112215
******************/
113216
bool setup_paths(void) {
217+
#define PATH_EXISTS(path) (access((path),R_OK)==0)
218+
114219
if (!PATH_EXISTS(asset_bundle_path)) {
115220
fprintf(stderr, "Asset Bundle Directory \"%s\" does not exist\n", asset_bundle_path);
116221
return false;
@@ -141,6 +246,8 @@ bool setup_paths(void) {
141246
}
142247

143248
return true;
249+
250+
#undef PATH_EXISTS
144251
}
145252

146253
bool init_display(void) {
@@ -284,6 +391,15 @@ bool init_application(void) {
284391
project_args.command_line_argc = argc;
285392
project_args.command_line_argv = argv;
286393
project_args.platform_message_callback = on_platform_message;
394+
project_args.custom_task_runners = &(FlutterCustomTaskRunners) {
395+
.struct_size = sizeof(FlutterCustomTaskRunners),
396+
.platform_task_runner = &(FlutterTaskRunnerDescription) {
397+
.struct_size = sizeof(FlutterTaskRunnerDescription),
398+
.user_data = NULL,
399+
.runs_task_on_current_thread_callback = &runs_platform_tasks_on_current_thread,
400+
.post_task_callback = &post_platform_task
401+
}
402+
};
287403

288404
// spin up the engine
289405
FlutterEngineResult _result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &renderer_config, &project_args, NULL, &engine);
@@ -316,7 +432,10 @@ void destroy_application(void) {
316432
}
317433
}
318434

319-
bool init_inputs(void) {
435+
/****************
436+
* Input-Output *
437+
****************/
438+
bool init_io(void) {
320439
mouse_filehandle = open("/dev/input/event0", O_RDONLY);
321440
if (mouse_filehandle < 0) {
322441
perror("error opening the mouse file");
@@ -325,7 +444,7 @@ bool init_inputs(void) {
325444

326445
return true;
327446
}
328-
bool read_input_events(void) {
447+
void* io_loop(void* userdata) {
329448
FlutterPointerPhase phase;
330449
struct input_event event[64];
331450
bool ok;
@@ -397,9 +516,25 @@ bool read_input_events(void) {
397516
printf("mouse position: %f, %f\n", mouse_x, mouse_y);
398517
}
399518

519+
return NULL;
520+
}
521+
bool run_io_thread(void) {
522+
int ok = pthread_create(&io_thread_id, NULL, &io_loop, NULL);
523+
if (ok != 0) {
524+
fprintf(stderr, "couldn't create flutter-pi io thread: [%s]", strerror(ok));
525+
return false;
526+
}
527+
528+
ok = pthread_setname_np(io_thread_id, "io.flutter-pi");
529+
if (ok != 0) {
530+
fprintf(stderr, "couldn't set name of flutter-pi io thread: [%s]", strerror(ok));
531+
return false;
532+
}
533+
400534
return true;
401535
}
402536

537+
403538
int main(int argc, const char *const * argv) {
404539
if (argc <= 1) {
405540
fprintf(stderr, "Invalid Arguments\n");
@@ -413,6 +548,10 @@ int main(int argc, const char *const * argv) {
413548
if (!setup_paths()) {
414549
return EXIT_FAILURE;
415550
}
551+
552+
if (!init_message_loop()) {
553+
return EXIT_FAILURE;
554+
}
416555

417556
// initialize display
418557
printf("initializing display...\n");
@@ -421,7 +560,7 @@ int main(int argc, const char *const * argv) {
421560
}
422561

423562
printf("Initializing Input devices...\n");
424-
if (!init_inputs()) {
563+
if (!init_io()) {
425564
return EXIT_FAILURE;
426565
}
427566

@@ -432,14 +571,16 @@ int main(int argc, const char *const * argv) {
432571
}
433572

434573
// read input events
435-
read_input_events();
574+
printf("Running IO thread...\n");
575+
run_io_thread();
576+
577+
// run message loop
578+
printf("Running message loop...\n");
579+
message_loop();
436580

437581
// exit
438582
destroy_application();
439583
destroy_display();
440584

441585
return EXIT_SUCCESS;
442-
}
443-
444-
445-
#undef PATH_EXISTS
586+
}

src/flutter-pi.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
#include <stdint.h>
55
#include <flutter_embedder.h>
66

7+
struct LinkedTaskListElement {
8+
struct LinkedTaskListElement* next;
9+
FlutterTask task;
10+
uint64_t target_time;
11+
};
12+
713
FlutterEngine engine;
814

915
#endif

0 commit comments

Comments
 (0)