// // 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(int32_t 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