blob: 71d5b3f3d23fd6864e63138ccd2f93a72bc868f4 [file]
// Copyright (C) 2018 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 "android/base/Compiler.h"
#include "android/base/Result.h"
#include "android/base/async/Looper.h"
#include "android/emulation/AndroidAsyncMessagePipe.h"
#include <memory>
// Forward declarations.
typedef struct PhysicalModel PhysicalModel;
namespace offworld {
class Response;
} // namespace offworld
namespace android {
namespace automation {
typedef android::base::Looper::DurationNs DurationNs;
// Forward declarations.
class AutomationEventSink;
enum class StartError {
InvalidFilename,
FileOpenError,
AlreadyStarted,
InternalError,
PlaybackFileCorrupt
};
using StartResult = base::Result<void, StartError>;
std::ostream& operator<<(std::ostream& os, const StartError& value);
enum class StopError { NotStarted, ParseError };
using StopResult = base::Result<void, StopError>;
std::ostream& operator<<(std::ostream& os, const StopError& value);
enum class ReplayError {
PlaybackInProgress,
ParseError,
InternalError,
};
using ReplayResult = base::Result<void, ReplayError>;
std::ostream& operator<<(std::ostream& os, const ReplayError& value);
enum class ListenError {
AlreadyListening,
StartFailed,
};
using ListenResult = base::Result<std::string, ListenError>;
std::ostream& operator<<(std::ostream& os, const ListenError& value);
//
// Controls recording and playback of emulator automation events.
//
class AutomationController {
protected:
DISALLOW_COPY_AND_ASSIGN(AutomationController);
// AutomationController is a singleton, use get() to get an instance.
AutomationController() = default;
public:
virtual ~AutomationController() = default;
// Initialize the AutomationController, called in qemu-setup.cpp.
static void initialize();
// Shutdown the AutomationController, called in qemu-setup.cpp.
static void shutdown();
// Get the global instance of the AutomationController. Asserts if called
// before initialize().
static AutomationController& get();
// Create an instance of the Looper for test usage.
static std::unique_ptr<AutomationController> createForTest(
PhysicalModel* physicalModel,
base::Looper* looper,
std::function<void(android::AsyncMessagePipeHandle,
const ::offworld::Response&)>
sendMessageCallback = nullptr);
// Advance the time if the AutomationController has been created.
static void tryAdvanceTime();
// Get the event sink for recording automation events.
virtual AutomationEventSink& getEventSink() = 0;
// Reset the current state and cancel any recordings or playback.
// Called on snapshot restore, since playback cannot be trivially resumed.
virtual void reset() = 0;
// Advance the state and process any playback events.
// Note that it is *not safe* to call this from a PhysicalModel callback.
//
// Returns the current time.
virtual DurationNs advanceTime() = 0;
// Start a recording to a file.
virtual StartResult startRecording(android::base::StringView filename) = 0;
// Stops a recording to a file.
virtual StopResult stopRecording() = 0;
// Start a playback from a file.
virtual StartResult startPlayback(android::base::StringView filename) = 0;
// Stop playback from a file.
virtual StopResult stopPlayback() = 0;
// Start playback with stop callback.
virtual StartResult startPlaybackWithCallback(
android::base::StringView filename,
void (*onStopCallback)()) = 0;
// Set the macro name in the header of a file.
virtual void setMacroName(android::base::StringView macroName,
android::base::StringView filename) = 0;
// Get the macro name from the header of a file.
virtual std::string getMacroName(android::base::StringView filename) = 0;
// Get the duration in nanoseconds from a file.
virtual uint64_t getDurationNs(android::base::StringView filename) = 0;
//
// Offworld API
//
// Replay an initial state event from the offworld pipe.
virtual ReplayResult replayInitialState(
android::base::StringView state) = 0;
// Replay an event through from the offworld pipe.
//
// If successful, replayEvent will send an async response to the pipe handle
// when replay has completed. The provided async id will be sent with that
// response. If an error is returned, no messages will be sent to the pipe
// and the caller should propagate the error to the user.
virtual ReplayResult replayEvent(android::AsyncMessagePipeHandle pipe,
android::base::StringView event,
uint32_t asyncId) = 0;
// Listen to the stream of automation events, returns an error if there is
// already a pending listen operations.
//
// If successful, any additional async responses will include the provided
// asyncId.
virtual ListenResult listen(android::AsyncMessagePipeHandle pipe,
uint32_t asyncId) = 0;
virtual void stopListening() = 0;
// Called on pipe close, to cancel any pending operations.
virtual void pipeClosed(android::AsyncMessagePipeHandle pipe) = 0;
};
} // namespace automation
} // namespace android