blob: bd4371e876f5cffe41780cc7f42e1369b402478d [file] [log] [blame]
//
// Copyright 2005 The Android Open Source Project
//
// Class that manages the simulated device.
//
#ifndef _SIM_DEVICE_MANAGER_H
#define _SIM_DEVICE_MANAGER_H
#include "UserEvent.h"
#include "Shmem.h"
#include "MessageStream.h"
#include "SimRuntime.h"
#include "ui/PixelFormat.h"
#include "ui/KeycodeLabels.h"
#include <sys/stat.h>
/*
* Manage the simulated device. This includes starting/stopping as well
* as sending messages to it and receiving events from it.
*
* The object may span multiple invocations of a specific device. If
* the simulator is reconfigured to use a device with different
* characteristics, the object should be destroyed and recreated (which
* guarantees that the runtime is restarted).
*/
class DeviceManager {
public:
DeviceManager(void);
virtual ~DeviceManager(void);
/*
* Initialize the object. Call this once.
*
* "numDisplays" is the number of displays that the simulated hardware
* supports. The displays themselves are configured with separate calls.
*
* "statusWindow" should be the main frame. Messages indicating runtime
* startup/shutdown are sent, as well as error messages that should be
* displayed in message boxes.
*/
bool Init(int numDisplays, wxWindow* statusWindow);
bool IsInitialized(void) const;
/*
* Tell the device manager that the windows used to display its output
* are closing down.
*/
void WindowsClosing(void);
/*
* "displayWindow" is the window to notify when a new frame of graphics
* data is available. This can be set independently for each display.
*/
bool SetDisplayConfig(int displayIndex, wxWindow* window,
int width, int height, android::PixelFormat format, int refresh);
/*
* set the key map
*/
bool SetKeyboardConfig(const char *keymap);
/*
* Return the number of displays we're configured for.
*/
int GetNumDisplays(void) const { return mNumDisplays; }
/*
* Return the shmem key for the Nth display.
*/
//int GetShmemKey(int displayIndex);
/*
* Is the runtime process still running?
*/
bool IsRunning(void) const {
if (mThread != NULL)
return mThread->IsRunning();
return false;
}
bool IsKillable(void) const {
return true;
}
// (Re-)configure the device, e.g. when #of displays changes because
// a different phone model has been selected. Call this before doing
// any display-specific setup. DO NOT call this if the runtime is active.
// void Configure(int numDisplays);
// start the runtime, acting as parent
bool StartRuntime(void);
// start the runtime, acting as peer
bool StartRuntime(android::Pipe* reader, android::Pipe* writer);
// politely ask the runtime to stop
bool StopRuntime(void);
// kill the runtime with extreme prejudice
void KillRuntime(void);
#if 0
// Returns if the executable is new
bool RefreshRuntime(void);
// Update the time of the current runtime because the user cancelled a
// refresh
void UserCancelledRefresh(void);
#endif
// send a key-up or key-down event to the runtime
void SendKeyEvent(KeyCode keyCode, bool down);
// send touch-screen events
void SendTouchEvent(android::Simulator::TouchMode mode, int x, int y);
wxBitmap* GetImageData(int displayIndex);
void BroadcastEvent(UserEvent &userEvent);
private:
/*
* Threads in wxWidgets use sub-classing to define interfaces and
* entry points. We use this to create the thread that interacts
* with the runtime.
*
* The "reader" and "writer" arguments may be NULL. If they are,
* we will launch the runtime ourselves. If not, we will use them
* to speak with an externally-launched runtime process. The thread
* will own the pipes, shutting them down when it exits.
*/
class DeviceThread : public wxThread {
public:
DeviceThread(DeviceManager* pDM, wxWindow* pStatusWindow,
android::Pipe* reader, android::Pipe* writer)
: wxThread(wxTHREAD_JOINABLE), mpStatusWindow(pStatusWindow),
mReader(reader), mWriter(writer),
mpDeviceManager(pDM), /*mTerminalFollowsChild(false),
mSlowExit(false), mIsExternal(false), mLastModified(0),*/
mRuntimeProcessGroup(0)
{}
virtual ~DeviceThread(void) {
delete mReader;
delete mWriter;
}
/* thread entry point */
virtual void* Entry(void);
// wxThread class supplies an IsRunning() method
/*
* This kills the runtime process to force this thread to exit.
* If the thread doesn't exit after a short period of time, it
* is forcibly terminated.
*/
void KillChildProcesses(void);
#if 0
/*
* Return if the runtime executable is new
*/
bool IsRuntimeNew(void);
void UpdateLastModified(void);
#endif
android::MessageStream* GetStream(void) { return &mStream; }
static bool LaunchProcess(wxWindow* statusWindow);
private:
void WaitForDeath(int delay);
void ResetProperties(void);
android::MessageStream mStream;
wxWindow* mpStatusWindow;
android::Pipe* mReader;
android::Pipe* mWriter;
DeviceManager* mpDeviceManager;
pid_t mRuntimeProcessGroup;
//time_t mLastModified;
wxString mRuntimeExe;
};
friend class DeviceThread;
/*
* We need one of these for each display on the device. Most devices
* only have one, but some flip phones have two.
*/
class Display {
public:
Display(void)
: mDisplayWindow(NULL), mpShmem(NULL), mShmemKey(0),
mImageData(NULL), mDisplayNum(-1), mWidth(-1), mHeight(-1),
mFormat(android::PIXEL_FORMAT_UNKNOWN), mRefresh(0)
{}
~Display() {
delete mpShmem;
delete[] mImageData;
}
/* initialize goodies */
bool Create(int displayNum, wxWindow* window, int width, int height,
android::PixelFormat format, int refresh);
/* call this if we're shutting down soon */
void Uncreate(void);
/* copy & convert data from shared memory */
void CopyFromShared(void);
/* get image data in the form of a 24bpp bitmap */
wxBitmap* GetImageData(void);
/* get a pointer to our display window */
wxWindow* GetWindow(void) const { return mDisplayWindow; }
/* get our shared memory key */
int GetShmemKey(void) const { return mShmemKey; }
int GetWidth(void) const { return mWidth; }
int GetHeight(void) const { return mHeight; }
android::PixelFormat GetFormat(void) const { return mFormat; }
int GetRefresh(void) const { return mRefresh; }
private:
int GenerateKey(int displayNum) {
return 0x41544d00 | displayNum;
}
// control access to image data shared between runtime mgr and UI
wxMutex mImageDataLock;
// we send an event here when we get stuff to display
wxWindow* mDisplayWindow;
// shared memory segment
android::Shmem* mpShmem;
int mShmemKey;
// local copy of data from shared mem, converted to 24bpp
unsigned char* mImageData;
// mainly for debugging -- which display are we?
int mDisplayNum;
// display characteristics
int mWidth;
int mHeight;
android::PixelFormat mFormat;
int mRefresh; // fps
};
Display* GetDisplay(int dispNum) { return &mDisplay[dispNum]; }
const char* GetKeyMap() { return mKeyMap ? mKeyMap : "qwerty"; }
void ShowFrame(int displayIndex);
void Vibrate(int vibrateOn);
// get the message stream from the device thread
android::MessageStream* GetStream(void);
// send a request to set the visible layers
void SendSetVisibleLayers(void);
// points at the runtime's thread (while it's running)
DeviceThread* mThread;
// array of Displays, one per display on the device
Display* mDisplay;
int mNumDisplays;
// the key map
const char * mKeyMap;
// which graphics layers are visible?
int mVisibleLayers;
// where to send status messages
wxWindow* mpStatusWindow;
};
#endif // _SIM_DEVICE_MANAGER_H