blob: a0bc7fcff37a1957b69a86c87529b90250167496 [file] [log] [blame]
/* Copyright (C) 2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
/*
* Contains the Core-side implementation of the "attach-ui" service that is
* used to establish connection between the UI and the Core.
*/
#include "android/android.h"
#include "android/globals.h"
#include "android/looper.h"
#include "android/async-utils.h"
#include "android/sync-utils.h"
#include "android/utils/debug.h"
#include "android/protocol/core-commands.h"
#include "android/protocol/core-commands-impl.h"
/* Descriptor for the UI attach-ui proxy. */
typedef struct AttachUIProxy {
/* Reader to detect UI disconnection. */
AsyncReader async_reader;
/* I/O associated with this descriptor. */
LoopIo io;
/* Looper used to communicate with the UI. */
Looper* looper;
/* Socket descriptor for this service. */
int sock;
} AttachUIProxy;
/* One and only one AttachUIProxy instance. */
static AttachUIProxy _attachUiProxy;
/* Implemented in android/console.c */
extern void destroy_attach_ui_client(void);
/* Asynchronous I/O callback for AttachUIProxy instance.
* We expect this callback to be called only on UI detachment condition. In this
* case the event should be LOOP_IO_READ, and read should fail with errno set
* to ECONNRESET.
* Param:
* opaque - AttachUIProxy instance.
*/
static void
_attachUiProxy_io_func(void* opaque, int fd, unsigned events)
{
AttachUIProxy* uicmd = (AttachUIProxy*)opaque;
AsyncReader reader;
AsyncStatus status;
uint8_t read_buf[1];
if (events & LOOP_IO_WRITE) {
derror("Unexpected LOOP_IO_WRITE in _attachUiProxy_io_func.\n");
return;
}
// Try to read
asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io);
status = asyncReader_read(&reader);
// We expect only error status here.
if (status != ASYNC_ERROR) {
derror("Unexpected read status %d in _attachUiProxy_io_func\n", status);
return;
}
// We expect only socket disconnection error here.
if (errno != ECONNRESET) {
derror("Unexpected read error %d (%s) in _attachUiProxy_io_func.\n",
errno, errno_str);
return;
}
// Client got disconnectted.
destroy_attach_ui_client();
}
int
attachUiProxy_create(int fd)
{
// Initialize the only AttachUIProxy instance.
_attachUiProxy.sock = fd;
_attachUiProxy.looper = looper_newCore();
loopIo_init(&_attachUiProxy.io, _attachUiProxy.looper, _attachUiProxy.sock,
_attachUiProxy_io_func, &_attachUiProxy);
loopIo_wantRead(&_attachUiProxy.io);
return 0;
}
void
attachUiProxy_destroy(void)
{
if (_attachUiProxy.looper != NULL) {
// Stop all I/O that may still be going on.
loopIo_done(&_attachUiProxy.io);
looper_free(_attachUiProxy.looper);
_attachUiProxy.looper = NULL;
}
_attachUiProxy.sock = -1;
}