aboutsummaryrefslogtreecommitdiff
path: root/guest/hals/camera/QemuClient.h
blob: 290ab41c705b7a77d355fa556df9fb1cf83c0cac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HW_EMULATOR_CAMERA_QEMU_CLIENT_H
#define HW_EMULATOR_CAMERA_QEMU_CLIENT_H

/*
 * Contains declaration of classes that encapsulate connection to camera
 * services in the emulator via qemu pipe.
 */

#include <hardware/qemud.h>

namespace android {

/****************************************************************************
 * Qemu query
 ***************************************************************************/

/* Encapsulates a query to the emulator.
 * Guest exchanges data with the emulator via queries sent over the qemu pipe.
 * The queries as well as replies to the queries are all strings (except for the
 * 'frame' query where reply is a framebuffer).
 * Each query is formatted as such:
 *
 *      "<query name>[ <parameters>]",
 *
 * where <query name> is a string representing query name, and <parameters> are
 * optional parameters for the query. If parameters are present, they must be
 * separated from the query name with a single space, and they must be formatted
 * as such:
 *
 *      "<name1>=<value1> <name2>=<value2> ... <nameN>=<valueN>"
 *
 * I.e.:
 *  - Every parameter must have a name, and a value.
 *  - Name and value must be separated with '='.
 *  - No spaces are allowed around '=' separating name and value.
 *  - Parameters must be separated with a single space character.
 *  - No '=' character is allowed in name and in value.
 *
 * There are certain restrictions on strings used in the query:
 *  - Spaces are allowed only as separators.
 *  - '=' are allowed only to divide parameter names from parameter values.
 *
 * Emulator replies to each query in two chunks:
 * - 8 bytes encoding the payload size as a string containing hexadecimal
 *   representation of the payload size value. This is done in order to simplify
 *   dealing with different endianness on the host, and on the guest.
 * - Payload, whose size is defined by the first chunk.
 *
 * Every payload always begins with two characters, encoding the result of the
 * query:
 *  - 'ok' Encoding the success
 *  - 'ko' Encoding a failure.
 * After that payload may have optional data. If payload has more data following
 * the query result, there is a ':' character separating them. If payload
 * carries only the result, it always ends with a zero-terminator. So, payload
 * 'ok'/'ko' prefix is always 3 bytes long: it either includes a
 * zero-terminator, if there is no data, or a ':' separator.
 */
class QemuQuery {
 public:
  /* Constructs an uninitialized QemuQuery instance. */
  QemuQuery();

  /* Constructs and initializes QemuQuery instance for a query.
   * Param:
   *  query_string - Query string. This constructor can also be used to
   *      construct a query that doesn't have parameters. In this case query
   *      name can be passed as a parameter here.
   */
  explicit QemuQuery(const char* query_string);

  /* Constructs and initializes QemuQuery instance for a query with parameters.
   * Param:
   *  query_name - Query name.
   *  query_param - Query parameters. Can be NULL.
   */
  QemuQuery(const char* query_name, const char* query_param);

  /* Destructs QemuQuery instance. */
  ~QemuQuery();

  /****************************************************************************
   * Public API
   ***************************************************************************/

  /* Creates new query.
   * Note: this method will reset this instance prior to creating a new query
   * in order to discard possible "leftovers" from the previous query.
   * Param:
   *  query_name - Query name.
   *  query_param - Query parameters. Can be NULL.
   * Return:
   *  NO_ERROR on success, or an appropriate error status.
   */
  status_t createQuery(const char* name, const char* param);

  /* Completes the query after a reply from the emulator.
   * This method will parse the reply buffer, and calculate the final query
   * status, which depends not only on the transport success / failure, but
   * also on 'ok' / 'ko' in the reply buffer.
   * Param:
   *  status - Query delivery status. This status doesn't necessarily reflects
   *      the final query status (which is defined by 'ok'/'ko' prefix in the
   *      reply buffer). This status simply states whether or not the query has
   *      been sent, and a reply has been received successfuly. However, if
   *      this status indicates a failure, it means that the entire query has
   *      failed.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure. Note that
   *  status returned here just signals whether or not the method has succeeded.
   *  Use isQuerySucceeded() / getCompletionStatus() methods of this class to
   *  check the final query status.
   */
  status_t completeQuery(status_t status);

  /* Resets the query from a previous use. */
  void resetQuery();

  /* Checks if query has succeeded.
   * Note that this method must be called after completeQuery() method of this
   * class has been executed.
   */
  inline bool isQuerySucceeded() const {
    return mQueryDeliveryStatus == NO_ERROR && mReplyStatus != 0;
  }

  /* Gets final completion status of the query.
   * Note that this method must be called after completeQuery() method of this
   * class has been executed.
   * Return:
   *  NO_ERROR if query has succeeded, or an appropriate error status on query
   *  failure.
   */
  inline status_t getCompletionStatus() const {
    if (mQueryDeliveryStatus == NO_ERROR) {
      if (mReplyStatus) {
        return NO_ERROR;
      } else {
        return EINVAL;
      }
    } else {
      return mQueryDeliveryStatus;
    }
  }

  /****************************************************************************
   * Public data memebers
   ***************************************************************************/

 public:
  /* Query string. */
  char* mQuery;
  /* Query delivery status. */
  status_t mQueryDeliveryStatus;
  /* Reply buffer */
  char* mReplyBuffer;
  /* Reply data (past 'ok'/'ko'). If NULL, there were no data in reply. */
  char* mReplyData;
  /* Reply buffer size. */
  size_t mReplySize;
  /* Reply data size. */
  size_t mReplyDataSize;
  /* Reply status: 1 - ok, 0 - ko. */
  int mReplyStatus;

  /****************************************************************************
   * Private data memebers
   ***************************************************************************/

 protected:
  /* Preallocated buffer for small queries. */
  char mQueryPrealloc[256];
};

/****************************************************************************
 * Qemu client base
 ***************************************************************************/

/* Encapsulates a connection to the 'camera' service in the emulator via qemu
 * pipe.
 */
class QemuClient {
 public:
  /* Constructs QemuClient instance. */
  QemuClient();

  /* Destructs QemuClient instance. */
  virtual ~QemuClient();

  /****************************************************************************
   * Qemu client API
   ***************************************************************************/

 public:
  /* Connects to the 'camera' service in the emulator via qemu pipe.
   * Param:
   *  param - Parameters to pass to the camera service. There are two types of
   *      camera services implemented by the emulator. The first one is a
   *      'camera factory' type of service that provides list of cameras
   *      connected to the host. Another one is an 'emulated camera' type of
   *      service that provides interface to a camera connected to the host. At
   *      the connection time emulator makes distinction between the two by
   *      looking at connection parameters: no parameters means connection to
   *      the 'factory' service, while connection with parameters means
   *      connection to an 'emulated camera' service, where camera is identified
   *      by one of the connection parameters. So, passing NULL, or an empty
   *      string to this method will establish a connection with the 'factory'
   *      service, while not empty string passed here will establish connection
   *      with an 'emulated camera' service. Parameters defining the emulated
   *      camera must be formatted as such:
   *
   *          "name=<device name> [inp_channel=<input channel #>]",
   *
   *      where 'device name' is a required parameter defining name of the
   *      camera device, and 'input channel' is an optional parameter (positive
   *      integer), defining the input channel to use on the camera device.
   *      Note that device name passed here must have been previously obtained
   *      from the factory service using 'list' query.
   * Return:
   *  NO_ERROR on success, or an appropriate error status.
   */
  virtual status_t connectClient(const char* param);

  /* Disconnects from the service. */
  virtual void disconnectClient();

  /* Sends data to the service.
   * Param:
   *  data, data_size - Data to send.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  virtual status_t sendMessage(const void* data, size_t data_size);

  /* Receives data from the service.
   * This method assumes that data to receive will come in two chunks: 8
   * characters encoding the payload size in hexadecimal string, followed by
   * the paylod (if any).
   * This method will allocate data buffer where to receive the response.
   * Param:
   *  data - Upon success contains address of the allocated data buffer with
   *      the data received from the service. The caller is responsible for
   *      freeing allocated data buffer.
   *  data_size - Upon success contains size of the data received from the
   *      service.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  virtual status_t receiveMessage(void** data, size_t* data_size);

  /* Sends a query, and receives a response from the service.
   * Param:
   *  query - Query to send to the service. When this method returns, the query
   *  is completed, and all its relevant data members are properly initialized.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure. Note that
   *  status returned here is not the final query status. Use
   * isQuerySucceeded(), or getCompletionStatus() method on the query object to
   * see if it has succeeded. However, if this method returns a failure, it
   * means that the query has failed, and there is no guarantee that its data
   * members are properly initialized (except for the 'mQueryDeliveryStatus',
   * which is always in the proper state).
   */
  virtual status_t doQuery(QemuQuery* query);

  /****************************************************************************
   * Data members
   ***************************************************************************/

 protected:
  /* Qemu pipe handle. */
  int mPipeFD;

 private:
  /* Camera service name. */
  static const char mCameraServiceName[];
};

/****************************************************************************
 * Qemu client for the 'factory' service.
 ***************************************************************************/

/* Encapsulates QemuClient for the 'factory' service. */
class FactoryQemuClient : public QemuClient {
 public:
  /* Constructs FactoryQemuClient instance. */
  FactoryQemuClient();

  /* Destructs FactoryQemuClient instance. */
  ~FactoryQemuClient();

  /****************************************************************************
   * Public API
   ***************************************************************************/

 public:
  /* Lists camera devices connected to the host.
   * Param:
   *  list - Upon success contains a list of cameras connected to the host. The
   *      list returned here is represented as a string, containing multiple
   *      lines separated with '\n', where each line represents a camera. Each
   *      camera line is formatted as such:
   *
   *          "name=<device name> channel=<num> pix=<num>
   * framedims=<dimensions>\n"
   *
   *      Where:
   *      - 'name' is the name of the camera device attached to the host. This
   *        name must be used for subsequent connection to the 'emulated camera'
   *        service for that camera.
   *      - 'channel' - input channel number (positive int) to use to
   * communicate with the camera.
   *      - 'pix' - pixel format (a "fourcc" uint), chosen for the video frames
   *        by the camera service.
   *      - 'framedims' contains a list of frame dimensions supported by the
   *        camera for the chosen pixel format. Each etry in the list is in form
   *        '<width>x<height>', where 'width' and 'height' are numeric values
   *        for width and height of a supported frame dimension. Entries in
   *        this list are separated with ',' with no spaces between the entries.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  status_t listCameras(char** list);

  /****************************************************************************
   * Names of the queries available for the emulated camera factory.
   ***************************************************************************/

 private:
  /* List cameras connected to the host. */
  static const char mQueryList[];
};

/****************************************************************************
 * Qemu client for an 'emulated camera' service.
 ***************************************************************************/

/* Encapsulates QemuClient for an 'emulated camera' service.
 */
class CameraQemuClient : public QemuClient {
 public:
  /* Constructs CameraQemuClient instance. */
  CameraQemuClient();

  /* Destructs CameraQemuClient instance. */
  ~CameraQemuClient();

  /****************************************************************************
   * Public API
   ***************************************************************************/

 public:
  /* Queries camera connection.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  status_t queryConnect();

  /* Queries camera disconnection.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  status_t queryDisconnect();

  /* Queries camera to start capturing video.
   * Param:
   *  pixel_format - Pixel format that is used by the client to push video
   *      frames to the camera framework.
   *  width, height - Frame dimensions, requested by the framework.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  status_t queryStart(uint32_t pixel_format, int width, int height);

  /* Queries camera to stop capturing video.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  status_t queryStop();

  /* Queries camera for the next video frame.
   * Param:
   *  vframe, vframe_size - Define buffer, allocated to receive a video frame.
   *      Any of these parameters can be 0, indicating that the caller is
   *      interested only in preview frame.
   *  pframe, pframe_size - Define buffer, allocated to receive a preview frame.
   *      Any of these parameters can be 0, indicating that the caller is
   *      interested only in video frame.
   *  r_scale, g_scale, b_scale - White balance scale.
   *  exposure_comp - Expsoure compensation.
   * Return:
   *  NO_ERROR on success, or an appropriate error status on failure.
   */
  status_t queryFrame(void* vframe, void* pframe, size_t vframe_size,
                      size_t pframe_size, float r_scale, float g_scale,
                      float b_scale, float exposure_comp);

  /****************************************************************************
   * Names of the queries available for the emulated camera.
   ***************************************************************************/

 private:
  /* Connect to the camera. */
  static const char mQueryConnect[];
  /* Disconnect from the camera. */
  static const char mQueryDisconnect[];
  /* Start video capturing. */
  static const char mQueryStart[];
  /* Stop video capturing. */
  static const char mQueryStop[];
  /* Query frame(s). */
  static const char mQueryFrame[];
};

}; /* namespace android */

#endif /* HW_EMULATOR_CAMERA_QEMU_CLIENT_H */