// 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 #include "aemu/base/files/Stream.h" #include "android_pipe_common.h" #include "VmLock.h" namespace android { namespace base { // Forward-declare looper here because it is only used by // initThreadingForTest. class Looper; } // namespace base // AndroidPipe is a mostly-abstract base class for Android pipe connections. // It's important to understand that most pipe operations (onGuestXXX methods) // are performed with the global VM lock held. // // - QEMU1 runs all CPU-related operations and all timers/io events on its // main loop. This will be referred as the 'device thread' here. // // - QEMU2 has dedicated CPU threads to run guest read/write operations and // a different main-loop thread to run timers, check for pending host I/O. // It uses a global lock that is held every time virtual device operations // are performed. The 'device thread' is whichever CPU thread is holding // the lock. // // IMPORTANT: Most AndroidPipe methods must be called from a thread that holds // the global VM state lock (i.e. where VmLock::isLockedBySelf() is true). // Failure to do so will result in incorrect results, and panics in debug // builds. // // A few methods can be called from any thread though, see signalWake() and // closeFromHost(). // // Usage is the following: // // 1) At emulation setup time (i.e. before the VM runs), call // AndroidPipe::initThreading() from the main loop thread and pass an // appropriate VmLock instance. // // 2) For each supported pipe service, create a new AndroidPipe::Service // instance, and register it globally by calling AndroidPipe::Service::add(). // This can happen before 1) and in different threads. // // 3) Once the VM starts, whenever a guest wants to connect to a specific // named service, its instance's 'create' method will be called from the // device thread. Alternatively, when resuming from a snapshot, the 'load' // method will be called iff 'canLoad()' is overloaded to return true. // // 4) During pipe operations, onGuestXXX() methods will be called from the // device thread to operate on the pipe. // // 5) The signalWake() and closeFromHost() pipe methods can be called from // any thread to signal i/o events, or ask for the pipe closure. // class AndroidPipe { public: // Call this function in the main loop thread to ensure proper threading // support. |vmLock| must be a valid android::VmLock instance that will be // used to determine whether the current thread holds the global VM // state lock or not (if not, operations are queued). static void initThreading(VmLock* vmLock); static void initThreadingForTest(VmLock* lock, base::Looper* looper); // A base class for all AndroidPipe services, which is in charge // of creating new instances when a guest client connects to the // service. class Service { public: // Explicit constructor. explicit Service(const char* name) : mName(name) {} // Default destructor. virtual ~Service() = default; // Return service name. const std::string& name() const { return mName; } // Create a new pipe instance. This will be called when a guest // client connects to the service identified by its registration // name (see add() below). |hwPipe| is the hardware-side // view of the pipe, and |args| potential arguments. Must // return nullptr on error. virtual AndroidPipe* create(void* hwPipe, const char* args, enum AndroidPipeFlags flags) = 0; // Called once per whole vm save/load operation. virtual void preLoad(android::base::Stream* stream) {} virtual void postLoad(android::base::Stream* stream) {} virtual void preSave(android::base::Stream* stream) {} virtual void postSave(android::base::Stream* stream) {} // Called for each pipe, override to save additional information. virtual void savePipe(AndroidPipe* pipe, android::base::Stream* stream) { pipe->onSave(stream); } // Returns true if loading pipe instances from a stream is // supported. If true, the load() method will be called to load // every pipe instance state from the stream, if false, the // method will never be loaded, and the guest pipe channels will // be force-closed instead. The default implementation returns // false. virtual bool canLoad() const { return false; } // Load a pipe instance from input |stream|. Only called if // canLoad() returns true. Default implementation returns nullptr // to indicate an error loading the instance. virtual AndroidPipe* load(void* hwPipe, const char* args, android::base::Stream* stream) { return nullptr; } // Register a new |service| instance. After the call, the object // is owned by the global service manager, and will be destroyed // when resetAll() is called. static void add(std::unique_ptr service); // Reset the list of registered services. Useful at the start and // end of a unit-test. static void resetAll(); protected: // No default constructor. Service() = delete; std::string mName; }; // Default destructor. virtual ~AndroidPipe(); // Called from the device thread to close the pipe entirely. // The pipe management code will never access the instance after this call, // which means the method is free to delete it before returning. virtual void onGuestClose(PipeCloseReason reason) = 0; // Called from the device thread to poll the pipe state. Must return a // combination of PIPE_POLL_IN, PIPE_POLL_OUT and PIPE_POLL_HUP. virtual unsigned onGuestPoll() const = 0; // Called from the device thread when the guest wants to receive data // from the pipe. |buffers| points to an array of |numBuffers| descriptors // that specify where to copy the data to. Return the number of bytes that // were actually transferred, 0 for EOF status, or a negative error // value otherwise, including PIPE_ERROR_AGAIN which indicates there // is no data yet to read. virtual int onGuestRecv(AndroidPipeBuffer* buffers, int numBuffers) = 0; // A blocking call that waits until guest is able to receive data from the pipe. // This can be used if a previous call to |onGuestRecv| returns PIPE_ERROR_AGAIN. virtual void waitGuestRecv() const {}; // Called from the device thread when the guest wants to send data to // the pipe. |buffers| points to an array of |numBuffers| descriptors that // specify where to copy the data from. Return the number of bytes that // were actually transferred, 0 for EOF status, or a negative error // value otherwise, including PIPE_ERROR_AGAIN which indicates the pipe // is not ready to receive any data yet. virtual int onGuestSend(const AndroidPipeBuffer* buffers, int numBuffers, void** newPipePtr) = 0; // A blocking call that waits until guest is able to send data to the pipe. // This can be used if a previous call to |onGuestSend| returns PIPE_ERROR_AGAIN. virtual void waitGuestSend() const {} // Called from the device thread when the guest wants to indicate it // wants to be woken up when the set of PIPE_WAKE_XXX event bits in |flags| // will occur. The pipe implementation should call the wake() method to // signal the guest. virtual void onGuestWantWakeOn(int flags) = 0; // Called to save the pipe state to a |stream|, i.e. when saving snapshots. // Note that this is never called if the service's canLoad() method returns // false. TODO(digit): Is this always called from the device thread? virtual void onSave(android::base::Stream* stream){}; // Method used to signal the guest that the events corresponding to the // PIPE_WAKE_XXX bits in |flags| occurred. NOTE: This can be called from // any thread. void signalWake(int flags); // Method used to signal the guest that the pipe instance wants to close // the pipe. NOTE: This can be called from any thread. void closeFromHost(); // Method for canceling any pending wake() or close() that's scheduled for // this pipe. void abortPendingOperation(); // Return the name of the AndroidPipe service. const char* name() const { return mService ? mService->name().c_str() : ""; } // The following functions are implementation details. They are in the // public scope to make the implementation of android_pipe_guest_save() // and android_pipe_guest_load() easier. DO NOT CALL THEM DIRECTLY. // Save an AndroidPipe instance state to a file |stream|. void saveToStream(android::base::Stream* stream); // Load an AndroidPipe instance from its saved state from |stream|. // |hwPipe| is the hardware-side view of the pipe. On success, return // a new instance pointer and sets |*pForceClose| to 0 or 1. A value // of 1 means that the guest pipe connection should be forcibly closed // because the implementation doesn't allow the state to be saved/loaded // (e.g. network pipes). static AndroidPipe* loadFromStream(android::base::Stream* stream, void* hwPipe, char* pForceClose); // A variant of loadFromStream() that is only used to support legacy // snapshot format for pipes. On success, sets |*pChannel|, |*pWakes| and // |*pClosed|, as well as |*pForceClose|. Only used by the QEMU1 virtual // pipe device, and will probably be removed in the future. static AndroidPipe* loadFromStreamLegacy(android::base::Stream* stream, void* hwPipe, uint64_t* pChannel, unsigned char* pWakes, unsigned char* pClosed, char* pForceClose); // Flags accessor void setFlags(AndroidPipeFlags flags) { mFlags = flags; } AndroidPipeFlags getFlags() const { return mFlags; } protected: // No default constructor. AndroidPipe() = delete; // Constructor used by derived classes only. AndroidPipe(void* hwPipe, Service* service) : mHwPipe(hwPipe), mService(service) {} void* const mHwPipe = nullptr; Service* mService = nullptr; std::string mArgs; AndroidPipeFlags mFlags = ANDROID_PIPE_DEFAULT; }; } // namespace android