| // 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 <memory> |
| #include "base/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) = 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> 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; |
| |
| // 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; |
| |
| // 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() : "<null>"; |
| } |
| |
| // 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 |