OSDN Git Service

Camera: Documentation updates am: 62cfd97
authorEino-Ville Talvala <etalvala@google.com>
Thu, 28 Apr 2016 17:30:07 +0000 (17:30 +0000)
committerandroid-build-merger <android-build-merger@google.com>
Thu, 28 Apr 2016 17:30:07 +0000 (17:30 +0000)
am: 58b8e6e

* commit '58b8e6e943da4e24daf3745a1b567cc99e241895':
  Camera: Documentation updates

Change-Id: I1fa2d5f1d74ce703ab9d2bc10448acc10fb1998f

77 files changed:
MODULE_LICENSE_APACHE2 [new file with mode: 0644]
NOTICE [new file with mode: 0644]
alsa_utils/Android.mk
alsa_utils/alsa_device_profile.c
alsa_utils/alsa_device_proxy.c
alsa_utils/alsa_format.c
audio/include/system/audio.h
audio/include/system/audio_policy.h
audio/include/system/sound_trigger.h
audio_effects/include/audio_effects/audio_effects_conf.h
audio_effects/include/audio_effects/effect_ns.h
audio_route/Android.mk
audio_route/audio_route.c
audio_utils/Android.mk
audio_utils/Doxyfile [new file with mode: 0644]
audio_utils/Doxyfile.orig [new file with mode: 0644]
audio_utils/conversion.cpp [new file with mode: 0644]
audio_utils/echo_reference.c
audio_utils/include/audio_utils/channels.h
audio_utils/include/audio_utils/conversion.h [new file with mode: 0644]
audio_utils/include/audio_utils/echo_reference.h
audio_utils/include/audio_utils/fifo.h
audio_utils/include/audio_utils/fixedfft.h
audio_utils/include/audio_utils/format.h
audio_utils/include/audio_utils/limiter.h [new file with mode: 0644]
audio_utils/include/audio_utils/minifloat.h
audio_utils/include/audio_utils/primitives.h
audio_utils/include/audio_utils/resampler.h
audio_utils/include/audio_utils/roundup.h
audio_utils/include/audio_utils/sndfile.h
audio_utils/limiter.c [new file with mode: 0644]
audio_utils/spdif/AC3FrameScanner.cpp
audio_utils/spdif/Android.mk
audio_utils/spdif/DTSFrameScanner.cpp
audio_utils/spdif/FrameScanner.cpp
audio_utils/spdif/SPDIFEncoder.cpp
audio_utils/tests/Android.mk
audio_utils/tests/README.md [new file with mode: 0644]
audio_utils/tests/fifo_tests.cpp
audio_utils/tests/limiter_tests.c [new file with mode: 0644]
audio_utils/tinysndfile.c
brillo/audio/audioservice/Android.mk [new file with mode: 0644]
brillo/audio/audioservice/audio_daemon.cpp [new file with mode: 0644]
brillo/audio/audioservice/audio_daemon.h [new file with mode: 0644]
brillo/audio/audioservice/audio_device_handler.cpp [new file with mode: 0644]
brillo/audio/audioservice/audio_device_handler.h [new file with mode: 0644]
brillo/audio/audioservice/brilloaudioserv.rc [new file with mode: 0644]
brillo/audio/audioservice/main_audio_service.cpp [new file with mode: 0644]
brillo/audio/audioservice/test/audio_device_handler_mock.h [new file with mode: 0644]
brillo/audio/audioservice/test/audio_device_handler_test.cpp [new file with mode: 0644]
camera/docs/ACameraMetadata.mako [new file with mode: 0644]
camera/docs/CameraDeviceInfo.mako [new file with mode: 0644]
camera/docs/CameraMetadataEnums.mako
camera/docs/CameraMetadataKeys.mako
camera/docs/CaptureResultTest.mako
camera/docs/camera_device_info.mako [new file with mode: 0644]
camera/docs/camera_device_info.proto [new file with mode: 0644]
camera/docs/docs.html
camera/docs/html.mako
camera/docs/metadata-generate
camera/docs/metadata_helpers.py
camera/docs/metadata_model.py
camera/docs/metadata_parser_xml.py
camera/docs/metadata_properties.xml
camera/docs/metadata_properties.xsd
camera/docs/metadata_template.mako
camera/docs/ndk_camera_metadata_tags.mako [new file with mode: 0644]
camera/include/system/camera_metadata_tags.h
camera/src/Android.mk
camera/src/camera_metadata.c
camera/src/camera_metadata_tag_info.c
camera/tests/Android.mk
camera/tests/camera_metadata_tests.cpp
camera/tests/camera_metadata_tests_fake_vendor.h
radio/include/system/radio_metadata.h
radio/src/Android.mk
radio/src/radio_metadata.c

diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
index 4b84a93..9b7f5dd 100644 (file)
@@ -27,7 +27,8 @@ LOCAL_C_INCLUDES += \
 LOCAL_EXPORT_C_INCLUDE_DIRS := system/media/alsa_utils/include
 LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils
 LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wno-unused-parameter
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -Wno-unused-parameter
 
 include $(BUILD_SHARED_LIBRARY)
 
index 054c77a..0d9bd88 100644 (file)
@@ -22,6 +22,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <cutils/properties.h>
 
 #include <log/log.h>
 
@@ -31,8 +32,7 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
-/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
-#define BUFF_DURATION_MS   5
+#define PERIOD_DURATION_US (5 * 1000)
 
 #define DEFAULT_PERIOD_SIZE 1024
 
@@ -113,11 +113,13 @@ unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sam
     if (profile == NULL) {
         return DEFAULT_PERIOD_SIZE;
     } else {
-        unsigned num_sample_frames = (sample_rate * BUFF_DURATION_MS) / 1000;
+        unsigned period_us = property_get_int32("ro.audio.usb.period_us", PERIOD_DURATION_US);
+        unsigned num_sample_frames = ((uint64_t)sample_rate * period_us) / 1000000;
+
         if (num_sample_frames < profile->min_period_size) {
             num_sample_frames = profile->min_period_size;
         }
-        return round_to_16_mult(num_sample_frames) * 2;
+        return round_to_16_mult(num_sample_frames);
     }
 }
 
@@ -332,7 +334,21 @@ static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_con
 #endif
 
     config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
+    // For output devices, let's make sure we choose at least stereo
+    // (assuming the device supports it).
+    if (profile->direction == PCM_OUT &&
+        config->channels < 2 && pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS) >= 2) {
+        config->channels = 2;
+    }
     config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
+    // Prefer 48K or 44.1K
+    if (config->rate < 48000 &&
+        pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 48000) {
+        config->rate = 48000;
+    } else if (config->rate < 441000 &&
+               pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 44100) {
+        config->rate = 44100;
+    }
     config->period_size = profile_calc_min_period_size(profile, config->rate);
     config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
     config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
index ac948f1..ee92ed0 100644 (file)
@@ -50,15 +50,30 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
     log_pcm_config(config, "proxy_setup()");
 #endif
 
-    proxy->alsa_config.format =
-        config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)
-            ? config->format : profile->default_config.format;
-    proxy->alsa_config.rate =
-        config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)
-            ? config->rate : profile->default_config.rate;
-    proxy->alsa_config.channels =
-        config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)
-            ? config->channels : profile->default_config.channels;
+    if (config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)) {
+        proxy->alsa_config.format = config->format;
+    } else {
+        ALOGW("Invalid format %d - using default %d.",
+              config->format, profile->default_config.format);
+        proxy->alsa_config.format = profile->default_config.format;
+    }
+
+    if (config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)) {
+        proxy->alsa_config.rate = config->rate;
+    } else {
+        ALOGW("Invalid sample rate %u - using default %u.",
+              config->rate, profile->default_config.rate);
+        proxy->alsa_config.rate = profile->default_config.rate;
+    }
+
+    if (config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)) {
+        proxy->alsa_config.channels = config->channels;
+    } else {
+        ALOGW("Invalid channel count %u - using default %u.",
+              config->channels, profile->default_config.channels);
+        proxy->alsa_config.channels = profile->default_config.channels;
+
+    }
 
     proxy->alsa_config.period_count = profile->default_config.period_count;
     proxy->alsa_config.period_size =
index 38f25c4..de8fcf2 100644 (file)
@@ -92,7 +92,6 @@ enum pcm_format get_pcm_format_for_mask(struct pcm_mask* mask)
 
     int slot_index, bit_index, table_index;
     table_index = 0;
-    int num_written = 0;
     for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
         unsigned bit_mask = 1;
         for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
index 2f33b2b..2d9839e 100644 (file)
 
 __BEGIN_DECLS
 
+/* The macro FCC_2 highlights places where there are 2-channel assumptions.
+ * This is typically due to legacy implementation of stereo input or output.
+ * Search also for "2", "left", "right", "[0]", "[1]", ">> 16", "<< 16", etc.
+ * Do not change this value.
+ */
+#define FCC_2 2     // FCC_2 = Fixed Channel Count 2
+
+/* The macro FCC_8 highlights places where there are 8-channel assumptions.
+ * This is typically due to audio mixer and resampler limitations.
+ * Do not change this value without verifying all locations that use it.
+ */
+#define FCC_8 8     // FCC_8 = Fixed Channel Count 8
+
 /* The enums were moved here mostly from
  * frameworks/base/include/media/AudioSystem.h
  */
@@ -64,6 +77,8 @@ typedef enum {
     AUDIO_STREAM_REROUTING        = 11, /* For dynamic policy output mixes */
     AUDIO_STREAM_PATCH            = 12, /* For internal audio flinger tracks. Fixed volume */
     AUDIO_STREAM_PUBLIC_CNT       = AUDIO_STREAM_TTS + 1,
+    AUDIO_STREAM_FOR_POLICY_CNT   = AUDIO_STREAM_PATCH, /* number of streams considered by
+                                           audio policy for volume and routing */
     AUDIO_STREAM_CNT              = AUDIO_STREAM_PATCH + 1,
 } audio_stream_type_t;
 
@@ -120,6 +135,7 @@ enum {
     AUDIO_FLAG_HW_HOTWORD                 = 0x20,
     AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY = 0x40,
     AUDIO_FLAG_BYPASS_MUTE                = 0x80,
+    AUDIO_FLAG_LOW_LATENCY                = 0x100,
 };
 
 /* Do not change these values without updating their counterparts
@@ -140,6 +156,9 @@ typedef enum {
                                           /* An example of remote presentation is Wifi Display */
                                           /*  where a dongle attached to a TV can be used to   */
                                           /*  play the mix captured by this audio source.      */
+    AUDIO_SOURCE_UNPROCESSED         = 9, /* Source for unprocessed sound.
+                                             Usage examples include level measurement and raw
+                                             signal analysis. */
     AUDIO_SOURCE_CNT,
     AUDIO_SOURCE_MAX                 = AUDIO_SOURCE_CNT - 1,
     AUDIO_SOURCE_FM_TUNER            = 1998,
@@ -161,6 +180,7 @@ typedef struct {
 } audio_attributes_t;
 
 /* special audio session values
+ * do not need to have audio_unique_id_get_use(session) == AUDIO_UNIQUE_ID_USE_SESSION
  * (XXX: should this be living in the audio effects land?)
  */
 typedef enum {
@@ -179,13 +199,44 @@ typedef enum {
      * and requests a new session ID to be allocated
      * TODO use unique values for AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE,
      * after all uses have been updated from 0 to the appropriate symbol, and have been tested.
+     * Corresponds to AudioManager.AUDIO_SESSION_ID_GENERATE and AudioSystem.AUDIO_SESSION_ALLOCATE.
      */
     AUDIO_SESSION_ALLOCATE = 0,
+
+    /* For use with AudioRecord::start(), this indicates no trigger session.
+     * It is also used with output tracks and patch tracks, which never have a session.
+     */
+    AUDIO_SESSION_NONE = 0,
 } audio_session_t;
 
-/* a unique ID allocated by AudioFlinger for use as a audio_io_handle_t or audio_session_t */
+/* a unique ID allocated by AudioFlinger for use as an audio_io_handle_t, audio_session_t,
+ * effect ID (int), audio_module_handle_t, and audio_patch_handle_t.
+ * Audio port IDs (audio_port_handle_t) are allocated by AudioPolicy
+ * in a different namespace than AudioFlinger unique IDs.
+ */
 typedef int audio_unique_id_t;
 
+/* Possible uses for an audio_unique_id_t */
+typedef enum {
+    AUDIO_UNIQUE_ID_USE_UNSPECIFIED = 0,
+    AUDIO_UNIQUE_ID_USE_SESSION = 1,    // for allocated sessions, not special AUDIO_SESSION_*
+    AUDIO_UNIQUE_ID_USE_MODULE = 2,
+    AUDIO_UNIQUE_ID_USE_EFFECT = 3,
+    AUDIO_UNIQUE_ID_USE_PATCH = 4,
+    AUDIO_UNIQUE_ID_USE_OUTPUT = 5,
+    AUDIO_UNIQUE_ID_USE_INPUT = 6,
+    // 7 is available
+    AUDIO_UNIQUE_ID_USE_MAX = 8,  // must be a power-of-two
+    AUDIO_UNIQUE_ID_USE_MASK = AUDIO_UNIQUE_ID_USE_MAX - 1
+} audio_unique_id_use_t;
+
+/* Return the use of an audio_unique_id_t */
+static inline audio_unique_id_use_t audio_unique_id_get_use(audio_unique_id_t id)
+{
+    return (audio_unique_id_use_t) (id & AUDIO_UNIQUE_ID_USE_MASK);
+}
+
+/* Reserved audio_unique_id_t values.  FIXME: not a complete list. */
 #define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE
 
 /* Audio sub formats (see enum audio_format). */
@@ -237,8 +288,9 @@ typedef enum {
 } audio_format_vorbis_sub_fmt_t;
 
 
-/* Audio format consists of a main format field (upper 8 bits) and a sub format
- * field (lower 24 bits).
+/* Audio format  is a 32-bit word that consists of:
+ *   main format field (upper 8 bits)
+ *   sub format field (lower 24 bits).
  *
  * The main format indicates the main codec type. The sub format field
  * indicates options and parameters for each format. The sub format is mainly
@@ -262,7 +314,9 @@ typedef enum {
     AUDIO_FORMAT_E_AC3               = 0x0A000000UL,
     AUDIO_FORMAT_DTS                 = 0x0B000000UL,
     AUDIO_FORMAT_DTS_HD              = 0x0C000000UL,
-    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000UL,
+    // IEC61937 is encoded audio wrapped in 16-bit PCM.
+    AUDIO_FORMAT_IEC61937            = 0x0D000000UL,
+    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000UL, /* Deprecated. Use audio_get_main_format() */
     AUDIO_FORMAT_SUB_MASK            = 0x00FFFFFFUL,
 
     /* Aliases */
@@ -483,14 +537,14 @@ typedef enum {
  */
 enum {
     AUDIO_CHANNEL_INDEX_HDR  = AUDIO_CHANNEL_REPRESENTATION_INDEX << AUDIO_CHANNEL_COUNT_MAX,
-    AUDIO_CHANNEL_INDEX_MASK_1 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 1) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_2 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 2) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_3 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 3) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_4 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 4) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_5 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 5) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_6 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 6) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_7 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 7) - 1,
-    AUDIO_CHANNEL_INDEX_MASK_8 =  AUDIO_CHANNEL_INDEX_HDR | (1 << 8) - 1,
+    AUDIO_CHANNEL_INDEX_MASK_1 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 1) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_2 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 2) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_3 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 3) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_4 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 4) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_5 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 5) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_6 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 6) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_7 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 7) - 1),
+    AUDIO_CHANNEL_INDEX_MASK_8 =  AUDIO_CHANNEL_INDEX_HDR | ((1 << 8) - 1),
     // FIXME FCC_8
 };
 
@@ -616,6 +670,8 @@ enum {
     /* limited-output speaker device for acoustic safety */
     AUDIO_DEVICE_OUT_SPEAKER_SAFE              = 0x400000,
     AUDIO_DEVICE_OUT_IP                        = 0x800000,
+    /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
+    AUDIO_DEVICE_OUT_BUS                       = 0x1000000,
     AUDIO_DEVICE_OUT_DEFAULT                   = AUDIO_DEVICE_BIT_DEFAULT,
     AUDIO_DEVICE_OUT_ALL      = (AUDIO_DEVICE_OUT_EARPIECE |
                                  AUDIO_DEVICE_OUT_SPEAKER |
@@ -641,6 +697,7 @@ enum {
                                  AUDIO_DEVICE_OUT_AUX_LINE |
                                  AUDIO_DEVICE_OUT_SPEAKER_SAFE |
                                  AUDIO_DEVICE_OUT_IP |
+                                 AUDIO_DEVICE_OUT_BUS |
                                  AUDIO_DEVICE_OUT_DEFAULT),
     AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
                                  AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -678,6 +735,8 @@ enum {
     AUDIO_DEVICE_IN_BLUETOOTH_A2DP        = AUDIO_DEVICE_BIT_IN | 0x20000,
     AUDIO_DEVICE_IN_LOOPBACK              = AUDIO_DEVICE_BIT_IN | 0x40000,
     AUDIO_DEVICE_IN_IP                    = AUDIO_DEVICE_BIT_IN | 0x80000,
+    /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
+    AUDIO_DEVICE_IN_BUS                   = AUDIO_DEVICE_BIT_IN | 0x100000,
     AUDIO_DEVICE_IN_DEFAULT               = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
 
     AUDIO_DEVICE_IN_ALL     = (AUDIO_DEVICE_IN_COMMUNICATION |
@@ -700,6 +759,7 @@ enum {
                                AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
                                AUDIO_DEVICE_IN_LOOPBACK |
                                AUDIO_DEVICE_IN_IP |
+                               AUDIO_DEVICE_IN_BUS |
                                AUDIO_DEVICE_IN_DEFAULT),
     AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
     AUDIO_DEVICE_IN_ALL_USB  = (AUDIO_DEVICE_IN_USB_ACCESSORY |
@@ -826,9 +886,24 @@ static const audio_config_t AUDIO_CONFIG_INITIALIZER = {
     frame_count: 0,
 };
 
+struct audio_config_base {
+    uint32_t sample_rate;
+    audio_channel_mask_t channel_mask;
+    audio_format_t  format;
+};
+
+typedef struct audio_config_base audio_config_base_t;
+
+static const audio_config_base_t AUDIO_CONFIG_BASE_INITIALIZER = {
+    sample_rate: 0,
+    channel_mask: AUDIO_CHANNEL_NONE,
+    format: AUDIO_FORMAT_DEFAULT
+};
 
 /* audio hw module handle functions or structures referencing a module */
-typedef int audio_module_handle_t;
+typedef enum {
+    AUDIO_MODULE_HANDLE_NONE = 0,
+} audio_module_handle_t;
 
 /******************************
  *  Volume control
@@ -1035,8 +1110,9 @@ struct audio_port {
  * But the same patch receives another system wide unique handle allocated by the framework.
  * This unique handle is used for all transactions inside the framework.
  */
-typedef int audio_patch_handle_t;
-#define AUDIO_PATCH_HANDLE_NONE 0
+typedef enum {
+    AUDIO_PATCH_HANDLE_NONE = 0,
+} audio_patch_handle_t;
 
 #define AUDIO_PATCH_PORTS_MAX   16
 
@@ -1365,15 +1441,44 @@ static inline bool audio_is_valid_format(audio_format_t format)
     case AUDIO_FORMAT_E_AC3:
     case AUDIO_FORMAT_DTS:
     case AUDIO_FORMAT_DTS_HD:
+    case AUDIO_FORMAT_IEC61937:
         return true;
     default:
         return false;
     }
 }
 
+/**
+ * Extract the primary format, eg. PCM, AC3, etc.
+ */
+static inline audio_format_t audio_get_main_format(audio_format_t format)
+{
+    return (audio_format_t)(format & AUDIO_FORMAT_MAIN_MASK);
+}
+
+/**
+ * Is the data plain PCM samples that can be scaled and mixed?
+ */
 static inline bool audio_is_linear_pcm(audio_format_t format)
 {
-    return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM);
+    return (audio_get_main_format(format) == AUDIO_FORMAT_PCM);
+}
+
+/**
+ * For this format, is the number of PCM audio frames directly proportional
+ * to the number of data bytes?
+ *
+ * In other words, is the format transported as PCM audio samples,
+ * but not necessarily scalable or mixable.
+ * This returns true for real PCM, but also for AUDIO_FORMAT_IEC61937,
+ * which is transported as 16 bit PCM audio, but where the encoded data
+ * cannot be mixed or scaled.
+ */
+static inline bool audio_has_proportional_frames(audio_format_t format)
+{
+    audio_format_t mainFormat = audio_get_main_format(format);
+    return (mainFormat == AUDIO_FORMAT_PCM
+            || mainFormat == AUDIO_FORMAT_IEC61937);
 }
 
 static inline size_t audio_bytes_per_sample(audio_format_t format)
@@ -1389,6 +1494,7 @@ static inline size_t audio_bytes_per_sample(audio_format_t format)
         size = sizeof(uint8_t) * 3;
         break;
     case AUDIO_FORMAT_PCM_16_BIT:
+    case AUDIO_FORMAT_IEC61937:
         size = sizeof(int16_t);
         break;
     case AUDIO_FORMAT_PCM_8_BIT:
@@ -1425,14 +1531,16 @@ static inline bool audio_device_is_digital(audio_devices_t device) {
         return (~AUDIO_DEVICE_BIT_IN & device & (AUDIO_DEVICE_IN_ALL_USB |
                           AUDIO_DEVICE_IN_HDMI |
                           AUDIO_DEVICE_IN_SPDIF |
-                          AUDIO_DEVICE_IN_IP)) != 0;
+                          AUDIO_DEVICE_IN_IP |
+                          AUDIO_DEVICE_IN_BUS)) != 0;
     } else {
         // output
         return (device & (AUDIO_DEVICE_OUT_ALL_USB |
                           AUDIO_DEVICE_OUT_HDMI |
                           AUDIO_DEVICE_OUT_HDMI_ARC |
                           AUDIO_DEVICE_OUT_SPDIF |
-                          AUDIO_DEVICE_OUT_IP)) != 0;
+                          AUDIO_DEVICE_OUT_IP |
+                          AUDIO_DEVICE_OUT_BUS)) != 0;
     }
 }
 
index 2881104..2e2e90b 100644 (file)
@@ -30,7 +30,9 @@ __BEGIN_DECLS
  * frameworks/base/include/media/AudioSystem.h
  */
 
-/* device categories used for audio_policy->set_force_use() */
+/* device categories used for audio_policy->set_force_use()
+ * These must match the values in AudioSystem.java
+ */
 typedef enum {
     AUDIO_POLICY_FORCE_NONE,
     AUDIO_POLICY_FORCE_SPEAKER,
@@ -45,6 +47,8 @@ typedef enum {
     AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
     AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
     AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED,
+    AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER,
+    AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS,
 
     AUDIO_POLICY_FORCE_CFG_CNT,
     AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
@@ -52,7 +56,9 @@ typedef enum {
     AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
 } audio_policy_forced_cfg_t;
 
-/* usages used for audio_policy->set_force_use() */
+/* usages used for audio_policy->set_force_use()
+ * These must match the values in AudioSystem.java
+ */
 typedef enum {
     AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
     AUDIO_POLICY_FORCE_FOR_MEDIA,
@@ -60,6 +66,7 @@ typedef enum {
     AUDIO_POLICY_FORCE_FOR_DOCK,
     AUDIO_POLICY_FORCE_FOR_SYSTEM,
     AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO,
+    AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
 
     AUDIO_POLICY_FORCE_USE_CNT,
     AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
index 773e4f7..8f80080 100644 (file)
@@ -36,6 +36,8 @@ typedef enum {
 #define RECOGNITION_MODE_USER_IDENTIFICATION 0x2 /* trigger only if one user in model identified */
 #define RECOGNITION_MODE_USER_AUTHENTICATION 0x4 /* trigger only if one user in mode
                                                     authenticated */
+#define RECOGNITION_MODE_GENERIC_TRIGGER 0x8     /* generic sound trigger */
+
 #define RECOGNITION_STATUS_SUCCESS 0
 #define RECOGNITION_STATUS_ABORT 1
 #define RECOGNITION_STATUS_FAILURE 2
@@ -44,7 +46,8 @@ typedef enum {
 
 typedef enum {
     SOUND_MODEL_TYPE_UNKNOWN = -1,    /* use for unspecified sound model type */
-    SOUND_MODEL_TYPE_KEYPHRASE = 0    /* use for key phrase sound models */
+    SOUND_MODEL_TYPE_KEYPHRASE = 0,    /* use for key phrase sound models */
+    SOUND_MODEL_TYPE_GENERIC = 1      /* use for all models other than keyphrase */
 } sound_trigger_sound_model_type_t;
 
 typedef struct sound_trigger_uuid_s {
@@ -92,7 +95,7 @@ struct sound_trigger_module_descriptor {
 typedef int sound_model_handle_t;
 
 /*
- * Generic sound model descriptor. This struct is the header of a larger block passed to
+ * Base sound model descriptor. This struct is the header of a larger block passed to
  * load_sound_model() and containing the binary data of the sound model.
  * Proprietary representation of users in binary data must match information indicated
  * by users field
@@ -131,6 +134,14 @@ struct sound_trigger_phrase_sound_model {
 
 
 /*
+ * Generic sound model, used for all cases except key phrase detection.
+ */
+struct sound_trigger_generic_sound_model {
+    struct sound_trigger_sound_model common;
+};
+
+
+/*
  * Generic recognition event sent via recognition callback
  */
 struct sound_trigger_recognition_event {
@@ -190,6 +201,10 @@ struct sound_trigger_phrase_recognition_event {
     struct sound_trigger_phrase_recognition_extra phrase_extras[SOUND_TRIGGER_MAX_PHRASES];
 };
 
+struct sound_trigger_generic_recognition_event {
+    struct sound_trigger_recognition_event common;
+};
+
 /*
  * configuration for sound trigger capture session passed to start_recognition()
  */
index d462c08..79f08a6 100755 (executable)
@@ -51,6 +51,7 @@
 #define CAMCORDER_SRC_TAG "camcorder"               // AUDIO_SOURCE_CAMCORDER
 #define VOICE_REC_SRC_TAG "voice_recognition"       // AUDIO_SOURCE_VOICE_RECOGNITION
 #define VOICE_COMM_SRC_TAG "voice_communication"    // AUDIO_SOURCE_VOICE_COMMUNICATION
+#define UNPROCESSED_SRC_TAG "unprocessed"           // AUDIO_SOURCE_UNPROCESSED
 
 // audio_stream_type_t
 #define AUDIO_STREAM_DEFAULT_TAG "default"
index a1f1602..8cda094 100644 (file)
@@ -32,7 +32,8 @@ const effect_uuid_t * const FX_IID_NS = &FX_IID_NS_;
 typedef enum
 {
     NS_PARAM_LEVEL,             // noise suppression level (t_ns_level)
-    NS_PARAM_PROPERTIES
+    NS_PARAM_PROPERTIES,
+    NS_PARAM_TYPE               // noise suppression type (t_ns_type)
 } t_ns_params;
 
 // noise suppression level
@@ -42,9 +43,16 @@ typedef enum {
     NS_LEVEL_HIGH
 } t_ns_level;
 
+// noise suppression type
+typedef enum {
+    NS_TYPE_SINGLE_CHANNEL,
+    NS_TYPE_MULTI_CHANNEL
+} t_ns_type;
+
 // s_ns_settings groups all current ns settings for backup and restore.
 typedef struct s_ns_settings {
     uint32_t  level;
+    uint32_t  type;
 } t_ns_settings;
 
 #if __cplusplus
index 2fcdc94..c32b88d 100644 (file)
@@ -8,4 +8,5 @@ LOCAL_SRC_FILES:= audio_route.c
 LOCAL_MODULE := libaudioroute
 LOCAL_SHARED_LIBRARIES:= liblog libcutils libutils libexpat libtinyalsa
 LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Werror -Wall
 include $(BUILD_SHARED_LIBRARY)
index 029951c..90b114d 100644 (file)
 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
 #define INITIAL_MIXER_PATH_SIZE 8
 
+union ctl_values {
+    int *enumerated;
+    long *integer;
+    void *ptr;
+    unsigned char *bytes;
+};
+
 struct mixer_state {
     struct mixer_ctl *ctl;
     unsigned int num_values;
-    int *old_value;
-    int *new_value;
-    int *reset_value;
+    union ctl_values old_value;
+    union ctl_values new_value;
+    union ctl_values reset_value;
 };
 
 struct mixer_setting {
     unsigned int ctl_index;
     unsigned int num_values;
-    int *value;
+    unsigned int type;
+    union ctl_values value;
 };
 
 struct mixer_value {
     unsigned int ctl_index;
     int index;
-    int value;
+    long value;
 };
 
 struct mixer_path {
@@ -83,18 +91,39 @@ static bool is_supported_ctl_type(enum mixer_ctl_type type)
     case MIXER_CTL_TYPE_BOOL:
     case MIXER_CTL_TYPE_INT:
     case MIXER_CTL_TYPE_ENUM:
+    case MIXER_CTL_TYPE_BYTE:
         return true;
     default:
         return false;
     }
 }
 
+/* as they match in alsa */
+static size_t sizeof_ctl_type(enum mixer_ctl_type type) {
+    switch (type) {
+    case MIXER_CTL_TYPE_BOOL:
+    case MIXER_CTL_TYPE_INT:
+        return sizeof(long);
+    case MIXER_CTL_TYPE_ENUM:
+        return sizeof(int);
+    case MIXER_CTL_TYPE_BYTE:
+        return sizeof(unsigned char);
+    case MIXER_CTL_TYPE_INT64:
+    case MIXER_CTL_TYPE_IEC958:
+    case MIXER_CTL_TYPE_UNKNOWN:
+    default:
+        LOG_ALWAYS_FATAL("Unsupported mixer ctl type: %d, check type before calling", (int)type);
+        return 0;
+    }
+}
+
 static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar,
                                              unsigned int ctl_index)
 {
     return ar->mixer_state[ctl_index].ctl;
 }
 
+#if 0
 static void path_print(struct audio_route *ar, struct mixer_path *path)
 {
     unsigned int i;
@@ -105,10 +134,19 @@ static void path_print(struct audio_route *ar, struct mixer_path *path)
         struct mixer_ctl *ctl = index_to_ctl(ar, path->setting[i].ctl_index);
 
         ALOGE("  id=%d: ctl=%s", i, mixer_ctl_get_name(ctl));
-        for (j = 0; j < path->setting[i].num_values; j++)
-            ALOGE("    id=%d value=%d", j, path->setting[i].value[j]);
+        if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) {
+            for (j = 0; j < path->setting[i].num_values; j++)
+                ALOGE("    id=%d value=0x%02x", j, path->setting[i].value.bytes[j]);
+        } else if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_ENUM) {
+            for (j = 0; j < path->setting[i].num_values; j++)
+                ALOGE("    id=%d value=%d", j, path->setting[i].value.enumerated[j]);
+        } else {
+            for (j = 0; j < path->setting[i].num_values; j++)
+                ALOGE("    id=%d value=%ld", j, path->setting[i].value.integer[j]);
+        }
     }
 }
+#endif
 
 static void path_free(struct audio_route *ar)
 {
@@ -118,12 +156,14 @@ static void path_free(struct audio_route *ar)
         if (ar->mixer_path[i].name)
             free(ar->mixer_path[i].name);
         if (ar->mixer_path[i].setting) {
-            if (ar->mixer_path[i].setting->value)
-                free(ar->mixer_path[i].setting->value);
+            if (ar->mixer_path[i].setting->value.ptr)
+                free(ar->mixer_path[i].setting->value.ptr);
             free(ar->mixer_path[i].setting);
         }
     }
     free(ar->mixer_path);
+    ar->mixer_path = NULL;
+    ar->mixer_path_size = 0;
 }
 
 static struct mixer_path *path_get_by_name(struct audio_route *ar,
@@ -227,16 +267,25 @@ static int path_add_setting(struct audio_route *ar, struct mixer_path *path,
         return -1;
     }
 
+    if (!is_supported_ctl_type(setting->type)) {
+        ALOGE("unsupported type %d", (int)setting->type);
+        return -1;
+    }
+
     path_index = alloc_path_setting(path);
     if (path_index < 0)
         return -1;
 
     path->setting[path_index].ctl_index = setting->ctl_index;
+    path->setting[path_index].type = setting->type;
     path->setting[path_index].num_values = setting->num_values;
-    path->setting[path_index].value = malloc(setting->num_values * sizeof(int));
+
+    size_t value_sz = sizeof_ctl_type(setting->type);
+
+    path->setting[path_index].value.ptr = calloc(setting->num_values, value_sz);
     /* copy all values */
-    memcpy(path->setting[path_index].value, setting->value,
-           setting->num_values * sizeof(int));
+    memcpy(path->setting[path_index].value.ptr, setting->value.ptr,
+           setting->num_values * value_sz);
 
     return 0;
 }
@@ -262,6 +311,11 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path,
     if (path_index < 0) {
         /* New path */
 
+        enum mixer_ctl_type type = mixer_ctl_get_type(ctl);
+        if (!is_supported_ctl_type(type)) {
+            ALOGE("unsupported type %d", (int)type);
+            return -1;
+        }
         path_index = alloc_path_setting(path);
         if (path_index < 0)
             return -1;
@@ -269,17 +323,38 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path,
         /* initialise the new path setting */
         path->setting[path_index].ctl_index = mixer_value->ctl_index;
         path->setting[path_index].num_values = num_values;
-        path->setting[path_index].value = malloc(num_values * sizeof(int));
-        path->setting[path_index].value[0] = mixer_value->value;
+        path->setting[path_index].type = type;
+
+        size_t value_sz = sizeof_ctl_type(type);
+        path->setting[path_index].value.ptr = calloc(num_values, value_sz);
+        if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
+            path->setting[path_index].value.bytes[0] = mixer_value->value;
+        else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
+            path->setting[path_index].value.enumerated[0] = mixer_value->value;
+        else
+            path->setting[path_index].value.integer[0] = mixer_value->value;
     }
 
     if (mixer_value->index == -1) {
         /* set all values the same */
-        for (i = 0; i < num_values; i++)
-            path->setting[path_index].value[i] = mixer_value->value;
+        if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) {
+            for (i = 0; i < num_values; i++)
+                path->setting[path_index].value.bytes[i] = mixer_value->value;
+        } else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) {
+            for (i = 0; i < num_values; i++)
+                path->setting[path_index].value.enumerated[i] = mixer_value->value;
+        } else {
+            for (i = 0; i < num_values; i++)
+                path->setting[path_index].value.integer[i] = mixer_value->value;
+        }
     } else {
         /* set only one value */
-        path->setting[path_index].value[mixer_value->index] = mixer_value->value;
+        if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
+            path->setting[path_index].value.bytes[mixer_value->index] = mixer_value->value;
+        else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
+            path->setting[path_index].value.enumerated[mixer_value->index] = mixer_value->value;
+        else
+            path->setting[path_index].value.integer[mixer_value->index] = mixer_value->value;
     }
 
     return 0;
@@ -310,10 +385,9 @@ static int path_apply(struct audio_route *ar, struct mixer_path *path)
         type = mixer_ctl_get_type(ctl);
         if (!is_supported_ctl_type(type))
             continue;
-
-        /* apply the new value(s) */
-        memcpy(ar->mixer_state[ctl_index].new_value, path->setting[i].value,
-               path->setting[i].num_values * sizeof(int));
+        size_t value_sz = sizeof_ctl_type(type);
+        memcpy(ar->mixer_state[ctl_index].new_value.ptr, path->setting[i].value.ptr,
+                   path->setting[i].num_values * value_sz);
     }
 
     return 0;
@@ -322,7 +396,6 @@ static int path_apply(struct audio_route *ar, struct mixer_path *path)
 static int path_reset(struct audio_route *ar, struct mixer_path *path)
 {
     unsigned int i;
-    unsigned int j;
     unsigned int ctl_index;
     struct mixer_ctl *ctl;
     enum mixer_ctl_type type;
@@ -333,11 +406,11 @@ static int path_reset(struct audio_route *ar, struct mixer_path *path)
         type = mixer_ctl_get_type(ctl);
         if (!is_supported_ctl_type(type))
             continue;
-
+        size_t value_sz = sizeof_ctl_type(type);
         /* reset the value(s) */
-        memcpy(ar->mixer_state[ctl_index].new_value,
-               ar->mixer_state[ctl_index].reset_value,
-               ar->mixer_state[ctl_index].num_values * sizeof(int));
+        memcpy(ar->mixer_state[ctl_index].new_value.ptr,
+               ar->mixer_state[ctl_index].reset_value.ptr,
+               ar->mixer_state[ctl_index].num_values * value_sz);
     }
 
     return 0;
@@ -368,7 +441,7 @@ static void start_tag(void *data, const XML_Char *tag_name,
     unsigned int i;
     unsigned int ctl_index;
     struct mixer_ctl *ctl;
-    int value;
+    long value;
     unsigned int id;
     struct mixer_value mixer_value;
     enum mixer_ctl_type type;
@@ -410,7 +483,10 @@ static void start_tag(void *data, const XML_Char *tag_name,
         switch (mixer_ctl_get_type(ctl)) {
         case MIXER_CTL_TYPE_BOOL:
         case MIXER_CTL_TYPE_INT:
-            value = (int) strtol((char *)attr_value, NULL, 0);
+            value = strtol((char *)attr_value, NULL, 0);
+            break;
+        case MIXER_CTL_TYPE_BYTE:
+            value = (unsigned char) strtol((char *)attr_value, NULL, 16);
             break;
         case MIXER_CTL_TYPE_ENUM:
             value = mixer_enum_string_to_value(ctl, (char *)attr_value);
@@ -436,14 +512,24 @@ static void start_tag(void *data, const XML_Char *tag_name,
                     /* set only one value */
                     id = atoi((char *)attr_id);
                     if (id < ar->mixer_state[ctl_index].num_values)
-                        ar->mixer_state[ctl_index].new_value[id] = value;
+                        if (type == MIXER_CTL_TYPE_BYTE)
+                            ar->mixer_state[ctl_index].new_value.bytes[id] = value;
+                        else if (type == MIXER_CTL_TYPE_ENUM)
+                            ar->mixer_state[ctl_index].new_value.enumerated[id] = value;
+                        else
+                            ar->mixer_state[ctl_index].new_value.integer[id] = value;
                     else
                         ALOGE("value id out of range for mixer ctl '%s'",
                               mixer_ctl_get_name(ctl));
                 } else {
                     /* set all values the same */
                     for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++)
-                        ar->mixer_state[ctl_index].new_value[i] = value;
+                        if (type == MIXER_CTL_TYPE_BYTE)
+                            ar->mixer_state[ctl_index].new_value.bytes[i] = value;
+                        else if (type == MIXER_CTL_TYPE_ENUM)
+                            ar->mixer_state[ctl_index].new_value.enumerated[i] = value;
+                        else
+                            ar->mixer_state[ctl_index].new_value.integer[i] = value;
                 }
             }
         } else {
@@ -473,13 +559,12 @@ static void end_tag(void *data, const XML_Char *tag_name)
 static int alloc_mixer_state(struct audio_route *ar)
 {
     unsigned int i;
-    unsigned int j;
     unsigned int num_values;
     struct mixer_ctl *ctl;
     enum mixer_ctl_type type;
 
     ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer);
-    ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state));
+    ar->mixer_state = calloc(ar->num_mixer_ctls, sizeof(struct mixer_state));
     if (!ar->mixer_state)
         return -1;
 
@@ -496,16 +581,18 @@ static int alloc_mixer_state(struct audio_route *ar)
         if (!is_supported_ctl_type(type))
             continue;
 
-        ar->mixer_state[i].old_value = malloc(num_values * sizeof(int));
-        ar->mixer_state[i].new_value = malloc(num_values * sizeof(int));
-        ar->mixer_state[i].reset_value = malloc(num_values * sizeof(int));
+        size_t value_sz = sizeof_ctl_type(type);
+        ar->mixer_state[i].old_value.ptr = calloc(num_values, value_sz);
+        ar->mixer_state[i].new_value.ptr = calloc(num_values, value_sz);
+        ar->mixer_state[i].reset_value.ptr = calloc(num_values, value_sz);
 
         if (type == MIXER_CTL_TYPE_ENUM)
-            ar->mixer_state[i].old_value[0] = mixer_ctl_get_value(ctl, 0);
+            ar->mixer_state[i].old_value.enumerated[0] = mixer_ctl_get_value(ctl, 0);
         else
-            mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value, num_values);
-        memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].old_value,
-               num_values * sizeof(int));
+            mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value.ptr, num_values);
+
+        memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].old_value.ptr,
+               num_values * value_sz);
     }
 
     return 0;
@@ -521,9 +608,9 @@ static void free_mixer_state(struct audio_route *ar)
         if (!is_supported_ctl_type(type))
             continue;
 
-        free(ar->mixer_state[i].old_value);
-        free(ar->mixer_state[i].new_value);
-        free(ar->mixer_state[i].reset_value);
+        free(ar->mixer_state[i].old_value.ptr);
+        free(ar->mixer_state[i].new_value.ptr);
+        free(ar->mixer_state[i].reset_value.ptr);
     }
 
     free(ar->mixer_state);
@@ -550,19 +637,38 @@ int audio_route_update_mixer(struct audio_route *ar)
 
         /* if the value has changed, update the mixer */
         bool changed = false;
-        for (j = 0; j < num_values; j++) {
-            if (ar->mixer_state[i].old_value[j] != ar->mixer_state[i].new_value[j]) {
-                changed = true;
-                break;
+        if (type == MIXER_CTL_TYPE_BYTE) {
+            for (j = 0; j < num_values; j++) {
+                if (ar->mixer_state[i].old_value.bytes[j] != ar->mixer_state[i].new_value.bytes[j]) {
+                    changed = true;
+                    break;
+                }
+            }
+         } else if (type == MIXER_CTL_TYPE_ENUM) {
+             for (j = 0; j < num_values; j++) {
+                 if (ar->mixer_state[i].old_value.enumerated[j]
+                         != ar->mixer_state[i].new_value.enumerated[j]) {
+                     changed = true;
+                     break;
+                 }
+             }
+         } else {
+            for (j = 0; j < num_values; j++) {
+                if (ar->mixer_state[i].old_value.integer[j] != ar->mixer_state[i].new_value.integer[j]) {
+                    changed = true;
+                    break;
+                }
             }
         }
         if (changed) {
             if (type == MIXER_CTL_TYPE_ENUM)
-                mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value[0]);
+                mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value.enumerated[0]);
             else
-                mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value, num_values);
-            memcpy(ar->mixer_state[i].old_value, ar->mixer_state[i].new_value,
-                   num_values * sizeof(int));
+                mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value.ptr, num_values);
+
+            size_t value_sz = sizeof_ctl_type(type);
+            memcpy(ar->mixer_state[i].old_value.ptr, ar->mixer_state[i].new_value.ptr,
+                   num_values * value_sz);
         }
     }
 
@@ -580,8 +686,9 @@ static void save_mixer_state(struct audio_route *ar)
         if (!is_supported_ctl_type(type))
             continue;
 
-        memcpy(ar->mixer_state[i].reset_value, ar->mixer_state[i].new_value,
-               ar->mixer_state[i].num_values * sizeof(int));
+        size_t value_sz = sizeof_ctl_type(type);
+        memcpy(ar->mixer_state[i].reset_value.ptr, ar->mixer_state[i].new_value.ptr,
+               ar->mixer_state[i].num_values * value_sz);
     }
 }
 
@@ -597,8 +704,9 @@ void audio_route_reset(struct audio_route *ar)
         if (!is_supported_ctl_type(type))
             continue;
 
-        memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].reset_value,
-               ar->mixer_state[i].num_values * sizeof(int));
+        size_t value_sz = sizeof_ctl_type(type);
+        memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].reset_value.ptr,
+            ar->mixer_state[i].num_values * value_sz);
     }
 }
 
@@ -681,14 +789,25 @@ static int audio_route_update_path(struct audio_route *ar, const char *name, boo
             continue;
         }
 
+       size_t value_sz = sizeof_ctl_type(type);
         /* if any value has changed, update the mixer */
         for (j = 0; j < ms->num_values; j++) {
-            if (ms->old_value[j] != ms->new_value[j]) {
-                if (type == MIXER_CTL_TYPE_ENUM)
-                    mixer_ctl_set_value(ms->ctl, 0, ms->new_value[0]);
-                else
-                    mixer_ctl_set_array(ms->ctl, ms->new_value, ms->num_values);
-                memcpy(ms->old_value, ms->new_value, ms->num_values * sizeof(int));
+            if (type == MIXER_CTL_TYPE_BYTE) {
+                if (ms->old_value.bytes[j] != ms->new_value.bytes[j]) {
+                    mixer_ctl_set_array(ms->ctl, ms->new_value.bytes, ms->num_values);
+                    memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values * value_sz);
+                    break;
+                }
+            } else if (type == MIXER_CTL_TYPE_ENUM) {
+                if (ms->old_value.enumerated[j] != ms->new_value.enumerated[j]) {
+                    mixer_ctl_set_value(ms->ctl, 0, ms->new_value.enumerated[0]);
+                    memcpy(ms->old_value.enumerated, ms->new_value.enumerated,
+                            ms->num_values * value_sz);
+                    break;
+                }
+            } else if (ms->old_value.integer[j] != ms->new_value.integer[j]) {
+                mixer_ctl_set_array(ms->ctl, ms->new_value.integer, ms->num_values);
+                memcpy(ms->old_value.integer, ms->new_value.integer, ms->num_values * value_sz);
                 break;
             }
         }
@@ -721,7 +840,6 @@ struct audio_route *audio_route_init(unsigned int card, const char *xml_path)
     FILE *file;
     int bytes_read;
     void *buf;
-    int i;
     struct audio_route *ar;
 
     ar = calloc(1, sizeof(struct audio_route));
@@ -793,6 +911,7 @@ struct audio_route *audio_route_init(unsigned int card, const char *xml_path)
     return ar;
 
 err_parse:
+    path_free(ar);
     XML_ParserFree(parser);
 err_parser_create:
     fclose(file);
@@ -811,5 +930,6 @@ void audio_route_free(struct audio_route *ar)
 {
     free_mixer_state(ar);
     mixer_close(ar->mixer);
+    path_free(ar);
     free(ar);
 }
index 03ba817..e3b63f5 100644 (file)
@@ -7,9 +7,11 @@ LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES:= \
        channels.c \
+       conversion.cpp \
        fifo.c \
        fixedfft.cpp.arm \
        format.c \
+       limiter.c \
        minifloat.c \
        primitives.c \
        resampler.c \
@@ -26,6 +28,7 @@ LOCAL_SHARED_LIBRARIES := \
        liblog \
        libspeexresampler
 
+LOCAL_CFLAGS := -Werror -Wall
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -35,12 +38,14 @@ LOCAL_SRC_FILES := \
        channels.c \
        fifo.c \
        format.c \
+       limiter.c \
        minifloat.c \
        primitives.c \
        roundup.c
 LOCAL_C_INCLUDES += \
        $(call include-path-for, audio-utils)
-LOCAL_CFLAGS := -D__unused=
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -D__unused='__attribute__((unused))'
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -54,7 +59,8 @@ LOCAL_SRC_FILES := \
 LOCAL_C_INCLUDES += \
        $(call include-path-for, audio-utils)
 
-LOCAL_CFLAGS := -UHAVE_STDERR
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -UHAVE_STDERR
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -71,6 +77,8 @@ LOCAL_C_INCLUDES += \
 
 #LOCAL_SHARED_LIBRARIES := libaudioutils
 
+LOCAL_CFLAGS := -Werror -Wall
+
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -86,6 +94,8 @@ LOCAL_SRC_FILES := \
 LOCAL_C_INCLUDES += \
        $(call include-path-for, audio-utils)
 
+LOCAL_CFLAGS := -Werror -Wall
+
 include $(BUILD_STATIC_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/audio_utils/Doxyfile b/audio_utils/Doxyfile
new file mode 100644 (file)
index 0000000..9826896
--- /dev/null
@@ -0,0 +1,2303 @@
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "My Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = include/audio_utils/ include/audio_utils/spdif/
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/audio_utils/Doxyfile.orig b/audio_utils/Doxyfile.orig
new file mode 100644 (file)
index 0000000..137facb
--- /dev/null
@@ -0,0 +1,2303 @@
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "My Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/audio_utils/conversion.cpp b/audio_utils/conversion.cpp
new file mode 100644 (file)
index 0000000..a2d931f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_conversion"
+
+#include <math.h>
+#include <audio_utils/conversion.h>
+#include <utils/Log.h>
+#include <audio_utils/limiter.h>
+
+// TODO: Speed up for special case of 2 channels?
+void mono_blend(void *buf, audio_format_t format, size_t channelCount, size_t frames, bool limit) {
+    if (channelCount < 2) {
+        return;
+    }
+    switch (format) {
+    case AUDIO_FORMAT_PCM_16_BIT: {
+        int16_t *out = (int16_t *)buf;
+        for (size_t i = 0; i < frames; ++i) {
+            const int16_t *in = out;
+            int accum = 0;
+            for (size_t j = 0; j < channelCount; ++j) {
+                accum += *in++;
+            }
+            accum /= channelCount; // round to 0
+            for (size_t j = 0; j < channelCount; ++j) {
+                *out++ = accum;
+            }
+        }
+    } break;
+    case AUDIO_FORMAT_PCM_FLOAT: {
+        float *out = (float *)buf;
+        const float recipdiv = 1. / channelCount;
+        for (size_t i = 0; i < frames; ++i) {
+            const float *in = out;
+            float accum = 0;
+            for (size_t j = 0; j < channelCount; ++j) {
+                accum += *in++;
+            }
+            if (limit && channelCount == 2) {
+                accum = limiter(accum * M_SQRT1_2);
+            } else {
+                accum *= recipdiv;
+            }
+            for (size_t j = 0; j < channelCount; ++j) {
+                *out++ = accum;
+            }
+        }
+    } break;
+    default:
+        ALOGE("mono_blend: invalid format %d", format);
+        break;
+    }
+}
index e2dc40c..178b306 100644 (file)
@@ -393,7 +393,7 @@ static int echo_reference_read(struct echo_reference_itfe *echo_reference,
 
             ALOGV("echo_reference_read(): EchoPathDelayDeviation between reference and DMA [%"
                     PRId64 "]", deltaNs);
-            if (abs(deltaNs) >= MIN_DELAY_DELTA_NS) {
+            if (llabs(deltaNs) >= MIN_DELAY_DELTA_NS) {
                 // smooth the variation and update the reference buffer only
                 // if a deviation in the same direction is observed for more than MIN_DELTA_NUM
                 // consecutive reads.
index a967681..573cab7 100644 (file)
 #ifndef ANDROID_AUDIO_CHANNELS_H
 #define ANDROID_AUDIO_CHANNELS_H
 
+/** \cond */
 __BEGIN_DECLS
+/** \endcond */
 
-/*
+/**
  * Expands or contracts sample data from one interleaved channel format to another.
  * Expanded channels are filled with zeros and put at the end of each audio frame.
  * Contracted channels are omitted from the end of each audio frame.
- *   in_buff points to the buffer of samples
- *   in_buff_channels Specifies the number of channels in the input buffer.
- *   out_buff points to the buffer to receive converted samples.
- *   out_buff_channels Specifies the number of channels in the output buffer.
- *   sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
+ *
+ *   \param in_buff              points to the buffer of samples
+ *   \param in_buff_chans        Specifies the number of channels in the input buffer.
+ *   \param out_buff             points to the buffer to receive converted samples.
+ *   \param out_buff_chans       Specifies the number of channels in the output buffer.
+ *   \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
  *     currently valid.
- *   num_in_bytes size of input buffer in BYTES
- * returns
+ *   \param num_in_bytes         size of input buffer in BYTES
+ *
+ * \return
  *   the number of BYTES of output data or 0 if an error occurs.
- * NOTE
+ *
+ * \note
  *   The out and sums buffers must either be completely separate (non-overlapping), or
  *   they must both start at the same address. Partially overlapping buffers are not supported.
  */
 size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
                        void* out_buff, size_t out_buff_chans,
                        unsigned sample_size_in_bytes, size_t num_in_bytes);
+
+/** \cond */
 __END_DECLS
+/** \endcond */
 
 #endif
diff --git a/audio_utils/include/audio_utils/conversion.h b/audio_utils/include/audio_utils/conversion.h
new file mode 100644 (file)
index 0000000..12e03e0
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_AUDIO_CONVERSION_H
+#define ANDROID_AUDIO_CONVERSION_H
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <system/audio.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+// for in-place conversion routines
+
+/**
+ * In-place mono blend using the arithmetic average of the channels in each audio frame.
+ *
+ *   \param buf          buffer of frames
+ *   \param format       one of AUDIO_FORMAT_PCM_16_BIT or AUDIO_FORMAT_PCM_FLOAT
+ *   \param channelCount number of channels per frame
+ *   \param frames       number of frames in buffer
+ *   \param limit        whether to use a limiter (experimental, currently only for stereo float)
+ *
+ * \return
+ *   none
+ *
+ */
+
+void mono_blend(void *buf, audio_format_t format, size_t channelCount, size_t frames,
+        bool limit = false);
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif
index 15edda4..dac0415 100644 (file)
@@ -22,7 +22,7 @@
 
 __BEGIN_DECLS
 
-/* Buffer descriptor used by read() and write() methods, including the time stamp and delay. */
+/** Buffer descriptor used by read() and write() methods, including the time stamp and delay. */
 struct echo_reference_buffer {
     void *raw;                  // pointer to audio frame
     size_t frame_count;         // number of frames in buffer
@@ -30,6 +30,7 @@ struct echo_reference_buffer {
     struct timespec time_stamp; // time stamp for this buffer (see comment below)
                                 // default ALSA gettimeofday() format
 };
+
 /**
  * + as input:
  *      - delay_ns is the delay introduced by playback buffers
index ba4c5c6..f882368 100644 (file)
@@ -43,40 +43,53 @@ struct audio_utils_fifo {
     volatile int32_t mRear;  // frame index of next frame slot available to write, or write index
 };
 
-// Initialize a FIFO object.
-// Input parameters:
-//  fifo        Pointer to the FIFO object.
-//  frameCount  Max number of significant frames to be stored in the FIFO > 0.
-//              If writes and reads always use the same count, and that count is a divisor of
-//              frameCount, then the writes and reads will never do a partial transfer.
-//  frameSize   Size of each frame in bytes.
-//  buffer      Pointer to a caller-allocated buffer of frameCount frames.
+/**
+ * Initialize a FIFO object.
+ *
+ *  \param fifo        Pointer to the FIFO object.
+ *  \param frameCount  Max number of significant frames to be stored in the FIFO > 0.
+ *                     If writes and reads always use the same count, and that count is a divisor of
+ *                     frameCount, then the writes and reads will never do a partial transfer.
+ *  \param frameSize   Size of each frame in bytes.
+ *  \param buffer      Pointer to a caller-allocated buffer of frameCount frames.
+ */
 void audio_utils_fifo_init(struct audio_utils_fifo *fifo, size_t frameCount, size_t frameSize,
         void *buffer);
 
-// De-initialize a FIFO object.
-// Input parameters:
-//  fifo        Pointer to the FIFO object.
+/**
+ * De-initialize a FIFO object.
+ *
+ *  \param fifo        Pointer to the FIFO object.
+ */
 void audio_utils_fifo_deinit(struct audio_utils_fifo *fifo);
 
-// Write to FIFO.
-// Input parameters:
-//  fifo        Pointer to the FIFO object.
-//  buffer      Pointer to source buffer containing 'count' frames of data.
-// Returns actual number of frames written <= count.
-// The actual transfer count may be zero if the FIFO is full,
-// or partial if the FIFO was almost full.
-// A negative return value indicates an error.  Currently there are no errors defined.
+/**
+ * Write to FIFO.
+ *
+ *  \param fifo        Pointer to the FIFO object.
+ *  \param buffer      Pointer to source buffer containing 'count' frames of data.
+ *  \param count       Desired number of frames to write.
+ *
+ * \return actual number of frames written <= count.
+ *
+ * The actual transfer count may be zero if the FIFO is full,
+ * or partial if the FIFO was almost full.
+ * A negative return value indicates an error.  Currently there are no errors defined.
+ */
 ssize_t audio_utils_fifo_write(struct audio_utils_fifo *fifo, const void *buffer, size_t count);
 
-// Read from FIFO.
-// Input parameters:
-//  fifo        Pointer to the FIFO object.
-//  buffer      Pointer to destination buffer to be filled with up to 'count' frames of data.
-// Returns actual number of frames read <= count.
-// The actual transfer count may be zero if the FIFO is empty,
-// or partial if the FIFO was almost empty.
-// A negative return value indicates an error.  Currently there are no errors defined.
+/** Read from FIFO.
+ *
+ *  \param fifo        Pointer to the FIFO object.
+ *  \param buffer      Pointer to destination buffer to be filled with up to 'count' frames of data.
+ *  \param count       Desired number of frames to read.
+ *
+ * \return actual number of frames read <= count.
+ *
+ * The actual transfer count may be zero if the FIFO is empty,
+ * or partial if the FIFO was almost empty.
+ * A negative return value indicates an error.  Currently there are no errors defined.
+ */
 ssize_t audio_utils_fifo_read(struct audio_utils_fifo *fifo, void *buffer, size_t count);
 
 #ifdef __cplusplus
index 5903619..85483be 100644 (file)
 #include <stdint.h>
 #include <sys/cdefs.h>
 
+/** \cond */
 __BEGIN_DECLS
+/** \endcond */
 
-/* See description in fixedfft.cpp */
+/** See description in fixedfft.cpp */
 extern void fixed_fft_real(int n, int32_t *v);
 
+/** \cond */
 __END_DECLS
+/** \endcond */
 
 #endif  // ANDROID_AUDIO_FIXEDFFT_H
index 7ac6539..dfcfecd 100644 (file)
 #include <sys/cdefs.h>
 #include <system/audio.h>
 
+/** \cond */
 __BEGIN_DECLS
+/** \endcond */
 
-/* Copy buffers with conversion between buffer sample formats.
+/**
+ * Copy buffers with conversion between buffer sample formats.
  *
- *  dst        Destination buffer
- *  dst_format Destination buffer format
- *  src        Source buffer
- *  src_format Source buffer format
- *  count      Number of samples to copy
+ *  \param dst        Destination buffer
+ *  \param dst_format Destination buffer format
+ *  \param src        Source buffer
+ *  \param src_format Source buffer format
+ *  \param count      Number of samples to copy
  *
  * Allowed format conversions are given by either case 1 or 2 below:
  *
@@ -37,10 +40,15 @@ __BEGIN_DECLS
  * AUDIO_FORMAT_PCM_FLOAT, and the other format type is one of:
  *
  * AUDIO_FORMAT_PCM_16_BIT
+ * <BR>
  * AUDIO_FORMAT_PCM_FLOAT
+ * <BR>
  * AUDIO_FORMAT_PCM_8_BIT
+ * <BR>
  * AUDIO_FORMAT_PCM_24_BIT_PACKED
+ * <BR>
  * AUDIO_FORMAT_PCM_32_BIT
+ * <BR>
  * AUDIO_FORMAT_PCM_8_24_BIT
  *
  * 2) Both dst_format and src_format are identical and of the list given
@@ -56,24 +64,28 @@ void memcpy_by_audio_format(void *dst, audio_format_t dst_format,
         const void *src, audio_format_t src_format, size_t count);
 
 
-/* This function creates an index array for converting audio data with different
+/**
+ * This function creates an index array for converting audio data with different
  * channel position and index masks, used by memcpy_by_index_array().
- * Returns the number of array elements required.
- * This may be greater than idxcount, so the return value should be checked
- * if idxary size is less than 32. Returns zero if the input masks are unrecognized.
  *
  * Note that idxary is a caller allocated array
  * of at least as many channels as present in the dst_mask.
  *
  * Parameters:
- *  idxary      Updated array of indices of channels in the src frame for the dst frame
- *  idxcount    Number of caller allocated elements in idxary
- *  dst_mask    Bit mask corresponding to destination channels present
- *  src_mask    Bit mask corresponding to source channels present
+ *  \param idxary            Updated array of indices of channels in the src frame for the dst frame
+ *  \param arysize           Number of caller allocated elements in idxary
+ *  \param dst_channel_mask  Bit mask corresponding to destination channels present
+ *  \param src_channel_mask  Bit mask corresponding to source channels present
+ *
+ * \return the number of array elements required.
+ * This may be greater than idxcount, so the return value should be checked
+ * if idxary size is less than 32. Returns zero if the input masks are unrecognized.
  */
 size_t memcpy_by_index_array_initialization_from_channel_mask(int8_t *idxary, size_t arysize,
         audio_channel_mask_t dst_channel_mask, audio_channel_mask_t src_channel_mask);
 
+/** \cond */
 __END_DECLS
+/** \endcond */
 
 #endif  // ANDROID_AUDIO_FORMAT_H
diff --git a/audio_utils/include/audio_utils/limiter.h b/audio_utils/include/audio_utils/limiter.h
new file mode 100644 (file)
index 0000000..eb57eba
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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 ANDROID_AUDIO_LIMITER_H
+#define ANDROID_AUDIO_LIMITER_H
+
+#include <sys/cdefs.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    /**
+     * This limiter function is the identity for [-sqrt(0.5), sqrt(0.5)]
+     * and then approximates atan or spline.
+     * \param in input in range [-sqrt(2), sqrt(2)]; out of range, inf, and NaN are not permitted
+     * \return the limited output in range no larger than [-1.0, 1.0].
+     * The implementation is permitted to limit the output to a slightly smaller range,
+     * so the minimum and maximum outputs may not be achievable.
+     */
+    extern float limiter(float in);
+#ifdef __cplusplus
+}
+#endif
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif /* !ANDROID_AUDIO_LIMITER_H */
index 1b664fc..a2934e0 100644 (file)
 #include <stdint.h>
 #include <sys/cdefs.h>
 
+/** \cond */
 __BEGIN_DECLS
+/** \endcond */
 
-/* A single gain expressed as minifloat */
+/** A single gain expressed as minifloat */
 typedef uint16_t gain_minifloat_t;
 
-/* A pair of gain_minifloat_t packed into a single word */
+/** A pair of gain_minifloat_t packed into a single word */
 typedef uint32_t gain_minifloat_packed_t;
 
-/* The nominal range of a gain, expressed as a float */
+/** The nominal range of a gain, expressed as a float */
 #define GAIN_FLOAT_ZERO         0.0f
 #define GAIN_FLOAT_UNITY        1.0f
 
-/* Unity gain expressed as a minifloat */
+/** Unity gain expressed as a minifloat */
 #define GAIN_MINIFLOAT_UNITY    0xE000
 
-/* Pack a pair of gain_mini_float_t into a combined gain_minifloat_packed_t */
+/** Pack a pair of gain_mini_float_t into a combined gain_minifloat_packed_t */
 static inline gain_minifloat_packed_t gain_minifloat_pack(gain_minifloat_t left,
         gain_minifloat_t right)
 {
     return (right << 16) | left;
 }
 
-/* Unpack a gain_minifloat_packed_t into the two gain_minifloat_t components */
+/** Unpack a gain_minifloat_packed_t into the two gain_minifloat_t components */
 static inline gain_minifloat_t gain_minifloat_unpack_left(gain_minifloat_packed_t packed)
 {
     return packed & 0xFFFF;
@@ -53,10 +55,11 @@ static inline gain_minifloat_t gain_minifloat_unpack_right(gain_minifloat_packed
     return packed >> 16;
 }
 
-/* A pair of unity gains expressed as a gain_minifloat_packed_t */
+/** A pair of unity gains expressed as a gain_minifloat_packed_t */
 #define GAIN_MINIFLOAT_PACKED_UNITY gain_minifloat_pack(GAIN_MINIFLOAT_UNITY, GAIN_MINIFLOAT_UNITY)
 
-/* Convert a float to the internal representation used for gains.
+/**
+ * Convert a float to the internal representation used for gains.
  * The nominal range [0.0, 1.0], but the hard range is [0.0, 2.0).
  * Negative and underflow values are converted to 0.0,
  * and values larger than the hard maximum are truncated to the hard maximum.
@@ -73,9 +76,11 @@ static inline gain_minifloat_t gain_minifloat_unpack_right(gain_minifloat_packed
  */
 gain_minifloat_t gain_from_float(float f);
 
-/* Convert the internal representation used for gains to float */
+/** Convert the internal representation used for gains to float */
 float float_from_gain(gain_minifloat_t gain);
 
+/** \cond */
 __END_DECLS
+/** \endcond */
 
 #endif  // ANDROID_AUDIO_MINIFLOAT_H
index 5fde7d4..e0f952e 100644 (file)
 #include <stdlib.h>
 #include <sys/cdefs.h>
 
+/** \cond */
 __BEGIN_DECLS
+/** \endcond */
 
-/* The memcpy_* conversion routines are designed to work in-place on same dst as src
+/**
+ * \file primitives.h
+ * The memcpy_* conversion routines are designed to work in-place on same dst as src
  * buffers only if the types shrink on copy, with the exception of memcpy_to_i16_from_u8().
  * This allows the loops to go upwards for faster cache access (and may be more flexible
  * for future optimization later).
@@ -47,389 +51,458 @@ __BEGIN_DECLS
  */
 void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c);
 
-/* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+/**
+ * Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count);
 
-/* Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+/**
+ * Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  * The conversion is done by truncation, without dithering, so it loses resolution.
  */
 void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count);
 
-/* Copy samples from float to unsigned 8-bit offset by 0x80.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+/**
+ * Copy samples from float to unsigned 8-bit offset by 0x80.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  * The conversion is done by truncation, without dithering, so it loses resolution.
  */
 void memcpy_to_u8_from_float(uint8_t *dst, const float *src, size_t count);
 
-/* Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+/**
+ * Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  * The conversion is done by truncation, without dithering, so it loses resolution.
  */
 void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count);
 
-/* Shrink and copy samples from single-precision floating-point to signed 16-bit.
+/**
+ * Shrink and copy samples from single-precision floating-point to signed 16-bit.
  * Each float should be in the range -1.0 to 1.0.  Values outside that range are clamped,
  * refer to clamp16_from_float().
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  * The conversion is done by truncation, without dithering, so it loses resolution.
  */
 void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count);
 
-/* Copy samples from signed fixed-point 32-bit Q4.27 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 32-bit Q4.27 to single-precision floating-point.
  * The nominal output float range is [-1.0, 1.0] if the fixed-point range is
  * [0xf8000000, 0x07ffffff].  The full float range is [-16.0, 16.0].  Note the closed range
  * at 1.0 and 16.0 is due to rounding on conversion to float. See float_from_q4_27() for details.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count);
 
-/* Copy samples from signed fixed-point 16 bit Q0.15 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 16 bit Q0.15 to single-precision floating-point.
  * The output float range is [-1.0, 1.0) for the fixed-point range [0x8000, 0x7fff].
  * No rounding is needed as the representation is exact.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count);
 
-/* Copy samples from unsigned fixed-point 8 bit to single-precision floating-point.
+/**
+ * Copy samples from unsigned fixed-point 8 bit to single-precision floating-point.
  * The output float range is [-1.0, 1.0) for the fixed-point range [0x00, 0xFF].
  * No rounding is needed as the representation is exact.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_float_from_u8(float *dst, const uint8_t *src, size_t count);
 
-/* Copy samples from signed fixed-point packed 24 bit Q0.23 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to single-precision floating-point.
  * The packed 24 bit input is stored in native endian format in a uint8_t byte array.
  * The output float range is [-1.0, 1.0) for the fixed-point range [0x800000, 0x7fffff].
  * No rounding is needed as the representation is exact.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count);
 
-/* Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed point 16 bit Q0.15.
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed point 16 bit Q0.15.
  * The packed 24 bit output is stored in native endian format in a uint8_t byte array.
  * The data is truncated without rounding.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count);
 
-/* Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed-point 32-bit Q0.31.
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed-point 32-bit Q0.31.
  * The packed 24 bit input is stored in native endian format in a uint8_t byte array.
  * The output data range is [0x80000000, 0x7fffff00] at intervals of 0x100.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count);
 
-/* Copy samples from signed fixed point 16 bit Q0.15 to signed fixed-point packed 24 bit Q0.23.
+/**
+ * Copy samples from signed fixed point 16 bit Q0.15 to signed fixed-point packed 24 bit Q0.23.
  * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
  * The output data range is [0x800000, 0x7fff00] (not full).
  * Nevertheless there is no DC offset on the output, if the input has no DC offset.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count);
 
-/* Copy samples from single-precision floating-point to signed fixed-point packed 24 bit Q0.23.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point packed 24 bit Q0.23.
  * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
  * The data is clamped and rounded to nearest, ties away from zero. See clamp24_from_float()
  * for details.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count);
 
-/* Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed-point packed 24 bit Q0.23.
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed-point packed 24 bit Q0.23.
  * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
  * The data is clamped to the range is [0x800000, 0x7fffff].
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count);
 
-/* Shrink and copy samples from signed 32-bit fixed-point Q0.31
+/**
+ * Shrink and copy samples from signed 32-bit fixed-point Q0.31
  * to signed fixed-point packed 24 bit Q0.23.
  * The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  * The conversion is done by truncation, without dithering, so it loses resolution.
  */
 void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count);
 
-/* Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q8.23.
+/**
+ * Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q8.23.
  * The output data range is [0xff800000, 0x007fff00] at intervals of 0x100.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count);
 
-/* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q8.23.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q8.23.
  * This copy will clamp the Q8.23 representation to [0xff800000, 0x007fffff] even though there
  * are guard bits available. Fractional lsb is rounded to nearest, ties away from zero.
  * See clamp24_from_float() for details.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count);
 
-/* Copy samples from signed fixed point packed 24-bit Q0.23 to signed fixed-point 32-bit Q8.23.
+/**
+ * Copy samples from signed fixed point packed 24-bit Q0.23 to signed fixed-point 32-bit Q8.23.
  * The output data range is [0xff800000, 0x007fffff].
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count);
 
-/* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q4.27.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q4.27.
  * The conversion will use the full available Q4.27 range, including guard bits.
  * Fractional lsb is rounded to nearest, ties away from zero.
  * See clampq4_27_from_float() for details.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count);
 
-/* Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed point 16-bit Q0.15.
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed point 16-bit Q0.15.
  * The data is clamped, and truncated without rounding.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count);
 
-/* Copy samples from signed fixed-point 32-bit Q8.23 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to single-precision floating-point.
  * The nominal output float range is [-1.0, 1.0) for the fixed-point
  * range [0xff800000, 0x007fffff]. The maximum output float range is [-256.0, 256.0).
  * No rounding is needed as the representation is exact for nominal values.
  * Rounding for overflow values is to nearest, ties to even.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count);
 
-/* Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q0.31.
+/**
+ * Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q0.31.
  * The output data range is [0x80000000, 0x7fff0000] at intervals of 0x10000.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must be completely separate.
  */
 void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count);
 
-/* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q0.31.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q0.31.
  * If rounding is needed on truncation, the fractional lsb is rounded to nearest,
  * ties away from zero. See clamp32_from_float() for details.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count);
 
-/* Copy samples from signed fixed-point 32-bit Q0.31 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 32-bit Q0.31 to single-precision floating-point.
  * The float range is [-1.0, 1.0] for the fixed-point range [0x80000000, 0x7fffffff].
  * Rounding is done according to float_from_i32().
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of samples to copy
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of samples to copy
+ *
  * The destination and source buffers must either be completely separate (non-overlapping), or
  * they must both start at the same address.  Partially overlapping buffers are not supported.
  */
 void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count);
 
-/* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of stereo frames to downmix
+/**
+ * Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of stereo frames to downmix
+ *
  * The destination and source buffers must be completely separate (non-overlapping).
  * The current implementation truncates the mean rather than dither, but this may change.
  */
 void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count);
 
-/* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
+/**
+ * Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
  * duplicating.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of mono samples to upmix
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of mono samples to upmix
+ *
  * The destination and source buffers must be completely separate (non-overlapping).
  */
 void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count);
 
-/* Downmix pairs of interleaved stereo input float samples to mono output float samples
+/**
+ * Downmix pairs of interleaved stereo input float samples to mono output float samples
  * by averaging the stereo pair together.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of stereo frames to downmix
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of stereo frames to downmix
+ *
  * The destination and source buffers must be completely separate (non-overlapping),
  * or they must both start at the same address.
  */
 void downmix_to_mono_float_from_stereo_float(float *dst, const float *src, size_t count);
 
-/* Upmix mono input float samples to pairs of interleaved stereo output float samples by
+/**
+ * Upmix mono input float samples to pairs of interleaved stereo output float samples by
  * duplicating.
- * Parameters:
- *  dst     Destination buffer
- *  src     Source buffer
- *  count   Number of mono samples to upmix
+ *
+ *  \param dst     Destination buffer
+ *  \param src     Source buffer
+ *  \param count   Number of mono samples to upmix
+ *
  * The destination and source buffers must be completely separate (non-overlapping).
  */
 void upmix_to_stereo_float_from_mono_float(float *dst, const float *src, size_t count);
 
-/* Return the total number of non-zero 32-bit samples */
+/**
+ * \return the total number of non-zero 32-bit samples.
+ */
 size_t nonZeroMono32(const int32_t *samples, size_t count);
 
-/* Return the total number of non-zero 16-bit samples */
+/**
+ * \return the total number of non-zero 16-bit samples.
+ */
 size_t nonZeroMono16(const int16_t *samples, size_t count);
 
-/* Return the total number of non-zero stereo frames, where a frame is considered non-zero
- * if either of its constituent 32-bit samples is non-zero
+/**
+ * \return the total number of non-zero stereo frames, where a frame is considered non-zero
+ * if either of its constituent 32-bit samples is non-zero.
  */
 size_t nonZeroStereo32(const int32_t *frames, size_t count);
 
-/* Return the total number of non-zero stereo frames, where a frame is considered non-zero
- * if either of its constituent 16-bit samples is non-zero
+/**
+ * \return the total number of non-zero stereo frames, where a frame is considered non-zero
+ * if either of its constituent 16-bit samples is non-zero.
  */
 size_t nonZeroStereo16(const int16_t *frames, size_t count);
 
-/* Copy frames, selecting source samples based on a source channel mask to fit
+/**
+ * Copy frames, selecting source samples based on a source channel mask to fit
  * the destination channel mask. Unmatched channels in the destination channel mask
  * are zero filled. Unmatched channels in the source channel mask are dropped.
  * Channels present in the channel mask are represented by set bits in the
  * uint32_t value and are matched without further interpretation.
- * Parameters:
- *  dst         Destination buffer
- *  dst_mask    Bit mask corresponding to destination channels present
- *  src         Source buffer
- *  src_mask    Bit mask corresponding to source channels present
- *  sample_size Size of each sample in bytes.  Must be 1, 2, 3, or 4.
- *  count       Number of frames to copy
+ *
+ *  \param dst         Destination buffer
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src         Source buffer
+ *  \param src_mask    Bit mask corresponding to source channels present
+ *  \param sample_size Size of each sample in bytes.  Must be 1, 2, 3, or 4.
+ *  \param count       Number of frames to copy
+ *
  * The destination and source buffers must be completely separate (non-overlapping).
  * If the sample size is not in range, the function will abort.
  */
 void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
         const void *src, uint32_t src_mask, size_t sample_size, size_t count);
 
-/* Copy frames, selecting source samples based on an index array (idxary).
+/**
+ * Copy frames, selecting source samples based on an index array (idxary).
  * The idxary[] consists of dst_channels number of elements.
  * The ith element if idxary[] corresponds the ith destination channel.
  * A non-negative value is the channel index in the source frame.
  * A negative index (-1) represents filling with 0.
  *
  * Example: Swapping L and R channels for stereo streams
+ * <PRE>
  * idxary[0] = 1;
  * idxary[1] = 0;
+ * </PRE>
  *
  * Example: Copying a mono source to the front center 5.1 channel
+ * <PRE>
  * idxary[0] = -1;
  * idxary[1] = -1;
  * idxary[2] = 0;
  * idxary[3] = -1;
  * idxary[4] = -1;
  * idxary[5] = -1;
+ * </PRE>
  *
  * This copy allows swizzling of channels or replication of channels.
  *
- * Parameters:
- *  dst           Destination buffer
- *  dst_channels  Number of destination channels per frame
- *  src           Source buffer
- *  src_channels  Number of source channels per frame
- *  idxary        Array of indices representing channels in the source frame
- *  sample_size   Size of each sample in bytes.  Must be 1, 2, 3, or 4.
- *  count         Number of frames to copy
+ *  \param dst           Destination buffer
+ *  \param dst_channels  Number of destination channels per frame
+ *  \param src           Source buffer
+ *  \param src_channels  Number of source channels per frame
+ *  \param idxary        Array of indices representing channels in the source frame
+ *  \param sample_size   Size of each sample in bytes.  Must be 1, 2, 3, or 4.
+ *  \param count         Number of frames to copy
+ *
  * The destination and source buffers must be completely separate (non-overlapping).
  * If the sample size is not in range, the function will abort.
  */
@@ -437,10 +510,15 @@ void memcpy_by_index_array(void *dst, uint32_t dst_channels,
         const void *src, uint32_t src_channels,
         const int8_t *idxary, size_t sample_size, size_t count);
 
-/* Prepares an index array (idxary) from channel masks, which can be later
- * used by memcpy_by_index_array(). Returns the number of array elements required.
+/**
+ * Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
  * This may be greater than idxcount, so the return value should be checked
- * if idxary size is less than 32. Note that idxary is a caller allocated array
+ * if idxary size is less than 32.
+ *
+ * Note that idxary is a caller allocated array
  * of at least as many channels as present in the dst_mask.
  * Channels present in the channel mask are represented by set bits in the
  * uint32_t value and are matched without further interpretation.
@@ -448,17 +526,19 @@ void memcpy_by_index_array(void *dst, uint32_t dst_channels,
  * This function is typically used for converting audio data with different
  * channel position masks.
  *
- * Parameters:
- *  idxary      Updated array of indices of channels in the src frame for the dst frame
- *  idxcount    Number of caller allocated elements in idxary
- *  dst_mask    Bit mask corresponding to destination channels present
- *  src_mask    Bit mask corresponding to source channels present
+ *  \param idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  \param idxcount    Number of caller allocated elements in idxary
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src_mask    Bit mask corresponding to source channels present
  */
 size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
         uint32_t dst_mask, uint32_t src_mask);
 
-/* Prepares an index array (idxary) from channel masks, which can be later
- * used by memcpy_by_index_array(). Returns the number of array elements required.
+/**
+ * Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
  *
  * For a source channel index mask, the source channels will map to the destination
  * channels as if counting the set bits in dst_mask in order from lsb to msb
@@ -466,17 +546,19 @@ size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
  * ith SET bit of dst_mask and the ith destination channel.  Hence, a zero ith
  * bit of the src_mask indicates that the ith destination channel plays silence.
  *
- * Parameters:
- *  idxary      Updated array of indices of channels in the src frame for the dst frame
- *  idxcount    Number of caller allocated elements in idxary
- *  dst_mask    Bit mask corresponding to destination channels present
- *  src_mask    Bit mask corresponding to source channels present
+ *  \param idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  \param idxcount    Number of caller allocated elements in idxary
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src_mask    Bit mask corresponding to source channels present
  */
 size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
         uint32_t dst_mask, uint32_t src_mask);
 
-/* Prepares an index array (idxary) from channel mask bits, which can be later
- * used by memcpy_by_index_array(). Returns the number of array elements required.
+/**
+ * Prepares an index array (idxary) from channel mask bits, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
  *
  * This initialization is for a destination channel index mask from a positional
  * source mask.
@@ -487,11 +569,10 @@ size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idx
  * of set destination bits (unlikely), the corresponding source channel will
  * be dropped.
  *
- * Parameters:
- *  idxary      Updated array of indices of channels in the src frame for the dst frame
- *  idxcount    Number of caller allocated elements in idxary
- *  dst_mask    Bit mask corresponding to destination channels present
- *  src_mask    Bit mask corresponding to source channels present
+ *  \param idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  \param idxcount    Number of caller allocated elements in idxary
+ *  \param dst_mask    Bit mask corresponding to destination channels present
+ *  \param src_mask    Bit mask corresponding to source channels present
  */
 size_t memcpy_by_index_array_initialization_dst_index(int8_t *idxary, size_t idxcount,
         uint32_t dst_mask, uint32_t src_mask);
@@ -506,7 +587,7 @@ static inline int16_t clamp16(int32_t sample)
     return sample;
 }
 
-/*
+/**
  * Convert a IEEE 754 single precision float [-1.0, 1.0) to int16_t [-32768, 32767]
  * with clamping.  Note the open bound at 1.0, values within 1/65536 of 1.0 map
  * to 32767 instead of 32768 (early clamping due to the smaller positive integer subrange).
@@ -545,7 +626,7 @@ static inline int16_t clamp16_from_float(float f)
     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
 }
 
-/*
+/**
  * Convert a IEEE 754 single precision float [-1.0, 1.0) to uint8_t [0, 0xff]
  * with clamping.  Note the open bound at 1.0, values within 1/128 of 1.0 map
  * to 255 instead of 256 (early clamping due to the smaller positive integer subrange).
@@ -584,7 +665,8 @@ static inline uint8_t clamp8_from_float(float f)
     return u.i; /* Return lower 8 bits, the part of interest in the significand. */
 }
 
-/* Convert a single-precision floating point value to a Q0.23 integer value, stored in a
+/**
+ * Convert a single-precision floating point value to a Q0.23 integer value, stored in a
  * 32 bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
  *
  * Rounds to nearest, ties away from 0.
@@ -611,7 +693,8 @@ static inline int32_t clamp24_from_float(float f)
     return f > 0 ? f + 0.5 : f - 0.5;
 }
 
-/* Convert a signed fixed-point 32-bit Q8.23 value to a Q0.23 integer value,
+/**
+ * Convert a signed fixed-point 32-bit Q8.23 value to a Q0.23 integer value,
  * stored in a 32-bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
  *
  * Values outside the range [-0x800000, 0x7fffff] are clamped to that range.
@@ -629,7 +712,8 @@ static inline int32_t clamp24_from_q8_23(int32_t ival)
     }
 }
 
-/* Convert a single-precision floating point value to a Q4.27 integer value.
+/**
+ * Convert a single-precision floating point value to a Q4.27 integer value.
  * Rounds to nearest, ties away from 0.
  *
  * Values outside the range [-16.0, 16.0) are properly clamped to -2147483648 and 2147483647,
@@ -654,7 +738,8 @@ static inline int32_t clampq4_27_from_float(float f)
     return f > 0 ? f + 0.5 : f - 0.5;
 }
 
-/* Convert a single-precision floating point value to a Q0.31 integer value.
+/**
+ * Convert a single-precision floating point value to a Q0.31 integer value.
  * Rounds to nearest, ties away from 0.
  *
  * Values outside the range [-1.0, 1.0) are properly clamped to -2147483648 and 2147483647,
@@ -679,7 +764,8 @@ static inline int32_t clamp32_from_float(float f)
     return f > 0 ? f + 0.5 : f - 0.5;
 }
 
-/* Convert a signed fixed-point 32-bit Q4.27 value to single-precision floating-point.
+/**
+ * Convert a signed fixed-point 32-bit Q4.27 value to single-precision floating-point.
  * The nominal output float range is [-1.0, 1.0] if the fixed-point range is
  * [0xf8000000, 0x07ffffff].  The full float range is [-16.0, 16.0].
  *
@@ -702,7 +788,8 @@ static inline float float_from_q4_27(int32_t ival)
     return ival * scale;
 }
 
-/* Convert an unsigned fixed-point 32-bit U4.28 value to single-precision floating-point.
+/**
+ * Convert an unsigned fixed-point 32-bit U4.28 value to single-precision floating-point.
  * The nominal output float range is [0.0, 1.0] if the fixed-point range is
  * [0x00000000, 0x10000000].  The full float range is [0.0, 16.0].
  *
@@ -718,7 +805,8 @@ static inline float float_from_u4_28(uint32_t uval)
     return uval * scale;
 }
 
-/* Convert an unsigned fixed-point 16-bit U4.12 value to single-precision floating-point.
+/**
+ * Convert an unsigned fixed-point 16-bit U4.12 value to single-precision floating-point.
  * The nominal output float range is [0.0, 1.0] if the fixed-point range is
  * [0x0000, 0x1000].  The full float range is [0.0, 16.0).
  */
@@ -729,7 +817,8 @@ static inline float float_from_u4_12(uint16_t uval)
     return uval * scale;
 }
 
-/* Convert a single-precision floating point value to a U4.28 integer value.
+/**
+ * Convert a single-precision floating point value to a U4.28 integer value.
  * Rounds to nearest, ties away from 0.
  *
  * Values outside the range [0, 16.0] are properly clamped to [0, 4294967295]
@@ -752,7 +841,8 @@ static inline uint32_t u4_28_from_float(float f)
     return f * scale + 0.5;
 }
 
-/* Convert a single-precision floating point value to a U4.12 integer value.
+/**
+ * Convert a single-precision floating point value to a U4.12 integer value.
  * Rounds to nearest, ties away from 0.
  *
  * Values outside the range [0, 16.0) are properly clamped to [0, 65535]
@@ -775,7 +865,8 @@ static inline uint16_t u4_12_from_float(float f)
     return f * scale + 0.5;
 }
 
-/* Convert a signed fixed-point 16-bit Q0.15 value to single-precision floating-point.
+/**
+ * Convert a signed fixed-point 16-bit Q0.15 value to single-precision floating-point.
  * The output float range is [-1.0, 1.0) for the fixed-point range
  * [0x8000, 0x7fff].
  *
@@ -794,7 +885,8 @@ static inline float float_from_i16(int16_t ival)
     return ival * scale;
 }
 
-/* Convert an unsigned fixed-point 8-bit U0.8 value to single-precision floating-point.
+/**
+ * Convert an unsigned fixed-point 8-bit U0.8 value to single-precision floating-point.
  * The nominal output float range is [-1.0, 1.0) if the fixed-point range is
  * [0x00, 0xff].
  */
@@ -805,7 +897,8 @@ static inline float float_from_u8(uint8_t uval)
     return ((int)uval - 128) * scale;
 }
 
-/* Convert a packed 24bit Q0.23 value stored native-endian in a uint8_t ptr
+/**
+ * Convert a packed 24bit Q0.23 value stored native-endian in a uint8_t ptr
  * to a signed fixed-point 32 bit integer Q0.31 value. The output Q0.31 range
  * is [0x80000000, 0x7fffff00] for the fixed-point range [0x800000, 0x7fffff].
  * Even though the output range is limited on the positive side, there is no
@@ -820,7 +913,8 @@ static inline int32_t i32_from_p24(const uint8_t *packed24)
     return (packed24[0] << 8) | (packed24[1] << 16) | (packed24[2] << 24);
 }
 
-/* Convert a 32-bit Q0.31 value to single-precision floating-point.
+/**
+ * Convert a 32-bit Q0.31 value to single-precision floating-point.
  * The output float range is [-1.0, 1.0] for the fixed-point range
  * [0x80000000, 0x7fffffff].
  *
@@ -835,7 +929,8 @@ static inline float float_from_i32(int32_t ival)
     return ival * scale;
 }
 
-/* Convert a packed 24bit Q0.23 value stored native endian in a uint8_t ptr
+/**
+ * Convert a packed 24bit Q0.23 value stored native endian in a uint8_t ptr
  * to single-precision floating-point. The output float range is [-1.0, 1.0)
  * for the fixed-point range [0x800000, 0x7fffff].
  *
@@ -846,7 +941,8 @@ static inline float float_from_p24(const uint8_t *packed24)
     return float_from_i32(i32_from_p24(packed24));
 }
 
-/* Convert a 24-bit Q8.23 value to single-precision floating-point.
+/**
+ * Convert a 24-bit Q8.23 value to single-precision floating-point.
  * The nominal output float range is [-1.0, 1.0) for the fixed-point
  * range [0xff800000, 0x007fffff].  The maximum float range is [-256.0, 256.0).
  *
@@ -954,6 +1050,8 @@ int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
 #endif
 }
 
+/** \cond */
 __END_DECLS
+/** \endcond */
 
 #endif  // ANDROID_AUDIO_PRIMITIVES_H
index 0c7046f..559e020 100644 (file)
@@ -38,7 +38,7 @@ struct resampler_buffer {
     size_t frame_count;
 };
 
-/* call back interface used by the resampler to get new data */
+/** call back interface used by the resampler to get new data */
 struct resampler_buffer_provider
 {
     /**
@@ -58,7 +58,7 @@ struct resampler_buffer_provider
             struct resampler_buffer *buffer);
 };
 
-/* resampler interface */
+/** resampler interface */
 struct resampler_itfe {
     /**
      * reset resampler state
@@ -82,7 +82,7 @@ struct resampler_itfe {
                     int16_t *out,
                     size_t *outFrameCount);
     /**
-     * return the latency introduced by the resampler in ns.
+     * \return the latency introduced by the resampler in ns.
      */
     int32_t (*delay_ns)(struct resampler_itfe *resampler);
 };
index ad34289..5ee4607 100644 (file)
@@ -21,7 +21,7 @@
 extern "C" {
 #endif
 
-// Round up to the next highest power of 2
+/** Round up to the next highest power of 2 */
 unsigned roundup(unsigned v);
 
 #ifdef __cplusplus
index e24632b..958b414 100644 (file)
@@ -26,7 +26,9 @@
 #include <stdio.h>
 #include <sys/cdefs.h>
 
+/** \cond */
 __BEGIN_DECLS
+/** \endcond */
 
 // visible to clients
 typedef int sf_count_t;
@@ -55,22 +57,30 @@ typedef struct SNDFILE_ SNDFILE;
 #define SF_FORMAT_PCM_32    8
 #define SF_FORMAT_PCM_24    10
 
-// Open stream
+/** Open stream */
 SNDFILE *sf_open(const char *path, int mode, SF_INFO *info);
 
-// Close stream
+/** Close stream */
 void sf_close(SNDFILE *handle);
 
-// Read interleaved frames and return actual number of frames read
+/**
+ * Read interleaved frames
+ * \return actual number of frames read
+ */
 sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desired);
 sf_count_t sf_readf_float(SNDFILE *handle, float *ptr, sf_count_t desired);
 sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desired);
 
-// Write interleaved frames and return actual number of frames written
+/**
+ * Write interleaved frames
+ * \return actual number of frames written
+ */
 sf_count_t sf_writef_short(SNDFILE *handle, const short *ptr, sf_count_t desired);
 sf_count_t sf_writef_float(SNDFILE *handle, const float *ptr, sf_count_t desired);
 sf_count_t sf_writef_int(SNDFILE *handle, const int *ptr, sf_count_t desired);
 
+/** \cond */
 __END_DECLS
+/** \endcond */
 
 #endif /* __AUDIO_UTIL_SNDFILE_H */
diff --git a/audio_utils/limiter.c b/audio_utils/limiter.c
new file mode 100644 (file)
index 0000000..47d21b9
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <math.h>
+#include <audio_utils/limiter.h>
+
+#undef USE_ATAN_APPROXIMATION
+
+#ifdef USE_ATAN_APPROXIMATION
+static inline float atan_approximation(float in)
+{
+    static const float kPi_2 = 1.5625;  // pi/2 ~= 2.0 * atan_approximation(1.0)
+    if (in <= 1.0) {
+        return in / (1.0 + 0.28 * in * in);
+    } else {
+        const float in_inverse = 1.0 / in;
+        return kPi_2 - in_inverse / (1.0 + 0.28 * in_inverse * in_inverse);
+    }
+}
+#endif
+
+float limiter(float in)
+{
+    static const float crossover = M_SQRT1_2;
+    float in_abs = fabsf(in);
+    if (in_abs <= crossover) {
+        return in;
+    }
+    float out;
+#ifdef USE_ATAN_APPROXIMATION
+    // atan approximation
+    static const float factor = 4.3125;
+    static const float ratio = 1.0 / factor;
+    out = crossover + atan_approximation((in_abs - crossover)*factor)*ratio;
+    if (out > 1.0) {
+        out = 1.0;
+    }
+#else
+    // polynomial spline
+    static const float A = 0.3431457505;
+    static const float B = -1.798989873;
+    static const float C = 3.029437252;
+    static const float D = -0.6568542495;
+    // Cubic solution Ax^3 + Bx^2 + Cx + D
+    if (in_abs < M_SQRT2) {
+        // TODO Use Estrin's method P3
+        out = ((A*in_abs + B)*in_abs + C)*in_abs + D;
+    } else {
+        out = 1.0;
+    }
+#endif
+    if (in < 0) {
+        out = -out;
+    }
+    return out;
+}
index ffbedb5..ab47274 100644 (file)
@@ -181,6 +181,10 @@ bool AC3FrameScanner::parseHeader()
         return false;
     }
 
+    // bitstream mode, main, commentary, etc.
+    uint32_t bsmod = mHeaderBuffer[5] & 7;
+    mDataTypeInfo = bsmod; // as per IEC61937-3, table 3.
+
     // The names fscod, frmsiz are from the AC3 spec.
     uint32_t fscod = mHeaderBuffer[4] >> 6;
     if (mDataType == SPDIF_DATA_TYPE_E_AC3) {
@@ -195,7 +199,7 @@ bool AC3FrameScanner::parseHeader()
         if (fscod == 3) {
             uint32_t fscod2 = (mHeaderBuffer[4] >> 4) & 0x03;
             if (fscod2 >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
-                ALOGW("Invalid EAC3 fscod2 = %d\n", fscod2);
+                ALOGW("Invalid EAC3 fscod2 = %d", fscod2);
                 return false;
             } else {
                 mSampleRate = kEAC3ReducedSampleRateTable[fscod2];
@@ -224,10 +228,10 @@ bool AC3FrameScanner::parseHeader()
         uint32_t frmsizcod = mHeaderBuffer[4] & 0x3F; // frame size code
 
         if (fscod >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
-            ALOGW("Invalid AC3 sampleRateCode = %d\n", fscod);
+            ALOGW("Invalid AC3 sampleRateCode = %d", fscod);
             return false;
         } else if (frmsizcod >= AC3_NUM_FRAME_SIZE_TABLE_ENTRIES) {
-            ALOGW("Invalid AC3 frameSizeCode = %d\n", frmsizcod);
+            ALOGW("Invalid AC3 frameSizeCode = %d", frmsizcod);
             return false;
         } else {
             mSampleRate = kAC3SampleRateTable[fscod];
@@ -238,7 +242,7 @@ bool AC3FrameScanner::parseHeader()
         mAudioBlocksPerSyncFrame = 6;
     }
     ALOGI_IF((mFormatDumpCount == 0),
-            "AC3 frame rate = %d * %d, size = %d, audioBlocksPerSyncFrame = %d\n",
+            "AC3 frame rate = %d * %d, size = %zu, audioBlocksPerSyncFrame = %d",
             mSampleRate, mRateMultiplier, mFrameSizeBytes, mAudioBlocksPerSyncFrame);
     mFormatDumpCount++;
     return true;
index 39c2fa2..b218bd3 100644 (file)
@@ -18,4 +18,5 @@ LOCAL_SHARED_LIBRARIES := \
        libcutils \
        liblog
 
+LOCAL_CFLAGS := -Werror -Wall
 include $(BUILD_SHARED_LIBRARY)
index f1fc356..944f4a7 100644 (file)
@@ -81,12 +81,12 @@ bool DTSFrameScanner::parseHeader()
 
     // These variables are named after the fields in the DTS spec 5.3.1
     // Extract field in order.
-    uint32_t ftype = parser.readBits(1);
-    uint32_t deficit = parser.readBits(5); // "short"
+    (void) /* uint32_t ftype = */ parser.readBits(1);
+    (void) /* uint32_t deficit = */ parser.readBits(5); // "short"
     uint32_t cpf = parser.readBits(1);
     uint32_t nblks = parser.readBits(7);
     uint32_t fsize = parser.readBits(14);
-    uint32_t amode = parser.readBits(6);
+    (void) /* uint32_t amode = */ parser.readBits(6);
     uint32_t sfreq = parser.readBits(4);
     // make sure we did not read past collected data
     ALOG_ASSERT((mSyncLength + ((parser.getBitCursor() + 7) >> 3))
@@ -129,7 +129,7 @@ bool DTSFrameScanner::parseHeader()
 
     mRateMultiplier = 1; // TODO what about "frequency extension"?
     ALOGI_IF((mFormatDumpCount == 0),
-            "DTS frame rate = %d * %d, size = %d\n",
+            "DTS frame rate = %d * %d, size = %zu",
             mSampleRate, mRateMultiplier, mFrameSizeBytes);
     mFormatDumpCount++;
     return true;
index 80c1d94..2b591e3 100644 (file)
@@ -51,7 +51,7 @@ FrameScanner::~FrameScanner()
 bool FrameScanner::scan(uint8_t byte)
 {
     bool result = false;
-    ALOGV("FrameScanner: byte = 0x%02X, mCursor = %d\n", byte, mCursor);
+    ALOGV("FrameScanner: byte = 0x%02X, mCursor = %d", byte, mCursor);
     assert(mCursor < sizeof(mHeaderBuffer));
     if (mCursor < mSyncLength) {
         // match sync word
index 2eeeba6..8e7e6cd 100644 (file)
@@ -34,7 +34,8 @@ static int32_t sEndianDetector = 1;
 #define isLittleEndian()  (*((uint8_t *)&sEndianDetector))
 
 SPDIFEncoder::SPDIFEncoder(audio_format_t format)
-  : mSampleRate(48000)
+  : mFramer(NULL)
+  , mSampleRate(48000)
   , mBurstBuffer(NULL)
   , mBurstBufferSizeBytes(0)
   , mRateMultiplier(1)
@@ -54,16 +55,18 @@ SPDIFEncoder::SPDIFEncoder(audio_format_t format)
             mFramer = new DTSFrameScanner();
             break;
         default:
-            ALOGE("SPDIFEncoder: ERROR invalid audio format = 0x%08X", format);
-            mFramer = NULL;
             break;
     }
 
+    // This a programmer error. Call isFormatSupported() first.
+    LOG_ALWAYS_FATAL_IF((mFramer == NULL),
+        "SPDIFEncoder: invalid audio format = 0x%08X", format);
+
     mBurstBufferSizeBytes = sizeof(uint16_t)
             * SPDIF_ENCODED_CHANNEL_COUNT
             * mFramer->getMaxSampleFramesPerSyncFrame();
 
-    ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %d, littleEndian = %d",
+    ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %zu, littleEndian = %d",
             mBurstBufferSizeBytes, isLittleEndian());
     mBurstBuffer = new uint16_t[mBurstBufferSizeBytes >> 1];
     clearBurstBuffer();
@@ -100,10 +103,12 @@ int SPDIFEncoder::getBytesPerOutputFrame()
 
 void SPDIFEncoder::writeBurstBufferShorts(const uint16_t *buffer, size_t numShorts)
 {
+    // avoid static analyser warning
+    LOG_ALWAYS_FATAL_IF((mBurstBuffer == NULL), "mBurstBuffer never allocated");
     mByteCursor = (mByteCursor + 1) & ~1; // round up to even byte
     size_t bytesToWrite = numShorts * sizeof(uint16_t);
     if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
-        ALOGE("SPDIFEncoder: Burst buffer overflow!\n");
+        ALOGE("SPDIFEncoder: Burst buffer overflow!");
         reset();
         return;
     }
@@ -123,7 +128,7 @@ void SPDIFEncoder::writeBurstBufferBytes(const uint8_t *buffer, size_t numBytes)
 {
     size_t bytesToWrite = numBytes;
     if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
-        ALOGE("SPDIFEncoder: Burst buffer overflow!\n");
+        ALOGE("SPDIFEncoder: Burst buffer overflow!");
         clearBurstBuffer();
         return;
     }
@@ -224,7 +229,7 @@ ssize_t SPDIFEncoder::write( const void *buffer, size_t numBytes )
 {
     size_t bytesLeft = numBytes;
     const uint8_t *data = (const uint8_t *)buffer;
-    ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %u)",
+    ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %zu)",
         mScanning, (uint) *data, numBytes);
     while (bytesLeft > 0) {
         if (mScanning) {
index 04e75b5..0db09dc 100644 (file)
@@ -17,6 +17,7 @@ LOCAL_SRC_FILES := \
 LOCAL_MODULE := primitives_tests
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_CFLAGS := -Werror -Wall
 include $(BUILD_NATIVE_TEST)
 
 include $(CLEAR_VARS)
@@ -26,6 +27,7 @@ LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
 LOCAL_SHARED_LIBRARIES := libaudioutils
 # libmedia libbinder libcutils libutils
 LOCAL_STATIC_LIBRARIES := libsndfile
+LOCAL_CFLAGS := -Werror -Wall
 include $(BUILD_EXECUTABLE)
 
 include $(CLEAR_VARS)
@@ -34,4 +36,13 @@ LOCAL_MODULE := fifo_tests
 LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
 # libmedia libbinder libcutils libutils
 LOCAL_STATIC_LIBRARIES := libsndfile libaudioutils liblog
+LOCAL_CFLAGS := -Werror -Wall
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := limiter_tests.c
+LOCAL_MODULE := limiter_tests
+LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
+LOCAL_STATIC_LIBRARIES := libaudioutils
+LOCAL_CFLAGS := -Werror -Wall
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/audio_utils/tests/README.md b/audio_utils/tests/README.md
new file mode 100644 (file)
index 0000000..021818a
--- /dev/null
@@ -0,0 +1,3 @@
+primitive\_tests uses gtest framework
+
+fifo\_tests does not run under gtest
index 1fea244..99e73c9 100644 (file)
@@ -159,6 +159,7 @@ usage:
     sf_count_t actualWritten = sf_writef_short(sfout, outputBuffer, framesRead);
     delete[] inputBuffer;
     delete[] outputBuffer;
+    delete[] fifoBuffer;
     if (actualWritten != (sf_count_t) framesRead) {
         fprintf(stderr, "%s: unexpected error\n", outputFile);
         sf_close(sfout);
diff --git a/audio_utils/tests/limiter_tests.c b/audio_utils/tests/limiter_tests.c
new file mode 100644 (file)
index 0000000..6a5a943
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <audio_utils/limiter.h>
+
+int main(int argc, char **argv)
+{
+    int i;
+    if (argc > 1) {
+        for (i = 1; i < argc; i++) {
+            float x = atof(argv[i]);
+            printf("limit(%g)=%g\n", x, limiter(x));
+        }
+    } else {
+        for (i = 0; i <= 150; i++) {
+            float in = (float) ((double) i * 0.01);
+            float out = limiter(in);
+            printf("%g,%g\n", in, out);
+            if (i != 0) {
+                out = limiter(-in);
+                printf("%g,%g\n", -in, out);
+            }
+        }
+    }
+    return EXIT_SUCCESS;
+}
index ca03a72..9c20862 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <system/audio.h>
 #include <audio_utils/sndfile.h>
 #include <audio_utils/primitives.h>
 #ifdef HAVE_STDERR
@@ -181,8 +182,7 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
                 fseek(stream, (long) (chunkSize - minSize), SEEK_CUR);
             }
             unsigned channels = little2u(&fmt[2]);
-            // FIXME FCC_8
-            if (channels != 1 && channels != 2 && channels != 4 && channels != 6 && channels != 8) {
+            if ((channels < 1) || (channels > FCC_8)) {
 #ifdef HAVE_STDERR
                 fprintf(stderr, "unsupported channels %u\n", channels);
 #endif
@@ -299,8 +299,7 @@ static SNDFILE *sf_open_write(const char *path, SF_INFO *info)
     int sub = info->format & SF_FORMAT_SUBMASK;
     if (!(
             (info->samplerate > 0) &&
-            // FIXME FCC_8
-            (info->channels > 0 && info->channels <= 8) &&
+            (info->channels > 0 && info->channels <= FCC_8) &&
             ((info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV) &&
             (sub == SF_FORMAT_PCM_16 || sub == SF_FORMAT_PCM_U8 || sub == SF_FORMAT_FLOAT ||
                 sub == SF_FORMAT_PCM_24 || sub == SF_FORMAT_PCM_32)
diff --git a/brillo/audio/audioservice/Android.mk b/brillo/audio/audioservice/Android.mk
new file mode 100644 (file)
index 0000000..8d4fb15
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright 2016 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.
+
+LOCAL_PATH := $(call my-dir)
+
+audio_service_shared_libraries := \
+  libbinderwrapper \
+  libbrillo \
+  libbrillo-binder \
+  libc \
+  libchrome \
+  libmedia \
+  libutils
+
+# Audio service.
+# =============================================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := brilloaudioservice
+LOCAL_SRC_FILES := \
+  audio_daemon.cpp \
+  audio_device_handler.cpp \
+  main_audio_service.cpp
+LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_INIT_RC := brilloaudioserv.rc
+include $(BUILD_EXECUTABLE)
+
+# Unit tests for audio device handler.
+# =============================================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := brilloaudioservice_test
+LOCAL_SRC_FILES := \
+  audio_device_handler.cpp \
+  test/audio_device_handler_test.cpp
+LOCAL_C_INCLUDES := external/gtest/include
+LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
+LOCAL_STATIC_LIBRARIES := \
+  libBionicGtestMain \
+  libchrome_test_helpers \
+  libgmock
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -Wno-sign-compare
+include $(BUILD_NATIVE_TEST)
diff --git a/brillo/audio/audioservice/audio_daemon.cpp b/brillo/audio/audioservice/audio_daemon.cpp
new file mode 100644 (file)
index 0000000..f764f1a
--- /dev/null
@@ -0,0 +1,121 @@
+// Copyright 2016 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.
+//
+
+// Implementation of audio_daemon.h.
+
+#include "audio_daemon.h"
+
+#include <sysexits.h>
+
+#include <base/bind.h>
+#include <base/files/file_enumerator.h>
+#include <base/files/file_path.h>
+#include <base/time/time.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <linux/input.h>
+
+namespace brillo {
+
+static const char kAPSServiceName[] = "media.audio_policy";
+static const char kInputDeviceDir[] = "/dev/input";
+
+void AudioDaemon::InitializeHandler() {
+  // Start and initialize the audio device handler.
+  audio_device_handler_ =
+      std::unique_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
+  audio_device_handler_->Init(aps_);
+
+  // Poll on all files in kInputDeviceDir.
+  base::FileEnumerator fenum(base::FilePath(kInputDeviceDir),
+                             false /*recursive*/, base::FileEnumerator::FILES);
+  for (base::FilePath name = fenum.Next(); !name.empty(); name = fenum.Next()) {
+    base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ);
+    if (file.IsValid()) {
+      MessageLoop* message_loop = MessageLoop::current();
+      int fd = file.GetPlatformFile();
+      // Move file to files_ and ensure that when binding we get a pointer from
+      // the object in files_.
+      files_.emplace(std::move(file));
+      base::Closure callback =
+          base::Bind(&AudioDaemon::Callback, weak_ptr_factory_.GetWeakPtr(),
+                     &files_.top());
+      message_loop->WatchFileDescriptor(fd, MessageLoop::kWatchRead,
+                                        true /*persistent*/, callback);
+    } else {
+      LOG(WARNING) << "Could not open " << name.value() << " for reading. ("
+                   << base::File::ErrorToString(file.error_details()) << ")";
+    }
+  }
+  handler_initialized_ = true;
+}
+
+void AudioDaemon::ConnectToAPS() {
+  android::BinderWrapper* binder_wrapper = android::BinderWrapper::Get();
+  auto binder = binder_wrapper->GetService(kAPSServiceName);
+  // If we didn't get the audio policy service, try again in 500 ms.
+  if (!binder.get()) {
+    LOG(INFO) << "Could not connect to audio policy service. Trying again...";
+    brillo::MessageLoop::current()->PostDelayedTask(
+        base::Bind(&AudioDaemon::ConnectToAPS, weak_ptr_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMilliseconds(500));
+    return;
+  }
+  LOG(INFO) << "Connected to audio policy service.";
+  binder_wrapper->RegisterForDeathNotifications(
+      binder,
+      base::Bind(&AudioDaemon::OnAPSDisconnected,
+                 weak_ptr_factory_.GetWeakPtr()));
+  VLOG(1) << "Registered death notification.";
+  aps_ = android::interface_cast<android::IAudioPolicyService>(binder);
+  if (!handler_initialized_)
+    InitializeHandler();
+  else
+    audio_device_handler_->APSConnect(aps_);
+}
+
+void AudioDaemon::OnAPSDisconnected() {
+  LOG(INFO) << "Audio policy service died. Will try to reconnect.";
+  audio_device_handler_->APSDisconnect();
+  aps_ = nullptr;
+  ConnectToAPS();
+}
+
+// OnInit, we want to do the following:
+//   - Get a binder to the audio policy service.
+//   - Initialize the audio device handler.
+//   - Set up polling on files in /dev/input.
+int AudioDaemon::OnInit() {
+  int exit_code = Daemon::OnInit();
+  if (exit_code != EX_OK) return exit_code;
+  // Initialize a binder wrapper.
+  android::BinderWrapper::Create();
+  // Initialize a binder watcher.
+  binder_watcher_.Init();
+  ConnectToAPS();
+  return EX_OK;
+}
+
+void AudioDaemon::Callback(base::File* file) {
+  input_event event;
+  int bytes_read =
+      file->ReadAtCurrentPos(reinterpret_cast<char*>(&event), sizeof(event));
+  if (bytes_read != sizeof(event)) {
+    LOG(WARNING) << "Couldn't read an input event.";
+    return;
+  }
+  audio_device_handler_->ProcessEvent(event);
+}
+
+}  // namespace brillo
diff --git a/brillo/audio/audioservice/audio_daemon.h b/brillo/audio/audioservice/audio_daemon.h
new file mode 100644 (file)
index 0000000..48aa35f
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright 2016 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.
+//
+
+// Main loop of the brillo audio service.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_H_
+
+#include <memory>
+#include <stack>
+
+#include <base/files/file.h>
+#include <base/memory/weak_ptr.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/daemons/daemon.h>
+#include <media/IAudioPolicyService.h>
+
+#include "audio_device_handler.h"
+
+namespace brillo {
+
+class AudioDaemon : public Daemon {
+ public:
+  AudioDaemon() {}
+
+ protected:
+  // Initialize the audio device handler and start pollig the files in
+  // /dev/input.
+  int OnInit() override;
+
+ private:
+  // Callback function for input events. Events are handled by the audio device
+  // handler.
+  void Callback(base::File* file);
+
+  // Callback function for audio policy service death notification.
+  void OnAPSDisconnected();
+
+  // Connect to the audio policy service and register a callback to be invoked
+  // if the audio policy service dies.
+  void ConnectToAPS();
+
+  // Initialize the audio_device_handler_.
+  //
+  // Note: This can only occur after we have connected to the audio policy
+  // service.
+  void InitializeHandler();
+
+  // Store the file objects that are created during initialization for the files
+  // being polled. This is done so these objects can be freed when the
+  // AudioDaemon object is destroyed.
+  std::stack<base::File> files_;
+  // Handler for audio device input events.
+  std::unique_ptr<AudioDeviceHandler> audio_device_handler_;
+  // Used to generate weak_ptr to AudioDaemon for use in base::Bind.
+  base::WeakPtrFactory<AudioDaemon> weak_ptr_factory_{this};
+  // Pointer to the audio policy service.
+  android::sp<android::IAudioPolicyService> aps_;
+  // Flag to indicate whether the handler has been initialized.
+  bool handler_initialized_ = false;
+  // Binder watcher to watch for binder messages.
+  brillo::BinderWatcher binder_watcher_;
+};
+
+}  // namespace brillo
+
+#endif  // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_H_
diff --git a/brillo/audio/audioservice/audio_device_handler.cpp b/brillo/audio/audioservice/audio_device_handler.cpp
new file mode 100644 (file)
index 0000000..af12c96
--- /dev/null
@@ -0,0 +1,177 @@
+// Copyright 2016 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.
+//
+
+// Implementation of audio_device_handler.h
+
+#include "audio_device_handler.h"
+
+#include <base/files/file.h>
+#include <base/logging.h>
+#include <media/AudioSystem.h>
+
+namespace brillo {
+
+static const char kH2WStateFile[] = "/sys/class/switch/h2w/state";
+
+AudioDeviceHandler::AudioDeviceHandler() {
+  headphone_ = false;
+  microphone_ = false;
+}
+
+AudioDeviceHandler::~AudioDeviceHandler() {}
+
+void AudioDeviceHandler::APSDisconnect() {
+  aps_.clear();
+}
+
+void AudioDeviceHandler::APSConnect(
+    android::sp<android::IAudioPolicyService> aps) {
+  aps_ = aps;
+  // Reset the state
+  connected_input_devices_.clear();
+  connected_output_devices_.clear();
+  // Inform audio policy service about the currently connected devices.
+  VLOG(1) << "Calling GetInitialAudioDeviceState on APSConnect.";
+  GetInitialAudioDeviceState(base::FilePath(kH2WStateFile));
+}
+
+void AudioDeviceHandler::Init(android::sp<android::IAudioPolicyService> aps) {
+  aps_ = aps;
+  // Reset audio policy service state in case this service crashed and there is
+  // a mismatch between the current system state and what audio policy service
+  // was previously told.
+  VLOG(1) << "Calling DisconnectAllSupportedDevices.";
+  DisconnectAllSupportedDevices();
+
+  // Get headphone jack state and update audio policy service with new state.
+  VLOG(1) << "Calling ReadInitialAudioDeviceState.";
+  GetInitialAudioDeviceState(base::FilePath(kH2WStateFile));
+}
+
+void AudioDeviceHandler::GetInitialAudioDeviceState(
+    const base::FilePath& path) {
+  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!file.IsValid()) {
+    LOG(WARNING) << "Kernel does not have wired headset support. Could not "
+                 << "open " << path.value() << "( "
+                 << base::File::ErrorToString(file.error_details()) << " ).";
+    return;
+  }
+  int state = 0;
+  int bytes_read = file.ReadAtCurrentPos(reinterpret_cast<char*>(&state), 1);
+  state -= '0';
+  if (bytes_read == 0) {
+    LOG(WARNING) << "Could not read from " << path.value();
+    return;
+  }
+  VLOG(1) << "Initial audio jack state is " << state;
+  static const int kHeadPhoneMask = 0x1;
+  bool headphone = state & kHeadPhoneMask;
+  static const int kMicrophoneMask = 0x2;
+  bool microphone = (state & kMicrophoneMask) >> 1;
+
+  UpdateAudioSystem(headphone, microphone);
+}
+
+void AudioDeviceHandler::NotifyAudioPolicyService(
+    audio_devices_t device, audio_policy_dev_state_t state) {
+  if (aps_ == nullptr) {
+    LOG(INFO) << "Audio device handler cannot call audio policy service. Will "
+              << "try again later.";
+    return;
+  }
+  VLOG(1) << "Calling Audio Policy Service to change " << device << " to state "
+          << state;
+  aps_->setDeviceConnectionState(device, state, "", "");
+}
+
+void AudioDeviceHandler::ConnectAudioDevice(audio_devices_t device) {
+  audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
+  NotifyAudioPolicyService(device, state);
+  if (audio_is_input_device(device))
+    connected_input_devices_.insert(device);
+  else
+    connected_output_devices_.insert(device);
+}
+
+void AudioDeviceHandler::DisconnectAudioDevice(audio_devices_t device) {
+  audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+  NotifyAudioPolicyService(device, state);
+  if (audio_is_input_device(device))
+    connected_input_devices_.erase(device);
+  else
+    connected_output_devices_.erase(device);
+}
+
+void AudioDeviceHandler::DisconnectAllSupportedDevices() {
+  for (auto device : kSupportedInputDevices_) {
+    DisconnectAudioDevice(device);
+  }
+  for (auto device : kSupportedOutputDevices_) {
+    DisconnectAudioDevice(device);
+  }
+}
+
+void AudioDeviceHandler::DisconnectAllConnectedDevices() {
+  while (!connected_input_devices_.empty()) {
+    audio_devices_t device = *(connected_input_devices_.begin());
+    DisconnectAudioDevice(device);
+  }
+  while (!connected_output_devices_.empty()) {
+    audio_devices_t device = *(connected_output_devices_.begin());
+    DisconnectAudioDevice(device);
+  }
+}
+
+void AudioDeviceHandler::UpdateAudioSystem(bool headphone, bool microphone) {
+  if (microphone) {
+    ConnectAudioDevice(AUDIO_DEVICE_IN_WIRED_HEADSET);
+  }
+  if (headphone && microphone) {
+    ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADSET);
+  } else if (headphone) {
+    ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
+  } else if (!microphone) {
+    // No devices are connected. Inform the audio policy service that all
+    // connected devices have been disconnected.
+    DisconnectAllConnectedDevices();
+  }
+}
+
+void AudioDeviceHandler::ProcessEvent(const struct input_event& event) {
+  VLOG(1) << event.type << " " << event.code << " " << event.value;
+  if (event.type == EV_SW) {
+    switch (event.code) {
+      case SW_HEADPHONE_INSERT:
+        headphone_ = event.value;
+        break;
+      case SW_MICROPHONE_INSERT:
+        microphone_ = event.value;
+        break;
+      default:
+        // This event code is not supported by this handler.
+        break;
+    }
+  } else if (event.type == EV_SYN) {
+    // We have received all input events. Update the audio system.
+    UpdateAudioSystem(headphone_, microphone_);
+    // Reset the headphone and microphone flags that are used to track
+    // information across multiple calls to ProcessEvent.
+    headphone_ = false;
+    microphone_ = false;
+  }
+}
+
+}  // namespace brillo
diff --git a/brillo/audio/audioservice/audio_device_handler.h b/brillo/audio/audioservice/audio_device_handler.h
new file mode 100644 (file)
index 0000000..335ae98
--- /dev/null
@@ -0,0 +1,152 @@
+// Copyright 2016 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.
+//
+
+// Handler for input events in /dev/input. AudioDeviceHandler handles events
+// only for audio devices being plugged in/removed from the system. Implements
+// some of the functionality present in WiredAccessoryManager.java.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DEVICE_HANDLER_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DEVICE_HANDLER_H_
+
+#include <set>
+#include <vector>
+
+#include <base/files/file_path.h>
+#include <gtest/gtest_prod.h>
+#include <linux/input.h>
+#include <media/IAudioPolicyService.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+namespace brillo {
+
+class AudioDeviceHandler {
+ public:
+  AudioDeviceHandler();
+  virtual ~AudioDeviceHandler();
+
+  // Get the current state of the headset jack and update AudioSystem based on
+  // the initial state.
+  //
+  // |aps| is a pointer to the binder object.
+  void Init(android::sp<android::IAudioPolicyService> aps);
+
+  // Process input events from the kernel. Connecting/disconnecting an audio
+  // device will result in multiple calls to this method.
+  //
+  // |event| is a pointer to an input_event. This function should be able to
+  // gracefully handle input events that are not relevant to the functionality
+  // provided by this class.
+  void ProcessEvent(const struct input_event& event);
+
+  // Inform the handler that the audio policy service has been disconnected.
+  void APSDisconnect();
+
+  // Inform the handler that the audio policy service is reconnected.
+  //
+  // |aps| is a pointer to the binder object.
+  void APSConnect(android::sp<android::IAudioPolicyService> aps);
+
+ private:
+  friend class AudioDeviceHandlerTest;
+  FRIEND_TEST(AudioDeviceHandlerTest,
+              DisconnectAllSupportedDevicesCallsDisconnect);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateMic);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadphone);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadset);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateNone);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateInvalid);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventEmpty);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophonePresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphonePresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophoneNotPresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphoneNotPresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventInvalid);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemNone);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectMic);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadphone);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadset);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectMic);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadphone);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadset);
+  FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceInput);
+  FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceOutput);
+  FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceInput);
+  FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput);
+
+  // Read the initial state of audio devices in /sys/class/* and update
+  // the audio policy service.
+  //
+  // |path| is the file that contains the initial audio jack state.
+  void GetInitialAudioDeviceState(const base::FilePath& path);
+
+  // Update the audio policy service once an input_event has completed.
+  //
+  // |headphone| is true is headphones are connected.
+  // |microphone| is true is microphones are connected.
+  void UpdateAudioSystem(bool headphone, bool microphone);
+
+  // Notify the audio policy service that this device has been removed.
+  //
+  // |device| is the audio device whose state is to be changed.
+  // |state| is the current state of |device|.
+  virtual void NotifyAudioPolicyService(audio_devices_t device,
+                                        audio_policy_dev_state_t state);
+
+  // Connect an audio device by calling aps and add it to the appropriate set
+  // (either connected_input_devices_ or connected_output_devices_).
+  //
+  // |device| is the audio device that has been added.
+  void ConnectAudioDevice(audio_devices_t device);
+
+  // Disconnect an audio device by calling aps and remove it from the
+  // appropriate set (either connected_input_devices_ or
+  // connected_output_devices_).
+  //
+  // |device| is the audio device that has been disconnected.
+  void DisconnectAudioDevice(audio_devices_t device);
+
+  // Disconnected all connected audio devices.
+  void DisconnectAllConnectedDevices();
+
+  // Disconnect all supported audio devices.
+  void DisconnectAllSupportedDevices();
+
+  // All input devices currently supported by AudioDeviceHandler.
+  std::vector<audio_devices_t> kSupportedInputDevices_{
+      AUDIO_DEVICE_IN_WIRED_HEADSET};
+  // All output devices currently supported by AudioDeviceHandler.
+  std::vector<audio_devices_t> kSupportedOutputDevices_{
+      AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE};
+  // Pointer to the audio policy service.
+  android::sp<android::IAudioPolicyService> aps_;
+
+ protected:
+  // Set of connected input devices.
+  std::set<audio_devices_t> connected_input_devices_;
+  // Set of connected output devices.
+  std::set<audio_devices_t> connected_output_devices_;
+  // Keeps track of whether a headphone has been connected. Used by ProcessEvent
+  // and UpdateAudioSystem.
+  bool headphone_;
+  // Keeps track of whether a microphone has been connected. Used by
+  // ProcessEvent and UpdateAudioSystem.
+  bool microphone_;
+};
+
+}  // namespace brillo
+
+#endif  // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DEVICE_HANDLER_H_
diff --git a/brillo/audio/audioservice/brilloaudioserv.rc b/brillo/audio/audioservice/brilloaudioserv.rc
new file mode 100644 (file)
index 0000000..a9b3898
--- /dev/null
@@ -0,0 +1,4 @@
+service brilloaudioserv /system/bin/brilloaudioservice
+    class late_start
+    user system
+    group input
diff --git a/brillo/audio/audioservice/main_audio_service.cpp b/brillo/audio/audioservice/main_audio_service.cpp
new file mode 100644 (file)
index 0000000..e8cb605
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+//
+
+#include <brillo/flag_helper.h>
+#include <brillo/syslog_logging.h>
+
+#include "audio_daemon.h"
+
+int main(int argc, char** argv) {
+  brillo::FlagHelper::Init(argc, argv, "Brillo audio service,");
+  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader);
+  LOG(INFO) << "Starting brilloaudioservice.";
+  brillo::AudioDaemon audio_daemon;
+  return audio_daemon.Run();
+}
diff --git a/brillo/audio/audioservice/test/audio_device_handler_mock.h b/brillo/audio/audioservice/test/audio_device_handler_mock.h
new file mode 100644 (file)
index 0000000..ce6dfd3
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright 2016 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.
+//
+
+// Mock of AudioDeviceHandler.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DEVICE_HANDLER_MOCK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DEVICE_HANDLER_MOCK_H_
+
+#include <base/files/file_path.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest_prod.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+#include "audio_device_handler.h"
+
+namespace brillo {
+
+class AudioDeviceHandlerMock : public AudioDeviceHandler {
+ public:
+  AudioDeviceHandlerMock() = default;
+  ~AudioDeviceHandlerMock() {}
+
+  // Reset all local data.
+  void Reset() {
+    connected_input_devices_.clear();
+    connected_output_devices_.clear();
+    headphone_ = false;
+    microphone_ = false;
+  }
+
+ private:
+  friend class AudioDeviceHandlerTest;
+  FRIEND_TEST(AudioDeviceHandlerTest,
+              DisconnectAllSupportedDevicesCallsDisconnect);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateMic);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadphone);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadset);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateNone);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateInvalid);
+  FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnect);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventEmpty);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophonePresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphonePresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophoneNotPresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphoneNotPresent);
+  FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventInvalid);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemNone);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectMic);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadphone);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadset);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectMic);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadphone);
+  FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadset);
+  FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceInput);
+  FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceOutput);
+  FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceInput);
+  FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput);
+
+  MOCK_METHOD2(NotifyAudioPolicyService,
+               void(audio_devices_t device, audio_policy_dev_state_t state));
+};
+
+}  // namespace brillo
+
+#endif  // BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DEVICE_HANDLER_MOCK_H_
diff --git a/brillo/audio/audioservice/test/audio_device_handler_test.cpp b/brillo/audio/audioservice/test/audio_device_handler_test.cpp
new file mode 100644 (file)
index 0000000..5487469
--- /dev/null
@@ -0,0 +1,353 @@
+// Copyright 2016 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.
+//
+
+// Tests for audio device handler.
+
+#include "audio_device_handler_mock.h"
+
+#include <string>
+
+#include <base/files/file_path.h>
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <base/strings/string_number_conversions.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using base::FilePath;
+using base::IntToString;
+using base::ScopedTempDir;
+using base::WriteFile;
+using brillo::AudioDeviceHandlerMock;
+using testing::_;
+using testing::AnyNumber;
+
+namespace brillo {
+
+class AudioDeviceHandlerTest : public testing::Test {
+ public:
+  void SetUp() override {
+    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+    h2w_file_path_ = temp_dir_.path().Append("h2wstate");
+  }
+
+  void TearDown() override { handler_.Reset(); }
+
+  // Method to store the current state of the audio jack to a file.
+  //
+  // |value| - Value in the h2w file.
+  void WriteToH2WFile(int value) {
+    std::string value_string = IntToString(value);
+    WriteFile(h2w_file_path_, value_string.c_str(), value_string.length());
+  }
+
+  AudioDeviceHandlerMock handler_;
+  FilePath h2w_file_path_;
+
+ private:
+  ScopedTempDir temp_dir_;
+};
+
+// Test that DisconnectAllSupportedDevices() calls NotifyAudioPolicyService()
+// the right number of times.
+TEST_F(AudioDeviceHandlerTest, DisconnectAllSupportedDevicesCallsDisconnect) {
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(
+                  _, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(3);
+  handler_.DisconnectAllSupportedDevices();
+}
+
+// Test that Init() calls DisconnectAllSupportedDevices().
+TEST_F(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices) {
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(
+                  _, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(3);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(
+                  _, AUDIO_POLICY_DEVICE_STATE_AVAILABLE)).Times(AnyNumber());
+  handler_.Init(nullptr);
+}
+
+// Test GetInitialAudioDeviceState() with just a microphone.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateMic) {
+  WriteToH2WFile(2);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.GetInitialAudioDeviceState(h2w_file_path_);
+  EXPECT_NE(
+      handler_.connected_input_devices_.find(AUDIO_DEVICE_IN_WIRED_HEADSET),
+      handler_.connected_input_devices_.end());
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test GetInitialAudioDeviceState() with a headphone.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateHeadphone) {
+  WriteToH2WFile(1);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.GetInitialAudioDeviceState(h2w_file_path_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_NE(
+      handler_.connected_output_devices_.find(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+      handler_.connected_output_devices_.end());
+}
+
+// Test GetInitialAudioDeviceState() with a headset.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateHeadset) {
+  WriteToH2WFile(3);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.GetInitialAudioDeviceState(h2w_file_path_);
+  EXPECT_NE(
+      handler_.connected_input_devices_.find(AUDIO_DEVICE_IN_WIRED_HEADSET),
+      handler_.connected_input_devices_.end());
+  EXPECT_NE(
+      handler_.connected_output_devices_.find(AUDIO_DEVICE_OUT_WIRED_HEADSET),
+      handler_.connected_output_devices_.end());
+}
+
+// Test GetInitialAudioDeviceState() without any devices connected to the audio
+// jack. No need to call NotifyAudioPolicyService() since that's already handled
+// by Init().
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateNone) {
+  WriteToH2WFile(0);
+  handler_.GetInitialAudioDeviceState(h2w_file_path_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test GetInitialAudioDeviceState() with an invalid file. The audio handler
+// should not fail in this case because it should work on boards that don't
+// support audio jacks.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateInvalid) {
+  FilePath path = h2w_file_path_;
+  handler_.GetInitialAudioDeviceState(h2w_file_path_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test ProcessEvent() with an empty input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventEmpty) {
+  struct input_event event;
+  event.type = 0;
+  event.code = 0;
+  event.value = 0;
+  handler_.ProcessEvent(event);
+  EXPECT_FALSE(handler_.headphone_);
+  EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a microphone present input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventMicrophonePresent) {
+  struct input_event event;
+  event.type = EV_SW;
+  event.code = SW_MICROPHONE_INSERT;
+  event.value = 1;
+  handler_.ProcessEvent(event);
+  EXPECT_FALSE(handler_.headphone_);
+  EXPECT_TRUE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a headphone present input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventHeadphonePresent) {
+  struct input_event event;
+  event.type = EV_SW;
+  event.code = SW_HEADPHONE_INSERT;
+  event.value = 1;
+  handler_.ProcessEvent(event);
+  EXPECT_TRUE(handler_.headphone_);
+  EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a microphone not present input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventMicrophoneNotPresent) {
+  struct input_event event;
+  event.type = EV_SW;
+  event.code = SW_MICROPHONE_INSERT;
+  event.value = 0;
+  handler_.ProcessEvent(event);
+  EXPECT_FALSE(handler_.headphone_);
+  EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a headphone not preset input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventHeadphoneNotPresent) {
+  struct input_event event;
+  event.type = EV_SW;
+  event.code = SW_HEADPHONE_INSERT;
+  event.value = 0;
+  handler_.ProcessEvent(event);
+  EXPECT_FALSE(handler_.headphone_);
+  EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with an unsupported input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventInvalid) {
+  struct input_event event;
+  event.type = EV_SW;
+  event.code = SW_MAX;
+  event.value = 0;
+  handler_.ProcessEvent(event);
+  EXPECT_FALSE(handler_.headphone_);
+  EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test UpdateAudioSystem() without any devices connected.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemNone) {
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(
+                  _, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(0);
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+}
+
+// Test UpdateAudioSystem() when disconnecting a microphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectMic) {
+  audio_devices_t device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+  handler_.connected_input_devices_.insert(device);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(device,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when disconnecting a headphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadphone) {
+  audio_devices_t device = AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+  handler_.connected_output_devices_.insert(device);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(device,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when disconnecting a headset & headphones.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadset) {
+  handler_.connected_input_devices_.insert(AUDIO_DEVICE_IN_WIRED_HEADSET);
+  handler_.connected_output_devices_.insert(AUDIO_DEVICE_OUT_WIRED_HEADSET);
+  handler_.connected_output_devices_.insert(AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when connecting a microphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemConnectMic) {
+  handler_.microphone_ = true;
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when connecting a headphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadphone) {
+  handler_.headphone_ = true;
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+}
+
+// Test UpdateAudioSystem() when connecting a headset.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadset) {
+  handler_.headphone_ = true;
+  handler_.microphone_ = true;
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+}
+
+// Test ConnectAudioDevice() with an input device.
+TEST_F(AudioDeviceHandlerTest, ConnectAudioDeviceInput) {
+  audio_devices_t device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(device,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.ConnectAudioDevice(device);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+  EXPECT_NE(
+      handler_.connected_input_devices_.find(device),
+      handler_.connected_input_devices_.end());
+}
+
+// Test ConnectAudioDevice() with an output device.
+TEST_F(AudioDeviceHandlerTest, ConnectAudioDeviceOutput) {
+  audio_devices_t device = AUDIO_DEVICE_OUT_WIRED_HEADSET;
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(device,
+                                       AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+  handler_.ConnectAudioDevice(device);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_NE(
+      handler_.connected_output_devices_.find(device),
+      handler_.connected_output_devices_.end());
+}
+
+// Test DisconnectAudioDevice() with an input device.
+TEST_F(AudioDeviceHandlerTest, DisconnectAudioDeviceInput) {
+  audio_devices_t device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+  handler_.connected_input_devices_.insert(device);
+  handler_.connected_output_devices_.insert(device);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(device,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  handler_.DisconnectAudioDevice(device);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+}
+
+// Test DisconnectAudioDevice() with an output device.
+TEST_F(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput) {
+  audio_devices_t device = AUDIO_DEVICE_OUT_WIRED_HEADSET;
+  handler_.connected_input_devices_.insert(device);
+  handler_.connected_output_devices_.insert(device);
+  EXPECT_CALL(handler_,
+              NotifyAudioPolicyService(device,
+                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+  handler_.DisconnectAudioDevice(device);
+  EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
+  EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+}  // namespace brillo
diff --git a/camera/docs/ACameraMetadata.mako b/camera/docs/ACameraMetadata.mako
new file mode 100644 (file)
index 0000000..b65efc1
--- /dev/null
@@ -0,0 +1,80 @@
+## -*- coding: utf-8 -*-
+##
+## Copyright (C) 2015 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.
+##
+\
+## Generate a list of only Static, Controls, or Dynamic properties.
+<%def name="single_kind_keys(kind_name)">\
+% for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
+  % for section in outer_namespace.sections:
+    % if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == kind_name) and \
+         any_visible(section, kind_name, ('public','ndk_public') ):
+      % for inner_namespace in get_children_by_filtering_kind(section, kind_name, 'namespaces'):
+## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
+## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
+        % for entry in filter_visibility(inner_namespace.merged_entries, ('public','ndk_public')):
+          % if not entry.synthetic:
+        case ${ndk(entry.name) | csym}:
+          % else:
+            assert(False),"A synthetic key should not present in NDK!"
+          % endif
+       % endfor
+    % endfor
+    % for entry in filter_visibility( \
+        get_children_by_filtering_kind(section, kind_name, 'merged_entries'), \
+                                         ('public','ndk_public')):
+      % if not entry.synthetic:
+        case ${ndk(entry.name) | csym}:
+      % endif
+    % endfor
+    % endif
+  % endfor
+% endfor
+</%def>\
+/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * The key entries below this point are generated from metadata
+ * definitions in /system/media/camera/docs. Do not modify by hand or
+ * modify the comment blocks at the start or end.
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+bool
+ACameraMetadata::isCaptureRequestTag(const uint32_t tag) {
+    // Skip check for vendor keys
+    if (isVendorTag(tag)) {
+        return true;
+    }
+
+    switch (tag) {
+${single_kind_keys("controls")}\
+            return true;
+        default:
+            return false;
+    }
+}
+
+// System tags that should be hidden from users
+std::unordered_set<uint32_t> ACameraMetadata::sSystemTags ({
+    % for sec in find_all_sections(metadata):
+      % for entry in remove_synthetic(find_unique_entries(sec)):
+        % if entry.applied_visibility == "system":
+    ${entry.name | csym},
+        % endif
+      % endfor
+    %endfor
+});
+
+/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * End generated code
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/camera/docs/CameraDeviceInfo.mako b/camera/docs/CameraDeviceInfo.mako
new file mode 100644 (file)
index 0000000..1f89865
--- /dev/null
@@ -0,0 +1,38 @@
+## -*- coding: utf-8 -*-
+##
+## Copyright (C) 2016 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.
+##
+    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * The key entries below this point are generated from metadata
+     * definitions in /system/media/camera/docs. Do not modify by hand or
+     * modify the comment blocks at the start or end.
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+    private static HashSet<String> getAllCharacteristicsKeyNames() {
+        HashSet<String> charsKeyNames = new HashSet<String>();
+% for sec in find_all_sections(metadata):
+  % for entry in find_unique_entries(sec):
+    % if entry.kind == 'static' and entry.visibility in ("public", "java_public"):
+        charsKeyNames.add(CameraCharacteristics.${jkey_identifier(entry.name)}.getName());
+    % endif
+  % endfor
+% endfor
+
+        return charsKeyNames;
+    }
+
+    /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * End generated code
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
index eb4b1b0..b61fcc4 100644 (file)
@@ -35,7 +35,7 @@
 ${value.notes | javadoc(metadata)}\
     % endif
      * @see ${target_class}#${entry.name | jkey_identifier}
-    % if entry.applied_visibility == 'hidden' or value.hidden:
+    % if entry.applied_visibility in ('hidden', 'ndk_public') or value.hidden:
      * @hide
     %endif
     % if value.deprecated:
@@ -52,11 +52,11 @@ ${value.notes | javadoc(metadata)}\
 % for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
   % for section in outer_namespace.sections:
     % if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == xml_name) and \
-         any_visible(section, xml_name, ('public','hidden') ):
+         any_visible(section, xml_name, ('public','hidden', 'ndk_public', 'java_public') ):
       % for inner_namespace in get_children_by_filtering_kind(section, xml_name, 'namespaces'):
 ## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
 ## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
-        % for entry in filter_visibility(inner_namespace.entries, ('hidden','public')):
+        % for entry in filter_visibility(inner_namespace.entries, ('hidden','public', 'ndk_public', 'java_public')):
           % if entry.enum \
               and not (entry.typedef and entry.typedef.languages.get('java')) \
               and not entry.is_clone():
@@ -66,7 +66,7 @@ ${generate_enum(entry, target_class)}\
       % endfor
       % for entry in filter_visibility( \
           get_children_by_filtering_kind(section, xml_name, 'entries'), \
-                                         ('hidden', 'public')):
+                                         ('hidden', 'public', 'ndk_public', 'java_public')):
         % if entry.enum \
              and not (entry.typedef and entry.typedef.languages.get('java')) \
              and not entry.is_clone():
index f9286fa..f9ce15e 100644 (file)
@@ -53,14 +53,14 @@ ${concatenated_info | javadoc(metadata)}\
   % if entry.deprecated:
      * @deprecated
   % endif
-  % if entry.applied_visibility == 'hidden':
+  % if entry.applied_visibility in ('hidden', 'ndk_public'):
      * @hide
   % endif
      */
   % if entry.deprecated:
     @Deprecated
   % endif
-  % if entry.applied_visibility == 'public':
+  % if entry.applied_visibility in ('public', 'java_public'):
     @PublicKey
   % endif
   % if entry.synthetic:
@@ -75,17 +75,17 @@ ${concatenated_info | javadoc(metadata)}\
 % for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
   % for section in outer_namespace.sections:
     % if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == xml_name) and \
-         any_visible(section, xml_name, ('public','hidden') ):
+         any_visible(section, xml_name, ('public','hidden','ndk_public','java_public') ):
       % for inner_namespace in get_children_by_filtering_kind(section, xml_name, 'namespaces'):
 ## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
 ## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
-        % for entry in filter_visibility(inner_namespace.merged_entries, ('hidden','public')):
+        % for entry in filter_visibility(inner_namespace.merged_entries, ('hidden','public', 'ndk_public', 'java_public')):
 ${generate_key(entry)}
        % endfor
     % endfor
     % for entry in filter_visibility( \
         get_children_by_filtering_kind(section, xml_name, 'merged_entries'), \
-                                         ('hidden', 'public')):
+                                         ('hidden', 'public', 'ndk_public', 'java_public')):
 ${generate_key(entry)}
     % endfor
     % endif
index 6fb4905..4878fd7 100644 (file)
@@ -24,7 +24,7 @@
         ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
 % for sec in find_all_sections(metadata):
   % for entry in find_unique_entries(sec):
-    % if entry.kind == 'dynamic' and entry.visibility == "public":
+    % if entry.kind == 'dynamic' and entry.visibility in ("public", "java_public"):
         resultKeys.add(CaptureResult.${jkey_identifier(entry.name)});
     % endif
   % endfor
diff --git a/camera/docs/camera_device_info.mako b/camera/docs/camera_device_info.mako
new file mode 100644 (file)
index 0000000..92b7ef2
--- /dev/null
@@ -0,0 +1,104 @@
+// LINT: LEGACY_NAMES
+syntax = "proto2";
+
+package wireless.android.partner.adl.proto;
+
+option java_package = "com.google.wireless.android.partner.adl.proto";
+option java_outer_classname = "CameraDeviceInfoProto";
+
+// Content of this file is generated from $(ANDROID_ROOT)/system/media/camera/doc
+// Keep internal protocol buffer definition in sync with this one
+// Camera related device information
+// Next Id: 9
+message CameraDeviceInfo {
+  // Supported profiles from CamcorderProfile.hasProfile
+  optional bool profile_480p = 1;
+  optional bool profile_720p = 2;
+  optional bool profile_1080p = 3;
+  optional bool profile_cif = 4;
+  optional bool profile_qcif = 5;
+  optional bool profile_qvga = 6;
+  optional int32 num_of_camera = 7;
+
+  message PerCameraInfo {
+    message Rational {
+        optional int32 numerator = 1;
+        optional int32 denominator = 2;
+    }
+
+    message Size {
+        optional int32 width = 1;
+        optional int32 height = 2;
+    }
+
+    message SizeF {
+        optional float width = 1;
+        optional float height = 2;
+    }
+
+    message Rect {
+        optional int32 left = 1;
+        optional int32 right = 2;
+        optional int32 top = 3;
+        optional int32 bottom = 4;
+    }
+
+    message StreamConfigurations {
+        message StreamConfig {
+            optional int32 format = 1;
+            optional int32 width = 2;
+            optional int32 height = 3;
+            optional bool input = 4;
+            optional int64 minFrameDuration = 5;
+        }
+        repeated StreamConfig availableStreamConfigurations = 1;
+    }
+
+    message RangeInt {
+        optional int32 lower = 1;
+        optional int32 upper = 2;
+    }
+
+    message RangeLong {
+        optional int64 lower = 1;
+        optional int64 upper = 2;
+    }
+
+    message ColorSpaceTransform {
+        repeated Rational elements = 1;
+    }
+
+    message BlackLevelPattern {
+        repeated int32 black_level_pattern = 1;
+    }
+
+    optional string cameraId = 1;
+
+    // Start of codegen fields
+<%\
+  section_idx = 1
+%>\
+% for sec in find_all_sections(metadata):
+## Reserve 2^16 tag id space for each section
+<%\
+  idx = section_idx * pow(2,16)
+%>\
+% for entry in find_unique_entries(sec):
+% if entry.kind == 'static' and entry.visibility in ("public", "java_public"):
+    ${protobuf_type(entry)} ${protobuf_name(entry)} = ${idx};
+<%\
+  idx += 1
+%>\
+% endif
+% endfor
+<%\
+  section_idx += 1
+%>\
+% endfor
+    // End of codegen fields
+  }
+
+  // Per camera (front/back) informations
+  repeated PerCameraInfo per_camera_info = 8;
+} // CameraDeviceInfo
+
diff --git a/camera/docs/camera_device_info.proto b/camera/docs/camera_device_info.proto
new file mode 100644 (file)
index 0000000..d857589
--- /dev/null
@@ -0,0 +1,160 @@
+// LINT: LEGACY_NAMES
+syntax = "proto2";
+
+package wireless.android.partner.adl.proto;
+
+option java_package = "com.google.wireless.android.partner.adl.proto";
+option java_outer_classname = "CameraDeviceInfoProto";
+
+// Content of this file is generated from $(ANDROID_ROOT)/system/media/camera/doc
+// Keep internal protocol buffer definition in sync with this one
+// Camera related device information
+// Next Id: 9
+message CameraDeviceInfo {
+  // Supported profiles from CamcorderProfile.hasProfile
+  optional bool profile_480p = 1;
+  optional bool profile_720p = 2;
+  optional bool profile_1080p = 3;
+  optional bool profile_cif = 4;
+  optional bool profile_qcif = 5;
+  optional bool profile_qvga = 6;
+  optional int32 num_of_camera = 7;
+
+  message PerCameraInfo {
+    message Rational {
+        optional int32 numerator = 1;
+        optional int32 denominator = 2;
+    }
+
+    message Size {
+        optional int32 width = 1;
+        optional int32 height = 2;
+    }
+
+    message SizeF {
+        optional float width = 1;
+        optional float height = 2;
+    }
+
+    message Rect {
+        optional int32 left = 1;
+        optional int32 right = 2;
+        optional int32 top = 3;
+        optional int32 bottom = 4;
+    }
+
+    message StreamConfigurations {
+        message StreamConfig {
+            optional int32 format = 1;
+            optional int32 width = 2;
+            optional int32 height = 3;
+            optional bool input = 4;
+            optional int64 minFrameDuration = 5;
+        }
+        repeated StreamConfig availableStreamConfigurations = 1;
+    }
+
+    message RangeInt {
+        optional int32 lower = 1;
+        optional int32 upper = 2;
+    }
+
+    message RangeLong {
+        optional int64 lower = 1;
+        optional int64 upper = 2;
+    }
+
+    message ColorSpaceTransform {
+        repeated Rational elements = 1;
+    }
+
+    message BlackLevelPattern {
+        repeated int32 black_level_pattern = 1;
+    }
+
+    optional string cameraId = 1;
+
+    // Start of codegen fields
+    repeated int32 android_colorCorrection_availableAberrationModes = 65536;
+    repeated int32 android_control_aeAvailableAntibandingModes = 131072;
+    repeated int32 android_control_aeAvailableModes = 131073;
+    repeated RangeInt android_control_aeAvailableTargetFpsRanges = 131074;
+    optional RangeInt android_control_aeCompensationRange = 131075;
+    optional Rational android_control_aeCompensationStep = 131076;
+    repeated int32 android_control_afAvailableModes = 131077;
+    repeated int32 android_control_availableEffects = 131078;
+    repeated int32 android_control_availableSceneModes = 131079;
+    repeated int32 android_control_availableVideoStabilizationModes = 131080;
+    repeated int32 android_control_awbAvailableModes = 131081;
+    optional int32 android_control_maxRegionsAe = 131082;
+    optional int32 android_control_maxRegionsAwb = 131083;
+    optional int32 android_control_maxRegionsAf = 131084;
+    optional bool android_control_aeLockAvailable = 131085;
+    optional bool android_control_awbLockAvailable = 131086;
+    repeated int32 android_control_availableModes = 131087;
+    optional RangeInt android_control_postRawSensitivityBoostRange = 131088;
+    repeated int32 android_edge_availableEdgeModes = 262144;
+    optional bool android_flash_info_available = 393216;
+    repeated int32 android_hotPixel_availableHotPixelModes = 458752;
+    repeated Size android_jpeg_availableThumbnailSizes = 524288;
+    optional int32 android_lens_facing = 589824;
+    repeated float android_lens_info_availableApertures = 655360;
+    repeated float android_lens_info_availableFilterDensities = 655361;
+    repeated float android_lens_info_availableFocalLengths = 655362;
+    repeated int32 android_lens_info_availableOpticalStabilization = 655363;
+    optional float android_lens_info_hyperfocalDistance = 655364;
+    optional float android_lens_info_minimumFocusDistance = 655365;
+    optional int32 android_lens_info_focusDistanceCalibration = 655366;
+    repeated int32 android_noiseReduction_availableNoiseReductionModes = 720896;
+    optional int32 android_request_maxNumOutputRaw = 851968;
+    optional int32 android_request_maxNumOutputProc = 851969;
+    optional int32 android_request_maxNumOutputProcStalling = 851970;
+    optional int32 android_request_maxNumInputStreams = 851971;
+    optional int32 android_request_pipelineMaxDepth = 851972;
+    optional int32 android_request_partialResultCount = 851973;
+    repeated int32 android_request_availableCapabilities = 851974;
+    optional float android_scaler_availableMaxDigitalZoom = 917504;
+    optional StreamConfigurations android_scaler_streamConfigurationMap = 917505;
+    optional int32 android_scaler_croppingType = 917506;
+    optional int32 android_sensor_referenceIlluminant1 = 983040;
+    optional int32 android_sensor_referenceIlluminant2 = 983041;
+    optional ColorSpaceTransform android_sensor_calibrationTransform1 = 983042;
+    optional ColorSpaceTransform android_sensor_calibrationTransform2 = 983043;
+    optional ColorSpaceTransform android_sensor_colorTransform1 = 983044;
+    optional ColorSpaceTransform android_sensor_colorTransform2 = 983045;
+    optional ColorSpaceTransform android_sensor_forwardMatrix1 = 983046;
+    optional ColorSpaceTransform android_sensor_forwardMatrix2 = 983047;
+    optional BlackLevelPattern android_sensor_blackLevelPattern = 983048;
+    optional int32 android_sensor_maxAnalogSensitivity = 983049;
+    optional int32 android_sensor_orientation = 983050;
+    repeated int32 android_sensor_availableTestPatternModes = 983051;
+    repeated Rect android_sensor_opticalBlackRegions = 983052;
+    optional Rect android_sensor_info_activeArraySize = 1048576;
+    optional RangeInt android_sensor_info_sensitivityRange = 1048577;
+    optional int32 android_sensor_info_colorFilterArrangement = 1048578;
+    optional RangeLong android_sensor_info_exposureTimeRange = 1048579;
+    optional int64 android_sensor_info_maxFrameDuration = 1048580;
+    optional SizeF android_sensor_info_physicalSize = 1048581;
+    optional Size android_sensor_info_pixelArraySize = 1048582;
+    optional int32 android_sensor_info_whiteLevel = 1048583;
+    optional int32 android_sensor_info_timestampSource = 1048584;
+    optional bool android_sensor_info_lensShadingApplied = 1048585;
+    optional Rect android_sensor_info_preCorrectionActiveArraySize = 1048586;
+    repeated int32 android_shading_availableModes = 1114112;
+    repeated int32 android_statistics_info_availableFaceDetectModes = 1245184;
+    optional int32 android_statistics_info_maxFaceCount = 1245185;
+    repeated bool android_statistics_info_availableHotPixelMapModes = 1245186;
+    repeated int32 android_statistics_info_availableLensShadingMapModes = 1245187;
+    optional int32 android_tonemap_maxCurvePoints = 1310720;
+    repeated int32 android_tonemap_availableToneMapModes = 1310721;
+    optional int32 android_info_supportedHardwareLevel = 1441792;
+    optional int32 android_sync_maxLatency = 1572864;
+    optional int32 android_reprocess_maxCaptureStall = 1638400;
+    optional bool android_depth_depthIsExclusive = 1703936;
+    // End of codegen fields
+  }
+
+  // Per camera (front/back) informations
+  repeated PerCameraInfo per_camera_info = 8;
+} // CameraDeviceInfo
+
index 5c463bd..7bb6181 100644 (file)
@@ -17,7 +17,7 @@
 <head>
   <!-- automatically generated from html.mako. do NOT edit directly -->
   <meta charset="utf-8" />
-  <title>Android Camera HAL3.2 Properties</title>
+  <title>Android Camera HAL3.4 Properties</title>
   <style type="text/css">
      body { background-color: #f7f7f7; font-family: Roboto, sans-serif;}
      h1 { color: #333333; }
             ><a href="#controls_android.control.sceneMode">android.control.sceneMode</a></li>
             <li
             ><a href="#controls_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
+            <li
+            ><a href="#controls_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
           </ul>
         </li>
         <li>
             ><a href="#static_android.control.awbLockAvailable">android.control.awbLockAvailable</a></li>
             <li
             ><a href="#static_android.control.availableModes">android.control.availableModes</a></li>
+            <li
+            ><a href="#static_android.control.postRawSensitivityBoostRange">android.control.postRawSensitivityBoostRange</a></li>
           </ul>
         </li>
         <li>
             ><a href="#dynamic_android.control.sceneMode">android.control.sceneMode</a></li>
             <li
             ><a href="#dynamic_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
           </ul>
         </li>
       </ul> <!-- toc_section -->
             ><a href="#static_android.sensor.profileHueSatMapDimensions">android.sensor.profileHueSatMapDimensions</a></li>
             <li
             ><a href="#static_android.sensor.availableTestPatternModes">android.sensor.availableTestPatternModes</a></li>
+            <li
+            ><a href="#static_android.sensor.opticalBlackRegions">android.sensor.opticalBlackRegions</a></li>
+            <li
+            ><a href="#static_android.sensor.opaqueRawSize">android.sensor.opaqueRawSize</a></li>
           </ul>
         </li>
         <li>
             ><a href="#dynamic_android.sensor.testPatternMode">android.sensor.testPatternMode</a></li>
             <li
             ><a href="#dynamic_android.sensor.rollingShutterSkew">android.sensor.rollingShutterSkew</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.dynamicBlackLevel">android.sensor.dynamicBlackLevel</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.dynamicWhiteLevel">android.sensor.dynamicWhiteLevel</a></li>
           </ul>
         </li>
       </ul> <!-- toc_section -->
@@ -3943,11 +3957,20 @@ range capture hardware.<wbr/> In all cases,<wbr/> a single image is
 produced in response to a capture request submitted
 while in HDR mode.<wbr/></p>
 <p>Since substantial post-processing is generally needed to
-produce an HDR image,<wbr/> only YUV and JPEG outputs are
-supported for LIMITED/<wbr/>FULL device HDR captures,<wbr/> and only
-JPEG outputs are supported for LEGACY HDR
-captures.<wbr/> Using a RAW output for HDR capture is not
-supported.<wbr/></p></span>
+produce an HDR image,<wbr/> only YUV,<wbr/> PRIVATE,<wbr/> and JPEG
+outputs are supported for LIMITED/<wbr/>FULL device HDR
+captures,<wbr/> and only JPEG outputs are supported for LEGACY
+HDR captures.<wbr/> Using a RAW output for HDR capture is not
+supported.<wbr/></p>
+<p>Some devices may also support always-on HDR,<wbr/> which
+applies HDR processing at full frame rate.<wbr/>  For these
+devices,<wbr/> intents other than STILL_<wbr/>CAPTURE will also
+produce an HDR output with no frame rate impact compared
+to normal operation,<wbr/> though the quality may be lower
+than for STILL_<wbr/>CAPTURE intents.<wbr/></p>
+<p>If SCENE_<wbr/>MODE_<wbr/>HDR is used with unsupported output types
+or capture intents,<wbr/> the images captured will be as if
+the SCENE_<wbr/>MODE was not enabled at all.<wbr/></p></span>
                   </li>
                   <li>
                     <span class="entry_type_enum_name">FACE_PRIORITY_LOW_LIGHT</span>
@@ -3975,6 +3998,24 @@ reducing the noise level of the captured images.<wbr/></p>
 <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
 remain active when FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT is set.<wbr/></p></span>
                   </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_START</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">100</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_END</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">127</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
                 </ul>
 
             </td> <!-- entry_type -->
@@ -4121,6 +4162,70 @@ both at the same time.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="controls_android.control.postRawSensitivityBoost">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of additional sensitivity boost applied to output images
+after RAW sensor data is captured.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.postRawSensitivityBoostRange">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Some camera devices support additional digital sensitivity boosting in the
+camera processing pipeline after sensor RAW image is captured.<wbr/>
+Such a boost will be applied to YUV/<wbr/>JPEG format output images but will not
+have effect on RAW output formats like RAW_<wbr/>SENSOR,<wbr/> RAW10,<wbr/> RAW12 or RAW_<wbr/>OPAQUE.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>100</code> in this key.<wbr/></p>
+<p>If the camera device cannot apply the exact boost requested,<wbr/> it will reduce the
+boost to the nearest supported value.<wbr/>
+The final boost value used will be available in the output capture result.<wbr/></p>
+<p>For devices that support post RAW sensitivity boost,<wbr/> the YUV/<wbr/>JPEG output images
+of such device will have the total sensitivity of
+<code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> * <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> /<wbr/> 100</code>
+The sensitivity of RAW format images will always be <code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></code></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
@@ -4325,17 +4430,24 @@ this camera device.<wbr/></p>
             <td class="entry_details" colspan="5">
               <p>For devices at the LEGACY level or above:</p>
 <ul>
-<li>This list will always include (30,<wbr/> 30).<wbr/></li>
-<li>Also,<wbr/> for constant-framerate recording,<wbr/> for each normal
+<li>
+<p>For constant-framerate recording,<wbr/> for each normal
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,<wbr/> that is,<wbr/> a
 <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
 <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a> in
 the range [<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_<wbr/>LOW</a>,<wbr/>
 <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_<wbr/>2160P</a>],<wbr/> if the profile is
 supported by the device and has
 <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code>,<wbr/> this list will
-always include (<code>x</code>,<wbr/><code>x</code>).<wbr/></li>
-<li>For preview streaming use case,<wbr/> this list will always include (<code>min</code>,<wbr/> <code>max</code>) where
-<code>min</code> &lt;= 15 and <code>max</code> &gt;= 30.<wbr/></li>
+always include (<code>x</code>,<wbr/><code>x</code>).<wbr/></p>
+</li>
+<li>
+<p>Also,<wbr/> a camera device must either not support any
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,<wbr/>
+or support at least one
+normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code> &gt;= 24.<wbr/></p>
+</li>
 </ul>
 <p>For devices at the LIMITED level or above:</p>
 <ul>
@@ -4790,7 +4902,7 @@ mode camera devices.<wbr/></p>
                 <span class="entry_type_array">
                   3
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -4838,7 +4950,7 @@ this value must be &gt;= 1 for AE and AF.<wbr/> The order of the elements is:
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -4898,7 +5010,7 @@ maxRegions to have this entry be automatically populated.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -4957,7 +5069,7 @@ maxRegions to have this entry be automatically populated.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -5382,6 +5494,75 @@ devices will always support OFF,<wbr/> AUTO modes.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="static_android.control.postRawSensitivityBoostRange">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+
+
+                <div class="entry_type_notes">Range of supported post RAW sensitivitiy boosts</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Range of boosts for <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> supported
+by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Devices support post RAW sensitivity boost  will advertise
+<a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> key for controling
+post RAW sensitivity boost.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>(100,<wbr/> 100)</code> in this key.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key is added in HAL3.<wbr/>4.<wbr/> For HAL3.<wbr/>3 or earlier devices,<wbr/> camera framework will
+generate this key as <code>(100,<wbr/> 100)</code> if device supports any of RAW output formats.<wbr/>
+All HAL3.<wbr/>4 and above devices should list this key if device supports any of RAW
+output formats.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
@@ -8422,11 +8603,20 @@ range capture hardware.<wbr/> In all cases,<wbr/> a single image is
 produced in response to a capture request submitted
 while in HDR mode.<wbr/></p>
 <p>Since substantial post-processing is generally needed to
-produce an HDR image,<wbr/> only YUV and JPEG outputs are
-supported for LIMITED/<wbr/>FULL device HDR captures,<wbr/> and only
-JPEG outputs are supported for LEGACY HDR
-captures.<wbr/> Using a RAW output for HDR capture is not
-supported.<wbr/></p></span>
+produce an HDR image,<wbr/> only YUV,<wbr/> PRIVATE,<wbr/> and JPEG
+outputs are supported for LIMITED/<wbr/>FULL device HDR
+captures,<wbr/> and only JPEG outputs are supported for LEGACY
+HDR captures.<wbr/> Using a RAW output for HDR capture is not
+supported.<wbr/></p>
+<p>Some devices may also support always-on HDR,<wbr/> which
+applies HDR processing at full frame rate.<wbr/>  For these
+devices,<wbr/> intents other than STILL_<wbr/>CAPTURE will also
+produce an HDR output with no frame rate impact compared
+to normal operation,<wbr/> though the quality may be lower
+than for STILL_<wbr/>CAPTURE intents.<wbr/></p>
+<p>If SCENE_<wbr/>MODE_<wbr/>HDR is used with unsupported output types
+or capture intents,<wbr/> the images captured will be as if
+the SCENE_<wbr/>MODE was not enabled at all.<wbr/></p></span>
                   </li>
                   <li>
                     <span class="entry_type_enum_name">FACE_PRIORITY_LOW_LIGHT</span>
@@ -8454,6 +8644,24 @@ reducing the noise level of the captured images.<wbr/></p>
 <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
 remain active when FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT is set.<wbr/></p></span>
                   </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_START</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">100</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_END</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">127</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
                 </ul>
 
             </td> <!-- entry_type -->
@@ -8600,6 +8808,70 @@ both at the same time.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="dynamic_android.control.postRawSensitivityBoost">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of additional sensitivity boost applied to output images
+after RAW sensor data is captured.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.postRawSensitivityBoostRange">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Some camera devices support additional digital sensitivity boosting in the
+camera processing pipeline after sensor RAW image is captured.<wbr/>
+Such a boost will be applied to YUV/<wbr/>JPEG format output images but will not
+have effect on RAW output formats like RAW_<wbr/>SENSOR,<wbr/> RAW10,<wbr/> RAW12 or RAW_<wbr/>OPAQUE.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>100</code> in this key.<wbr/></p>
+<p>If the camera device cannot apply the exact boost requested,<wbr/> it will reduce the
+boost to the nearest supported value.<wbr/>
+The final boost value used will be available in the output capture result.<wbr/></p>
+<p>For devices that support post RAW sensitivity boost,<wbr/> the YUV/<wbr/>JPEG output images
+of such device will have the total sensitivity of
+<code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> * <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> /<wbr/> 100</code>
+The sensitivity of RAW format images will always be <code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></code></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
@@ -10194,7 +10466,7 @@ are stuck at an arbitrary value or are oversensitive).<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">byte</span>
 
-              <span class="entry_type_visibility"> [public as location]</span>
+              <span class="entry_type_visibility"> [java_public as location]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -10247,7 +10519,7 @@ viewed by anyone who receives the JPEG image.<wbr/></p>
                 <span class="entry_type_array">
                   3
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -10291,7 +10563,7 @@ EXIF.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">byte</span>
 
-              <span class="entry_type_visibility"> [hidden as string]</span>
+              <span class="entry_type_visibility"> [ndk_public as string]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -10334,7 +10606,7 @@ include in EXIF.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int64</span>
 
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -10806,7 +11078,7 @@ JPEG</p>
             <td class="entry_type">
                 <span class="entry_type_name">byte</span>
 
-              <span class="entry_type_visibility"> [public as location]</span>
+              <span class="entry_type_visibility"> [java_public as location]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -10859,7 +11131,7 @@ viewed by anyone who receives the JPEG image.<wbr/></p>
                 <span class="entry_type_array">
                   3
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -10903,7 +11175,7 @@ EXIF.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">byte</span>
 
-              <span class="entry_type_visibility"> [hidden as string]</span>
+              <span class="entry_type_visibility"> [ndk_public as string]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -10946,7 +11218,7 @@ include in EXIF.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int64</span>
 
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -12045,7 +12317,7 @@ the MANUAL_<wbr/>SENSOR capability.<wbr/></p>
                 <span class="entry_type_array">
                   2
                 </span>
-              <span class="entry_type_visibility"> [hidden as size]</span>
+              <span class="entry_type_visibility"> [ndk_public as size]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -14654,7 +14926,7 @@ REPROCESS.<wbr/> For HAL3,<wbr/> this tag is redundant.<wbr/></p>
                 <span class="entry_type_array">
                   3
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -14728,7 +15000,7 @@ into the 3 stream types as below:</p>
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -14791,7 +15063,7 @@ never support raw streams.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -14859,7 +15131,7 @@ processed format -- it will return 0 for a non-stalling stream.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -15642,7 +15914,7 @@ DEPTH).<wbr/></p>
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -15715,7 +15987,7 @@ via
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -15796,7 +16068,7 @@ here or in the vendor tag list.<wbr/></p>
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -16405,8 +16677,10 @@ the full set of performance guarantees.<wbr/></p></span>
                     <span class="entry_type_enum_name">RAW_OPAQUE</span>
                     <span class="entry_type_enum_optional">[optional]</span>
                     <span class="entry_type_enum_value">0x24</span>
-                    <span class="entry_type_enum_notes"><p>RAW_<wbr/>OPAQUE is a format for raw image buffers coming from an
-image sensor.<wbr/></p>
+                    <span class="entry_type_enum_notes"><p>RAW_<wbr/>OPAQUE (or
+<a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW_PRIVATE">RAW_<wbr/>PRIVATE</a>
+as referred in public API) is a format for raw image buffers
+coming from an image sensor.<wbr/></p>
 <p>The actual structure of buffers of this format is
 platform-specific,<wbr/> but must follow several constraints:</p>
 <ol>
@@ -17100,7 +17374,7 @@ additional formats if it so chooses.<wbr/></p>
                 <span class="entry_type_array">
                   n x 4
                 </span>
-              <span class="entry_type_visibility"> [hidden as streamConfiguration]</span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfiguration]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -17287,7 +17561,7 @@ YUV_<wbr/>420_<wbr/>888 must also be available for IMPLEMENTATION_<wbr/>DEFINED.
                 <span class="entry_type_array">
                   4 x n
                 </span>
-              <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -17353,7 +17627,7 @@ calculating the max frame rate.<wbr/></p>
                 <span class="entry_type_array">
                   4 x n
                 </span>
-              <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -17469,7 +17743,7 @@ and IMPLEMENTATION_<wbr/>DEFINED must not have stall durations.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public as streamConfigurationMap]</span>
+              <span class="entry_type_visibility"> [java_public as streamConfigurationMap]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -18135,6 +18409,8 @@ is guaranteed to use only analog amplification for applying the gain.<wbr/></p>
 requested,<wbr/> it will reduce the gain to the nearest supported
 value.<wbr/> The final sensitivity used will be available in the
 output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
             </td>
           </tr>
 
@@ -18918,6 +19194,11 @@ each channel is specified by the offset in the
 (8-14 bits is expected),<wbr/> or by the point where the sensor response
 becomes too non-linear to be useful.<wbr/>  The default value for this is
 maximum representable value for a 16-bit raw sample (2^16 - 1).<wbr/></p>
+<p>The white level values of captured images may vary for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> This key
+represents a coarse approximation for such case.<wbr/> It is recommended
+to use <a href="#dynamic_android.sensor.dynamicWhiteLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level</a> for captures when supported
+by the camera device,<wbr/> which provides more accurate white level values.<wbr/></p>
             </td>
           </tr>
 
@@ -19886,6 +20167,15 @@ sensor is represented by the value in <a href="#static_android.sensor.info.white
 layout key (see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>),<wbr/> i.<wbr/>e.<wbr/> the
 nth value given corresponds to the black level offset for the nth
 color channel listed in the CFA.<wbr/></p>
+<p>The black level values of captured images may vary for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> This key
+represents a coarse approximation for such case.<wbr/> It is recommended to
+use <a href="#dynamic_android.sensor.dynamicBlackLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level</a> or use pixels from
+<a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> directly for captures when
+supported by the camera device,<wbr/> which provides more accurate black
+level values.<wbr/> For raw capture in particular,<wbr/> it is recommended to use
+pixels from <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> to calculate black
+level values for each frame.<wbr/></p>
             </td>
           </tr>
 
@@ -20130,6 +20420,152 @@ supported by this camera device.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="static_android.sensor.opticalBlackRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x num_regions
+                </span>
+              <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of disjoint rectangles indicating the sensor
+optically shielded black pixel regions.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>In most camera sensors,<wbr/> the active array is surrounded by some
+optically shielded pixel areas.<wbr/> By blocking light,<wbr/> these pixels
+provides a reliable black reference for black level compensation
+in active array region.<wbr/></p>
+<p>This key provides a list of disjoint rectangles specifying the
+regions of optically shielded (with metal shield) black pixel
+regions if the camera device is capable of reading out these black
+pixels in the output raw images.<wbr/> In comparison to the fixed black
+level values reported by <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a>,<wbr/> this key
+may provide a more accurate way for the application to calculate
+black level of each captured raw images.<wbr/></p>
+<p>When this key is reported,<wbr/> the <a href="#dynamic_android.sensor.dynamicBlackLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level</a> and
+<a href="#dynamic_android.sensor.dynamicWhiteLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level</a> will also be reported.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This array contains (xmin,<wbr/> ymin,<wbr/> width,<wbr/> height).<wbr/> The (xmin,<wbr/> ymin)
+must be &gt;= (0,<wbr/>0) and &lt;=
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/> The (width,<wbr/> height) must be
+&lt;= <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/> Each region must be
+outside the region reported by
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>The HAL must report minimal number of disjoint regions for the
+optically shielded back pixel regions.<wbr/> For example,<wbr/> if a region can
+be covered by one rectangle,<wbr/> the HAL must not split this region into
+multiple rectangles.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.opaqueRawSize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>opaque<wbr/>Raw<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 3
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Size in bytes for all the listed opaque RAW buffer sizes</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Must be large enough to fit the opaque RAW of corresponding size produced by
+the camera</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This configurations are listed as <code>(width,<wbr/> height,<wbr/> size_<wbr/>in_<wbr/>bytes)</code> tuples.<wbr/>
+This is used for sizing the gralloc buffers for opaque RAW buffers.<wbr/>
+All RAW_<wbr/>OPAQUE output stream configuration listed in
+<a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> will have a corresponding tuple in
+this key.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key is added in HAL3.<wbr/>4.<wbr/>
+For HAL3.<wbr/>4 or above: devices advertising RAW_<wbr/>OPAQUE format output must list this key.<wbr/>
+For HAL3.<wbr/>3 or earlier devices: if RAW_<wbr/>OPAQUE ouput is advertised,<wbr/> camera framework
+will derive this key by assuming each pixel takes two bytes and no padding bytes
+between rows.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
@@ -20397,6 +20833,8 @@ is guaranteed to use only analog amplification for applying the gain.<wbr/></p>
 requested,<wbr/> it will reduce the gain to the nearest supported
 value.<wbr/> The final sensitivity used will be available in the
 output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
             </td>
           </tr>
 
@@ -21181,6 +21619,160 @@ exposure at the same time.<wbr/></p>
           <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
            <!-- end of entry -->
         
+                
+          <tr class="entry" id="dynamic_android.sensor.dynamicBlackLevel">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+                <div class="entry_type_notes">2x2 raw count block</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A per-frame dynamic black level offset for each of the color filter
+arrangement (CFA) mosaic channels.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0 for each.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Camera sensor black levels may vary dramatically for different
+capture settings (e.<wbr/>g.<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> The fixed black
+level reported by <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may be too
+inaccurate to represent the actual value on a per-frame basis.<wbr/> The
+camera device internal pipeline relies on reliable black level values
+to process the raw images appropriately.<wbr/> To get the best image
+quality,<wbr/> the camera device may choose to estimate the per frame black
+level values either based on optically shielded black regions
+(<a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a>) or its internal model.<wbr/></p>
+<p>This key reports the camera device estimated per-frame zero light
+value for each of the CFA mosaic channels in the camera sensor.<wbr/> The
+<a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may only represent a coarse
+approximation of the actual black level values.<wbr/> This value is the
+black level used in camera device internal image processing pipeline
+and generally more accurate than the fixed black level values.<wbr/>
+However,<wbr/> since they are estimated values by the camera device,<wbr/> they
+may not be as accurate as the black level values calculated from the
+optical black pixels reported by <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a>.<wbr/></p>
+<p>The values are given in the same order as channels listed for the CFA
+layout key (see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>),<wbr/> i.<wbr/>e.<wbr/> the
+nth value given corresponds to the black level offset for the nth
+color channel listed in the CFA.<wbr/></p>
+<p>This key will be available if <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> is
+available or the camera device advertises this key via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys">CameraCharacteristics#getAvailableCaptureResultKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The values are given in row-column scan order,<wbr/> with the first value
+corresponding to the element of the CFA in row=0,<wbr/> column=0.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.dynamicWhiteLevel">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum raw value output by sensor for this frame.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Since the <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may change for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>),<wbr/> the white
+level will change accordingly.<wbr/> This key is similar to
+<a href="#static_android.sensor.info.whiteLevel">android.<wbr/>sensor.<wbr/>info.<wbr/>white<wbr/>Level</a>,<wbr/> but specifies the camera device
+estimated white level for each frame.<wbr/></p>
+<p>This key will be available if <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> is
+available or the camera device advertises this key via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The full bit depth of the sensor must be available in the raw data,<wbr/>
+so the value for linear sensors should not be significantly lower
+than maximum raw value supported,<wbr/> i.<wbr/>e.<wbr/> 2^(sensor bits per pixel).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
         
 
       <!-- end of kind -->
@@ -22423,7 +23015,7 @@ FULL mode must also fill in <a href="#dynamic_android.statistics.faceIds">androi
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -22479,7 +23071,7 @@ assigned a new ID.<wbr/></p>
                 <span class="entry_type_array">
                   n x 6
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -22536,7 +23128,7 @@ faces.<wbr/></p>
                 <span class="entry_type_array">
                   n x 4
                 </span>
-              <span class="entry_type_visibility"> [hidden as rectangle]</span>
+              <span class="entry_type_visibility"> [ndk_public as rectangle]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -22593,7 +23185,7 @@ faces.<wbr/></p>
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -22657,7 +23249,7 @@ all times is illegal).<wbr/></p>
                 <span class="entry_type_array">
                   n
                 </span>
-              <span class="entry_type_visibility"> [public as face]</span>
+              <span class="entry_type_visibility"> [java_public as face]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -23003,7 +23595,7 @@ image of a gray wall (using bicubic interpolation for visual quality) as capture
                 <span class="entry_type_array">
                   4 x n x m
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -23016,8 +23608,8 @@ image of a gray wall (using bicubic interpolation for visual quality) as capture
 
             <td class="entry_description">
               <p>The shading map is a low-resolution floating-point map
-that lists the coefficients used to correct for vignetting,<wbr/> for each
-Bayer color channel of RAW image data.<wbr/></p>
+that lists the coefficients used to correct for vignetting and color shading,<wbr/>
+for each Bayer color channel of RAW image data.<wbr/></p>
             </td>
 
             <td class="entry_units">
@@ -23036,8 +23628,18 @@ Bayer color channel of RAW image data.<wbr/></p>
           </tr>
           <tr class="entry_cont">
             <td class="entry_details" colspan="5">
-              <p>The least shaded section of the image should have a gain factor
-of 1; all other sections should have gains above 1.<wbr/></p>
+              <p>The lens shading correction is defined as a full shading correction that
+corrects both color shading for the output non-RAW images.<wbr/> After the
+shading map is applied,<wbr/> the output non-RAW images will be flat-field images
+for flat scenes under uniform illumination.<wbr/></p>
+<p>When there is no lens shading correction applied to RAW output images
+(<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> <code>==</code> false),<wbr/> this map is a full lens
+shading correction map; when there is some lens shading correction applied
+to the RAW output image (<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> <code>==</code> true),<wbr/>
+this map reports the remaining lens shading correction map that needs to be
+applied to get fully shading corrected images.<wbr/></p>
+<p>For a full shading correction map,<wbr/> the least shaded section of the image
+should have a gain factor of 1; all other sections should have gains above 1.<wbr/></p>
 <p>When <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> = TRANSFORM_<wbr/>MATRIX,<wbr/> the map
 must take into account the colorCorrection settings.<wbr/></p>
 <p>The shading map is for the entire active pixel array,<wbr/> and is not
@@ -23557,7 +24159,7 @@ the output result metadata.<wbr/></p>
                 <span class="entry_type_array">
                   n x 2
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -23610,7 +24212,7 @@ CONTRAST_<wbr/>CURVE.<wbr/></p>
                 <span class="entry_type_array">
                   n x 2
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -23663,7 +24265,7 @@ CONTRAST_<wbr/>CURVE.<wbr/></p>
                 <span class="entry_type_array">
                   n x 2
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -23764,7 +24366,7 @@ control points used as are available.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">float</span>
 
-              <span class="entry_type_visibility"> [public as tonemapCurve]</span>
+              <span class="entry_type_visibility"> [java_public as tonemapCurve]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -24271,7 +24873,7 @@ capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same outp
                 <span class="entry_type_array">
                   n x 2
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -24324,7 +24926,7 @@ CONTRAST_<wbr/>CURVE.<wbr/></p>
                 <span class="entry_type_array">
                   n x 2
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -24377,7 +24979,7 @@ CONTRAST_<wbr/>CURVE.<wbr/></p>
                 <span class="entry_type_array">
                   n x 2
                 </span>
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[full] </span>
@@ -24478,7 +25080,7 @@ control points used as are available.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">float</span>
 
-              <span class="entry_type_visibility"> [public as tonemapCurve]</span>
+              <span class="entry_type_visibility"> [java_public as tonemapCurve]</span>
 
               <span class="entry_type_synthetic">[synthetic] </span>
 
@@ -25080,15 +25682,75 @@ doesn't violate the above rules.<wbr/></p>
                 <ul class="entry_type_enum">
                   <li>
                     <span class="entry_type_enum_name">LIMITED</span>
-                    <span class="entry_type_enum_notes"><p>This camera device has only limited capabilities.<wbr/></p></span>
+                    <span class="entry_type_enum_notes"><p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
+better.<wbr/></p>
+<p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a> documentation are guaranteed to be supported.<wbr/></p>
+<p>All <code>LIMITED</code> devices support the <code>BACKWARDS_<wbr/>COMPATIBLE</code> capability,<wbr/> indicating basic
+support for color image capture.<wbr/> The only exception is that the device may
+alternatively support only the <code>DEPTH_<wbr/>OUTPUT</code> capability,<wbr/> if it can only output depth
+measurements and not color images.<wbr/></p>
+<p><code>LIMITED</code> devices and above require the use of <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>
+to lock exposure metering (and calculate flash power,<wbr/> for cameras with flash) before
+capturing a high-quality still image.<wbr/></p>
+<p>A <code>LIMITED</code> device that only lists the <code>BACKWARDS_<wbr/>COMPATIBLE</code> capability is only
+required to support full-automatic operation and post-processing (<code>OFF</code> is not
+supported for <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>,<wbr/> or
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>)</p>
+<p>Additional capabilities may optionally be supported by a <code>LIMITED</code>-level device,<wbr/> and
+can be checked for in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p></span>
                   </li>
                   <li>
                     <span class="entry_type_enum_name">FULL</span>
-                    <span class="entry_type_enum_notes"><p>This camera device is capable of supporting advanced imaging applications.<wbr/></p></span>
+                    <span class="entry_type_enum_notes"><p>This camera device is capable of supporting advanced imaging applications.<wbr/></p>
+<p>The stream configurations listed in the <code>FULL</code>,<wbr/> <code>LEGACY</code> and <code>LIMITED</code> tables in the
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a> documentation are guaranteed to be supported.<wbr/></p>
+<p>A <code>FULL</code> device will support below capabilities:</p>
+<ul>
+<li><code>BURST_<wbr/>CAPTURE</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>BURST_<wbr/>CAPTURE</code>)</li>
+<li>Per frame control (<a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> <code>==</code> PER_<wbr/>FRAME_<wbr/>CONTROL)</li>
+<li>Manual sensor control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains <code>MANUAL_<wbr/>SENSOR</code>)</li>
+<li>Manual post-processing control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>MANUAL_<wbr/>POST_<wbr/>PROCESSING</code>)</li>
+<li>The required exposure time range defined in <a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></li>
+<li>The required maxFrameDuration defined in <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a></li>
+</ul>
+<p>Note:
+Pre-API level 23,<wbr/> FULL devices also supported arbitrary cropping region
+(<a href="#static_android.scaler.croppingType">android.<wbr/>scaler.<wbr/>cropping<wbr/>Type</a> <code>== FREEFORM</code>); this requirement was relaxed in API level
+23,<wbr/> and <code>FULL</code> devices may only support <code>CENTERED</code> cropping.<wbr/></p></span>
                   </li>
                   <li>
                     <span class="entry_type_enum_name">LEGACY</span>
-                    <span class="entry_type_enum_notes"><p>This camera device is running in backward compatibility mode.<wbr/></p></span>
+                    <span class="entry_type_enum_notes"><p>This camera device is running in backward compatibility mode.<wbr/></p>
+<p>Only the stream configurations listed in the <code>LEGACY</code> table in the <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a>
+documentation are supported.<wbr/></p>
+<p>A <code>LEGACY</code> device does not support per-frame control,<wbr/> manual sensor control,<wbr/> manual
+post-processing,<wbr/> arbitrary cropping regions,<wbr/> and has relaxed performance constraints.<wbr/>
+No additional capabilities beyond <code>BACKWARD_<wbr/>COMPATIBLE</code> will ever be listed by a
+<code>LEGACY</code> device in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+<p>In addition,<wbr/> the <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is not functional on <code>LEGACY</code>
+devices.<wbr/> Instead,<wbr/> every request that includes a JPEG-format output target is treated
+as triggering a still capture,<wbr/> internally executing a precapture trigger.<wbr/>  This may
+fire the flash for flash power metering during precapture,<wbr/> and then fire the flash
+for the final capture,<wbr/> if a flash is available on the device and the AE mode is set to
+enable the flash.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">3</span>
+                    <span class="entry_type_enum_notes"><p>This camera device is capable of YUV reprocessing and RAW data capture,<wbr/> in addition to
+FULL-level capabilities.<wbr/></p>
+<p>The stream configurations listed in the <code>LEVEL_<wbr/>3</code>,<wbr/> <code>RAW</code>,<wbr/> <code>FULL</code>,<wbr/> <code>LEGACY</code> and
+<code>LIMITED</code> tables in the <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a>
+documentation are guaranteed to be supported.<wbr/></p>
+<p>The following additional capabilities are guaranteed to be supported:</p>
+<ul>
+<li><code>YUV_<wbr/>REPROCESSING</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>YUV_<wbr/>REPROCESSING</code>)</li>
+<li><code>RAW</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>RAW</code>)</li>
+</ul></span>
                   </li>
                 </ul>
 
@@ -25113,22 +25775,39 @@ doesn't violate the above rules.<wbr/></p>
           </tr>
           <tr class="entry_cont">
             <td class="entry_details" colspan="5">
-              <p>Camera devices will come in three flavors: LEGACY,<wbr/> LIMITED and FULL.<wbr/></p>
-<p>A FULL device will support below capabilities:</p>
+              <p>The supported hardware level is a high-level description of the camera device's
+capabilities,<wbr/> summarizing several capabilities into one field.<wbr/>  Each level adds additional
+features to the previous one,<wbr/> and is always a strict superset of the previous level.<wbr/>
+The ordering is <code>LEGACY &lt; LIMITED &lt; FULL &lt; LEVEL_<wbr/>3</code>.<wbr/></p>
+<p>Starting from <code>LEVEL_<wbr/>3</code>,<wbr/> the level enumerations are guaranteed to be in increasing
+numerical value as well.<wbr/> To check if a given device is at least at a given hardware level,<wbr/>
+the following code snippet can be used:</p>
+<pre><code>//<wbr/> Returns true if the device supports the required hardware level,<wbr/> or better.<wbr/>
+boolean isHardwareLevelSupported(CameraCharacteristics c,<wbr/> int requiredLevel) {
+    int deviceLevel = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>INFO_<wbr/>SUPPORTED_<wbr/>HARDWARE_<wbr/>LEVEL);
+    if (deviceLevel == Camera<wbr/>Characteristics.<wbr/>INFO_<wbr/>SUPPORTED_<wbr/>HARDWARE_<wbr/>LEVEL_<wbr/>LEGACY) {
+        return requiredLevel == deviceLevel;
+    }
+    //<wbr/> deviceLevel is not LEGACY,<wbr/> can use numerical sort
+    return requiredLevel &lt;= deviceLevel;
+}
+</code></pre>
+<p>At a high level,<wbr/> the levels are:</p>
 <ul>
-<li>BURST_<wbr/>CAPTURE capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains BURST_<wbr/>CAPTURE)</li>
-<li>Per frame control (<a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> <code>==</code> PER_<wbr/>FRAME_<wbr/>CONTROL)</li>
-<li>Manual sensor control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains MANUAL_<wbr/>SENSOR)</li>
-<li>Manual post-processing control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
-  MANUAL_<wbr/>POST_<wbr/>PROCESSING)</li>
-<li>At least 3 processed (but not stalling) format output streams
-  (<a href="#static_android.request.maxNumOutputProc">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Proc</a> <code>&gt;=</code> 3)</li>
-<li>The required stream configurations defined in <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a></li>
-<li>The required exposure time range defined in <a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></li>
-<li>The required maxFrameDuration defined in <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a></li>
+<li><code>LEGACY</code> devices operate in a backwards-compatibility mode for older
+  Android devices,<wbr/> and have very limited capabilities.<wbr/></li>
+<li><code>LIMITED</code> devices represent the
+  baseline feature set,<wbr/> and may also include additional capabilities that are
+  subsets of <code>FULL</code>.<wbr/></li>
+<li><code>FULL</code> devices additionally support per-frame manual control of sensor,<wbr/> flash,<wbr/> lens and
+  post-processing settings,<wbr/> and image capture at a high rate.<wbr/></li>
+<li><code>LEVEL_<wbr/>3</code> devices additionally support YUV reprocessing and RAW image capture,<wbr/> along
+  with additional output stream configurations.<wbr/></li>
 </ul>
-<p>A LIMITED device may have some or none of the above characteristics.<wbr/>
-To find out more refer to <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+<p>See the individual level enums for full descriptions of the supported capabilities.<wbr/>  The
+<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> entry describes the device's capabilities at a
+finer-grain level,<wbr/> if needed.<wbr/> In addition,<wbr/> many controls have their available settings or
+ranges defined in individual <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a> entries.<wbr/></p>
 <p>Some features are not part of any particular hardware level or capability and must be
 queried separately.<wbr/> These include:</p>
 <ul>
@@ -25139,14 +25818,6 @@ queried separately.<wbr/> These include:</p>
   (<a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a>,<wbr/>
    <a href="#static_android.control.availableVideoStabilizationModes">android.<wbr/>control.<wbr/>available<wbr/>Video<wbr/>Stabilization<wbr/>Modes</a>)</li>
 </ul>
-<p>A LEGACY device does not support per-frame control,<wbr/> manual sensor control,<wbr/> manual
-post-processing,<wbr/> arbitrary cropping regions,<wbr/> and has relaxed performance constraints.<wbr/></p>
-<p>Each higher level supports everything the lower level supports
-in this order: FULL <code>&gt;</code> LIMITED <code>&gt;</code> LEGACY.<wbr/></p>
-<p>Note:
-Pre-API level 23,<wbr/> FULL devices also supported arbitrary cropping region
-(<a href="#static_android.scaler.croppingType">android.<wbr/>scaler.<wbr/>cropping<wbr/>Type</a> <code>==</code> FREEFORM); this requirement was relaxed in API level 23,<wbr/>
-and FULL devices may only support CENTERED cropping.<wbr/></p>
             </td>
           </tr>
 
@@ -25155,17 +25826,16 @@ and FULL devices may only support CENTERED cropping.<wbr/></p>
           </tr>
           <tr class="entry_cont">
             <td class="entry_details" colspan="5">
-              <p>The camera 3 HAL device can implement one of two possible
-operational modes; limited and full.<wbr/> Full support is
-expected from new higher-end devices.<wbr/> Limited mode has
-hardware requirements roughly in line with those for a
-camera HAL device v1 implementation,<wbr/> and is expected from
-older or inexpensive devices.<wbr/> Full is a strict superset of
-limited,<wbr/> and they share the same essential operational flow.<wbr/></p>
+              <p>The camera 3 HAL device can implement one of three possible operational modes; LIMITED,<wbr/>
+FULL,<wbr/> and LEVEL_<wbr/>3.<wbr/></p>
+<p>FULL support or better is expected from new higher-end devices.<wbr/> Limited
+mode has hardware requirements roughly in line with those for a camera HAL device v1
+implementation,<wbr/> and is expected from older or inexpensive devices.<wbr/> Each level is a strict
+superset of the previous level,<wbr/> and they share the same essential operational flow.<wbr/></p>
 <p>For full details refer to "S3.<wbr/> Operational Modes" in camera3.<wbr/>h</p>
-<p>Camera HAL3+ must not implement LEGACY mode.<wbr/> It is there
-for backwards compatibility in the <code>android.<wbr/>hardware.<wbr/>camera2</code>
-user-facing API only.<wbr/></p>
+<p>Camera HAL3+ must not implement LEGACY mode.<wbr/> It is there for backwards compatibility in
+the <code>android.<wbr/>hardware.<wbr/>camera2</code> user-facing API only on HALv1 devices,<wbr/> and is implemented
+by the camera framework code.<wbr/></p>
             </td>
           </tr>
 
@@ -25451,7 +26121,7 @@ possible again.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name entry_type_name_enum">int64</span>
 
-              <span class="entry_type_visibility"> [hidden]</span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
 
 
               <span class="entry_type_hwlevel">[legacy] </span>
@@ -25712,7 +26382,7 @@ where resultN has frameNumber N.<wbr/>
 <code>4 - 2 = 2</code>.<wbr/></p>
 <p>Use <code>frame_<wbr/>count</code> from camera3_<wbr/>request_<wbr/>t instead of
 <a href="#controls_android.request.frameCount">android.<wbr/>request.<wbr/>frame<wbr/>Count</a> or
-<code>@link{android.<wbr/>hardware.<wbr/>camera2.<wbr/>Capture<wbr/>Result#get<wbr/>Frame<wbr/>Number}</code>.<wbr/></p>
+<code><a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html#getFrameNumber">CaptureResult#getFrameNumber</a></code>.<wbr/></p>
 <p>LIMITED devices are strongly encouraged to use a non-negative
 value.<wbr/> If UNKNOWN is used here then app developers do not have a way
 to know when sensor settings have been applied.<wbr/></p>
@@ -25763,7 +26433,7 @@ to know when sensor settings have been applied.<wbr/></p>
             <td class="entry_type">
                 <span class="entry_type_name">float</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
 
               <span class="entry_type_hwlevel">[limited] </span>
@@ -25871,7 +26541,7 @@ Similarly,<wbr/> for edge enhancement reprocessing,<wbr/> it is only effective w
             <td class="entry_type">
                 <span class="entry_type_name">float</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
 
               <span class="entry_type_hwlevel">[limited] </span>
@@ -25979,7 +26649,7 @@ Similarly,<wbr/> for edge enhancement reprocessing,<wbr/> it is only effective w
             <td class="entry_type">
                 <span class="entry_type_name">int32</span>
 
-              <span class="entry_type_visibility"> [public]</span>
+              <span class="entry_type_visibility"> [java_public]</span>
 
 
               <span class="entry_type_hwlevel">[limited] </span>
@@ -26137,7 +26807,7 @@ not be defined.<wbr/></p>
                 <span class="entry_type_array">
                   n x 4
                 </span>
-              <span class="entry_type_visibility"> [hidden as streamConfiguration]</span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfiguration]</span>
 
 
               <span class="entry_type_hwlevel">[limited] </span>
@@ -26210,7 +26880,7 @@ the entries for HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>Y16.<wbr/></p>
                 <span class="entry_type_array">
                   4 x n
                 </span>
-              <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
 
 
               <span class="entry_type_hwlevel">[limited] </span>
@@ -26275,7 +26945,7 @@ calculating the max frame rate.<wbr/></p>
                 <span class="entry_type_array">
                   4 x n
                 </span>
-              <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
 
 
               <span class="entry_type_hwlevel">[limited] </span>
@@ -26549,6 +27219,8 @@ corrupted during depth measurement.<wbr/></p>
           <li><a href="#dynamic_android.sensor.profileHueSatMap">android.sensor.profileHueSatMap</a> (dynamic)</li>
           <li><a href="#dynamic_android.sensor.profileToneCurve">android.sensor.profileToneCurve</a> (dynamic)</li>
           <li><a href="#dynamic_android.sensor.greenSplit">android.sensor.greenSplit</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.dynamicBlackLevel">android.sensor.dynamicBlackLevel</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.dynamicWhiteLevel">android.sensor.dynamicWhiteLevel</a> (dynamic)</li>
           <li><a href="#controls_android.statistics.hotPixelMapMode">android.statistics.hotPixelMapMode</a> (controls)</li>
           <li><a href="#static_android.statistics.info.availableHotPixelMapModes">android.statistics.info.availableHotPixelMapModes</a> (static)</li>
           <li><a href="#dynamic_android.statistics.hotPixelMap">android.statistics.hotPixelMap</a> (dynamic)</li>
index b117a5a..113a38d 100644 (file)
@@ -18,7 +18,7 @@
 <head>
   <!-- automatically generated from html.mako. do NOT edit directly -->
   <meta charset="utf-8" />
-  <title>Android Camera HAL3.2 Properties</title>
+  <title>Android Camera HAL3.4 Properties</title>
   <style type="text/css">
      body { background-color: #f7f7f7; font-family: Roboto, sans-serif;}
      h1 { color: #333333; }
index fd21fbd..a013eaf 100755 (executable)
@@ -21,7 +21,9 @@
 #   docs.html
 #   ../src/camera_metadata_tag_info.c
 #   ../src/camera_metadata_tags.h
-#   ../../../../cts/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
+#   ../../../../frameworks/av/include/camera/ndk/NdkCameraMetadataTags.h
+#   ../../../../frameworks/av/camera/ndk/impl/ACameraMetadata.cpp
+#   ../../../../cts/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
 #   ../../../../frameworks/base/core/java/android/hardware/camera2/CameraCharacteristics.java
 #   ../../../../frameworks/base/core/java/android/hardware/camera2/CaptureRequest.java
 #   ../../../../frameworks/base/core/java/android/hardware/camera2/CaptureResult.java
@@ -34,8 +36,12 @@ fi
 thisdir=$(cd "$(dirname "$0")"; pwd)
 fwkdir="$ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/camera2/"
 fwkdir_html="$ANDROID_BUILD_TOP/frameworks/base/docs/html"
-ctsdir="$ANDROID_BUILD_TOP/cts/tests/tests/hardware/src/android/hardware/camera2/cts"
+ctsdir="$ANDROID_BUILD_TOP/cts/tests/camera/src/android/hardware/camera2/cts"
 outdir="$ANDROID_PRODUCT_OUT/obj/ETC/system-media-camera-docs_intermediates"
+ndk_header_dir="$ANDROID_BUILD_TOP/frameworks/av/include/camera/ndk"
+ndk_impl_dir="$ANDROID_BUILD_TOP/frameworks/av/camera/ndk/impl"
+device_info_dir="$ANDROID_BUILD_TOP/cts/tools/cts-device-info/"`
+        `"src/com/android/cts/deviceinfo"
 out_files=()
 
 function relpath() {
@@ -190,20 +196,36 @@ gen_file html.mako docs.html || exit 1
 gen_file camera_metadata_tag_info.mako ../src/camera_metadata_tag_info.c || exit 1
 gen_file camera_metadata_tags.mako ../include/system/camera_metadata_tags.h || exit 1
 
+#Generate NDK header
+gen_file_abs ndk_camera_metadata_tags.mako "$ndk_header_dir/NdkCameraMetadataTags.h" || exit 1
+
 # Generate Java API definitions
 mkdir -p "${outdir}"
 gen_file_abs CameraMetadataEnums.mako "$outdir/CameraMetadataEnums.java.part" no || exit 1
 gen_file_abs CameraCharacteristicsKeys.mako "$outdir/CameraCharacteristicsKeys.java.part" no || exit 1
 gen_file_abs CaptureRequestKeys.mako "$outdir/CaptureRequestKeys.java.part" no || exit 1
 gen_file_abs CaptureResultKeys.mako "$outdir/CaptureResultKeys.java.part" no || exit 1
-gen_file_abs CaptureResultTest.mako "$outdir/CaptureResultTest.java.part" no || exit 1
 
 insert_file "$outdir/CameraMetadataEnums.java.part" "$fwkdir/CameraMetadata.java" || exit 1
 insert_file "$outdir/CameraCharacteristicsKeys.java.part" "$fwkdir/CameraCharacteristics.java" || exit 1
 insert_file "$outdir/CaptureRequestKeys.java.part" "$fwkdir/CaptureRequest.java" || exit 1
 insert_file "$outdir/CaptureResultKeys.java.part" "$fwkdir/CaptureResult.java" || exit 1
+
+# Generate CTS test code
+gen_file_abs CaptureResultTest.mako "$outdir/CaptureResultTest.java.part" no || exit 1
 insert_file "$outdir/CaptureResultTest.java.part" "$ctsdir/CaptureResultTest.java" || exit 1
 
+# Generate NDK implementation
+gen_file_abs ACameraMetadata.mako "$outdir/ACameraMetadata.cpp.part" no || exit 1
+insert_file "$outdir/ACameraMetadata.cpp.part" "$ndk_impl_dir/ACameraMetadata.cpp" || exit 1
+
+# Generate CameraDeviceInfo code
+gen_file_abs CameraDeviceInfo.mako "$outdir/CameraDeviceInfo.java.part" no || exit 1
+insert_file "$outdir/CameraDeviceInfo.java.part" "$device_info_dir/CameraDeviceInfo.java" || exit 1
+
+# Generate protocol buffer definition corresponding to CameraDeviceInfo
+gen_file camera_device_info.mako ./camera_device_info.proto || exit 1
+
 # Copy ./images directory into javadoc directory
 copy_directory "images" "$fwkdir_html" || exit 1
 
index 9a6fe9b..3ebaf26 100644 (file)
@@ -127,6 +127,86 @@ def path_name(node):
 
   return ".".join((i.name for i in path))
 
+def ndk(name):
+  """
+  Return the NDK version of given name, which replace
+  the leading "android" to "acamera"
+
+  Args:
+    name: name string of an entry
+
+  Returns:
+    A NDK version name string of the input name
+  """
+  name_list = name.split(".")
+  if name_list[0] == "android":
+    name_list[0] = "acamera"
+  return ".".join(name_list)
+
+def protobuf_type(entry):
+  """
+  Return the protocol buffer message type for input metadata entry.
+  Only support types used by static metadata right now
+
+  Returns:
+    A string of protocol buffer type. Ex: "optional int32" or "repeated RangeInt"
+  """
+  typeName = None
+  if entry.typedef is None:
+    typeName = entry.type
+  else:
+    typeName = entry.typedef.name
+
+  typename_to_protobuftype = {
+    "rational"               : "Rational",
+    "size"                   : "Size",
+    "sizeF"                  : "SizeF",
+    "rectangle"              : "Rect",
+    "streamConfigurationMap" : "StreamConfigurations",
+    "rangeInt"               : "RangeInt",
+    "rangeLong"              : "RangeLong",
+    "colorSpaceTransform"    : "ColorSpaceTransform",
+    "blackLevelPattern"      : "BlackLevelPattern",
+    "byte"                   : "int32", # protocol buffer don't support byte
+    "boolean"                : "bool",
+    "float"                  : "float",
+    "double"                 : "double",
+    "int32"                  : "int32",
+    "int64"                  : "int64",
+    "enumList"               : "int32"
+  }
+
+  if typeName not in typename_to_protobuftype:
+    print >> sys.stderr,\
+      "  ERROR: Could not find protocol buffer type for {%s} type {%s} typedef {%s}" % \
+          (entry.name, entry.type, entry.typedef)
+
+  proto_type = typename_to_protobuftype[typeName]
+
+  prefix = "optional"
+  if entry.container == 'array':
+    has_variable_size = False
+    for size in entry.container_sizes:
+      try:
+        size_int = int(size)
+      except ValueError:
+        has_variable_size = True
+
+    if has_variable_size:
+      prefix = "repeated"
+
+  return "%s %s" %(prefix, proto_type)
+
+
+def protobuf_name(entry):
+  """
+  Return the protocol buffer field name for input metadata entry
+
+  Returns:
+    A string. Ex: "android_colorCorrection_availableAberrationModes"
+  """
+  return entry.name.replace(".", "_")
+
 def has_descendants_with_enums(node):
   """
   Determine whether or not the current node is or has any descendants with an
@@ -754,7 +834,7 @@ def javadoc(metadata, indent = 4):
     # Convert metadata entry "android.x.y.z" to form
     # "{@link CaptureRequest#X_Y_Z android.x.y.z}"
     def javadoc_crossref_filter(node):
-      if node.applied_visibility == 'public':
+      if node.applied_visibility in ('public', 'java_public'):
         return '{@link %s#%s %s}' % (kind_mapping[node.kind],
                                      jkey_identifier(node.name),
                                      node.name)
@@ -764,7 +844,7 @@ def javadoc(metadata, indent = 4):
     # For each public tag "android.x.y.z" referenced, add a
     # "@see CaptureRequest#X_Y_Z"
     def javadoc_crossref_see_filter(node_set):
-      node_set = (x for x in node_set if x.applied_visibility == 'public')
+      node_set = (x for x in node_set if x.applied_visibility in ('public', 'java_public'))
 
       text = '\n'
       for node in node_set:
@@ -788,6 +868,81 @@ def javadoc(metadata, indent = 4):
 
   return javadoc_formatter
 
+def ndkdoc(metadata, indent = 4):
+  """
+  Returns a function to format a markdown syntax text block as a
+  NDK camera API C/C++ comment section, given a set of metadata
+
+  Args:
+    metadata: A Metadata instance, representing the the top-level root
+      of the metadata for cross-referencing
+    indent: baseline level of indentation for comment block
+  Returns:
+    A function that transforms a String text block as follows:
+    - Indent and * for insertion into a comment block
+    - Trailing whitespace removed
+    - Entire body rendered via markdown
+    - All tag names converted to appropriate NDK tag name for each tag
+
+  Example:
+    "This is a comment for NDK\n" +
+    "     with multiple lines, that should be   \n" +
+    "     formatted better\n" +
+    "\n" +
+    "    That covers multiple lines as well\n"
+    "    And references android.control.mode\n"
+
+    transforms to
+    "    * This is a comment for NDK\n" +
+    "    * with multiple lines, that should be\n" +
+    "    * formatted better\n" +
+    "    * That covers multiple lines as well\n" +
+    "    * and references ACAMERA_CONTROL_MODE\n" +
+    "    *\n" +
+    "    * @see ACAMERA_CONTROL_MODE\n"
+  """
+  def ndkdoc_formatter(text):
+    # render with markdown => HTML
+    ndktext = md(text, JAVADOC_IMAGE_SRC_METADATA)
+
+    # Convert metadata entry "android.x.y.z" to form
+    # NDK tag format of "ACAMERA_X_Y_Z"
+    def ndkdoc_crossref_filter(node):
+      if node.applied_ndk_visible == 'true':
+        return csym(ndk(node.name))
+      else:
+        return node.name
+
+    # For each public tag "android.x.y.z" referenced, add a
+    # "@see ACAMERA_X_Y_Z"
+    def ndkdoc_crossref_see_filter(node_set):
+      node_set = (x for x in node_set if x.applied_ndk_visible == 'true')
+
+      text = '\n'
+      for node in node_set:
+        text = text + '\n@see %s' % (csym(ndk(node.name)))
+
+      return text if text != '\n' else ''
+
+    ndktext = filter_tags(ndktext, metadata, ndkdoc_crossref_filter, ndkdoc_crossref_see_filter)
+
+    ndktext = ndk_replace_tag_wildcards(ndktext, metadata)
+
+    comment_prefix = " " * indent + " * ";
+
+    def line_filter(line):
+      # Indent each line
+      # Add ' * ' to it for stylistic reasons
+      # Strip right side of trailing whitespace
+      return (comment_prefix + line).rstrip()
+
+    # Process each line with above filter
+    ndktext = "\n".join(line_filter(i) for i in ndktext.split("\n")) + "\n"
+
+    return ndktext
+
+  return ndkdoc_formatter
+
 def dedent(text):
   """
   Remove all common indentation from every line but the 0th.
@@ -960,6 +1115,28 @@ def filter_tags(text, metadata, filter_function, summary_function = None):
     else:
       return text
 
+def ndk_replace_tag_wildcards(text, metadata):
+    """
+    Find all references to tags in the form android.xxx.* or android.xxx.yyy.*
+    in the provided text, and replace them by NDK format of "ACAMERA_XXX_*" or
+    "ACAMERA_XXX_YYY_*"
+
+    Args:
+      text: A string representing a block of text destined for output
+      metadata: A Metadata instance, the root of the metadata properties tree
+    """
+    tag_match = r"android\.([a-zA-Z0-9\n]+)\.\*"
+    tag_match_2 = r"android\.([a-zA-Z0-9\n]+)\.([a-zA-Z0-9\n]+)\*"
+
+    def filter_sub(match):
+      return "ACAMERA_" + match.group(1).upper() + "_*"
+    def filter_sub_2(match):
+      return "ACAMERA_" + match.group(1).upper() + match.group(2).upper() + "_*"
+
+    text = re.sub(tag_match, filter_sub, text)
+    text = re.sub(tag_match_2, filter_sub_2, text)
+    return text
+
 def filter_links(text, filter_function, summary_function = None):
     """
     Find all references to tags in the form {@link xxx#yyy [zzz]} in the
@@ -1053,6 +1230,18 @@ def remove_synthetic(entries):
   """
   return (e for e in entries if not e.synthetic)
 
+def filter_ndk_visible(entries):
+  """
+  Filter the given entries by removing those that are not NDK visible.
+
+  Args:
+    entries: An iterable of Entry nodes
+
+  Yields:
+    An iterable of Entry nodes
+  """
+  return (e for e in entries if e.applied_ndk_visible == 'true')
+
 def wbr(text):
   """
   Insert word break hints for the browser in the form of <wbr> HTML tags.
index 315c97c..e059e33 100644 (file)
@@ -351,6 +351,21 @@ class Metadata(Node):
       self._entry_map[p.kind].pop(p.name)
       self._entries_ordered.remove(p)
 
+  def is_entry_this_kind(self, entry, kind):
+    """
+    Check if input entry if of input kind
+
+    Args:
+      entry: an Entry object
+      kind: a string. Possible values are "static", "dynamic", "controls"
+
+    Returns:
+      A boolean indicating whether input entry is of input kind.
+    """
+    if kind not in ("static", "dynamic", "controls"):
+      assert(False), "Unknown kind value " + kind
+
+    return entry.name in self._entry_map[kind]
 
   # After all entries/clones are inserted,
   # invoke this to generate the parent/child node graph all these objects
@@ -946,15 +961,18 @@ class EnumValue(Node):
     deprecated: A boolean, True if the enum should be deprecated.
     optional: A boolean
     hidden: A boolean, True if the enum should be hidden.
+    ndk_hidden: A boolean, True if the enum should be hidden in NDK
     notes: A string describing the notes, or None.
     parent: An edge to the parent, always an Enum instance.
   """
-  def __init__(self, name, parent, id=None, deprecated=False, optional=False, hidden=False, notes=None):
+  def __init__(self, name, parent,
+      id=None, deprecated=False, optional=False, hidden=False, notes=None, ndk_hidden=False):
     self._name = name                    # str, e.g. 'ON' or 'OFF'
     self._id = id                        # int, e.g. '0'
     self._deprecated = deprecated        # bool
     self._optional = optional            # bool
     self._hidden = hidden                # bool
+    self._ndk_hidden = ndk_hidden        # bool
     self._notes = notes                  # None or str
     self._parent = parent
 
@@ -975,6 +993,10 @@ class EnumValue(Node):
     return self._hidden
 
   @property
+  def ndk_hidden(self):
+    return self._ndk_hidden
+
+  @property
   def notes(self):
     return self._notes
 
@@ -991,10 +1013,11 @@ class Enum(Node):
     has_values_with_id: A boolean representing if any of the children have a
         non-empty id property.
   """
-  def __init__(self, parent, values, ids={}, deprecateds=[], optionals=[], hiddens=[], notes={}):
+  def __init__(self, parent, values, ids={}, deprecateds=[],
+      optionals=[], hiddens=[], notes={}, ndk_hiddens=[]):
     self._values =                                                             \
       [ EnumValue(val, self, ids.get(val), val in deprecateds, val in optionals, val in hiddens,  \
-                  notes.get(val))                                              \
+                  notes.get(val), val in ndk_hiddens)                                              \
         for val in values ]
 
     self._parent = parent
@@ -1031,6 +1054,9 @@ class Entry(Node):
                 public entries are visible in the Android SDK.
     applied_visibility: As visibility, but always valid, defaulting to 'system'
                         if no visibility is given for an entry.
+    applied_ndk_visible: Always valid. Default is 'false'.
+                         Set to 'true' when the visibility implied entry is visible
+                         in NDK.
     synthetic: The C-level visibility of this entry ('false', 'true').
                Synthetic entries will not be generated into the native metadata
                list of entries (in C code). In general a synthetic entry is
@@ -1137,6 +1163,12 @@ class Entry(Node):
     return self._visibility or 'system'
 
   @property
+  def applied_ndk_visible(self):
+    if self._visibility in ("public", "ndk_public"):
+      return "true"
+    return "false"
+
+  @property
   def synthetic(self):
     return self._synthetic
 
@@ -1246,6 +1278,7 @@ class Entry(Node):
     enum_deprecateds = kwargs.get('enum_deprecateds')
     enum_optionals = kwargs.get('enum_optionals')
     enum_hiddens = kwargs.get('enum_hiddens')
+    enum_ndk_hiddens = kwargs.get('enum_ndk_hiddens')
     enum_notes = kwargs.get('enum_notes')  # { value => notes }
     enum_ids = kwargs.get('enum_ids')  # { value => notes }
     self._tuple_values = kwargs.get('tuple_values')
@@ -1265,7 +1298,7 @@ class Entry(Node):
 
     if kwargs.get('enum', False):
       self._enum = Enum(self, enum_values, enum_ids, enum_deprecateds, enum_optionals,
-                        enum_hiddens, enum_notes)
+                        enum_hiddens, enum_notes, enum_ndk_hiddens)
     else:
       self._enum = None
 
@@ -1274,6 +1307,7 @@ class Entry(Node):
     self._hwlevel = kwargs.get('hwlevel')
     self._deprecated = kwargs.get('deprecated', False)
     self._optional = kwargs.get('optional')
+    self._ndk_visible = kwargs.get('ndk_visible')
 
     self._property_keys = kwargs
 
@@ -1470,6 +1504,7 @@ class MergedEntry(Entry):
                     'type',
                     'type_notes',
                     'visibility',
+                    'ndk_visible',
                     'synthetic',
                     'hwlevel',
                     'deprecated',
index 57be227..6759306 100755 (executable)
@@ -208,6 +208,7 @@ class MetadataParserXml:
       enum_deprecateds = []
       enum_optionals = []
       enum_hiddens = []
+      enum_ndk_hiddens = []
       enum_notes = {}
       enum_ids = {}
       for value in entry.enum.find_all('value'):
@@ -224,6 +225,9 @@ class MetadataParserXml:
         if value.attrs.get('hidden', 'false') == 'true':
           enum_hiddens.append(value_body)
 
+        if value.attrs.get('ndk_hidden', 'false') == 'true':
+          enum_ndk_hiddens.append(value_body)
+
         notes = value.find('notes')
         if notes is not None:
           enum_notes[value_body] = notes.string
@@ -235,6 +239,7 @@ class MetadataParserXml:
       d['enum_deprecateds'] = enum_deprecateds
       d['enum_optionals'] = enum_optionals
       d['enum_hiddens'] = enum_hiddens
+      d['enum_ndk_hiddens'] = enum_ndk_hiddens
       d['enum_notes'] = enum_notes
       d['enum_ids'] = enum_ids
       d['enum'] = True
index 42457d1..8071bec 100644 (file)
@@ -1704,11 +1704,22 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
               while in HDR mode.
 
               Since substantial post-processing is generally needed to
-              produce an HDR image, only YUV and JPEG outputs are
-              supported for LIMITED/FULL device HDR captures, and only
-              JPEG outputs are supported for LEGACY HDR
-              captures. Using a RAW output for HDR capture is not
+              produce an HDR image, only YUV, PRIVATE, and JPEG
+              outputs are supported for LIMITED/FULL device HDR
+              captures, and only JPEG outputs are supported for LEGACY
+              HDR captures. Using a RAW output for HDR capture is not
               supported.
+
+              Some devices may also support always-on HDR, which
+              applies HDR processing at full frame rate.  For these
+              devices, intents other than STILL_CAPTURE will also
+              produce an HDR output with no frame rate impact compared
+              to normal operation, though the quality may be lower
+              than for STILL_CAPTURE intents.
+
+              If SCENE_MODE_HDR is used with unsupported output types
+              or capture intents, the images captured will be as if
+              the SCENE_MODE was not enabled at all.
               </notes>
             </value>
             <value optional="true" hidden="true">FACE_PRIORITY_LOW_LIGHT
@@ -1737,6 +1748,20 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
               remain active when FACE_PRIORITY_LOW_LIGHT is set.
               </notes>
             </value>
+            <value optional="true" hidden="true" id="100">DEVICE_CUSTOM_START
+              <notes>
+                Scene mode values within the range of
+                `[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]` are reserved for device specific
+                customized scene modes.
+              </notes>
+            </value>
+            <value optional="true" hidden="true" id="127">DEVICE_CUSTOM_END
+              <notes>
+                Scene mode values within the range of
+                `[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]` are reserved for device specific
+                customized scene modes.
+              </notes>
+            </value>
           </enum>
           <description>
           Control for which scene mode is currently active.
@@ -1885,8 +1910,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           <details>
           For devices at the LEGACY level or above:
 
-          * This list will always include (30, 30).
-          * Also, for constant-framerate recording, for each normal
+          * For constant-framerate recording, for each normal
+          {@link android.media.CamcorderProfile CamcorderProfile}, that is, a
           {@link android.media.CamcorderProfile CamcorderProfile} that has
           {@link android.media.CamcorderProfile#quality quality} in
           the range [{@link android.media.CamcorderProfile#QUALITY_LOW QUALITY_LOW},
@@ -1894,8 +1919,12 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           supported by the device and has
           {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} `x`, this list will
           always include (`x`,`x`).
-          * For preview streaming use case, this list will always include (`min`, `max`) where
-          `min` &lt;= 15 and `max` &gt;= 30.
+
+          * Also, a camera device must either not support any
+          {@link android.media.CamcorderProfile CamcorderProfile},
+          or support at least one
+          normal {@link android.media.CamcorderProfile CamcorderProfile} that has
+          {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} `x` &gt;= 24.
 
           For devices at the LIMITED level or above:
 
@@ -2066,7 +2095,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </details>
           <tag id="BC" />
         </entry>
-        <entry name="maxRegions" type="int32" visibility="hidden"
+        <entry name="maxRegions" type="int32" visibility="ndk_public"
                container="array" hwlevel="legacy">
           <array>
             <size>3</size>
@@ -2084,7 +2113,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           `(AE, AWB, AF)`.</range>
           <tag id="BC" />
         </entry>
-        <entry name="maxRegionsAe" type="int32" visibility="public"
+        <entry name="maxRegionsAe" type="int32" visibility="java_public"
                synthetic="true" hwlevel="legacy">
           <description>
           The maximum number of metering regions that can be used by the auto-exposure (AE)
@@ -2101,7 +2130,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           maxRegions to have this entry be automatically populated.
           </hal_details>
         </entry>
-        <entry name="maxRegionsAwb" type="int32" visibility="public"
+        <entry name="maxRegionsAwb" type="int32" visibility="java_public"
                synthetic="true" hwlevel="legacy">
           <description>
           The maximum number of metering regions that can be used by the auto-white balance (AWB)
@@ -2117,7 +2146,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           maxRegions to have this entry be automatically populated.
           </hal_details>
         </entry>
-        <entry name="maxRegionsAf" type="int32" visibility="public"
+        <entry name="maxRegionsAf" type="int32" visibility="java_public"
                synthetic="true" hwlevel="legacy">
           <description>
           The maximum number of metering regions that can be used by the auto-focus (AF) routine.
@@ -2699,7 +2728,70 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
               devices will always support OFF, AUTO modes.
           </details>
         </entry>
+        <entry name="postRawSensitivityBoostRange" type="int32" visibility="public"
+            type_notes="Range of supported post RAW sensitivitiy boosts"
+            container="array" typedef="rangeInt">
+          <array>
+            <size>2</size>
+          </array>
+          <description>Range of boosts for android.control.postRawSensitivityBoost supported
+            by this camera device.
+          </description>
+          <units>ISO arithmetic units, the same as android.sensor.sensitivity</units>
+          <details>
+            Devices support post RAW sensitivity boost  will advertise
+            android.control.postRawSensitivityBoost key for controling
+            post RAW sensitivity boost.
+
+            This key will be `null` for devices that do not support any RAW format
+            outputs. For devices that do support RAW format outputs, this key will always
+            present, and if a device does not support post RAW sensitivity boost, it will
+            list `(100, 100)` in this key.
+          </details>
+          <hal_details>
+             This key is added in HAL3.4. For HAL3.3 or earlier devices, camera framework will
+             generate this key as `(100, 100)` if device supports any of RAW output formats.
+             All HAL3.4 and above devices should list this key if device supports any of RAW
+             output formats.
+          </hal_details>
+        </entry>
       </static>
+      <controls>
+        <entry name="postRawSensitivityBoost" type="int32" visibility="public">
+          <description>The amount of additional sensitivity boost applied to output images
+             after RAW sensor data is captured.
+          </description>
+          <units>ISO arithmetic units, the same as android.sensor.sensitivity</units>
+          <range>android.control.postRawSensitivityBoostRange</range>
+          <details>
+          Some camera devices support additional digital sensitivity boosting in the
+          camera processing pipeline after sensor RAW image is captured.
+          Such a boost will be applied to YUV/JPEG format output images but will not
+          have effect on RAW output formats like RAW_SENSOR, RAW10, RAW12 or RAW_OPAQUE.
+
+          This key will be `null` for devices that do not support any RAW format
+          outputs. For devices that do support RAW format outputs, this key will always
+          present, and if a device does not support post RAW sensitivity boost, it will
+          list `100` in this key.
+
+          If the camera device cannot apply the exact boost requested, it will reduce the
+          boost to the nearest supported value.
+          The final boost value used will be available in the output capture result.
+
+          For devices that support post RAW sensitivity boost, the YUV/JPEG output images
+          of such device will have the total sensitivity of
+          `android.sensor.sensitivity * android.control.postRawSensitivityBoost / 100`
+          The sensitivity of RAW format images will always be `android.sensor.sensitivity`
+
+          This control is only effective if android.control.aeMode or android.control.mode is set to
+          OFF; otherwise the auto-exposure algorithm will override this value.
+          </details>
+        </entry>
+      </controls>
+      <dynamic>
+        <clone entry="android.control.postRawSensitivityBoost" kind="controls">
+        </clone>
+      </dynamic>
     </section>
     <section name="demosaic">
       <controls>
@@ -3059,7 +3151,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
     </section>
     <section name="jpeg">
       <controls>
-        <entry name="gpsLocation" type="byte" visibility="public" synthetic="true"
+        <entry name="gpsLocation" type="byte" visibility="java_public" synthetic="true"
         typedef="location" hwlevel="legacy">
           <description>
           A location object to use when generating image GPS metadata.
@@ -3070,7 +3162,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           viewed by anyone who receives the JPEG image.
           </details>
         </entry>
-        <entry name="gpsCoordinates" type="double" visibility="hidden"
+        <entry name="gpsCoordinates" type="double" visibility="ndk_public"
         type_notes="latitude, longitude, altitude. First two in degrees, the third in meters"
         container="array" hwlevel="legacy">
           <array>
@@ -3081,14 +3173,14 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           <range>(-180 - 180], [-90,90], [-inf, inf]</range>
           <tag id="BC" />
         </entry>
-        <entry name="gpsProcessingMethod" type="byte" visibility="hidden"
+        <entry name="gpsProcessingMethod" type="byte" visibility="ndk_public"
                typedef="string" hwlevel="legacy">
           <description>32 characters describing GPS algorithm to
           include in EXIF.</description>
           <units>UTF-8 null-terminated string</units>
           <tag id="BC" />
         </entry>
-        <entry name="gpsTimestamp" type="int64" visibility="hidden" hwlevel="legacy">
+        <entry name="gpsTimestamp" type="int64" visibility="ndk_public" hwlevel="legacy">
           <description>Time GPS fix was made to include in
           EXIF.</description>
           <units>UTC in seconds since January 1, 1970</units>
@@ -3496,7 +3588,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             the MANUAL_SENSOR capability.</hal_details>
             <tag id="V1" />
           </entry>
-          <entry name="shadingMapSize" type="int32" visibility="hidden"
+          <entry name="shadingMapSize" type="int32" visibility="ndk_public"
                  type_notes="width and height (N, M) of lens shading map provided by the camera device."
                  container="array" typedef="size" hwlevel="full">
             <array>
@@ -4205,8 +4297,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
         </entry>
       </controls>
       <static>
-        <entry name="maxNumOutputStreams" type="int32" visibility="hidden"
-        container="array" hwlevel="legacy">
+        <entry name="maxNumOutputStreams" type="int32" visibility="ndk_public"
+               container="array" hwlevel="legacy">
           <array>
             <size>3</size>
           </array>
@@ -4248,7 +4340,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </details>
           <tag id="BC" />
         </entry>
-        <entry name="maxNumOutputRaw" type="int32" visibility="public" synthetic="true" hwlevel="legacy">
+        <entry name="maxNumOutputRaw" type="int32" visibility="java_public" synthetic="true"
+               hwlevel="legacy">
           <description>The maximum numbers of different types of output streams
           that can be configured and used simultaneously by a camera device
           for any `RAW` formats.
@@ -4275,7 +4368,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           never support raw streams.
           </details>
         </entry>
-        <entry name="maxNumOutputProc" type="int32" visibility="public" synthetic="true" hwlevel="legacy">
+        <entry name="maxNumOutputProc" type="int32" visibility="java_public" synthetic="true"
+               hwlevel="legacy">
           <description>The maximum numbers of different types of output streams
           that can be configured and used simultaneously by a camera device
           for any processed (but not-stalling) formats.
@@ -4310,7 +4404,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           LEGACY devices will support at least 2 processing/non-stalling streams.
           </details>
         </entry>
-        <entry name="maxNumOutputProcStalling" type="int32" visibility="public" synthetic="true" hwlevel="legacy">
+        <entry name="maxNumOutputProcStalling" type="int32" visibility="java_public" synthetic="true"
+               hwlevel="legacy">
           <description>The maximum numbers of different types of output streams
           that can be configured and used simultaneously by a camera device
           for any processed (and stalling) formats.
@@ -4572,7 +4667,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
                 by the camera device.
               </notes>
             </value>
-            <value optional="true">PRIVATE_REPROCESSING
+            <value optional="true" ndk_hidden="true">PRIVATE_REPROCESSING
               <notes>
               The camera device supports the Zero Shutter Lag reprocessing use case.
 
@@ -4667,7 +4762,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
               consistent image output.
               </notes>
             </value>
-            <value optional="true">YUV_REPROCESSING
+            <value optional="true" ndk_hidden="true">YUV_REPROCESSING
               <notes>
               The camera device supports the YUV_420_888 reprocessing use case, similar as
               PRIVATE_REPROCESSING, This capability requires the camera device to support the
@@ -4741,7 +4836,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
               rate, including depth stall time.
               </notes>
             </value>
-            <value optional="true">CONSTRAINED_HIGH_SPEED_VIDEO
+            <value optional="true" ndk_hidden="true">CONSTRAINED_HIGH_SPEED_VIDEO
               <notes>
               The device supports constrained high speed video recording (frame rate >=120fps)
               use case. The camera device will support high speed capture session created by
@@ -4889,8 +4984,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           DEPTH).
           </hal_details>
         </entry>
-        <entry name="availableRequestKeys" type="int32" visibility="hidden"
-          container="array" hwlevel="legacy">
+        <entry name="availableRequestKeys" type="int32" visibility="ndk_public"
+               container="array" hwlevel="legacy">
           <array>
             <size>n</size>
           </array>
@@ -4921,8 +5016,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureRequestKeys}.
           </hal_details>
         </entry>
-        <entry name="availableResultKeys" type="int32" visibility="hidden"
-          container="array" hwlevel="legacy">
+        <entry name="availableResultKeys" type="int32" visibility="ndk_public"
+               container="array" hwlevel="legacy">
           <array>
             <size>n</size>
           </array>
@@ -4964,8 +5059,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys}.
           </hal_details>
         </entry>
-        <entry name="availableCharacteristicsKeys" type="int32" visibility="hidden"
-          container="array" hwlevel="legacy">
+        <entry name="availableCharacteristicsKeys" type="int32" visibility="ndk_public"
+               container="array" hwlevel="legacy">
           <array>
             <size>n</size>
           </array>
@@ -5128,8 +5223,10 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             </value>
             <value optional="true" id="0x24">RAW_OPAQUE
               <notes>
-              RAW_OPAQUE is a format for raw image buffers coming from an
-              image sensor.
+              RAW_OPAQUE (or
+              {@link android.graphics.ImageFormat#RAW_PRIVATE RAW_PRIVATE}
+              as referred in public API) is a format for raw image buffers
+              coming from an image sensor.
 
               The actual structure of buffers of this format is
               platform-specific, but must follow several constraints:
@@ -5424,9 +5521,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </hal_details>
           <tag id="REPROC" />
         </entry>
-        <entry name="availableStreamConfigurations" type="int32" visibility="hidden"
-          enum="true" container="array"
-          typedef="streamConfiguration" hwlevel="legacy">
+        <entry name="availableStreamConfigurations" type="int32" visibility="ndk_public"
+               enum="true" container="array" typedef="streamConfiguration" hwlevel="legacy">
           <array>
             <size>n</size>
             <size>4</size>
@@ -5526,9 +5622,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           * available[Processed,Raw,Jpeg]Sizes
           </hal_details>
         </entry>
-        <entry name="availableMinFrameDurations" type="int64" visibility="hidden"
-               container="array"
-               typedef="streamConfigurationDuration" hwlevel="legacy">
+        <entry name="availableMinFrameDurations" type="int64" visibility="ndk_public"
+               container="array" typedef="streamConfigurationDuration" hwlevel="legacy">
           <array>
             <size>4</size>
             <size>n</size>
@@ -5557,7 +5652,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </details>
           <tag id="V1" />
         </entry>
-        <entry name="availableStallDurations" type="int64" visibility="hidden"
+        <entry name="availableStallDurations" type="int64" visibility="ndk_public"
                container="array" typedef="streamConfigurationDuration" hwlevel="legacy">
           <array>
             <size>4</size>
@@ -5641,7 +5736,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </hal_details>
           <tag id="V1" />
         </entry>
-        <entry name="streamConfigurationMap" type="int32" visibility="public"
+        <entry name="streamConfigurationMap" type="int32" visibility="java_public"
                synthetic="true" typedef="streamConfigurationMap"
                hwlevel="legacy">
           <description>The available stream configurations that this
@@ -5897,6 +5992,9 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           requested, it will reduce the gain to the nearest supported
           value. The final sensitivity used will be available in the
           output capture result.
+
+          This control is only effective if android.control.aeMode or android.control.mode is set to
+          OFF; otherwise the auto-exposure algorithm will override this value.
           </details>
           <hal_details>ISO 12232:2006 REI method is acceptable.</hal_details>
           <tag id="V1" />
@@ -6088,6 +6186,12 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             (8-14 bits is expected), or by the point where the sensor response
             becomes too non-linear to be useful.  The default value for this is
             maximum representable value for a 16-bit raw sample (2^16 - 1).
+
+            The white level values of captured images may vary for different
+            capture settings (e.g., android.sensor.sensitivity). This key
+            represents a coarse approximation for such case. It is recommended
+            to use android.sensor.dynamicWhiteLevel for captures when supported
+            by the camera device, which provides more accurate white level values.
             </details>
             <hal_details>
             The full bit depth of the sensor must be available in the raw data,
@@ -6521,6 +6625,16 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           layout key (see android.sensor.info.colorFilterArrangement), i.e. the
           nth value given corresponds to the black level offset for the nth
           color channel listed in the CFA.
+
+          The black level values of captured images may vary for different
+          capture settings (e.g., android.sensor.sensitivity). This key
+          represents a coarse approximation for such case. It is recommended to
+          use android.sensor.dynamicBlackLevel or use pixels from
+          android.sensor.opticalBlackRegions directly for captures when
+          supported by the camera device, which provides more accurate black
+          level values. For raw capture in particular, it is recommended to use
+          pixels from android.sensor.opticalBlackRegions to calculate black
+          level values for each frame.
           </details>
           <hal_details>
           The values are given in row-column scan order, with the first value
@@ -7011,6 +7125,145 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           <tag id="V1" />
         </entry>
       </dynamic>
+      <static>
+        <entry name="opticalBlackRegions" type="int32" visibility="public" optional="true"
+          container="array" typedef="rectangle">
+          <array>
+            <size>4</size>
+            <size>num_regions</size>
+          </array>
+          <description>List of disjoint rectangles indicating the sensor
+          optically shielded black pixel regions.
+          </description>
+          <details>
+            In most camera sensors, the active array is surrounded by some
+            optically shielded pixel areas. By blocking light, these pixels
+            provides a reliable black reference for black level compensation
+            in active array region.
+
+            This key provides a list of disjoint rectangles specifying the
+            regions of optically shielded (with metal shield) black pixel
+            regions if the camera device is capable of reading out these black
+            pixels in the output raw images. In comparison to the fixed black
+            level values reported by android.sensor.blackLevelPattern, this key
+            may provide a more accurate way for the application to calculate
+            black level of each captured raw images.
+
+            When this key is reported, the android.sensor.dynamicBlackLevel and
+            android.sensor.dynamicWhiteLevel will also be reported.
+          </details>
+          <hal_details>
+            This array contains (xmin, ymin, width, height). The (xmin, ymin)
+            must be &amp;gt;= (0,0) and &amp;lt;=
+            android.sensor.info.pixelArraySize. The (width, height) must be
+            &amp;lt;= android.sensor.info.pixelArraySize. Each region must be
+            outside the region reported by
+            android.sensor.info.preCorrectionActiveArraySize.
+
+            The HAL must report minimal number of disjoint regions for the
+            optically shielded back pixel regions. For example, if a region can
+            be covered by one rectangle, the HAL must not split this region into
+            multiple rectangles.
+          </hal_details>
+        </entry>
+      </static>
+      <dynamic>
+        <entry name="dynamicBlackLevel" type="float" visibility="public"
+        optional="true" type_notes="2x2 raw count block" container="array">
+          <array>
+            <size>4</size>
+          </array>
+          <description>
+          A per-frame dynamic black level offset for each of the color filter
+          arrangement (CFA) mosaic channels.
+          </description>
+          <range>&amp;gt;= 0 for each.</range>
+          <details>
+          Camera sensor black levels may vary dramatically for different
+          capture settings (e.g. android.sensor.sensitivity). The fixed black
+          level reported by android.sensor.blackLevelPattern may be too
+          inaccurate to represent the actual value on a per-frame basis. The
+          camera device internal pipeline relies on reliable black level values
+          to process the raw images appropriately. To get the best image
+          quality, the camera device may choose to estimate the per frame black
+          level values either based on optically shielded black regions
+          (android.sensor.opticalBlackRegions) or its internal model.
+
+          This key reports the camera device estimated per-frame zero light
+          value for each of the CFA mosaic channels in the camera sensor. The
+          android.sensor.blackLevelPattern may only represent a coarse
+          approximation of the actual black level values. This value is the
+          black level used in camera device internal image processing pipeline
+          and generally more accurate than the fixed black level values.
+          However, since they are estimated values by the camera device, they
+          may not be as accurate as the black level values calculated from the
+          optical black pixels reported by android.sensor.opticalBlackRegions.
+
+          The values are given in the same order as channels listed for the CFA
+          layout key (see android.sensor.info.colorFilterArrangement), i.e. the
+          nth value given corresponds to the black level offset for the nth
+          color channel listed in the CFA.
+
+          This key will be available if android.sensor.opticalBlackRegions is
+          available or the camera device advertises this key via
+          {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys}.
+          </details>
+          <hal_details>
+          The values are given in row-column scan order, with the first value
+          corresponding to the element of the CFA in row=0, column=0.
+          </hal_details>
+          <tag id="RAW" />
+        </entry>
+        <entry name="dynamicWhiteLevel" type="int32" visibility="public"
+        optional="true" >
+          <description>
+          Maximum raw value output by sensor for this frame.
+          </description>
+          <range> &amp;gt;= 0</range>
+          <details>
+          Since the android.sensor.blackLevelPattern may change for different
+          capture settings (e.g., android.sensor.sensitivity), the white
+          level will change accordingly. This key is similar to
+          android.sensor.info.whiteLevel, but specifies the camera device
+          estimated white level for each frame.
+
+          This key will be available if android.sensor.opticalBlackRegions is
+          available or the camera device advertises this key via
+          {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureRequestKeys}.
+          </details>
+          <hal_details>
+          The full bit depth of the sensor must be available in the raw data,
+          so the value for linear sensors should not be significantly lower
+          than maximum raw value supported, i.e. 2^(sensor bits per pixel).
+          </hal_details>
+          <tag id="RAW" />
+        </entry>
+      </dynamic>
+      <static>
+        <entry name="opaqueRawSize" type="int32" visibility="system" container="array">
+          <array>
+            <size>n</size>
+            <size>3</size>
+          </array>
+          <description>Size in bytes for all the listed opaque RAW buffer sizes</description>
+          <range>Must be large enough to fit the opaque RAW of corresponding size produced by
+          the camera</range>
+          <details>
+          This configurations are listed as `(width, height, size_in_bytes)` tuples.
+          This is used for sizing the gralloc buffers for opaque RAW buffers.
+          All RAW_OPAQUE output stream configuration listed in
+          android.scaler.availableStreamConfigurations will have a corresponding tuple in
+          this key.
+          </details>
+          <hal_details>
+              This key is added in HAL3.4.
+              For HAL3.4 or above: devices advertising RAW_OPAQUE format output must list this key.
+              For HAL3.3 or earlier devices: if RAW_OPAQUE ouput is advertised, camera framework
+              will derive this key by assuming each pixel takes two bytes and no padding bytes
+              between rows.
+          </hal_details>
+        </entry>
+      </static>
     </section>
     <section name="shading">
       <controls>
@@ -7260,8 +7513,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
       <dynamic>
         <clone entry="android.statistics.faceDetectMode"
                kind="controls"></clone>
-        <entry name="faceIds" type="int32" visibility="hidden" container="array"
-               hwlevel="legacy">
+        <entry name="faceIds" type="int32" visibility="ndk_public"
+               container="array" hwlevel="legacy">
           <array>
             <size>n</size>
           </array>
@@ -7274,9 +7527,9 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           Only available if android.statistics.faceDetectMode == FULL</details>
           <tag id="BC" />
         </entry>
-        <entry name="faceLandmarks" type="int32" visibility="hidden"
-        type_notes="(leftEyeX, leftEyeY, rightEyeX, rightEyeY, mouthX, mouthY)"
-        container="array" hwlevel="legacy">
+        <entry name="faceLandmarks" type="int32" visibility="ndk_public"
+               type_notes="(leftEyeX, leftEyeY, rightEyeX, rightEyeY, mouthX, mouthY)"
+               container="array" hwlevel="legacy">
           <array>
             <size>n</size>
             <size>6</size>
@@ -7290,9 +7543,9 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             Only available if android.statistics.faceDetectMode == FULL</details>
           <tag id="BC" />
         </entry>
-        <entry name="faceRectangles" type="int32" visibility="hidden"
-        type_notes="(xmin, ymin, xmax, ymax). (0,0) is top-left of active pixel area"
-        container="array" typedef="rectangle" hwlevel="legacy">
+        <entry name="faceRectangles" type="int32" visibility="ndk_public"
+               type_notes="(xmin, ymin, xmax, ymax). (0,0) is top-left of active pixel area"
+               container="array" typedef="rectangle" hwlevel="legacy">
           <array>
             <size>n</size>
             <size>4</size>
@@ -7306,8 +7559,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             Only available if android.statistics.faceDetectMode != OFF</details>
           <tag id="BC" />
         </entry>
-        <entry name="faceScores" type="byte" visibility="hidden" container="array"
-               hwlevel="legacy">
+        <entry name="faceScores" type="byte" visibility="ndk_public"
+               container="array" hwlevel="legacy">
           <array>
             <size>n</size>
           </array>
@@ -7321,7 +7574,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           all times is illegal).</hal_details>
           <tag id="BC" />
         </entry>
-        <entry name="faces" type="int32" visibility="public" synthetic="true"
+        <entry name="faces" type="int32" visibility="java_public" synthetic="true"
                container="array" typedef="face" hwlevel="legacy">
           <array>
             <size>n</size>
@@ -7418,7 +7671,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           ![Image of a uniform white wall (inverse shading map)](android.statistics.lensShadingMap/inv_shading.png)
           </details>
         </entry>
-        <entry name="lensShadingMap" type="float" visibility="hidden"
+        <entry name="lensShadingMap" type="float" visibility="ndk_public"
                type_notes="2D array of float gain factors per channel to correct lens shading"
                container="array" hwlevel="full">
           <array>
@@ -7427,11 +7680,24 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             <size>m</size>
           </array>
           <description>The shading map is a low-resolution floating-point map
-          that lists the coefficients used to correct for vignetting, for each
-          Bayer color channel of RAW image data.</description>
+          that lists the coefficients used to correct for vignetting and color shading,
+          for each Bayer color channel of RAW image data.</description>
           <range>Each gain factor is &amp;gt;= 1</range>
-          <details>The least shaded section of the image should have a gain factor
-          of 1; all other sections should have gains above 1.
+          <details>
+          The lens shading correction is defined as a full shading correction that
+          corrects both color shading for the output non-RAW images. After the
+          shading map is applied, the output non-RAW images will be flat-field images
+          for flat scenes under uniform illumination.
+
+          When there is no lens shading correction applied to RAW output images
+          (android.sensor.info.lensShadingApplied `==` false), this map is a full lens
+          shading correction map; when there is some lens shading correction applied
+          to the RAW output image (android.sensor.info.lensShadingApplied `==` true),
+          this map reports the remaining lens shading correction map that needs to be
+          applied to get fully shading corrected images.
+
+          For a full shading correction map, the least shaded section of the image
+          should have a gain factor of 1; all other sections should have gains above 1.
 
           When android.colorCorrection.mode = TRANSFORM_MATRIX, the map
           must take into account the colorCorrection settings.
@@ -7655,7 +7921,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
     </section>
     <section name="tonemap">
       <controls>
-        <entry name="curveBlue" type="float" visibility="hidden"
+        <entry name="curveBlue" type="float" visibility="ndk_public"
         type_notes="1D array of float pairs (P_IN, P_OUT). The maximum number of pairs is specified by android.tonemap.maxCurvePoints."
         container="array" hwlevel="full">
           <array>
@@ -7667,7 +7933,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           CONTRAST_CURVE.</description>
           <details>See android.tonemap.curveRed for more details.</details>
         </entry>
-        <entry name="curveGreen" type="float" visibility="hidden"
+        <entry name="curveGreen" type="float" visibility="ndk_public"
         type_notes="1D array of float pairs (P_IN, P_OUT). The maximum number of pairs is specified by android.tonemap.maxCurvePoints."
         container="array" hwlevel="full">
           <array>
@@ -7679,7 +7945,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           CONTRAST_CURVE.</description>
           <details>See android.tonemap.curveRed for more details.</details>
         </entry>
-        <entry name="curveRed" type="float" visibility="hidden"
+        <entry name="curveRed" type="float" visibility="ndk_public"
         type_notes="1D array of float pairs (P_IN, P_OUT). The maximum number of pairs is specified by android.tonemap.maxCurvePoints."
         container="array" hwlevel="full">
           <array>
@@ -7754,7 +8020,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           control points used as are available.
         </hal_details>
         </entry>
-        <entry name="curve" type="float" visibility="public" synthetic="true"
+        <entry name="curve" type="float" visibility="java_public" synthetic="true"
                typedef="tonemapCurve"
                hwlevel="full">
           <description>Tonemapping / contrast / gamma curve to use when android.tonemap.mode
@@ -8063,19 +8329,96 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             <value>
               LIMITED
               <notes>
-              This camera device has only limited capabilities.
+              This camera device does not have enough capabilities to qualify as a `FULL` device or
+              better.
+
+              Only the stream configurations listed in the `LEGACY` and `LIMITED` tables in the
+              {@link android.hardware.camera2.CameraDevice#createCaptureSession
+              createCaptureSession} documentation are guaranteed to be supported.
+
+              All `LIMITED` devices support the `BACKWARDS_COMPATIBLE` capability, indicating basic
+              support for color image capture. The only exception is that the device may
+              alternatively support only the `DEPTH_OUTPUT` capability, if it can only output depth
+              measurements and not color images.
+
+              `LIMITED` devices and above require the use of android.control.aePrecaptureTrigger
+              to lock exposure metering (and calculate flash power, for cameras with flash) before
+              capturing a high-quality still image.
+
+              A `LIMITED` device that only lists the `BACKWARDS_COMPATIBLE` capability is only
+              required to support full-automatic operation and post-processing (`OFF` is not
+              supported for android.control.aeMode, android.control.afMode, or
+              android.control.awbMode)
+
+              Additional capabilities may optionally be supported by a `LIMITED`-level device, and
+              can be checked for in android.request.availableCapabilities.
               </notes>
             </value>
             <value>
               FULL
               <notes>
               This camera device is capable of supporting advanced imaging applications.
+
+              The stream configurations listed in the `FULL`, `LEGACY` and `LIMITED` tables in the
+              {@link android.hardware.camera2.CameraDevice#createCaptureSession
+              createCaptureSession} documentation are guaranteed to be supported.
+
+              A `FULL` device will support below capabilities:
+
+              * `BURST_CAPTURE` capability (android.request.availableCapabilities contains
+                `BURST_CAPTURE`)
+              * Per frame control (android.sync.maxLatency `==` PER_FRAME_CONTROL)
+              * Manual sensor control (android.request.availableCapabilities contains `MANUAL_SENSOR`)
+              * Manual post-processing control (android.request.availableCapabilities contains
+                `MANUAL_POST_PROCESSING`)
+              * The required exposure time range defined in android.sensor.info.exposureTimeRange
+              * The required maxFrameDuration defined in android.sensor.info.maxFrameDuration
+
+              Note:
+              Pre-API level 23, FULL devices also supported arbitrary cropping region
+              (android.scaler.croppingType `== FREEFORM`); this requirement was relaxed in API level
+              23, and `FULL` devices may only support `CENTERED` cropping.
               </notes>
             </value>
             <value>
               LEGACY
               <notes>
               This camera device is running in backward compatibility mode.
+
+              Only the stream configurations listed in the `LEGACY` table in the {@link
+              android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession}
+              documentation are supported.
+
+              A `LEGACY` device does not support per-frame control, manual sensor control, manual
+              post-processing, arbitrary cropping regions, and has relaxed performance constraints.
+              No additional capabilities beyond `BACKWARD_COMPATIBLE` will ever be listed by a
+              `LEGACY` device in android.request.availableCapabilities.
+
+              In addition, the android.control.aePrecaptureTrigger is not functional on `LEGACY`
+              devices. Instead, every request that includes a JPEG-format output target is treated
+              as triggering a still capture, internally executing a precapture trigger.  This may
+              fire the flash for flash power metering during precapture, and then fire the flash
+              for the final capture, if a flash is available on the device and the AE mode is set to
+              enable the flash.
+              </notes>
+            </value>
+            <value>
+              3
+              <notes>
+              This camera device is capable of YUV reprocessing and RAW data capture, in addition to
+              FULL-level capabilities.
+
+              The stream configurations listed in the `LEVEL_3`, `RAW`, `FULL`, `LEGACY` and
+              `LIMITED` tables in the {@link
+              android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession}
+              documentation are guaranteed to be supported.
+
+              The following additional capabilities are guaranteed to be supported:
+
+              * `YUV_REPROCESSING` capability (android.request.availableCapabilities contains
+                `YUV_REPROCESSING`)
+              * `RAW` capability (android.request.availableCapabilities contains
+                `RAW`)
               </notes>
             </value>
           </enum>
@@ -8083,23 +8426,41 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           Generally classifies the overall set of the camera device functionality.
           </description>
           <details>
-          Camera devices will come in three flavors: LEGACY, LIMITED and FULL.
+          The supported hardware level is a high-level description of the camera device's
+          capabilities, summarizing several capabilities into one field.  Each level adds additional
+          features to the previous one, and is always a strict superset of the previous level.
+          The ordering is `LEGACY &lt; LIMITED &lt; FULL &lt; LEVEL_3`.
+
+          Starting from `LEVEL_3`, the level enumerations are guaranteed to be in increasing
+          numerical value as well. To check if a given device is at least at a given hardware level,
+          the following code snippet can be used:
+
+              // Returns true if the device supports the required hardware level, or better.
+              boolean isHardwareLevelSupported(CameraCharacteristics c, int requiredLevel) {
+                  int deviceLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+                  if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
+                      return requiredLevel == deviceLevel;
+                  }
+                  // deviceLevel is not LEGACY, can use numerical sort
+                  return requiredLevel &lt;= deviceLevel;
+              }
 
-          A FULL device will support below capabilities:
+          At a high level, the levels are:
 
-          * BURST_CAPTURE capability (android.request.availableCapabilities contains BURST_CAPTURE)
-          * Per frame control (android.sync.maxLatency `==` PER_FRAME_CONTROL)
-          * Manual sensor control (android.request.availableCapabilities contains MANUAL_SENSOR)
-          * Manual post-processing control (android.request.availableCapabilities contains
-            MANUAL_POST_PROCESSING)
-          * At least 3 processed (but not stalling) format output streams
-            (android.request.maxNumOutputProc `&gt;=` 3)
-          * The required stream configurations defined in android.scaler.availableStreamConfigurations
-          * The required exposure time range defined in android.sensor.info.exposureTimeRange
-          * The required maxFrameDuration defined in android.sensor.info.maxFrameDuration
+          * `LEGACY` devices operate in a backwards-compatibility mode for older
+            Android devices, and have very limited capabilities.
+          * `LIMITED` devices represent the
+            baseline feature set, and may also include additional capabilities that are
+            subsets of `FULL`.
+          * `FULL` devices additionally support per-frame manual control of sensor, flash, lens and
+            post-processing settings, and image capture at a high rate.
+          * `LEVEL_3` devices additionally support YUV reprocessing and RAW image capture, along
+            with additional output stream configurations.
 
-          A LIMITED device may have some or none of the above characteristics.
-          To find out more refer to android.request.availableCapabilities.
+          See the individual level enums for full descriptions of the supported capabilities.  The
+          android.request.availableCapabilities entry describes the device's capabilities at a
+          finer-grain level, if needed. In addition, many controls have their available settings or
+          ranges defined in individual {@link android.hardware.camera2.CameraCharacteristics} entries.
 
           Some features are not part of any particular hardware level or capability and must be
           queried separately. These include:
@@ -8111,31 +8472,21 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
             (android.lens.info.availableOpticalStabilization,
              android.control.availableVideoStabilizationModes)
 
-          A LEGACY device does not support per-frame control, manual sensor control, manual
-          post-processing, arbitrary cropping regions, and has relaxed performance constraints.
-
-          Each higher level supports everything the lower level supports
-          in this order: FULL `&gt;` LIMITED `&gt;` LEGACY.
-
-          Note:
-          Pre-API level 23, FULL devices also supported arbitrary cropping region
-          (android.scaler.croppingType `==` FREEFORM); this requirement was relaxed in API level 23,
-          and FULL devices may only support CENTERED cropping.
           </details>
           <hal_details>
-          The camera 3 HAL device can implement one of two possible
-          operational modes; limited and full. Full support is
-          expected from new higher-end devices. Limited mode has
-          hardware requirements roughly in line with those for a
-          camera HAL device v1 implementation, and is expected from
-          older or inexpensive devices. Full is a strict superset of
-          limited, and they share the same essential operational flow.
+          The camera 3 HAL device can implement one of three possible operational modes; LIMITED,
+          FULL, and LEVEL_3.
+
+          FULL support or better is expected from new higher-end devices. Limited
+          mode has hardware requirements roughly in line with those for a camera HAL device v1
+          implementation, and is expected from older or inexpensive devices. Each level is a strict
+          superset of the previous level, and they share the same essential operational flow.
 
           For full details refer to "S3. Operational Modes" in camera3.h
 
-          Camera HAL3+ must not implement LEGACY mode. It is there
-          for backwards compatibility in the `android.hardware.camera2`
-          user-facing API only.
+          Camera HAL3+ must not implement LEGACY mode. It is there for backwards compatibility in
+          the `android.hardware.camera2` user-facing API only on HALv1 devices, and is implemented
+          by the camera framework code.
           </hal_details>
         </entry>
       </static>
@@ -8213,8 +8564,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
     </section>
     <section name="sync">
       <dynamic>
-        <entry name="frameNumber" type="int64" visibility="hidden" enum="true"
-               hwlevel="legacy">
+        <entry name="frameNumber" type="int64" visibility="ndk_public"
+               enum="true" hwlevel="legacy">
           <enum>
             <value id="-1">CONVERGING
               <notes>
@@ -8393,7 +8744,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
 
           Use `frame_count` from camera3_request_t instead of
           android.request.frameCount or
-          `@link{android.hardware.camera2.CaptureResult#getFrameNumber}`.
+          `{@link android.hardware.camera2.CaptureResult#getFrameNumber}`.
 
           LIMITED devices are strongly encouraged to use a non-negative
           value. If UNKNOWN is used here then app developers do not have a way
@@ -8405,7 +8756,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
     </section>
     <section name="reprocess">
       <controls>
-        <entry name="effectiveExposureFactor" type="float" visibility="public" hwlevel="limited">
+        <entry name="effectiveExposureFactor" type="float" visibility="java_public" hwlevel="limited">
             <description>
             The amount of exposure time increase factor applied to the original output
             frame by the application processing before sending for reprocessing.
@@ -8456,7 +8807,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
       </clone>
       </dynamic>
       <static>
-        <entry name="maxCaptureStall" type="int32" visibility="public" hwlevel="limited">
+        <entry name="maxCaptureStall" type="int32" visibility="java_public" hwlevel="limited">
           <description>
           The maximal camera capture pipeline stall (in unit of frame count) introduced by a
           reprocess capture request.
@@ -8505,9 +8856,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </details>
           <tag id="DEPTH" />
         </entry>
-        <entry name="availableDepthStreamConfigurations" type="int32" visibility="hidden"
-          enum="true" container="array"
-          typedef="streamConfiguration" hwlevel="limited">
+        <entry name="availableDepthStreamConfigurations" type="int32" visibility="ndk_public"
+               enum="true" container="array" typedef="streamConfiguration" hwlevel="limited">
           <array>
             <size>n</size>
             <size>4</size>
@@ -8537,9 +8887,8 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </details>
           <tag id="DEPTH" />
         </entry>
-        <entry name="availableDepthMinFrameDurations" type="int64" visibility="hidden"
-               container="array"
-               typedef="streamConfigurationDuration" hwlevel="limited">
+        <entry name="availableDepthMinFrameDurations" type="int64" visibility="ndk_public"
+               container="array" typedef="streamConfigurationDuration" hwlevel="limited">
           <array>
             <size>4</size>
             <size>n</size>
@@ -8568,7 +8917,7 @@ xsi:schemaLocation="http://schemas.android.com/service/camera/metadata/ metadata
           </details>
           <tag id="DEPTH" />
         </entry>
-        <entry name="availableDepthStallDurations" type="int64" visibility="hidden"
+        <entry name="availableDepthStallDurations" type="int64" visibility="ndk_public"
                container="array" typedef="streamConfigurationDuration" hwlevel="limited">
           <array>
             <size>4</size>
index a71a6c9..b4661d8 100644 (file)
         <attribute name="visibility">
             <simpleType>
                 <restriction base="string">
-                    <enumeration value="system" /> <!-- do not expose to java -->
-                    <enumeration value="hidden" /> <!-- java as @hide -->
-                    <enumeration value="public" /> <!-- java as public SDK -->
+                    <enumeration value="system" /> <!-- do not expose to java/NDK API -->
+                    <enumeration value="java_public" /> <!-- java as public SDK. Not included in NDK -->
+                    <enumeration value="ndk_public" /> <!-- public in NDK. @hide in java -->
+                    <enumeration value="hidden" /> <!-- java as @hide. Not included in NDK -->
+                    <enumeration value="public" /> <!-- public to both java and NDK -->
                 </restriction>
             </simpleType>
         </attribute>
                 </restriction>
             </simpleType>
         </attribute>
+        <attribute name="ndk_hidden">
+            <simpleType>
+                <restriction base="string">
+                    <enumeration value="true"></enumeration>
+                    <enumeration value="false"></enumeration>
+                </restriction>
+            </simpleType>
+        </attribute>
         <attribute name="id" type="string" />
     </complexType>
 
index 360e1e4..3022abb 100644 (file)
                     % if value.hidden:
                              hidden="true"
                     % endif:
+                    % if value.ndk_hidden:
+                             ndk_hidden="true"
+                    % endif:
                     % if value.id is not None:
                              id="${value.id}"
                     % endif
diff --git a/camera/docs/ndk_camera_metadata_tags.mako b/camera/docs/ndk_camera_metadata_tags.mako
new file mode 100644 (file)
index 0000000..83f9cb5
--- /dev/null
@@ -0,0 +1,174 @@
+## -*- coding: utf-8 -*-
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_METADATA_TAGS_H
+#define _NDK_CAMERA_METADATA_TAGS_H
+<%!
+  def annotated_type(entry):
+    type = entry.type
+    if entry.container == 'array':
+       type += '[' + '*'.join(entry.container_sizes) + ']'
+    if entry.enum:
+       type += ' (enum)'
+
+    return type
+%>\
+\
+
+typedef enum acamera_metadata_section {
+  % for i in find_all_sections(metadata):
+    ${ndk(path_name(i)) | csym},
+  % endfor
+    ACAMERA_SECTION_COUNT,
+
+    ACAMERA_VENDOR = 0x8000
+} acamera_metadata_section_t;
+
+/**
+ * Hierarchy positions in enum space.
+ */
+typedef enum acamera_metadata_section_start {
+  % for i in find_all_sections(metadata):
+    ${ndk(path_name(i)) + '.start' | csym,ljust(30)} = ${ndk(path_name(i)) | csym,pad(64)} << 16,
+  % endfor
+    ACAMERA_VENDOR_START           = ACAMERA_VENDOR            << 16
+} acamera_metadata_section_start_t;
+
+/**
+ * Main enum for camera metadata tags.
+ */
+typedef enum acamera_metadata_tag {
+    % for sec in find_all_sections(metadata):
+<%
+      entries = remove_synthetic(find_unique_entries(sec))
+      skip_sec = all(e.applied_ndk_visible == "false" for e in entries)
+      if skip_sec:
+        continue
+%>\
+      % for idx,entry in enumerate(remove_synthetic(find_unique_entries(sec))):
+        % if entry.applied_ndk_visible == "true":
+          % if entry.deprecated:
+    ${ndk(entry.name) + " = " | csym,ljust(60)}// Deprecated! DO NOT USE
+          % else:
+            % if entry.description or entry.details:
+    /**
+${entry.description | ndkdoc(metadata)}\
+     *
+     * <p>This tag may appear in:</p>
+     * <ul>
+              % if metadata.is_entry_this_kind(entry, 'static'):
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+              % endif
+              % if metadata.is_entry_this_kind(entry, 'dynamic'):
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+              % endif
+              % if metadata.is_entry_this_kind(entry, 'controls'):
+     *   <li>ACaptureRequest</li>
+              % endif
+     * </ul>
+     *
+${entry.details | ndkdoc(metadata)}\
+     */
+            % endif
+    ${ndk(entry.name) + " = " | csym,ljust(60)}// ${annotated_type(entry)}
+          % endif
+          % if idx == 0:
+            ${ndk(path_name(find_parent_section(entry))) | csym}_START,
+          % else:
+            ${ndk(path_name(find_parent_section(entry))) | csym}_START + ${idx},
+          % endif
+        % endif
+      % endfor
+    ${ndk(path_name(sec)) | csym}_END,
+
+    %endfor
+} acamera_metadata_tag_t;
+
+/**
+ * Enumeration definitions for the various entries that need them
+ */
+
+% for sec in find_all_sections(metadata):
+  % for entry in filter_ndk_visible(remove_synthetic(find_unique_entries(sec))):
+    % if entry.enum:
+// ${ndk(entry.name) | csym}
+typedef enum acamera_metadata_enum_${csym(ndk(entry.name)).lower()} {
+<%
+      i = 0
+%>\
+      % for val in entry.enum.values:
+        % if val.ndk_hidden:
+<%
+          print "  WARNING: {}_{} is marked as hidden".format(csym(ndk(entry.name)), val.name) + \
+                " enum in NDK. Please double check this value is properly hidden" +  \
+                " in NDK API implementation"
+%>\
+        % endif
+        % if val.hidden or val.ndk_hidden:
+          % if val.id:
+<%
+            i = int(val.id, 0) + 1
+            continue
+%>\
+          % else:
+<%
+            i += 1
+            continue
+%>\
+          % endif
+        % endif
+        % if (val.notes or val.deprecated):
+    /**
+          % if val.notes:
+${val.notes | ndkdoc(metadata)}\
+          % endif
+          % if val.deprecated:
+     *
+     * <b>Deprecated</b>: please refer to this API documentation to find the alternatives
+          % endif
+     */
+        % endif
+        % if val.id:
+    ${'%s_%s'%(csym(ndk(entry.name)), val.name) | pad(70)} = ${val.id},
+<%
+          i = int(val.id, 0)
+%>\
+        % else:
+    ${'%s_%s'%(csym(ndk(entry.name)), val.name) | pad(70)} = ${i},
+        % endif
+<%
+        i += 1
+%>
+      % endfor
+} acamera_metadata_enum_${csym(entry.name).lower()}_t;
+
+    % endif
+  % endfor
+
+% endfor
+
+#endif //_NDK_CAMERA_METADATA_TAGS_H
index 334610b..443af40 100644 (file)
@@ -146,7 +146,7 @@ typedef enum camera_metadata_tag {
     ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
                                                       // byte[]       | public
     ANDROID_CONTROL_AWB_AVAILABLE_MODES,              // byte[]       | public
-    ANDROID_CONTROL_MAX_REGIONS,                      // int32[]      | hidden
+    ANDROID_CONTROL_MAX_REGIONS,                      // int32[]      | ndk_public
     ANDROID_CONTROL_SCENE_MODE_OVERRIDES,             // byte[]       | system
     ANDROID_CONTROL_AE_PRECAPTURE_ID,                 // int32        | system
     ANDROID_CONTROL_AE_STATE,                         // enum         | public
@@ -158,6 +158,8 @@ typedef enum camera_metadata_tag {
     ANDROID_CONTROL_AE_LOCK_AVAILABLE,                // enum         | public
     ANDROID_CONTROL_AWB_LOCK_AVAILABLE,               // enum         | public
     ANDROID_CONTROL_AVAILABLE_MODES,                  // byte[]       | public
+    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[]      | public
+    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,       // int32        | public
     ANDROID_CONTROL_END,
 
     ANDROID_DEMOSAIC_MODE =                           // enum         | system
@@ -189,10 +191,10 @@ typedef enum camera_metadata_tag {
     ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,      // byte[]       | public
     ANDROID_HOT_PIXEL_END,
 
-    ANDROID_JPEG_GPS_COORDINATES =                    // double[]     | hidden
+    ANDROID_JPEG_GPS_COORDINATES =                    // double[]     | ndk_public
             ANDROID_JPEG_START,
-    ANDROID_JPEG_GPS_PROCESSING_METHOD,               // byte         | hidden
-    ANDROID_JPEG_GPS_TIMESTAMP,                       // int64        | hidden
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,               // byte         | ndk_public
+    ANDROID_JPEG_GPS_TIMESTAMP,                       // int64        | ndk_public
     ANDROID_JPEG_ORIENTATION,                         // int32        | public
     ANDROID_JPEG_QUALITY,                             // byte         | public
     ANDROID_JPEG_THUMBNAIL_QUALITY,                   // byte         | public
@@ -224,7 +226,7 @@ typedef enum camera_metadata_tag {
     ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,// byte[]       | public
     ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,            // float        | public
     ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,         // float        | public
-    ANDROID_LENS_INFO_SHADING_MAP_SIZE,               // int32[]      | hidden
+    ANDROID_LENS_INFO_SHADING_MAP_SIZE,               // int32[]      | ndk_public
     ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,     // enum         | public
     ANDROID_LENS_INFO_END,
 
@@ -250,16 +252,16 @@ typedef enum camera_metadata_tag {
     ANDROID_REQUEST_METADATA_MODE,                    // enum         | system
     ANDROID_REQUEST_OUTPUT_STREAMS,                   // int32[]      | system
     ANDROID_REQUEST_TYPE,                             // enum         | system
-    ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,           // int32[]      | hidden
+    ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,           // int32[]      | ndk_public
     ANDROID_REQUEST_MAX_NUM_REPROCESS_STREAMS,        // int32[]      | system
     ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,            // int32        | public
     ANDROID_REQUEST_PIPELINE_DEPTH,                   // byte         | public
     ANDROID_REQUEST_PIPELINE_MAX_DEPTH,               // byte         | public
     ANDROID_REQUEST_PARTIAL_RESULT_COUNT,             // int32        | public
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES,           // enum[]       | public
-    ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,           // int32[]      | hidden
-    ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,            // int32[]      | hidden
-    ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,   // int32[]      | hidden
+    ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,           // int32[]      | ndk_public
+    ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,            // int32[]      | ndk_public
+    ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,   // int32[]      | ndk_public
     ANDROID_REQUEST_END,
 
     ANDROID_SCALER_CROP_REGION =                      // int32[]      | public
@@ -273,9 +275,9 @@ typedef enum camera_metadata_tag {
     ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,       // int64[]      | system
     ANDROID_SCALER_AVAILABLE_RAW_SIZES,               // int32[]      | system
     ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP,// int32        | hidden
-    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,   // enum[]       | hidden
-    ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,     // int64[]      | hidden
-    ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,         // int64[]      | hidden
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,   // enum[]       | ndk_public
+    ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,     // int64[]      | ndk_public
+    ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,         // int64[]      | ndk_public
     ANDROID_SCALER_CROPPING_TYPE,                     // enum         | public
     ANDROID_SCALER_END,
 
@@ -307,6 +309,10 @@ typedef enum camera_metadata_tag {
     ANDROID_SENSOR_TEST_PATTERN_MODE,                 // enum         | public
     ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,      // int32[]      | public
     ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,              // int64        | public
+    ANDROID_SENSOR_OPTICAL_BLACK_REGIONS,             // int32[]      | public
+    ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL,               // float[]      | public
+    ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL,               // int32        | public
+    ANDROID_SENSOR_OPAQUE_RAW_SIZE,                   // int32[]      | system
     ANDROID_SENSOR_END,
 
     ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE =           // int32[]      | public
@@ -335,14 +341,14 @@ typedef enum camera_metadata_tag {
     ANDROID_STATISTICS_HISTOGRAM_MODE,                // enum         | system
     ANDROID_STATISTICS_SHARPNESS_MAP_MODE,            // enum         | system
     ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,            // enum         | public
-    ANDROID_STATISTICS_FACE_IDS,                      // int32[]      | hidden
-    ANDROID_STATISTICS_FACE_LANDMARKS,                // int32[]      | hidden
-    ANDROID_STATISTICS_FACE_RECTANGLES,               // int32[]      | hidden
-    ANDROID_STATISTICS_FACE_SCORES,                   // byte[]       | hidden
+    ANDROID_STATISTICS_FACE_IDS,                      // int32[]      | ndk_public
+    ANDROID_STATISTICS_FACE_LANDMARKS,                // int32[]      | ndk_public
+    ANDROID_STATISTICS_FACE_RECTANGLES,               // int32[]      | ndk_public
+    ANDROID_STATISTICS_FACE_SCORES,                   // byte[]       | ndk_public
     ANDROID_STATISTICS_HISTOGRAM,                     // int32[]      | system
     ANDROID_STATISTICS_SHARPNESS_MAP,                 // int32[]      | system
     ANDROID_STATISTICS_LENS_SHADING_CORRECTION_MAP,   // byte         | public
-    ANDROID_STATISTICS_LENS_SHADING_MAP,              // float[]      | hidden
+    ANDROID_STATISTICS_LENS_SHADING_MAP,              // float[]      | ndk_public
     ANDROID_STATISTICS_PREDICTED_COLOR_GAINS,         // float[]      | hidden
     ANDROID_STATISTICS_PREDICTED_COLOR_TRANSFORM,     // rational[]   | hidden
     ANDROID_STATISTICS_SCENE_FLICKER,                 // enum         | public
@@ -364,10 +370,10 @@ typedef enum camera_metadata_tag {
                                                       // byte[]       | public
     ANDROID_STATISTICS_INFO_END,
 
-    ANDROID_TONEMAP_CURVE_BLUE =                      // float[]      | hidden
+    ANDROID_TONEMAP_CURVE_BLUE =                      // float[]      | ndk_public
             ANDROID_TONEMAP_START,
-    ANDROID_TONEMAP_CURVE_GREEN,                      // float[]      | hidden
-    ANDROID_TONEMAP_CURVE_RED,                        // float[]      | hidden
+    ANDROID_TONEMAP_CURVE_GREEN,                      // float[]      | ndk_public
+    ANDROID_TONEMAP_CURVE_RED,                        // float[]      | ndk_public
     ANDROID_TONEMAP_MODE,                             // enum         | public
     ANDROID_TONEMAP_MAX_CURVE_POINTS,                 // int32        | public
     ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,         // byte[]       | public
@@ -388,22 +394,22 @@ typedef enum camera_metadata_tag {
             ANDROID_BLACK_LEVEL_START,
     ANDROID_BLACK_LEVEL_END,
 
-    ANDROID_SYNC_FRAME_NUMBER =                       // enum         | hidden
+    ANDROID_SYNC_FRAME_NUMBER =                       // enum         | ndk_public
             ANDROID_SYNC_START,
     ANDROID_SYNC_MAX_LATENCY,                         // enum         | public
     ANDROID_SYNC_END,
 
-    ANDROID_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =     // float        | public
+    ANDROID_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =     // float        | java_public
             ANDROID_REPROCESS_START,
-    ANDROID_REPROCESS_MAX_CAPTURE_STALL,              // int32        | public
+    ANDROID_REPROCESS_MAX_CAPTURE_STALL,              // int32        | java_public
     ANDROID_REPROCESS_END,
 
     ANDROID_DEPTH_MAX_DEPTH_SAMPLES =                 // int32        | system
             ANDROID_DEPTH_START,
     ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
-                                                      // enum[]       | hidden
-    ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,// int64[]      | hidden
-    ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,    // int64[]      | hidden
+                                                      // enum[]       | ndk_public
+    ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,// int64[]      | ndk_public
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,    // int64[]      | ndk_public
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,                 // enum         | public
     ANDROID_DEPTH_END,
 
@@ -548,6 +554,8 @@ typedef enum camera_metadata_enum_android_control_scene_mode {
     ANDROID_CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO,
     ANDROID_CONTROL_SCENE_MODE_HDR,
     ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT,
+    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START              = 100,
+    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END                = 127,
 } camera_metadata_enum_android_control_scene_mode_t;
 
 // ANDROID_CONTROL_VIDEO_STABILIZATION_MODE
@@ -880,6 +888,7 @@ typedef enum camera_metadata_enum_android_info_supported_hardware_level {
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,
 } camera_metadata_enum_android_info_supported_hardware_level_t;
 
 
index 0e0fe22..395089a 100644 (file)
@@ -18,6 +18,8 @@ LOCAL_MODULE_TAGS := optional
 
 LOCAL_CFLAGS += \
        -Wall \
+       -Wextra \
+       -Werror \
        -fvisibility=hidden \
        -std=c99
 
index eb914eb..c58a966 100644 (file)
@@ -524,7 +524,7 @@ static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
 
     if (dst == NULL) return ERROR;
     if (dst->entry_count == dst->entry_capacity) return ERROR;
-    if (data == NULL) return ERROR;
+    if (data_count && data == NULL) return ERROR;
 
     size_t data_bytes =
             calculate_camera_metadata_entry_data_size(type, data_count);
@@ -823,6 +823,7 @@ int get_camera_metadata_tag_type(uint32_t tag) {
 
 int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
     // **DEPRECATED**
+    (void) ops;
     ALOGE("%s: This function has been deprecated", __FUNCTION__);
     return ERROR;
 }
index a267191..1716a84 100644 (file)
@@ -212,6 +212,10 @@ static tag_info_t android_control[ANDROID_CONTROL_END -
     { "awbLockAvailable",              TYPE_BYTE   },
     [ ANDROID_CONTROL_AVAILABLE_MODES - ANDROID_CONTROL_START ] =
     { "availableModes",                TYPE_BYTE   },
+    [ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE - ANDROID_CONTROL_START ] =
+    { "postRawSensitivityBoostRange",  TYPE_INT32  },
+    [ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST - ANDROID_CONTROL_START ] =
+    { "postRawSensitivityBoost",       TYPE_INT32  },
 };
 
 static tag_info_t android_demosaic[ANDROID_DEMOSAIC_END -
@@ -492,6 +496,14 @@ static tag_info_t android_sensor[ANDROID_SENSOR_END -
     { "availableTestPatternModes",     TYPE_INT32  },
     [ ANDROID_SENSOR_ROLLING_SHUTTER_SKEW - ANDROID_SENSOR_START ] =
     { "rollingShutterSkew",            TYPE_INT64  },
+    [ ANDROID_SENSOR_OPTICAL_BLACK_REGIONS - ANDROID_SENSOR_START ] =
+    { "opticalBlackRegions",           TYPE_INT32  },
+    [ ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL - ANDROID_SENSOR_START ] =
+    { "dynamicBlackLevel",             TYPE_FLOAT  },
+    [ ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL - ANDROID_SENSOR_START ] =
+    { "dynamicWhiteLevel",             TYPE_INT32  },
+    [ ANDROID_SENSOR_OPAQUE_RAW_SIZE - ANDROID_SENSOR_START ] =
+    { "opaqueRawSize",                 TYPE_INT32  },
 };
 
 static tag_info_t android_sensor_info[ANDROID_SENSOR_INFO_END -
@@ -1137,6 +1149,14 @@ int camera_metadata_enum_snprint(uint32_t tag,
                     msg = "FACE_PRIORITY_LOW_LIGHT";
                     ret = 0;
                     break;
+                case ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START:
+                    msg = "DEVICE_CUSTOM_START";
+                    ret = 0;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END:
+                    msg = "DEVICE_CUSTOM_END";
+                    ret = 0;
+                    break;
                 default:
                     msg = "error: enum value out of range";
             }
@@ -1324,6 +1344,12 @@ int camera_metadata_enum_snprint(uint32_t tag,
         case ANDROID_CONTROL_AVAILABLE_MODES: {
             break;
         }
+        case ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE: {
+            break;
+        }
+        case ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST: {
+            break;
+        }
 
         case ANDROID_DEMOSAIC_MODE: {
             switch (value) {
@@ -2088,6 +2114,18 @@ int camera_metadata_enum_snprint(uint32_t tag,
         case ANDROID_SENSOR_ROLLING_SHUTTER_SKEW: {
             break;
         }
+        case ANDROID_SENSOR_OPTICAL_BLACK_REGIONS: {
+            break;
+        }
+        case ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL: {
+            break;
+        }
+        case ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL: {
+            break;
+        }
+        case ANDROID_SENSOR_OPAQUE_RAW_SIZE: {
+            break;
+        }
 
         case ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE: {
             break;
@@ -2456,6 +2494,10 @@ int camera_metadata_enum_snprint(uint32_t tag,
                     msg = "LEGACY";
                     ret = 0;
                     break;
+                case ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3:
+                    msg = "3";
+                    ret = 0;
+                    break;
                 default:
                     msg = "error: enum value out of range";
             }
index b39b3b5..c50d89a 100644 (file)
@@ -14,6 +14,8 @@ LOCAL_C_INCLUDES := \
 LOCAL_SRC_FILES := \
        camera_metadata_tests.cpp
 
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
 LOCAL_MODULE := camera_metadata_tests
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE_STEM_32 := camera_metadata_tests
index 916db15..2ee660e 100644 (file)
@@ -300,7 +300,7 @@ TEST(camera_metadata, add_get_normal) {
     result = get_camera_metadata_entry(m,
             index, &entry);
     EXPECT_EQ(OK, result);
-    EXPECT_EQ(index, (int)entry.index);
+    EXPECT_EQ(index, entry.index);
     EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, entry.tag);
     EXPECT_EQ(TYPE_INT64, entry.type);
     EXPECT_EQ((size_t)1, entry.count);
@@ -462,8 +462,6 @@ TEST(camera_metadata, copy_metadata) {
     const size_t entry_capacity = 50;
     const size_t data_capacity = 450;
 
-    int result;
-
     m = allocate_camera_metadata(entry_capacity, data_capacity);
 
     add_test_metadata(m, entry_capacity);
@@ -517,8 +515,6 @@ TEST(camera_metadata, copy_metadata_extraspace) {
 
     const size_t extra_space = 10;
 
-    int result;
-
     m = allocate_camera_metadata(entry_capacity, data_capacity);
 
     add_test_metadata(m, entry_capacity);
@@ -575,8 +571,6 @@ TEST(camera_metadata, copy_metadata_nospace) {
     const size_t entry_capacity = 5;
     const size_t data_capacity = 50;
 
-    int result;
-
     m = allocate_camera_metadata(entry_capacity, data_capacity);
 
     add_test_metadata(m, entry_capacity);
@@ -1780,7 +1774,7 @@ TEST(camera_metadata, memcpy) {
 
     EXPECT_EQ(OK, validate_camera_metadata_structure(m2, &m_size));
 
-    delete dst;
+    delete[] dst;
     FINISH_USING_CAMERA_METADATA(m);
 }
 
index cdd219e..aa92421 100644 (file)
@@ -123,7 +123,8 @@ static const vendor_tag_ops_t fakevendor_ops = {
     get_fakevendor_tags,
     get_fakevendor_section_name,
     get_fakevendor_tag_name,
-    get_fakevendor_tag_type
+    get_fakevendor_tag_type,
+    {NULL}
 };
 
 const char *get_fakevendor_section_name(const vendor_tag_ops_t *v,
index 01c0403..7dc35cc 100644 (file)
@@ -42,21 +42,27 @@ enum {
     RADIO_METADATA_KEY_GENRE        = 8,      /* Musical genre          - text  */
     RADIO_METADATA_KEY_ICON         = 9,      /* Station icon           - raw  */
     RADIO_METADATA_KEY_ART          = 10,     /* Album art              - raw  */
+    RADIO_METADATA_KEY_CLOCK        = 11,     /* Clock                  - radio_metadata_clock_t */
     RADIO_METADATA_KEY_MIN          = RADIO_METADATA_KEY_RDS_PI,
-    RADIO_METADATA_KEY_MAX          = RADIO_METADATA_KEY_ART,
+    RADIO_METADATA_KEY_MAX          = RADIO_METADATA_KEY_CLOCK,
 };
 typedef int radio_metadata_key_t;
 
-
 enum {
     RADIO_METADATA_TYPE_INVALID    = -1,
     RADIO_METADATA_TYPE_INT        = 0,      /* signed 32 bit integer  */
     RADIO_METADATA_TYPE_TEXT       = 1,      /* text in UTF-8 format, NUL terminated.
                                                 RADIO_METADATA_TEXT_LEN_MAX length including NUL. */
     RADIO_METADATA_TYPE_RAW        = 2,      /* raw binary data (icon or art) */
+    RADIO_METADATA_TYPE_CLOCK      = 3,      /* clock data, see radio_metadata_clock_t */
 };
 typedef int radio_metadata_type_t;
 
+typedef struct radio_metadata_clock {
+    uint64_t utc_seconds_since_epoch;            /* Seconds since epoch at GMT + 0. */
+    int32_t timezone_offset_in_minutes;       /* Minutes offset from the GMT. */
+} radio_metadata_clock_t;
+
 /*
  * Return the type of the meta data corresponding to the key specified
  *
@@ -156,6 +162,25 @@ int radio_metadata_add_raw(radio_metadata_t **metadata,
                            const unsigned int size);
 
 /*
+ * Add a clock meta data to the buffer.
+ *
+ * arguments:
+ * - metadata: the address of the meta data buffer. I/O. the meta data can be modified if the
+ * buffer is re-allocated.
+ * - key: the meta data key.
+ * - value: the meta data value.
+ *
+ * returns:
+ * 0 if successfully added
+ * - EINVAL if the buffer passed is invalid or the key does not match a raw type
+ * - ENOMEM if meta data buffer cannot be re-allocated
+ */
+ANDROID_API
+int radio_metadata_add_clock(radio_metadata_t **metadata,
+                             const radio_metadata_key_t key,
+                             const radio_metadata_clock_t *clock);
+
+/*
  * add all meta data in source buffer to destinaiton buffer.
  *
  * arguments:
index b96a40a..01787ec 100644 (file)
@@ -16,8 +16,8 @@ LOCAL_SHARED_LIBRARIES := \
 LOCAL_MODULE := libradio_metadata
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_CFLAGS += \
-       -fvisibility=hidden
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -fvisibility=hidden
 
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include
 
index 41c67d8..4cf03e8 100644 (file)
@@ -39,6 +39,7 @@ const radio_metadata_type_t metadata_key_type_table[] =
     RADIO_METADATA_TYPE_TEXT,
     RADIO_METADATA_TYPE_RAW,
     RADIO_METADATA_TYPE_RAW,
+    RADIO_METADATA_TYPE_CLOCK,
 };
 
 /**
@@ -232,6 +233,19 @@ int radio_metadata_add_raw(radio_metadata_t **metadata,
     return add_metadata((radio_metadata_buffer_t **)metadata, key, type, value, size);
 }
 
+int radio_metadata_add_clock(radio_metadata_t **metadata,
+                             const radio_metadata_key_t key,
+                             const radio_metadata_clock_t *clock) {
+    radio_metadata_type_t type = radio_metadata_type_of_key(key);
+    if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_CLOCK ||
+        clock == NULL || clock->timezone_offset_in_minutes < (-12 * 60) ||
+        clock->timezone_offset_in_minutes > (14 * 60)) {
+        return -EINVAL;
+    }
+    return add_metadata(
+        (radio_metadata_buffer_t **)metadata, key, type, clock, sizeof(radio_metadata_clock_t));
+}
+
 int radio_metadata_add_metadata(radio_metadata_t **dst_metadata,
                            radio_metadata_t *src_metadata)
 {
@@ -348,8 +362,6 @@ int radio_metadata_get_at_index(const radio_metadata_t *metadata,
                                 void **value,
                                 unsigned int *size)
 {
-    unsigned int index_offset;
-    unsigned int data_offset;
     radio_metadata_entry_t *entry;
     radio_metadata_buffer_t *metadata_buf =
             (radio_metadata_buffer_t *)metadata;