• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef HW_EMULATOR_CAMERA_QEMU_CLIENT_H
18 #define HW_EMULATOR_CAMERA_QEMU_CLIENT_H
19 
20 /*
21  * Contains declaration of classes that encapsulate connection to camera
22  * services in the emulator via qemu pipe.
23  */
24 
25 #include <hardware/qemud.h>
26 
27 namespace android {
28 
29 /****************************************************************************
30  * Qemu query
31  ***************************************************************************/
32 
33 /* Encapsulates a query to the emulator.
34  * Guest exchanges data with the emulator via queries sent over the qemu pipe.
35  * The queries as well as replies to the queries are all strings (except for the
36  * 'frame' query where reply is a framebuffer).
37  * Each query is formatted as such:
38  *
39  *      "<query name>[ <parameters>]",
40  *
41  * where <query name> is a string representing query name, and <parameters> are
42  * optional parameters for the query. If parameters are present, they must be
43  * separated from the query name with a single space, and they must be formatted
44  * as such:
45  *
46  *      "<name1>=<value1> <name2>=<value2> ... <nameN>=<valueN>"
47  *
48  * I.e.:
49  *  - Every parameter must have a name, and a value.
50  *  - Name and value must be separated with '='.
51  *  - No spaces are allowed around '=' separating name and value.
52  *  - Parameters must be separated with a single space character.
53  *  - No '=' character is allowed in name and in value.
54  *
55  * There are certain restrictions on strings used in the query:
56  *  - Spaces are allowed only as separators.
57  *  - '=' are allowed only to divide parameter names from parameter values.
58  *
59  * Emulator replies to each query in two chunks:
60  * - 8 bytes encoding the payload size as a string containing hexadecimal
61  *   representation of the payload size value. This is done in order to simplify
62  *   dealing with different endianness on the host, and on the guest.
63  * - Payload, whose size is defined by the first chunk.
64  *
65  * Every payload always begins with two characters, encoding the result of the
66  * query:
67  *  - 'ok' Encoding the success
68  *  - 'ko' Encoding a failure.
69  * After that payload may have optional data. If payload has more data following
70  * the query result, there is a ':' character separating them. If payload
71  * carries only the result, it always ends with a zero-terminator. So, payload
72  * 'ok'/'ko' prefix is always 3 bytes long: it either includes a
73  * zero-terminator, if there is no data, or a ':' separator.
74  */
75 class QemuQuery {
76  public:
77   /* Constructs an uninitialized QemuQuery instance. */
78   QemuQuery();
79 
80   /* Constructs and initializes QemuQuery instance for a query.
81    * Param:
82    *  query_string - Query string. This constructor can also be used to
83    *      construct a query that doesn't have parameters. In this case query
84    *      name can be passed as a parameter here.
85    */
86   explicit QemuQuery(const char* query_string);
87 
88   /* Constructs and initializes QemuQuery instance for a query with parameters.
89    * Param:
90    *  query_name - Query name.
91    *  query_param - Query parameters. Can be NULL.
92    */
93   QemuQuery(const char* query_name, const char* query_param);
94 
95   /* Destructs QemuQuery instance. */
96   ~QemuQuery();
97 
98   /****************************************************************************
99    * Public API
100    ***************************************************************************/
101 
102   /* Creates new query.
103    * Note: this method will reset this instance prior to creating a new query
104    * in order to discard possible "leftovers" from the previous query.
105    * Param:
106    *  query_name - Query name.
107    *  query_param - Query parameters. Can be NULL.
108    * Return:
109    *  NO_ERROR on success, or an appropriate error status.
110    */
111   status_t createQuery(const char* name, const char* param);
112 
113   /* Completes the query after a reply from the emulator.
114    * This method will parse the reply buffer, and calculate the final query
115    * status, which depends not only on the transport success / failure, but
116    * also on 'ok' / 'ko' in the reply buffer.
117    * Param:
118    *  status - Query delivery status. This status doesn't necessarily reflects
119    *      the final query status (which is defined by 'ok'/'ko' prefix in the
120    *      reply buffer). This status simply states whether or not the query has
121    *      been sent, and a reply has been received successfuly. However, if
122    *      this status indicates a failure, it means that the entire query has
123    *      failed.
124    * Return:
125    *  NO_ERROR on success, or an appropriate error status on failure. Note that
126    *  status returned here just signals whether or not the method has succeeded.
127    *  Use isQuerySucceeded() / getCompletionStatus() methods of this class to
128    *  check the final query status.
129    */
130   status_t completeQuery(status_t status);
131 
132   /* Resets the query from a previous use. */
133   void resetQuery();
134 
135   /* Checks if query has succeeded.
136    * Note that this method must be called after completeQuery() method of this
137    * class has been executed.
138    */
139   inline bool isQuerySucceeded() const {
140     return mQueryDeliveryStatus == NO_ERROR && mReplyStatus != 0;
141   }
142 
143   /* Gets final completion status of the query.
144    * Note that this method must be called after completeQuery() method of this
145    * class has been executed.
146    * Return:
147    *  NO_ERROR if query has succeeded, or an appropriate error status on query
148    *  failure.
149    */
150   inline status_t getCompletionStatus() const {
151     if (mQueryDeliveryStatus == NO_ERROR) {
152       if (mReplyStatus) {
153         return NO_ERROR;
154       } else {
155         return EINVAL;
156       }
157     } else {
158       return mQueryDeliveryStatus;
159     }
160   }
161 
162   /****************************************************************************
163    * Public data memebers
164    ***************************************************************************/
165 
166  public:
167   /* Query string. */
168   char* mQuery;
169   /* Query delivery status. */
170   status_t mQueryDeliveryStatus;
171   /* Reply buffer */
172   char* mReplyBuffer;
173   /* Reply data (past 'ok'/'ko'). If NULL, there were no data in reply. */
174   char* mReplyData;
175   /* Reply buffer size. */
176   size_t mReplySize;
177   /* Reply data size. */
178   size_t mReplyDataSize;
179   /* Reply status: 1 - ok, 0 - ko. */
180   int mReplyStatus;
181 
182   /****************************************************************************
183    * Private data memebers
184    ***************************************************************************/
185 
186  protected:
187   /* Preallocated buffer for small queries. */
188   char mQueryPrealloc[256];
189 };
190 
191 /****************************************************************************
192  * Qemu client base
193  ***************************************************************************/
194 
195 /* Encapsulates a connection to the 'camera' service in the emulator via qemu
196  * pipe.
197  */
198 class QemuClient {
199  public:
200   /* Constructs QemuClient instance. */
201   QemuClient();
202 
203   /* Destructs QemuClient instance. */
204   virtual ~QemuClient();
205 
206   /****************************************************************************
207    * Qemu client API
208    ***************************************************************************/
209 
210  public:
211   /* Connects to the 'camera' service in the emulator via qemu pipe.
212    * Param:
213    *  param - Parameters to pass to the camera service. There are two types of
214    *      camera services implemented by the emulator. The first one is a
215    *      'camera factory' type of service that provides list of cameras
216    *      connected to the host. Another one is an 'emulated camera' type of
217    *      service that provides interface to a camera connected to the host. At
218    *      the connection time emulator makes distinction between the two by
219    *      looking at connection parameters: no parameters means connection to
220    *      the 'factory' service, while connection with parameters means
221    *      connection to an 'emulated camera' service, where camera is identified
222    *      by one of the connection parameters. So, passing NULL, or an empty
223    *      string to this method will establish a connection with the 'factory'
224    *      service, while not empty string passed here will establish connection
225    *      with an 'emulated camera' service. Parameters defining the emulated
226    *      camera must be formatted as such:
227    *
228    *          "name=<device name> [inp_channel=<input channel #>]",
229    *
230    *      where 'device name' is a required parameter defining name of the
231    *      camera device, and 'input channel' is an optional parameter (positive
232    *      integer), defining the input channel to use on the camera device.
233    *      Note that device name passed here must have been previously obtained
234    *      from the factory service using 'list' query.
235    * Return:
236    *  NO_ERROR on success, or an appropriate error status.
237    */
238   virtual status_t connectClient(const char* param);
239 
240   /* Disconnects from the service. */
241   virtual void disconnectClient();
242 
243   /* Sends data to the service.
244    * Param:
245    *  data, data_size - Data to send.
246    * Return:
247    *  NO_ERROR on success, or an appropriate error status on failure.
248    */
249   virtual status_t sendMessage(const void* data, size_t data_size);
250 
251   /* Receives data from the service.
252    * This method assumes that data to receive will come in two chunks: 8
253    * characters encoding the payload size in hexadecimal string, followed by
254    * the paylod (if any).
255    * This method will allocate data buffer where to receive the response.
256    * Param:
257    *  data - Upon success contains address of the allocated data buffer with
258    *      the data received from the service. The caller is responsible for
259    *      freeing allocated data buffer.
260    *  data_size - Upon success contains size of the data received from the
261    *      service.
262    * Return:
263    *  NO_ERROR on success, or an appropriate error status on failure.
264    */
265   virtual status_t receiveMessage(void** data, size_t* data_size);
266 
267   /* Sends a query, and receives a response from the service.
268    * Param:
269    *  query - Query to send to the service. When this method returns, the query
270    *  is completed, and all its relevant data members are properly initialized.
271    * Return:
272    *  NO_ERROR on success, or an appropriate error status on failure. Note that
273    *  status returned here is not the final query status. Use
274    * isQuerySucceeded(), or getCompletionStatus() method on the query object to
275    * see if it has succeeded. However, if this method returns a failure, it
276    * means that the query has failed, and there is no guarantee that its data
277    * members are properly initialized (except for the 'mQueryDeliveryStatus',
278    * which is always in the proper state).
279    */
280   virtual status_t doQuery(QemuQuery* query);
281 
282   /****************************************************************************
283    * Data members
284    ***************************************************************************/
285 
286  protected:
287   /* Qemu pipe handle. */
288   int mPipeFD;
289 
290  private:
291   /* Camera service name. */
292   static const char mCameraServiceName[];
293 };
294 
295 /****************************************************************************
296  * Qemu client for the 'factory' service.
297  ***************************************************************************/
298 
299 /* Encapsulates QemuClient for the 'factory' service. */
300 class FactoryQemuClient : public QemuClient {
301  public:
302   /* Constructs FactoryQemuClient instance. */
303   FactoryQemuClient();
304 
305   /* Destructs FactoryQemuClient instance. */
306   ~FactoryQemuClient();
307 
308   /****************************************************************************
309    * Public API
310    ***************************************************************************/
311 
312  public:
313   /* Lists camera devices connected to the host.
314    * Param:
315    *  list - Upon success contains a list of cameras connected to the host. The
316    *      list returned here is represented as a string, containing multiple
317    *      lines separated with '\n', where each line represents a camera. Each
318    *      camera line is formatted as such:
319    *
320    *          "name=<device name> channel=<num> pix=<num>
321    * framedims=<dimensions>\n"
322    *
323    *      Where:
324    *      - 'name' is the name of the camera device attached to the host. This
325    *        name must be used for subsequent connection to the 'emulated camera'
326    *        service for that camera.
327    *      - 'channel' - input channel number (positive int) to use to
328    * communicate with the camera.
329    *      - 'pix' - pixel format (a "fourcc" uint), chosen for the video frames
330    *        by the camera service.
331    *      - 'framedims' contains a list of frame dimensions supported by the
332    *        camera for the chosen pixel format. Each etry in the list is in form
333    *        '<width>x<height>', where 'width' and 'height' are numeric values
334    *        for width and height of a supported frame dimension. Entries in
335    *        this list are separated with ',' with no spaces between the entries.
336    * Return:
337    *  NO_ERROR on success, or an appropriate error status on failure.
338    */
339   status_t listCameras(char** list);
340 
341   /****************************************************************************
342    * Names of the queries available for the emulated camera factory.
343    ***************************************************************************/
344 
345  private:
346   /* List cameras connected to the host. */
347   static const char mQueryList[];
348 };
349 
350 /****************************************************************************
351  * Qemu client for an 'emulated camera' service.
352  ***************************************************************************/
353 
354 /* Encapsulates QemuClient for an 'emulated camera' service.
355  */
356 class CameraQemuClient : public QemuClient {
357  public:
358   /* Constructs CameraQemuClient instance. */
359   CameraQemuClient();
360 
361   /* Destructs CameraQemuClient instance. */
362   ~CameraQemuClient();
363 
364   /****************************************************************************
365    * Public API
366    ***************************************************************************/
367 
368  public:
369   /* Queries camera connection.
370    * Return:
371    *  NO_ERROR on success, or an appropriate error status on failure.
372    */
373   status_t queryConnect();
374 
375   /* Queries camera disconnection.
376    * Return:
377    *  NO_ERROR on success, or an appropriate error status on failure.
378    */
379   status_t queryDisconnect();
380 
381   /* Queries camera to start capturing video.
382    * Param:
383    *  pixel_format - Pixel format that is used by the client to push video
384    *      frames to the camera framework.
385    *  width, height - Frame dimensions, requested by the framework.
386    * Return:
387    *  NO_ERROR on success, or an appropriate error status on failure.
388    */
389   status_t queryStart(uint32_t pixel_format, int width, int height);
390 
391   /* Queries camera to stop capturing video.
392    * Return:
393    *  NO_ERROR on success, or an appropriate error status on failure.
394    */
395   status_t queryStop();
396 
397   /* Queries camera for the next video frame.
398    * Param:
399    *  vframe, vframe_size - Define buffer, allocated to receive a video frame.
400    *      Any of these parameters can be 0, indicating that the caller is
401    *      interested only in preview frame.
402    *  pframe, pframe_size - Define buffer, allocated to receive a preview frame.
403    *      Any of these parameters can be 0, indicating that the caller is
404    *      interested only in video frame.
405    *  r_scale, g_scale, b_scale - White balance scale.
406    *  exposure_comp - Expsoure compensation.
407    * Return:
408    *  NO_ERROR on success, or an appropriate error status on failure.
409    */
410   status_t queryFrame(void* vframe, void* pframe, size_t vframe_size,
411                       size_t pframe_size, float r_scale, float g_scale,
412                       float b_scale, float exposure_comp);
413 
414   /****************************************************************************
415    * Names of the queries available for the emulated camera.
416    ***************************************************************************/
417 
418  private:
419   /* Connect to the camera. */
420   static const char mQueryConnect[];
421   /* Disconnect from the camera. */
422   static const char mQueryDisconnect[];
423   /* Start video capturing. */
424   static const char mQueryStart[];
425   /* Stop video capturing. */
426   static const char mQueryStop[];
427   /* Query frame(s). */
428   static const char mQueryFrame[];
429 };
430 
431 }; /* namespace android */
432 
433 #endif /* HW_EMULATOR_CAMERA_QEMU_CLIENT_H */
434