The Android Open Source Project | 52d4c30 | 2009-03-03 19:29:09 -0800 | [diff] [blame] | 1 | // |
| 2 | // Copyright 2005 The Android Open Source Project |
| 3 | // |
| 4 | // Class that manages the simulated device. |
| 5 | // |
| 6 | #ifndef _SIM_DEVICE_MANAGER_H |
| 7 | #define _SIM_DEVICE_MANAGER_H |
| 8 | |
| 9 | #include "UserEvent.h" |
| 10 | |
| 11 | #include "Shmem.h" |
| 12 | #include "MessageStream.h" |
| 13 | #include "SimRuntime.h" |
| 14 | |
| 15 | #include "ui/PixelFormat.h" |
| 16 | #include "ui/KeycodeLabels.h" |
| 17 | |
| 18 | #include <sys/stat.h> |
| 19 | |
| 20 | /* |
| 21 | * Manage the simulated device. This includes starting/stopping as well |
| 22 | * as sending messages to it and receiving events from it. |
| 23 | * |
| 24 | * The object may span multiple invocations of a specific device. If |
| 25 | * the simulator is reconfigured to use a device with different |
| 26 | * characteristics, the object should be destroyed and recreated (which |
| 27 | * guarantees that the runtime is restarted). |
| 28 | */ |
| 29 | class DeviceManager { |
| 30 | public: |
| 31 | DeviceManager(void); |
| 32 | virtual ~DeviceManager(void); |
| 33 | |
| 34 | /* |
| 35 | * Initialize the object. Call this once. |
| 36 | * |
| 37 | * "numDisplays" is the number of displays that the simulated hardware |
| 38 | * supports. The displays themselves are configured with separate calls. |
| 39 | * |
| 40 | * "statusWindow" should be the main frame. Messages indicating runtime |
| 41 | * startup/shutdown are sent, as well as error messages that should be |
| 42 | * displayed in message boxes. |
| 43 | */ |
| 44 | bool Init(int numDisplays, wxWindow* statusWindow); |
| 45 | bool IsInitialized(void) const; |
| 46 | |
| 47 | /* |
| 48 | * Tell the device manager that the windows used to display its output |
| 49 | * are closing down. |
| 50 | */ |
| 51 | void WindowsClosing(void); |
| 52 | |
| 53 | /* |
| 54 | * "displayWindow" is the window to notify when a new frame of graphics |
| 55 | * data is available. This can be set independently for each display. |
| 56 | */ |
| 57 | bool SetDisplayConfig(int displayIndex, wxWindow* window, |
| 58 | int width, int height, android::PixelFormat format, int refresh); |
| 59 | |
| 60 | /* |
| 61 | * set the key map |
| 62 | */ |
| 63 | bool SetKeyboardConfig(const char *keymap); |
| 64 | |
| 65 | /* |
| 66 | * Return the number of displays we're configured for. |
| 67 | */ |
| 68 | int GetNumDisplays(void) const { return mNumDisplays; } |
| 69 | |
| 70 | /* |
| 71 | * Return the shmem key for the Nth display. |
| 72 | */ |
| 73 | //int GetShmemKey(int displayIndex); |
| 74 | |
| 75 | /* |
| 76 | * Is the runtime process still running? |
| 77 | */ |
| 78 | bool IsRunning(void) const { |
| 79 | if (mThread != NULL) |
| 80 | return mThread->IsRunning(); |
| 81 | return false; |
| 82 | } |
| 83 | bool IsKillable(void) const { |
| 84 | return true; |
| 85 | } |
| 86 | |
| 87 | // (Re-)configure the device, e.g. when #of displays changes because |
| 88 | // a different phone model has been selected. Call this before doing |
| 89 | // any display-specific setup. DO NOT call this if the runtime is active. |
| 90 | // void Configure(int numDisplays); |
| 91 | |
| 92 | // start the runtime, acting as parent |
| 93 | bool StartRuntime(void); |
| 94 | // start the runtime, acting as peer |
| 95 | bool StartRuntime(android::Pipe* reader, android::Pipe* writer); |
| 96 | // politely ask the runtime to stop |
| 97 | bool StopRuntime(void); |
| 98 | // kill the runtime with extreme prejudice |
| 99 | void KillRuntime(void); |
| 100 | |
| 101 | #if 0 |
| 102 | // Returns if the executable is new |
| 103 | bool RefreshRuntime(void); |
| 104 | // Update the time of the current runtime because the user cancelled a |
| 105 | // refresh |
| 106 | void UserCancelledRefresh(void); |
| 107 | #endif |
| 108 | |
| 109 | // send a key-up or key-down event to the runtime |
| 110 | void SendKeyEvent(KeyCode keyCode, bool down); |
| 111 | // send touch-screen events |
| 112 | void SendTouchEvent(android::Simulator::TouchMode mode, int x, int y); |
| 113 | |
| 114 | wxBitmap* GetImageData(int displayIndex); |
| 115 | |
| 116 | void BroadcastEvent(UserEvent &userEvent); |
| 117 | |
| 118 | private: |
| 119 | /* |
| 120 | * Threads in wxWidgets use sub-classing to define interfaces and |
| 121 | * entry points. We use this to create the thread that interacts |
| 122 | * with the runtime. |
| 123 | * |
| 124 | * The "reader" and "writer" arguments may be NULL. If they are, |
| 125 | * we will launch the runtime ourselves. If not, we will use them |
| 126 | * to speak with an externally-launched runtime process. The thread |
| 127 | * will own the pipes, shutting them down when it exits. |
| 128 | */ |
| 129 | class DeviceThread : public wxThread { |
| 130 | public: |
| 131 | DeviceThread(DeviceManager* pDM, wxWindow* pStatusWindow, |
| 132 | android::Pipe* reader, android::Pipe* writer) |
| 133 | : wxThread(wxTHREAD_JOINABLE), mpStatusWindow(pStatusWindow), |
| 134 | mReader(reader), mWriter(writer), |
| 135 | mpDeviceManager(pDM), /*mTerminalFollowsChild(false), |
| 136 | mSlowExit(false), mIsExternal(false), mLastModified(0),*/ |
| 137 | mRuntimeProcessGroup(0) |
| 138 | {} |
| 139 | virtual ~DeviceThread(void) { |
| 140 | delete mReader; |
| 141 | delete mWriter; |
| 142 | } |
| 143 | |
| 144 | /* thread entry point */ |
| 145 | virtual void* Entry(void); |
| 146 | |
| 147 | // wxThread class supplies an IsRunning() method |
| 148 | |
| 149 | /* |
| 150 | * This kills the runtime process to force this thread to exit. |
| 151 | * If the thread doesn't exit after a short period of time, it |
| 152 | * is forcibly terminated. |
| 153 | */ |
| 154 | void KillChildProcesses(void); |
| 155 | |
| 156 | #if 0 |
| 157 | /* |
| 158 | * Return if the runtime executable is new |
| 159 | */ |
| 160 | bool IsRuntimeNew(void); |
| 161 | |
| 162 | void UpdateLastModified(void); |
| 163 | #endif |
| 164 | |
| 165 | android::MessageStream* GetStream(void) { return &mStream; } |
| 166 | |
| 167 | static bool LaunchProcess(wxWindow* statusWindow); |
| 168 | |
| 169 | private: |
| 170 | void WaitForDeath(int delay); |
| 171 | void ResetProperties(void); |
| 172 | |
| 173 | android::MessageStream mStream; |
| 174 | wxWindow* mpStatusWindow; |
| 175 | android::Pipe* mReader; |
| 176 | android::Pipe* mWriter; |
| 177 | DeviceManager* mpDeviceManager; |
| 178 | pid_t mRuntimeProcessGroup; |
| 179 | //time_t mLastModified; |
| 180 | wxString mRuntimeExe; |
| 181 | }; |
| 182 | |
| 183 | friend class DeviceThread; |
| 184 | |
| 185 | /* |
| 186 | * We need one of these for each display on the device. Most devices |
| 187 | * only have one, but some flip phones have two. |
| 188 | */ |
| 189 | class Display { |
| 190 | public: |
| 191 | Display(void) |
| 192 | : mDisplayWindow(NULL), mpShmem(NULL), mShmemKey(0), |
| 193 | mImageData(NULL), mDisplayNum(-1), mWidth(-1), mHeight(-1), |
| 194 | mFormat(android::PIXEL_FORMAT_UNKNOWN), mRefresh(0) |
| 195 | {} |
| 196 | ~Display() { |
| 197 | delete mpShmem; |
| 198 | delete[] mImageData; |
| 199 | } |
| 200 | |
| 201 | /* initialize goodies */ |
| 202 | bool Create(int displayNum, wxWindow* window, int width, int height, |
| 203 | android::PixelFormat format, int refresh); |
| 204 | |
| 205 | /* call this if we're shutting down soon */ |
| 206 | void Uncreate(void); |
| 207 | |
| 208 | /* copy & convert data from shared memory */ |
| 209 | void CopyFromShared(void); |
| 210 | |
| 211 | /* get image data in the form of a 24bpp bitmap */ |
| 212 | wxBitmap* GetImageData(void); |
| 213 | |
| 214 | /* get a pointer to our display window */ |
| 215 | wxWindow* GetWindow(void) const { return mDisplayWindow; } |
| 216 | |
| 217 | /* get our shared memory key */ |
| 218 | int GetShmemKey(void) const { return mShmemKey; } |
| 219 | |
| 220 | int GetWidth(void) const { return mWidth; } |
| 221 | int GetHeight(void) const { return mHeight; } |
| 222 | android::PixelFormat GetFormat(void) const { return mFormat; } |
| 223 | int GetRefresh(void) const { return mRefresh; } |
| 224 | |
| 225 | private: |
| 226 | int GenerateKey(int displayNum) { |
| 227 | return 0x41544d00 | displayNum; |
| 228 | } |
| 229 | |
| 230 | // control access to image data shared between runtime mgr and UI |
| 231 | wxMutex mImageDataLock; |
| 232 | // we send an event here when we get stuff to display |
| 233 | wxWindow* mDisplayWindow; |
| 234 | |
| 235 | // shared memory segment |
| 236 | android::Shmem* mpShmem; |
| 237 | int mShmemKey; |
| 238 | |
| 239 | // local copy of data from shared mem, converted to 24bpp |
| 240 | unsigned char* mImageData; |
| 241 | |
| 242 | // mainly for debugging -- which display are we? |
| 243 | int mDisplayNum; |
| 244 | |
| 245 | // display characteristics |
| 246 | int mWidth; |
| 247 | int mHeight; |
| 248 | android::PixelFormat mFormat; |
| 249 | int mRefresh; // fps |
| 250 | }; |
| 251 | |
| 252 | Display* GetDisplay(int dispNum) { return &mDisplay[dispNum]; } |
| 253 | |
| 254 | const char* GetKeyMap() { return mKeyMap ? mKeyMap : "qwerty"; } |
| 255 | |
| 256 | void ShowFrame(int displayIndex); |
| 257 | |
| 258 | void Vibrate(int vibrateOn); |
| 259 | |
| 260 | // get the message stream from the device thread |
| 261 | android::MessageStream* GetStream(void); |
| 262 | |
| 263 | // send a request to set the visible layers |
| 264 | void SendSetVisibleLayers(void); |
| 265 | |
| 266 | // points at the runtime's thread (while it's running) |
| 267 | DeviceThread* mThread; |
| 268 | |
| 269 | // array of Displays, one per display on the device |
| 270 | Display* mDisplay; |
| 271 | int mNumDisplays; |
| 272 | |
| 273 | // the key map |
| 274 | const char * mKeyMap; |
| 275 | |
| 276 | // which graphics layers are visible? |
| 277 | int mVisibleLayers; |
| 278 | |
| 279 | // where to send status messages |
| 280 | wxWindow* mpStatusWindow; |
| 281 | |
| 282 | }; |
| 283 | |
| 284 | #endif // _SIM_DEVICE_MANAGER_H |