From 89e2dcf83fa3901090893e98c17708e279dea47f Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Mon, 24 Nov 2014 15:11:41 -0800 Subject: recovery: Initial dialog implementation Implement two types of dialogs: info and error. Info dialogs are intended to show that an operation is in progress and cannot be interrupted. Error dialogs are intended to show that an error occurred. The user must respond by dismissing the dialog with any input (a swipe or keypress). Dialogs may be initiated internally within the UI code or externally via a named local socket. Dialogs created via socket are presumed to be info and may not be dismissed. When the client socket is closed, the dialog automatically dismisses. Initial implementation shows dialogs for adb backup and restore. Future work will show dialogs for all errors and lengthy operations. Change-Id: Icefea12ec0fd70fb487d54aa2eb1cae9dd451355 --- ui.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index 38a8099..a5896ce 100644 --- a/ui.cpp +++ b/ui.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -40,8 +41,83 @@ #include "voldclient.h" +#include "messagesocket.h" + #define UI_WAIT_KEY_TIMEOUT_SEC 120 +static int string_split(char* s, char** fields, int maxfields) +{ + int n = 0; + while (n+1 < maxfields) { + char* p = strchr(s, ' '); + if (!p) + break; + *p = '\0'; + printf("string_split: field[%d]=%s\n", n, s); + fields[n++] = s; + s = p+1; + } + fields[n] = s; + printf("string_split: last field[%d]=%s\n", n, s); + return n+1; +} + +static int message_socket_client_event(int fd, uint32_t epevents, void *data) +{ + MessageSocket* client = (MessageSocket*)data; + + printf("message_socket client event\n"); + if (!(epevents & EPOLLIN)) { + return 0; + } + + char buf[256]; + ssize_t nread; + nread = client->Read(buf, sizeof(buf)); + if (nread <= 0) { + ev_del_fd(fd); + self->DialogDismiss(); + client->Close(); + delete client; + return 0; + } + + printf("message_socket client message <%s>\n", buf); + + // Parse the message. Right now we support: + // dialog show + // dialog dismiss + char* fields[3]; + int nfields; + nfields = string_split(buf, fields, 3); + printf("fields=%d\n", nfields); + if (nfields < 2) + return 0; + printf("field[0]=%s, field[1]=%s\n", fields[0], fields[1]); + if (strcmp(fields[0], "dialog") == 0) { + if (strcmp(fields[1], "show") == 0 && nfields > 2) { + self->DialogShowInfo(fields[2]); + } + if (strcmp(fields[1], "dismiss") == 0) { + self->DialogDismiss(); + } + } + + return 0; +} + +static int message_socket_listen_event(int fd, uint32_t epevents, void *data) +{ + MessageSocket* ms = (MessageSocket*)data; + MessageSocket* client = ms->Accept(); + printf("message_socket_listen_event: event on %d\n", fd); + if (client) { + printf("message_socket client connected\n"); + ev_add_fd(client->fd(), message_socket_client_event, client); + } + return 0; +} + RecoveryUI::RecoveryUI() : key_queue_len(0), key_last_down(-1), @@ -86,6 +162,9 @@ static void* InputThreadLoop(void*) { void RecoveryUI::Init() { ev_init(InputCallback, this); + message_socket.ServerInit(); + ev_add_fd(message_socket.fd(), message_socket_listen_event, &message_socket); + ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1)); pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr); @@ -212,6 +291,12 @@ void RecoveryUI::time_key(int key_code, int count) { } void RecoveryUI::EnqueueKey(int key_code) { + if (DialogShowing()) { + if (DialogDismissable()) { + DialogDismiss(); + } + return; + } pthread_mutex_lock(&key_queue_mutex); const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]); if (key_queue_len < queue_max) { -- cgit v1.1