185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine/* Copyright (C) 2010 The Android Open Source Project
285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine**
385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** This software is licensed under the terms of the GNU General Public
485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and
585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** may be copied, distributed, and modified under those terms.
685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine**
785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** This program is distributed in the hope that it will be useful,
885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of
985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine** GNU General Public License for more details.
1185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine*/
1285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
1385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine/*
1485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine * Contains the Core-side implementation of the "attach-ui" service that is
1585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine * used to establish connection between the UI and the Core.
1685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine */
1785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
1885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/android.h"
1985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/globals.h"
2085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/looper.h"
2185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/async-utils.h"
2285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/sync-utils.h"
2385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/utils/debug.h"
2485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/protocol/core-commands.h"
2585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine#include "android/protocol/core-commands-impl.h"
2685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
2785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine/* Descriptor for the UI attach-ui proxy. */
2885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinetypedef struct AttachUIProxy {
2985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    /* Reader to detect UI disconnection. */
3085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    AsyncReader         async_reader;
3185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
3285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    /* I/O associated with this descriptor. */
3385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    LoopIo              io;
3485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
3585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    /* Looper used to communicate with the UI. */
3685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    Looper*             looper;
3785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
3885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    /* Socket descriptor for this service. */
3985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    int                 sock;
4085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine} AttachUIProxy;
4185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
4285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine/* One and only one AttachUIProxy instance. */
4385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinestatic AttachUIProxy    _attachUiProxy;
4485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
4585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine/* Implemented in android/console.c */
4685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkineextern void destroy_attach_ui_client(void);
4785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
4885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine/* Asynchronous I/O callback for AttachUIProxy instance.
4985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine * We expect this callback to be called only on UI detachment condition. In this
5085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine * case the event should be LOOP_IO_READ, and read should fail with errno set
5185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine * to ECONNRESET.
5285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine * Param:
5385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine *  opaque - AttachUIProxy instance.
5485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine */
5585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinestatic void
5685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine_attachUiProxy_io_func(void* opaque, int fd, unsigned events)
5785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine{
5885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    AttachUIProxy* uicmd = (AttachUIProxy*)opaque;
5985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    AsyncReader reader;
6085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    AsyncStatus status;
6185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    uint8_t read_buf[1];
6285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
6385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    if (events & LOOP_IO_WRITE) {
6485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        derror("Unexpected LOOP_IO_WRITE in _attachUiProxy_io_func.\n");
6585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        return;
6685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
6785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
6885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    // Try to read
6985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io);
70f9e333ade2529f257ced6bcff8e5824cb07eacf9David 'Digit' Turner    status = asyncReader_read(&reader);
7185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    // We expect only error status here.
7285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    if (status != ASYNC_ERROR) {
7385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        derror("Unexpected read status %d in _attachUiProxy_io_func\n", status);
7485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        return;
7585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
7685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    // We expect only socket disconnection error here.
7785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    if (errno != ECONNRESET) {
7885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        derror("Unexpected read error %d (%s) in _attachUiProxy_io_func.\n",
7985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine               errno, errno_str);
8085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        return;
8185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
8285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
8385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    // Client got disconnectted.
8485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    destroy_attach_ui_client();
8585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine}
8685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
8785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkineint
8885276806ec6ac969d7befa2496c1de59adaaac74Vladimir ChtchetkineattachUiProxy_create(int fd)
8985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine{
9085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    // Initialize the only AttachUIProxy instance.
9185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    _attachUiProxy.sock = fd;
9285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    _attachUiProxy.looper = looper_newCore();
9385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    loopIo_init(&_attachUiProxy.io, _attachUiProxy.looper, _attachUiProxy.sock,
9485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine                _attachUiProxy_io_func, &_attachUiProxy);
9585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    loopIo_wantRead(&_attachUiProxy.io);
9685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
9785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    return 0;
9885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine}
9985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
10085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinevoid
10185276806ec6ac969d7befa2496c1de59adaaac74Vladimir ChtchetkineattachUiProxy_destroy(void)
10285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine{
10385276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    if (_attachUiProxy.looper != NULL) {
10485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        // Stop all I/O that may still be going on.
10585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        loopIo_done(&_attachUiProxy.io);
10685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        looper_free(_attachUiProxy.looper);
10785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        _attachUiProxy.looper = NULL;
10885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
10985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    _attachUiProxy.sock = -1;
11085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine}
111