| // Copyright 2020 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| #pragma once |
| |
| #include "base/Stream.h" |
| #include "base/export.h" |
| #include "android_pipe_common.h" |
| |
| #include <stdbool.h> |
| #include <stdint.h> |
| |
| #define ANDROID_PIPE_DEVICE_EXPORT extern AEMU_EXPORT |
| |
| // TECHNICAL NOTE: |
| // |
| // An Android pipe is a very fast communication channel between the guest |
| // system and the emulator program. |
| // |
| // To open a new pipe to the emulator, a guest client will do the following: |
| // |
| // fd = open("/dev/qemu_pipe", O_RDWR); |
| // ret = write(fd, pipeServiceName, strlen(pipeServiceName) + 1); |
| // if (ret < 0) { |
| // // something bad happened, see errno |
| // } |
| // |
| // Where 'pipeServiceName' is a string that looke like "pipe:<service>" |
| // or "pipe:<service>:<args>", terminated by a zero. |
| // |
| // now read()/write() to communicate with <pipeServiceName> service in the |
| // emulator. select() and non-blocking i/o will also work properly. |
| // |
| |
| // The Goldfish pipe virtual device is in charge of communicating with the |
| // kernel to manage pipe operations. |
| // |
| // Each pipe connection corresponds to two objects: |
| // |
| // - A hardware-side opaque object (implemented by the virtual pipe device) |
| // identified here as a |hwpipe| value. |
| // |
| // - A host-specific opaque object, identified here either as |host-pipe|. |
| // |
| // (virtual device) |hwpipe| <-----> |host-pipe| (emulator) |
| // |
| // Expected usage is the following: |
| // |
| // 1/ During setup, the virtual device should call android_pipe_set_hw_funcs() |
| // to point to callbacks it provides to implement a few functions called |
| // from the host, later at runtime. |
| // |
| // 2/ During setup, the emulator should register host pipe service instances, |
| // each one identified by a name, before the VM starts. |
| // |
| // 3/ At runtime, when a guest opens /dev/goldfish_pipe, this ends up creating |
| // a new |hwpipe| object in the virtual device, which will then call |
| // android_pipe_guest_open() to create a corresponding |host-pipe| |
| // object. |
| // |
| // Note that at this point, the |host-pipe| corresponds to a special |
| // host-side pipe state that waits for the name of the pipe service to |
| // connect to, and potential arguments. This is called a |connect-pipe| |
| // here: |
| // |
| // android_pipe_guest_open() |
| // |hwpipe| <---------------------------> |connect-pipe| |
| // |
| // 4/ When the pipe service name is fully written, the |connect-pipe| finds a |
| // service registered for it, and calls its ::init() callback to create |
| // a new |service-pipe| instance. |
| // |
| // |hwpipe| <---------------------------> |connect-pipe| |
| // |
| // |service-pipe| |
| // |
| // 5/ It then calls the AndroidPipeHwFuncs::resetPipe() callback provided |
| // by the virtual device to reattach the |hwpipe| to the |service-pipe| |
| // then later delete the now-useless |connect-pipe|. |
| // |
| // |hwpipe| <------------+ |connect-pipe| |
| // | |
| // +---------------->|service-pipe| |
| // |
| // VERY IMPORTANT NOTE: |
| // |
| // All operations should happen on the thread that currently holds the |
| // global VM state lock (see host-common/VmLock.h). It's up to |
| // the host implementation to ensure that this is always the case. |
| // |
| |
| //////////////////////////////////////////////////////////////////////////// |
| // |
| // The following functions are called from the virtual device only and are |
| // implemented by AndroidEmu. They will always be called from the device thread |
| // context as well. |
| |
| // Open a new Android pipe. |hwpipe| is a unique pointer value identifying the |
| // hardware-side view of the pipe, and will be passed to the 'init' callback |
| // from AndroidPipeHwFuncs. This returns a new |internal-pipe| value that is |
| // only used by the virtual device to call android_pipe_xxx() functions below. |
| ANDROID_PIPE_DEVICE_EXPORT void* android_pipe_guest_open( |
| void* hwpipe); |
| |
| // Similar to android_pipe_guest_open(), but has a flags parameter that is used |
| // to communicate unique transport properties about the pipe. |
| ANDROID_PIPE_DEVICE_EXPORT void* android_pipe_guest_open_with_flags( |
| void* hwpipe, uint32_t flags); |
| |
| // Close and free an Android pipe. |pipe| must be the result of a previous |
| // android_pipe_guest_open() call or the second parameter to |
| // android_pipe_reset(). |
| // This must *not* be called from the host side, see android_pipe_host_close() |
| // instead. |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_close( |
| void* internal_pipe, PipeCloseReason reason); |
| |
| // Hooks for a start/end of save/load operations, called once per each snapshot. |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_pre_load(android::base::Stream* file); |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_post_load(android::base::Stream* file); |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_pre_save(android::base::Stream* file); |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_post_save(android::base::Stream* file); |
| |
| // Save the state of an Android pipe to a stream. |internal_pipe| is the pipe |
| // instance from android_pipe_guest_open() or android_pipe_guest_load(), and |
| // |file| is the |
| // output stream. |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_save( |
| void* internal_pipe, android::base::Stream* file); |
| |
| // Load the state of an Android pipe from a stream. |file| is the input stream, |
| // |hwpipe| is the hardware-side pipe descriptor. On success, return a new |
| // internal pipe instance (similar to one returned by |
| // android_pipe_guest_open()), and |
| // sets |*force_close| to 1 to indicate that the pipe must be force-closed |
| // just after its load/creation (only useful for certain services that can't |
| // preserve state into streams). Return NULL on faillure. |
| ANDROID_PIPE_DEVICE_EXPORT void* android_pipe_guest_load( |
| android::base::Stream* file, void* hwpipe, char* force_close); |
| |
| // Similar to android_pipe_guest_load(), but this function is only called from |
| // the |
| // QEMU1 virtual pipe device, to support legacy snapshot formats. It can be |
| // ignored by the QEMU2 virtual device implementation. |
| // |
| // The difference is that this must also read the hardware-specific state |
| // fields, and store them into |*channel|, |*wakes| and |*closed| on |
| // success. |
| ANDROID_PIPE_DEVICE_EXPORT void* android_pipe_guest_load_legacy( |
| android::base::Stream* file, void* hwpipe, uint64_t* channel, |
| unsigned char* wakes, unsigned char* closed, char* force_close); |
| |
| // Call the poll() callback of the client associated with |pipe|. |
| ANDROID_PIPE_DEVICE_EXPORT unsigned android_pipe_guest_poll(void* internal_pipe); |
| |
| // Call the recvBuffers() callback of the client associated with |pipe|. |
| ANDROID_PIPE_DEVICE_EXPORT int android_pipe_guest_recv( |
| void* internal_pipe, AndroidPipeBuffer* buffers, int numBuffers); |
| |
| // Call the sendBuffers() callback of the client associated with |pipe|. |
| ANDROID_PIPE_DEVICE_EXPORT int android_pipe_guest_send( |
| void** internal_pipe, const AndroidPipeBuffer* buffer, int numBuffer); |
| |
| // Call the wakeOn() callback of the client associated with |pipe|. |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_guest_wake_on( |
| void* internal_pipe, unsigned wakes); |
| |
| // Utility functions to look up pipe instances and ids. |
| ANDROID_PIPE_DEVICE_EXPORT int android_pipe_get_id(void* internal_pipe); |
| ANDROID_PIPE_DEVICE_EXPORT void* android_pipe_lookup_by_id(int id); |
| |
| // Each pipe type should regiter its callback to lookup instances by it. |
| // |android_pipe_lookup_by_id| will go through the list of callbacks and |
| // will check if no more than one value is returned, it will crash otherwise. |
| // The |tag| argiment will be used in the crash message. |
| ANDROID_PIPE_DEVICE_EXPORT void android_pipe_append_lookup_by_id_callback( |
| void*(*callback)(int), const char* tag); |