You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
11 KiB
254 lines
11 KiB
// 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
|