Home | History | Annotate | Download | only in protocol
      1 /* Copyright (C) 2010 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 
     13 /*
     14  * Contains the Core-side implementation of the "attach-ui" service that is
     15  * used to establish connection between the UI and the Core.
     16  */
     17 
     18 #include "android/android.h"
     19 #include "android/globals.h"
     20 #include "android/looper.h"
     21 #include "android/async-utils.h"
     22 #include "android/sync-utils.h"
     23 #include "android/utils/debug.h"
     24 #include "android/protocol/core-commands.h"
     25 #include "android/protocol/core-commands-impl.h"
     26 
     27 /* Descriptor for the UI attach-ui proxy. */
     28 typedef struct AttachUIProxy {
     29     /* Reader to detect UI disconnection. */
     30     AsyncReader         async_reader;
     31 
     32     /* I/O associated with this descriptor. */
     33     LoopIo              io;
     34 
     35     /* Looper used to communicate with the UI. */
     36     Looper*             looper;
     37 
     38     /* Socket descriptor for this service. */
     39     int                 sock;
     40 } AttachUIProxy;
     41 
     42 /* One and only one AttachUIProxy instance. */
     43 static AttachUIProxy    _attachUiProxy;
     44 
     45 /* Implemented in android/console.c */
     46 extern void destroy_attach_ui_client(void);
     47 
     48 /* Asynchronous I/O callback for AttachUIProxy instance.
     49  * We expect this callback to be called only on UI detachment condition. In this
     50  * case the event should be LOOP_IO_READ, and read should fail with errno set
     51  * to ECONNRESET.
     52  * Param:
     53  *  opaque - AttachUIProxy instance.
     54  */
     55 static void
     56 _attachUiProxy_io_func(void* opaque, int fd, unsigned events)
     57 {
     58     AttachUIProxy* uicmd = (AttachUIProxy*)opaque;
     59     AsyncReader reader;
     60     AsyncStatus status;
     61     uint8_t read_buf[1];
     62 
     63     if (events & LOOP_IO_WRITE) {
     64         derror("Unexpected LOOP_IO_WRITE in _attachUiProxy_io_func.\n");
     65         return;
     66     }
     67 
     68     // Try to read
     69     asyncReader_init(&reader, read_buf, sizeof(read_buf), &uicmd->io);
     70     status = asyncReader_read(&reader);
     71     // We expect only error status here.
     72     if (status != ASYNC_ERROR) {
     73         derror("Unexpected read status %d in _attachUiProxy_io_func\n", status);
     74         return;
     75     }
     76     // We expect only socket disconnection error here.
     77     if (errno != ECONNRESET) {
     78         derror("Unexpected read error %d (%s) in _attachUiProxy_io_func.\n",
     79                errno, errno_str);
     80         return;
     81     }
     82 
     83     // Client got disconnectted.
     84     destroy_attach_ui_client();
     85 }
     86 
     87 int
     88 attachUiProxy_create(int fd)
     89 {
     90     // Initialize the only AttachUIProxy instance.
     91     _attachUiProxy.sock = fd;
     92     _attachUiProxy.looper = looper_newCore();
     93     loopIo_init(&_attachUiProxy.io, _attachUiProxy.looper, _attachUiProxy.sock,
     94                 _attachUiProxy_io_func, &_attachUiProxy);
     95     loopIo_wantRead(&_attachUiProxy.io);
     96 
     97     return 0;
     98 }
     99 
    100 void
    101 attachUiProxy_destroy(void)
    102 {
    103     if (_attachUiProxy.looper != NULL) {
    104         // Stop all I/O that may still be going on.
    105         loopIo_done(&_attachUiProxy.io);
    106         looper_free(_attachUiProxy.looper);
    107         _attachUiProxy.looper = NULL;
    108     }
    109     _attachUiProxy.sock = -1;
    110 }
    111