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