Full Code of android/ndk-samples for AI

main 988d73bed0fd cached
797 files
6.0 MB
1.6M tokens
1555 symbols
1 requests
Download .txt
Showing preview only (6,429K chars total). Download the full file or copy to clipboard to get everything.
Repository: android/ndk-samples
Branch: main
Commit: 988d73bed0fd
Files: 797
Total size: 6.0 MB

Directory structure:
gitextract_om9grlgx/

├── .clang-format
├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .google/
│   └── packaging.yaml
├── .pre-commit-config.yaml
├── ARCHITECTURE.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── REFERENCE.md
├── audio-echo/
│   └── README.md
├── base/
│   ├── .gitignore
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── cpp/
│               ├── CMakeLists.txt
│               ├── include/
│               │   └── base/
│               │       ├── errno_restorer.h
│               │       ├── logging.h
│               │       └── macros.h
│               ├── logging.cpp
│               └── logging_splitters.h
├── bitmap-plasma/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── jni.cpp
│               │   ├── libplasma.map.txt
│               │   ├── plasma.cpp
│               │   └── plasma.h
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── plasma/
│               │               └── Plasma.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── build-logic/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── android/
│                       └── ndk/
│                           └── samples/
│                               └── buildlogic/
│                                   ├── AndroidApplicationConventionPlugin.kt
│                                   ├── AndroidLibraryConventionPlugin.kt
│                                   ├── KotlinConventionPlugin.kt
│                                   └── Versions.kt
├── build.gradle
├── camera/
│   ├── README.md
│   ├── basic/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── android_main.cpp
│   │           │   ├── camera_engine.cpp
│   │           │   ├── camera_engine.h
│   │           │   ├── camera_listeners.cpp
│   │           │   ├── camera_manager.cpp
│   │           │   ├── camera_manager.h
│   │           │   ├── camera_ui.cpp
│   │           │   ├── image_reader.cpp
│   │           │   ├── image_reader.h
│   │           │   └── libndk_camera.map.txt
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           └── camera/
│   │           │               └── basic/
│   │           │                   └── CameraActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               └── values/
│   │                   └── strings.xml
│   ├── camera-utils/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── cpp/
│   │               ├── CMakeLists.txt
│   │               ├── camera_utils.cpp
│   │               └── include/
│   │                   └── ndksamples/
│   │                       └── camera/
│   │                           ├── camera_utils.h
│   │                           └── native_debug.h
│   └── texture-view/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── android_main.cpp
│               │   ├── camera_engine.cpp
│               │   ├── camera_engine.h
│               │   ├── camera_listeners.cpp
│               │   ├── camera_manager.cpp
│               │   ├── camera_manager.h
│               │   └── libcamera_textureview.map.txt
│               ├── java/
│               │   └── com/
│               │       └── sample/
│               │           └── textureview/
│               │               └── ViewActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── activity_main.xml
│                   └── values/
│                       └── strings.xml
├── cmake/
│   └── AppLibrary.cmake
├── endless-tunnel/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── android_main.cpp
│               │   ├── anim.cpp
│               │   ├── anim.hpp
│               │   ├── ascii_to_geom.cpp
│               │   ├── ascii_to_geom.hpp
│               │   ├── common.hpp
│               │   ├── data/
│               │   │   ├── alphabet.inl
│               │   │   ├── ascii_art.inl
│               │   │   ├── blurb.inl
│               │   │   ├── cube_geom.inl
│               │   │   ├── our_shader.inl
│               │   │   ├── strings.inl
│               │   │   └── tunnel_geom.inl
│               │   ├── dialog_scene.cpp
│               │   ├── dialog_scene.hpp
│               │   ├── engine.hpp
│               │   ├── game_consts.hpp
│               │   ├── glm/
│               │   │   ├── CMakeLists.txt
│               │   │   ├── common.hpp
│               │   │   ├── detail/
│               │   │   │   ├── _features.hpp
│               │   │   │   ├── _fixes.hpp
│               │   │   │   ├── _literals.hpp
│               │   │   │   ├── _noise.hpp
│               │   │   │   ├── _swizzle.hpp
│               │   │   │   ├── _swizzle_func.hpp
│               │   │   │   ├── _vectorize.hpp
│               │   │   │   ├── func_common.hpp
│               │   │   │   ├── func_common.inl
│               │   │   │   ├── func_exponential.hpp
│               │   │   │   ├── func_exponential.inl
│               │   │   │   ├── func_geometric.hpp
│               │   │   │   ├── func_geometric.inl
│               │   │   │   ├── func_integer.hpp
│               │   │   │   ├── func_integer.inl
│               │   │   │   ├── func_matrix.hpp
│               │   │   │   ├── func_matrix.inl
│               │   │   │   ├── func_noise.hpp
│               │   │   │   ├── func_noise.inl
│               │   │   │   ├── func_packing.hpp
│               │   │   │   ├── func_packing.inl
│               │   │   │   ├── func_trigonometric.hpp
│               │   │   │   ├── func_trigonometric.inl
│               │   │   │   ├── func_vector_relational.hpp
│               │   │   │   ├── func_vector_relational.inl
│               │   │   │   ├── glm.cpp
│               │   │   │   ├── hint.hpp
│               │   │   │   ├── intrinsic_common.hpp
│               │   │   │   ├── intrinsic_common.inl
│               │   │   │   ├── intrinsic_exponential.hpp
│               │   │   │   ├── intrinsic_exponential.inl
│               │   │   │   ├── intrinsic_geometric.hpp
│               │   │   │   ├── intrinsic_geometric.inl
│               │   │   │   ├── intrinsic_integer.hpp
│               │   │   │   ├── intrinsic_integer.inl
│               │   │   │   ├── intrinsic_matrix.hpp
│               │   │   │   ├── intrinsic_matrix.inl
│               │   │   │   ├── intrinsic_trigonometric.hpp
│               │   │   │   ├── intrinsic_trigonometric.inl
│               │   │   │   ├── intrinsic_vector_relational.hpp
│               │   │   │   ├── intrinsic_vector_relational.inl
│               │   │   │   ├── precision.hpp
│               │   │   │   ├── precision.inl
│               │   │   │   ├── setup.hpp
│               │   │   │   ├── type_float.hpp
│               │   │   │   ├── type_gentype.hpp
│               │   │   │   ├── type_gentype.inl
│               │   │   │   ├── type_half.hpp
│               │   │   │   ├── type_half.inl
│               │   │   │   ├── type_int.hpp
│               │   │   │   ├── type_mat.hpp
│               │   │   │   ├── type_mat.inl
│               │   │   │   ├── type_mat2x2.hpp
│               │   │   │   ├── type_mat2x2.inl
│               │   │   │   ├── type_mat2x3.hpp
│               │   │   │   ├── type_mat2x3.inl
│               │   │   │   ├── type_mat2x4.hpp
│               │   │   │   ├── type_mat2x4.inl
│               │   │   │   ├── type_mat3x2.hpp
│               │   │   │   ├── type_mat3x2.inl
│               │   │   │   ├── type_mat3x3.hpp
│               │   │   │   ├── type_mat3x3.inl
│               │   │   │   ├── type_mat3x4.hpp
│               │   │   │   ├── type_mat3x4.inl
│               │   │   │   ├── type_mat4x2.hpp
│               │   │   │   ├── type_mat4x2.inl
│               │   │   │   ├── type_mat4x3.hpp
│               │   │   │   ├── type_mat4x3.inl
│               │   │   │   ├── type_mat4x4.hpp
│               │   │   │   ├── type_mat4x4.inl
│               │   │   │   ├── type_vec.hpp
│               │   │   │   ├── type_vec.inl
│               │   │   │   ├── type_vec1.hpp
│               │   │   │   ├── type_vec1.inl
│               │   │   │   ├── type_vec2.hpp
│               │   │   │   ├── type_vec2.inl
│               │   │   │   ├── type_vec3.hpp
│               │   │   │   ├── type_vec3.inl
│               │   │   │   ├── type_vec4.hpp
│               │   │   │   └── type_vec4.inl
│               │   │   ├── exponential.hpp
│               │   │   ├── ext.hpp
│               │   │   ├── fwd.hpp
│               │   │   ├── geometric.hpp
│               │   │   ├── glm.hpp
│               │   │   ├── gtc/
│               │   │   │   ├── constants.hpp
│               │   │   │   ├── constants.inl
│               │   │   │   ├── epsilon.hpp
│               │   │   │   ├── epsilon.inl
│               │   │   │   ├── matrix_access.hpp
│               │   │   │   ├── matrix_access.inl
│               │   │   │   ├── matrix_integer.hpp
│               │   │   │   ├── matrix_inverse.hpp
│               │   │   │   ├── matrix_inverse.inl
│               │   │   │   ├── matrix_transform.hpp
│               │   │   │   ├── matrix_transform.inl
│               │   │   │   ├── noise.hpp
│               │   │   │   ├── noise.inl
│               │   │   │   ├── packing.hpp
│               │   │   │   ├── packing.inl
│               │   │   │   ├── quaternion.hpp
│               │   │   │   ├── quaternion.inl
│               │   │   │   ├── random.hpp
│               │   │   │   ├── random.inl
│               │   │   │   ├── reciprocal.hpp
│               │   │   │   ├── reciprocal.inl
│               │   │   │   ├── type_precision.hpp
│               │   │   │   ├── type_precision.inl
│               │   │   │   ├── type_ptr.hpp
│               │   │   │   ├── type_ptr.inl
│               │   │   │   ├── ulp.hpp
│               │   │   │   └── ulp.inl
│               │   │   ├── gtx/
│               │   │   │   ├── associated_min_max.hpp
│               │   │   │   ├── associated_min_max.inl
│               │   │   │   ├── bit.hpp
│               │   │   │   ├── bit.inl
│               │   │   │   ├── closest_point.hpp
│               │   │   │   ├── closest_point.inl
│               │   │   │   ├── color_space.hpp
│               │   │   │   ├── color_space.inl
│               │   │   │   ├── color_space_YCoCg.hpp
│               │   │   │   ├── color_space_YCoCg.inl
│               │   │   │   ├── compatibility.hpp
│               │   │   │   ├── compatibility.inl
│               │   │   │   ├── component_wise.hpp
│               │   │   │   ├── component_wise.inl
│               │   │   │   ├── constants.hpp
│               │   │   │   ├── dual_quaternion.hpp
│               │   │   │   ├── dual_quaternion.inl
│               │   │   │   ├── epsilon.hpp
│               │   │   │   ├── euler_angles.hpp
│               │   │   │   ├── euler_angles.inl
│               │   │   │   ├── extend.hpp
│               │   │   │   ├── extend.inl
│               │   │   │   ├── extented_min_max.hpp
│               │   │   │   ├── extented_min_max.inl
│               │   │   │   ├── fast_exponential.hpp
│               │   │   │   ├── fast_exponential.inl
│               │   │   │   ├── fast_square_root.hpp
│               │   │   │   ├── fast_square_root.inl
│               │   │   │   ├── fast_trigonometry.hpp
│               │   │   │   ├── fast_trigonometry.inl
│               │   │   │   ├── gradient_paint.hpp
│               │   │   │   ├── gradient_paint.inl
│               │   │   │   ├── handed_coordinate_space.hpp
│               │   │   │   ├── handed_coordinate_space.inl
│               │   │   │   ├── inertia.hpp
│               │   │   │   ├── inertia.inl
│               │   │   │   ├── int_10_10_10_2.hpp
│               │   │   │   ├── int_10_10_10_2.inl
│               │   │   │   ├── integer.hpp
│               │   │   │   ├── integer.inl
│               │   │   │   ├── intersect.hpp
│               │   │   │   ├── intersect.inl
│               │   │   │   ├── io.hpp
│               │   │   │   ├── io.inl
│               │   │   │   ├── log_base.hpp
│               │   │   │   ├── log_base.inl
│               │   │   │   ├── matrix_cross_product.hpp
│               │   │   │   ├── matrix_cross_product.inl
│               │   │   │   ├── matrix_interpolation.hpp
│               │   │   │   ├── matrix_interpolation.inl
│               │   │   │   ├── matrix_major_storage.hpp
│               │   │   │   ├── matrix_major_storage.inl
│               │   │   │   ├── matrix_operation.hpp
│               │   │   │   ├── matrix_operation.inl
│               │   │   │   ├── matrix_query.hpp
│               │   │   │   ├── matrix_query.inl
│               │   │   │   ├── matrix_transform_2d.hpp
│               │   │   │   ├── matrix_transform_2d.inl
│               │   │   │   ├── mixed_product.hpp
│               │   │   │   ├── mixed_product.inl
│               │   │   │   ├── multiple.hpp
│               │   │   │   ├── multiple.inl
│               │   │   │   ├── noise.hpp
│               │   │   │   ├── norm.hpp
│               │   │   │   ├── norm.inl
│               │   │   │   ├── normal.hpp
│               │   │   │   ├── normal.inl
│               │   │   │   ├── normalize_dot.hpp
│               │   │   │   ├── normalize_dot.inl
│               │   │   │   ├── number_precision.hpp
│               │   │   │   ├── number_precision.inl
│               │   │   │   ├── optimum_pow.hpp
│               │   │   │   ├── optimum_pow.inl
│               │   │   │   ├── orthonormalize.hpp
│               │   │   │   ├── orthonormalize.inl
│               │   │   │   ├── perpendicular.hpp
│               │   │   │   ├── perpendicular.inl
│               │   │   │   ├── polar_coordinates.hpp
│               │   │   │   ├── polar_coordinates.inl
│               │   │   │   ├── projection.hpp
│               │   │   │   ├── projection.inl
│               │   │   │   ├── quaternion.hpp
│               │   │   │   ├── quaternion.inl
│               │   │   │   ├── random.hpp
│               │   │   │   ├── raw_data.hpp
│               │   │   │   ├── raw_data.inl
│               │   │   │   ├── reciprocal.hpp
│               │   │   │   ├── rotate_normalized_axis.hpp
│               │   │   │   ├── rotate_normalized_axis.inl
│               │   │   │   ├── rotate_vector.hpp
│               │   │   │   ├── rotate_vector.inl
│               │   │   │   ├── scalar_relational.hpp
│               │   │   │   ├── scalar_relational.inl
│               │   │   │   ├── simd_mat4.hpp
│               │   │   │   ├── simd_mat4.inl
│               │   │   │   ├── simd_quat.hpp
│               │   │   │   ├── simd_quat.inl
│               │   │   │   ├── simd_vec4.hpp
│               │   │   │   ├── simd_vec4.inl
│               │   │   │   ├── spline.hpp
│               │   │   │   ├── spline.inl
│               │   │   │   ├── std_based_type.hpp
│               │   │   │   ├── std_based_type.inl
│               │   │   │   ├── string_cast.hpp
│               │   │   │   ├── string_cast.inl
│               │   │   │   ├── transform.hpp
│               │   │   │   ├── transform.inl
│               │   │   │   ├── transform2.hpp
│               │   │   │   ├── transform2.inl
│               │   │   │   ├── ulp.hpp
│               │   │   │   ├── unsigned_int.hpp
│               │   │   │   ├── unsigned_int.inl
│               │   │   │   ├── vec1.hpp
│               │   │   │   ├── vec1.inl
│               │   │   │   ├── vector_angle.hpp
│               │   │   │   ├── vector_angle.inl
│               │   │   │   ├── vector_query.hpp
│               │   │   │   ├── vector_query.inl
│               │   │   │   ├── wrap.hpp
│               │   │   │   └── wrap.inl
│               │   │   ├── integer.hpp
│               │   │   ├── mat2x2.hpp
│               │   │   ├── mat2x3.hpp
│               │   │   ├── mat2x4.hpp
│               │   │   ├── mat3x2.hpp
│               │   │   ├── mat3x3.hpp
│               │   │   ├── mat3x4.hpp
│               │   │   ├── mat4x2.hpp
│               │   │   ├── mat4x3.hpp
│               │   │   ├── mat4x4.hpp
│               │   │   ├── matrix.hpp
│               │   │   ├── packing.hpp
│               │   │   ├── trigonometric.hpp
│               │   │   ├── vec2.hpp
│               │   │   ├── vec3.hpp
│               │   │   ├── vec4.hpp
│               │   │   ├── vector_relational.hpp
│               │   │   └── virtrev/
│               │   │       └── xstream.hpp
│               │   ├── indexbuf.cpp
│               │   ├── indexbuf.hpp
│               │   ├── input_util.cpp
│               │   ├── input_util.hpp
│               │   ├── jni_util.cpp
│               │   ├── jni_util.hpp
│               │   ├── joystick-support.hpp
│               │   ├── libgame.map.txt
│               │   ├── native_engine.cpp
│               │   ├── native_engine.hpp
│               │   ├── obstacle.cpp
│               │   ├── obstacle.hpp
│               │   ├── obstacle_generator.cpp
│               │   ├── obstacle_generator.hpp
│               │   ├── our_key_codes.hpp
│               │   ├── our_shader.cpp
│               │   ├── our_shader.hpp
│               │   ├── play_scene.cpp
│               │   ├── play_scene.hpp
│               │   ├── scene.cpp
│               │   ├── scene.hpp
│               │   ├── scene_manager.cpp
│               │   ├── scene_manager.hpp
│               │   ├── sfxman.cpp
│               │   ├── sfxman.hpp
│               │   ├── shader.cpp
│               │   ├── shader.hpp
│               │   ├── shape_renderer.cpp
│               │   ├── shape_renderer.hpp
│               │   ├── simplegeom.hpp
│               │   ├── tex_quad.cpp
│               │   ├── tex_quad.hpp
│               │   ├── text_renderer.cpp
│               │   ├── text_renderer.hpp
│               │   ├── texture.cpp
│               │   ├── texture.hpp
│               │   ├── ui_scene.cpp
│               │   ├── ui_scene.hpp
│               │   ├── util.cpp
│               │   ├── util.hpp
│               │   ├── vertexbuf.cpp
│               │   ├── vertexbuf.hpp
│               │   ├── welcome_scene.cpp
│               │   └── welcome_scene.hpp
│               └── res/
│                   └── values/
│                       ├── strings.xml
│                       └── styles.xml
├── exceptions/
│   ├── .gitignore
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── exception_helper.cpp
│               │   ├── exception_helper.h
│               │   ├── libexceptions.map.txt
│               │   └── native-lib.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── exceptions/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   ├── values-night/
│                   │   └── themes.xml
│                   └── xml/
│                       ├── backup_rules.xml
│                       └── data_extraction_rules.xml
├── gles3jni/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── RendererES2.cpp
│               │   ├── RendererES3.cpp
│               │   ├── gles3jni.cpp
│               │   ├── gles3jni.h
│               │   └── libgles3jni.map.txt
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── gles3jni/
│               │               ├── GLES3JNIActivity.java
│               │               ├── GLES3JNILib.java
│               │               └── GLES3JNIView.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── gradle/
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── hello-gl2/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── gl_code.cpp
│               │   └── libgl2jni.map.txt
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── gl2jni/
│               │               ├── GL2JNIActivity.java
│               │               ├── GL2JNILib.java
│               │               └── GL2JNIView.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── hello-jni/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── hello-jni.cpp
│               │   └── libhello-jni.map.txt
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── hellojni/
│               │               └── HelloJni.kt
│               └── res/
│                   ├── layout/
│                   │   └── activity_hello_jni.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
├── hello-jniCallback/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── hello-jnicallback.cpp
│               │   └── libhello-jnicallback.map.txt
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── hellojnicallback/
│               │               ├── JniHandler.java
│               │               └── MainActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
├── hello-oboe/
│   └── README.md
├── hello-vulkan/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── hellovk.h
│               │   ├── libhellovkjni.map.txt
│               │   └── vk_main.cpp
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── hellovk/
│               │               └── VulkanActivity.kt
│               ├── res/
│               │   └── values/
│               │       ├── strings.xml
│               │       └── themes.xml
│               └── shaders/
│                   ├── shader.frag
│                   └── shader.vert
├── native-activity/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libnative-activity.map.txt
│               │   └── main.cpp
│               └── res/
│                   └── values/
│                       └── strings.xml
├── native-audio/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── assets/
│               │   └── README.txt
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── android_clip.h
│               │   ├── hello_clip.h
│               │   ├── libnative-audio-jni.map.txt
│               │   └── native-audio-jni.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── nativeaudio/
│               │               └── NativeAudio.java
│               └── res/
│                   ├── layout/
│                   │   └── main.xml
│                   └── values/
│                       └── strings.xml
├── native-codec/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libnative-codec-jni.map.txt
│               │   ├── looper.cpp
│               │   ├── looper.h
│               │   └── native-codec-jni.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── nativecodec/
│               │               ├── MyGLSurfaceView.java
│               │               └── NativeCodec.java
│               └── res/
│                   ├── layout/
│                   │   └── main.xml
│                   └── values/
│                       └── strings.xml
├── native-media/
│   └── README.md
├── native-midi/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── AndroidDebug.h
│               │   ├── AppMidiManager.cpp
│               │   ├── CMakeLists.txt
│               │   ├── MainActivity.cpp
│               │   ├── MidiSpec.h
│               │   └── libnative_midi.map.txt
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── nativemidi/
│               │               ├── AppMidiManager.java
│               │               ├── MainActivity.java
│               │               ├── MidiDataHelper.java
│               │               └── MidiSpec.java
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
├── nn-samples/
│   └── README.md
├── orderfile/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── demo.orderfile
│               │   ├── liborderfiledemo.map.txt
│               │   └── orderfile.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── orderfiledemo/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   └── values-night/
│                       └── themes.xml
├── prefab/
│   └── README.md
├── san-angeles/
│   └── README.md
├── sanitizers/
│   ├── .gitignore
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           ├── asan/
│           │   └── resources/
│           │       └── .gitignore
│           ├── hwasan/
│           │   └── resources/
│           │       └── lib/
│           │           └── arm64-v8a/
│           │               └── wrap.sh
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libsanitizers.map.txt
│               │   └── native-lib.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── sanitizers/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   ├── values-night/
│                   │   └── themes.xml
│                   └── xml/
│                       ├── backup_rules.xml
│                       └── data_extraction_rules.xml
├── sensor-graph/
│   ├── README.md
│   └── accelerometer/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── assets/
│               │   ├── shader.glslf
│               │   └── shader.glslv
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libaccelerometergraph.map.txt
│               │   └── sensorgraph.cpp
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── accelerometergraph/
│               │               ├── AccelerometerGraphActivity.java
│               │               └── AccelerometerGraphJNI.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── settings.gradle
├── teapots/
│   ├── .gitignore
│   ├── README.md
│   ├── choreographer-30fps/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── ShaderPlain.fsh
│   │           │       └── VS_ShaderPlain.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── ChoreographerNativeActivity.cpp
│   │           │   ├── TeapotRenderer.cpp
│   │           │   ├── TeapotRenderer.h
│   │           │   ├── libChoreographerNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── choreographer/
│   │           │           │   ├── ChoreographerApplication.java
│   │           │           │   └── ChoreographerNativeActivity.java
│   │           │           └── helper/
│   │           │               └── NDKHelper.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   ├── classic-teapot/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── ShaderPlain.fsh
│   │           │       └── VS_ShaderPlain.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── TeapotNativeActivity.cpp
│   │           │   ├── TeapotRenderer.cpp
│   │           │   ├── TeapotRenderer.h
│   │           │   ├── libTeapotNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── helper/
│   │           │           │   └── NDKHelper.java
│   │           │           └── teapot/
│   │           │               ├── TeapotApplication.java
│   │           │               └── TeapotNativeActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   ├── common/
│   │   └── ndk_helper/
│   │       ├── CMakeLists.txt
│   │       ├── GLContext.cpp
│   │       ├── GLContext.h
│   │       ├── JNIHelper.cpp
│   │       ├── JNIHelper.h
│   │       ├── NDKHelper.h
│   │       ├── gestureDetector.cpp
│   │       ├── gestureDetector.h
│   │       ├── gl3stub.c
│   │       ├── gl3stub.cpp
│   │       ├── gl3stub.h
│   │       ├── interpolator.cpp
│   │       ├── interpolator.h
│   │       ├── perfMonitor.cpp
│   │       ├── perfMonitor.h
│   │       ├── sensorManager.cpp
│   │       ├── sensorManager.h
│   │       ├── shader.cpp
│   │       ├── shader.h
│   │       ├── tapCamera.cpp
│   │       ├── tapCamera.h
│   │       ├── vecmath.cpp
│   │       └── vecmath.h
│   ├── image-decoder/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── 2DTexture.fsh
│   │           │       ├── 2DTexture.vsh
│   │           │       ├── Cubemap.fsh
│   │           │       ├── Cubemap.vsh
│   │           │       ├── ShaderPlain.fsh
│   │           │       └── VS_ShaderPlain.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── ImageDecoderRender.cpp
│   │           │   ├── ImageDecoderRender.h
│   │           │   ├── TeapotNativeActivity.cpp
│   │           │   ├── TeapotRenderer.cpp
│   │           │   ├── TeapotRenderer.h
│   │           │   ├── Texture.cpp
│   │           │   ├── Texture.h
│   │           │   ├── android_debug.h
│   │           │   ├── libImageDecoderNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── helper/
│   │           │           │   └── NDKHelper.java
│   │           │           └── imagedecoder/
│   │           │               ├── TeapotApplication.java
│   │           │               └── TeapotNativeActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   ├── more-teapots/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── ShaderPlain.fsh
│   │           │       ├── ShaderPlainES3.fsh
│   │           │       ├── VS_ShaderPlain.vsh
│   │           │       └── VS_ShaderPlainES3.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── MoreTeapotsNativeActivity.cpp
│   │           │   ├── MoreTeapotsRenderer.cpp
│   │           │   ├── MoreTeapotsRenderer.h
│   │           │   ├── libMoreTeapotsNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── helper/
│   │           │           │   └── NDKHelper.java
│   │           │           └── moreteapots/
│   │           │               ├── MoreTeapotsApplication.java
│   │           │               └── MoreTeapotsNativeActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   └── textured-teapot/
│       ├── README.md
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── assets/
│               │   ├── Shaders/
│               │   │   ├── 2DTexture.fsh
│               │   │   ├── 2DTexture.vsh
│               │   │   ├── Cubemap.fsh
│               │   │   ├── Cubemap.vsh
│               │   │   ├── ShaderPlain.fsh
│               │   │   └── VS_ShaderPlain.vsh
│               │   └── Textures/
│               │       ├── back.tga
│               │       ├── bottom.tga
│               │       ├── front.tga
│               │       ├── left.tga
│               │       ├── right.tga
│               │       └── top.tga
│               ├── cpp/
│               │   ├── AssetUtil.cpp
│               │   ├── AssetUtil.h
│               │   ├── CMakeLists.txt
│               │   ├── TeapotNativeActivity.cpp
│               │   ├── TeapotRenderer.cpp
│               │   ├── TeapotRenderer.h
│               │   ├── Texture.cpp
│               │   ├── Texture.h
│               │   ├── TexturedTeapotRender.cpp
│               │   ├── TexturedTeapotRender.h
│               │   ├── android_debug.h
│               │   ├── libTexturedTeapotNativeActivity.map.txt
│               │   └── teapot.inl
│               ├── java/
│               │   └── com/
│               │       └── sample/
│               │           ├── helper/
│               │           │   └── NDKHelper.java
│               │           └── texturedteapot/
│               │               ├── TeapotApplication.java
│               │               └── TeapotNativeActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── widgets.xml
│                   ├── values/
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   ├── values-v11/
│                   │   └── styles.xml
│                   └── values-v14/
│                       └── styles.xml
├── unit-test/
│   ├── .gitignore
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           ├── androidTest/
│           │   └── java/
│           │       └── com/
│           │           └── example/
│           │               └── unittest/
│           │                   └── NativeTests.kt
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── adder.cpp
│               │   ├── adder.h
│               │   ├── adder_test.cpp
│               │   ├── libunittest.map.txt
│               │   └── native-lib.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── unittest/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   ├── values-night/
│                   │   └── themes.xml
│                   └── xml/
│                       ├── backup_rules.xml
│                       └── data_extraction_rules.xml
└── vectorization/
    ├── .gitignore
    ├── README.md
    ├── build.gradle.kts
    └── src/
        └── main/
            ├── AndroidManifest.xml
            ├── cpp/
            │   ├── CMakeLists.txt
            │   ├── auto_vectorization.h
            │   ├── benchmark.cpp
            │   ├── benchmark.h
            │   ├── clang_vector.h
            │   ├── jni.cpp
            │   ├── libapp.map.txt
            │   ├── matrix.h
            │   └── omp_simd.h
            ├── java/
            │   └── com/
            │       └── android/
            │           └── ndk/
            │               └── samples/
            │                   └── vectorization/
            │                       ├── VectorizationActivity.kt
            │                       └── ui/
            │                           └── theme/
            │                               ├── Color.kt
            │                               ├── Theme.kt
            │                               └── Type.kt
            └── res/
                ├── drawable/
                │   └── ic_launcher_background.xml
                ├── drawable-v24/
                │   └── ic_launcher_foreground.xml
                ├── mipmap-anydpi-v26/
                │   ├── ic_launcher.xml
                │   └── ic_launcher_round.xml
                └── values/
                    ├── colors.xml
                    ├── strings.xml
                    └── themes.xml

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
BasedOnStyle: Google
DerivePointerAlignment: false


================================================
FILE: .github/workflows/build.yml
================================================
name: build

on:
  workflow_dispatch:
  push:
  pull_request:

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: set up JDK 21
      uses: actions/setup-java@v1
      with:
        java-version: 21

    - uses: pre-commit/action@v3.0.0

    - name: Setup Android SDK
      uses: android-actions/setup-android@v3
      with:
        packages: "cmake;4.1.0"

    - name: build samples
      run: |
        ./gradlew build


================================================
FILE: .gitignore
================================================
.gradle
.idea
**/*.iml
local.properties
build
*~
.externalNativeBuild
libwebp
.DS_Store
**/ndkHelperBin
**/.cxx
display-p3/third_party



================================================
FILE: .google/packaging.yaml
================================================
status: PUBLISHED
technologies:
  - Android
  - NDK
  - Platform
categories:
  - NDK
languages:
  - C++
solutions:
  - Mobile
github: android/ndk-samples
license: apache2


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
    -   id: check-xml
    -   id: check-yaml


================================================
FILE: ARCHITECTURE.md
================================================
# Architecture

This document describes the layout of the samples repository.

The top level directory is a Gradle project. This directory can be opened in
Android Studio (and that will be the easiest way to work with the samples).

## Directory structure

### Samples

Most subdirectories are the individual sample apps. These can't be opened in
Android Studio individually, as they rely on common code from the top level
project. These subdirectories have their own `build.gradle` (the Groovy DSL) or
`build.gradle.kts` (the Kotlin DSL) files. In Gradle terms these are "projects".
Android Studio calls them "modules". The documentation in this repository will
typically call them "modules".

Each sample has its own README.md that explains what features it demonstrates,
as well as any unique requirements.

To run a sample, use the configuration selector in the top panel of Android
Studio to select the sample and then click run. For example, to run the
endless-tunnel sample game:

![Select and run a sample][docs/run-sample.png]

#### Build types

Android Gradle modules have multiple "build types", sometimes called "variants".
For most of the samples, there are only two build types: debug and release. A
few samples, notably the sanitizers sample, have more. To view the build types
for the modules in this repository, in the Android Studio application menu,
select View -> Tool Windows -> Build Variants. A window will open that lets you
select the active variant for each sample.

### build-logic

The `build-logic` directory contains Gradle convention plugins used by this
repository. This is where Gradle policy decisions that apply to the whole
repository are made.

See the README.md in that directory for more details.

### docs

Documentation and supporting artifacts for this repository. Yes, for now it's
just images for the READMEs and this doc.

### gradle/libs.versions.toml

This is a Gradle [version catalog]. It's the central location that defines the
library and plugin dependencies for each sample.

The Android Gradle Plugin does not support evaluating version catalog fields in
its DSL, so versions for SDK and NDK tools (`ndkVersion`, `compileSdkVersion`,
`targetSdkVersion`, etc) are all defined by the convention plugins in
[build-logic](#build-logic).

[version catalog]: https://docs.gradle.org/current/userguide/platforms.html

### Gradle wrapper

The `gradlew` and `gradlew.bat` scripts are the Gradle wrappers, macOS/Linux-
and Windows batch-compatible respectively. They will manage the Gradle
installation used by this repository for you, ensuring that the correct versions
and environment are used. These should be used instead of running `gradle`
directly.

`gradle/wrapper/gradle-wrapper.properties` defines which version of Gradle will
be used. This should rarely be modified manually. Android Studio's Upgrade
Assistant will manage that file and upgrade to whatever version of Gradle it
prefers for that version of Android Studio and Android Gradle.

### build.gradle and settings.gradle

The build.gradle (or build.gradle.kts) file is the top level build file. It
doesn't do anything interesting but declares which plugins will be used by the
child modules. Each sample's module has its own build.gradle file that defines
properties of the app.

The settings.gradle (or settings.gradle.kts) file configures repositories for
fetching dependencies, and declares each app module.

### Metadata directories

#### .github

This directory contains GitHub metadata files, such as GitHub Action workflows
and Issue templates.

#### .google

The `packaging.yaml` file in this directory is used by Android Studio to enable
the File -> New -> Import Sample feature. As this repository is a monolithic
sample project, it should not need to be changed.


================================================
FILE: CONTRIBUTING.md
================================================
# How to become a contributor and submit your own code

## Contributor License Agreements

We'd love to accept your sample apps and patches! Before we can take them, we
have to jump a couple of legal hurdles.

Please fill out either the individual or corporate Contributor License Agreement
(CLA).

- If you are an individual writing original source code and you're sure you own
  the intellectual property, then you'll need to sign an
  [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).
- If you work for a company that wants to allow you to contribute your work,
  then you'll need to sign a
  [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).

Follow either of the two links above to access the appropriate CLA and
instructions for how to sign and return it. Once we receive it, we'll be able to
accept your pull requests.

## Contributing a Patch

1. Sign a Contributor License Agreement, if you have not yet done so (see
   details above).
1. Create your change to the repo in question.
   - Fork the desired repo, develop and test your code changes.
   - Ensure that your code is clear and comprehensible.
   - Ensure that your code has an appropriate set of unit tests which all pass.
1. Submit a pull request.
1. The repo owner will review your request. If it is approved, the change will
   be merged. If it needs additional work, the repo owner will respond with
   useful comments.


================================================
FILE: LICENSE
================================================
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:

You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
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
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.

================================================
FILE: README.md
================================================
# Android NDK Samples

This repository contains sample apps that use the [Android NDK].

For an explanation of the layout of this repository, see
[ARCHITECTURE.md](ARCHITECTURE.md).

## Build and run

[![build](https://github.com/android/ndk-samples/actions/workflows/build.yml/badge.svg)](https://github.com/android/ndk-samples/actions)

1. Clone the repository
2. Open the whole project in Android Studio
3. Install CMake 4.1.0 via the SDK Manager (must be done manually until
   https://issuetracker.google.com/443137057 is fixed).
4. Select the sample you want to run in the top bar (you may need to sync gradle
   first)
5. Click the play button to run the sample

You can also build the samples from the command line if you prefer. Use
`./gradlew build` to build everything (if you're on Windows, use `.\gradlew.bat`
instead of `./gradlew`). For individual tasks, see `./gradlew tasks`. To see the
tasks for an individual sample, run the `tasks` task for that directory. For
example, `./gradlew :camera:basic:tasks` will show the tasks for the
`camera/basic` app.

## I just want something to copy from as a starting point

The samples in this repository are generally not a good starting point for a
production quality app. They aim to demonstrate individual NDK APIs, but often
make sacrifices to be succinct that make them unsuitable for a production app.
This is gradually changing, but for now you should not do this.

[Now in Android](https://github.com/android/nowinandroid/) is an excellent
resource for production quality apps in general, but does not touch on NDK-
specific issues. https://github.com/DanAlbert/ndk-app-template can help some
with that until this repository is able to.

You're most likely best served by using the New Project wizard in Android Studio
to create a new app, then using those resources and the samples here as a
reference. Android Studio's "Native C++" template is a good starting point for
typical applications that need to use some C++ via JNI. The "Game Activity"
template is a good starting point for game-like apps (that is, apps that do not
use the Android UI, but instead render their own UI using OpenGL or Vulkan).

## Best practices shown here

There are a few best practices shown throughout this repository that should be
explained, but there's no central place to discuss those in the code, so we'll
discuss those here.

### `RegisterNatives`

We prefer using `RegisterNatives()` via `JNI_OnLoad()` over the name-based
matching that Studio's New Project Wizard will typically create, e.g. JNI
functions that follow the pattern `JNIEXPORT void JNICALL
Java_com_etc_ClassName_methodName()`. That approach to matching C/C++ functions
to their Java `native` function (or Kotlin `external fun`) makes for a shorter
demo when there are only a small number of functions, but it has a number of
disadvantages. See the [JNI tips] guide for details.

[JNI tips]: https://developer.android.com/ndk/guides/jni-tips#native-libraries

### Version scripts

All of the app libraries shown here are built using a version script. This is a
file that explicitly lists which symbols should be exported from the library,
and hides all the others. Version scripts function similarly to
`-fvisibility=hidden`, but can go a step further and are capable of hiding
symbols in static libraries that are used by your app. Hiding as many symbols as
possible results in smaller binaries that load faster, as there are fewer
relocations required and LTO can do a better job. They also run faster as
same-library function calls do not need to be made through the PLT. There are no
good reasons to not use a version script for your NDK code. See the NDK
documentation on [controlling symbol visibility] for more information.

You can find these in each sample as the `lib<name>.map.txt` file (where
`<name>` is the name of the library passed to `add_app_library()` in the
`CMakeLists.txt` file). The build plumbing that uses the version scripts is in
the definition of `add_app_library()` in `cmake/AppLibrary.cmake`.

[controlling symbol visibility]: https://developer.android.com/ndk/guides/symbol-visibility

## Additional documentation

- [Add Native Code to Your Project](https://developer.android.com/studio/projects/add-native-code.html)
- [Configure NDK for Android Studio/Gradle Plugin](https://developer.android.com/studio/projects/configure-agp-ndk)
- [CMake for NDK](https://developer.android.com/ndk/guides/cmake.html)

## Support

If you've found an issue with a sample and you know how to fix it, please
[send us a PR!](CONTRIBUTING.md).

If you need to report a bug, where it needs to be filed depends on the type of
issue:

- Problems with the samples themselves:
  https://github.com/googlesamples/android-ndk/issues
- Problems with the OS APIs: http://b.android.com (usually the Framework
  component)
- Problems with NDK (that is, the compiler):
  https://github.com/android/ndk/issues

For questions about using the NDK or the platform APIs, you can ask on:

- [The NDK mailing list](https://groups.google.com/g/android-ndk) (best if
  you're not sure where else to ask)
- The [Discussions](https://github.com/android/ndk-samples/discussions) tab of
  this repo (best for questions about the samples themselves)
- The NDK's [Discussions](https://github.com/android/ndk/discussions) (best for
  questions about the NDK compilers and build systems)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/android)

## Additional NDK samples:

- [Google Play Game Samples with Android Studio](https://github.com/playgameservices/cpp-android-basic-samples)
- [Google Android Vulkan Tutorials](https://github.com/googlesamples/android-vulkan-tutorials)
- [Android Vulkan API Basic Samples](https://github.com/googlesamples/vulkan-basic-samples)
- [Android High Performance Audio](https://github.com/googlesamples/android-audio-high-performance)

## License

Copyright 2015 The Android Open Source Project, Inc.

Licensed to the Apache Software Foundation (ASF) under one or more contributor
license agreements. See the NOTICE file distributed with this work for
additional information regarding copyright ownership. The ASF licenses this file
to you 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

https://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.

[LICENSE](LICENSE)

[Android NDK]: https://developer.android.com/ndk


================================================
FILE: REFERENCE.md
================================================
Android Studio/Gradle DSL References

| Name           | Function            | Type | Options      | Default |
| -------------- | ------------------- | :--: | ------------ | ------- |
| debuggable     | Debugging Java code | bool | true / false |         |
| ndk.debuggable | Debugging JNI code  | bool | true / false |         |

Notation: dot(".") notation is same as closure ("{}") notation


================================================
FILE: audio-echo/README.md
================================================
# Sample removed

This sample has been removed because the API it demonstrated (OpenSLES) is
deprecated. New apps should instead use [Oboe], which has its own samples.

[Oboe]: https://github.com/google/oboe


================================================
FILE: base/.gitignore
================================================
/build

================================================
FILE: base/build.gradle.kts
================================================
plugins {
    id("ndksamples.android.library")
}

android {
    namespace = "com.android.ndk.samples.base"

    externalNativeBuild {
        cmake {
            path = file("src/main/cpp/CMakeLists.txt")
        }
    }

    buildFeatures {
        prefabPublishing = true
    }

    prefab {
        create("base") {
            headers = "src/main/cpp/include"
        }
    }
}

dependencies {

    implementation(libs.appcompat)
    implementation(libs.material)
    testImplementation(libs.junit)
    androidTestImplementation(libs.ext.junit)
    androidTestImplementation(libs.espresso.core)
}

================================================
FILE: base/src/main/cpp/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.22.1)
project(Base LANGUAGES CXX)

include(AppLibrary)

add_app_library(base
    STATIC
    logging.cpp
)

target_compile_features(base PRIVATE cxx_std_23)
target_compile_options(base PRIVATE -Wno-vla-cxx-extension)
target_include_directories(base PUBLIC include)
target_link_libraries(base PUBLIC log)


================================================
FILE: base/src/main/cpp/include/base/errno_restorer.h
================================================
/*
 * Copyright (C) 2020 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.
 */

#pragma once

#include <errno.h>

namespace ndksamples::base {

class ErrnoRestorer {
 public:
  ErrnoRestorer() : saved_errno_(errno) {}
  ErrnoRestorer(const ErrnoRestorer&) = delete;

  ~ErrnoRestorer() { errno = saved_errno_; }

  ErrnoRestorer& operator=(const ErrnoRestorer&) = delete;

  // Allow this object to be used as part of && operation.
  explicit operator bool() const { return true; }

 private:
  const int saved_errno_;
};

}  // namespace ndksamples::base


================================================
FILE: base/src/main/cpp/include/base/logging.h
================================================
/*
 * 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.
 */

#pragma once

/**
 * @file logging.h
 * @brief Logging and assertion utilities.
 *
 * This is a modified version of AOSP's android-base/logging.h:
 * https://cs.android.com/android/platform/superproject/main/+/main:system/libbase/include/android-base/logging.h
 *
 * The original file contained a lot of dependencies for things we don't need
 * (kernel logging, support for non-Android platforms, non-logd loggers, etc).
 * That's all been removed so we don't need to pull in those dependencies.
 *
 * If you copy from this sample, you may want to replace this with something
 * like absl, which provides a very similar (if not identical) interface for all
 * platforms. absl was not used here because we didn't need much, and it was
 * preferable to avoid an additional dependency.
 */

//
// Google-style C++ logging.
//

// This header provides a C++ stream interface to logging.
//
// To log:
//
//   LOG(INFO) << "Some text; " << some_value;
//
// Replace `INFO` with any severity from `enum LogSeverity`.
// Most devices filter out VERBOSE logs by default, run
// `adb shell setprop log.tag.<TAG> V` to see them in adb logcat.
//
// To log the result of a failed function and include the string
// representation of `errno` at the end:
//
//   PLOG(ERROR) << "Write failed";
//
// The output will be something like `Write failed: I/O error`.
// Remember this as 'P' as in perror(3).
//
// To output your own types, simply implement operator<< as normal.
//
// By default, output goes to logcat on Android and stderr on the host.
// A process can use `SetLogger` to decide where all logging goes.
// Implementations are provided for logcat, stderr, and dmesg.
//
// By default, the process' name is used as the log tag.
// Code can choose a specific log tag by defining LOG_TAG
// before including this header.

// This header also provides assertions:
//
//   CHECK(must_be_true);
//   CHECK_EQ(a, b) << z_is_interesting_too;

#include <base/errno_restorer.h>
#include <base/macros.h>

#include <functional>
#include <memory>
#include <optional>
#include <ostream>
#include <string_view>

// Note: DO NOT USE DIRECTLY. Use LOG_TAG instead.
#ifdef _LOG_TAG_INTERNAL
#error "_LOG_TAG_INTERNAL must not be defined"
#endif
#ifdef LOG_TAG
#define _LOG_TAG_INTERNAL LOG_TAG
#else
#define _LOG_TAG_INTERNAL nullptr
#endif

namespace ndksamples::base {

enum LogSeverity {
  VERBOSE,
  DEBUG,
  INFO,
  WARNING,
  ERROR,
  FATAL_WITHOUT_ABORT,  // For loggability tests, this is considered identical
                        // to FATAL.
  FATAL,
};

enum LogId {
  DEFAULT,
  MAIN,
  SYSTEM,
  RADIO,
  CRASH,
};

using LogFunction = std::function<void(
    LogId /*log_buffer_id*/, LogSeverity /*severity*/, const char* /*tag*/,
    const char* /*file*/, unsigned int /*line*/, const char* /*message*/)>;
using AbortFunction = std::function<void(const char* /*abort_message*/)>;

void DefaultAborter(const char* abort_message);

void SetDefaultTag(const std::string& tag);

// The LogdLogger sends chunks of up to ~4000 bytes at a time to logd.  It does
// not prevent other threads from writing to logd between sending each chunk, so
// other threads may interleave their messages.  If preventing interleaving is
// required, then a custom logger that takes a lock before calling this logger
// should be provided.
class LogdLogger {
 public:
  explicit LogdLogger(LogId default_log_id = ndksamples::base::MAIN);

  void operator()(LogId, LogSeverity, const char* tag, const char* file,
                  unsigned int line, const char* message);

 private:
  LogId default_log_id_;
};

// Configure logging based on ANDROID_LOG_TAGS environment variable.
// We need to parse a string that looks like
//
//      *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
//
// The tag (or '*' for the global level) comes first, followed by a colon and a
// letter indicating the minimum priority level we're expected to log.  This can
// be used to reveal or conceal logs with specific tags.
#define INIT_LOGGING_DEFAULT_LOGGER LogdLogger()
void InitLogging(const std::optional<std::string_view> default_tag = {},
                 std::optional<LogSeverity> log_level = {},
                 LogFunction&& logger = INIT_LOGGING_DEFAULT_LOGGER,
                 AbortFunction&& aborter = DefaultAborter);
#undef INIT_LOGGING_DEFAULT_LOGGER

// Replace the current logger and return the old one.
LogFunction SetLogger(LogFunction&& logger);

// Replace the current aborter and return the old one.
AbortFunction SetAborter(AbortFunction&& aborter);

// A helper macro that produces an expression that accepts both a qualified name
// and an unqualified name for a LogSeverity, and returns a LogSeverity value.
// Note: DO NOT USE DIRECTLY. This is an implementation detail.
#define SEVERITY_LAMBDA(severity)                  \
  ([&]() {                                         \
    using ::ndksamples::base::VERBOSE;             \
    using ::ndksamples::base::DEBUG;               \
    using ::ndksamples::base::INFO;                \
    using ::ndksamples::base::WARNING;             \
    using ::ndksamples::base::ERROR;               \
    using ::ndksamples::base::FATAL_WITHOUT_ABORT; \
    using ::ndksamples::base::FATAL;               \
    return (severity);                             \
  }())

#define ABORT_AFTER_LOG_FATAL
#define ABORT_AFTER_LOG_EXPR_IF(c, x) (x)
#define MUST_LOG_MESSAGE(severity) false
#define ABORT_AFTER_LOG_FATAL_EXPR(x) ABORT_AFTER_LOG_EXPR_IF(true, x)

// Defines whether the given severity will be logged or silently swallowed.
#define WOULD_LOG(severity)                                          \
  (UNLIKELY(::ndksamples::base::ShouldLog(SEVERITY_LAMBDA(severity), \
                                          _LOG_TAG_INTERNAL)) ||     \
   MUST_LOG_MESSAGE(severity))

// Get an ostream that can be used for logging at the given severity and to the
// default destination.
//
// Notes:
// 1) This will not check whether the severity is high enough. One should use
// WOULD_LOG to filter
//    usage manually.
// 2) This does not save and restore errno.
#define LOG_STREAM(severity)                                                \
  ::ndksamples::base::LogMessage(                                           \
      __FILE__, __LINE__, SEVERITY_LAMBDA(severity), _LOG_TAG_INTERNAL, -1) \
      .stream()

// Logs a message to logcat on Android otherwise to stderr. If the severity is
// FATAL it also causes an abort. For example:
//
//     LOG(FATAL) << "We didn't expect to reach here";
#define LOG(severity) LOGGING_PREAMBLE(severity) && LOG_STREAM(severity)

// Checks if we want to log something, and sets up appropriate RAII objects if
// so.
// Note: DO NOT USE DIRECTLY. This is an implementation detail.
#define LOGGING_PREAMBLE(severity)                                        \
  (WOULD_LOG(severity) &&                                                 \
   ABORT_AFTER_LOG_EXPR_IF(                                               \
       (SEVERITY_LAMBDA(severity)) == ::ndksamples::base::FATAL, true) && \
   ::ndksamples::base::ErrnoRestorer())

// A variant of LOG that also logs the current errno value. To be used when
// library calls fail.
#define PLOG(severity)                                          \
  LOGGING_PREAMBLE(severity) &&                                 \
      ::ndksamples::base::LogMessage(__FILE__, __LINE__,        \
                                     SEVERITY_LAMBDA(severity), \
                                     _LOG_TAG_INTERNAL, errno)  \
          .stream()

// Marker that code is yet to be implemented.
#define UNIMPLEMENTED(level) \
  LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "

// Check whether condition x holds and LOG(FATAL) if not. The value of the
// expression x is only evaluated once. Extra logging can be appended using <<
// after. For example:
//
//     CHECK(false == true) results in a log message of
//       "Check failed: false == true".
#define CHECK(x)                                                \
  LIKELY((x)) || ABORT_AFTER_LOG_FATAL_EXPR(false) ||           \
      ::ndksamples::base::LogMessage(__FILE__, __LINE__,        \
                                     ::ndksamples::base::FATAL, \
                                     _LOG_TAG_INTERNAL, -1)     \
              .stream()                                         \
          << "Check failed: " #x << " "

// clang-format off
// Helper for CHECK_xx(x,y) macros.
#define CHECK_OP(LHS, RHS, OP)                                                                   \
  for (auto _values = ::ndksamples::base::MakeEagerEvaluator(LHS, RHS);                             \
       UNLIKELY(!(_values.lhs.v OP _values.rhs.v));                                              \
       /* empty */)                                                                              \
  ABORT_AFTER_LOG_FATAL                                                                          \
  ::ndksamples::base::LogMessage(__FILE__, __LINE__, ::ndksamples::base::FATAL, _LOG_TAG_INTERNAL, -1) \
          .stream()                                                                              \
      << "Check failed: " << #LHS << " " << #OP << " " << #RHS << " (" #LHS "="                  \
      << ::ndksamples::base::LogNullGuard<decltype(_values.lhs.v)>::Guard(_values.lhs.v)            \
      << ", " #RHS "="                                                                           \
      << ::ndksamples::base::LogNullGuard<decltype(_values.rhs.v)>::Guard(_values.rhs.v)            \
      << ") "
// clang-format on

// Check whether a condition holds between x and y, LOG(FATAL) if not. The value
// of the expressions x and y is evaluated once. Extra logging can be appended
// using << after. For example:
//
//     CHECK_NE(0 == 1, false) results in
//       "Check failed: false != false (0==1=false, false=false) ".
#define CHECK_EQ(x, y) CHECK_OP(x, y, ==)
#define CHECK_NE(x, y) CHECK_OP(x, y, !=)
#define CHECK_LE(x, y) CHECK_OP(x, y, <=)
#define CHECK_LT(x, y) CHECK_OP(x, y, <)
#define CHECK_GE(x, y) CHECK_OP(x, y, >=)
#define CHECK_GT(x, y) CHECK_OP(x, y, >)

// clang-format off
// Helper for CHECK_STRxx(s1,s2) macros.
#define CHECK_STROP(s1, s2, sense)                                             \
  while (UNLIKELY((strcmp(s1, s2) == 0) != (sense)))                           \
    ABORT_AFTER_LOG_FATAL                                                      \
    ::ndksamples::base::LogMessage(__FILE__, __LINE__,  ::ndksamples::base::FATAL,   \
                                 _LOG_TAG_INTERNAL, -1)                        \
        .stream()                                                              \
        << "Check failed: " << "\"" << (s1) << "\""                            \
        << ((sense) ? " == " : " != ") << "\"" << (s2) << "\""
// clang-format on

// Check for string (const char*) equality between s1 and s2, LOG(FATAL) if not.
#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)

// Perform the pthread function call(args), LOG(FATAL) on error.
#define CHECK_PTHREAD_CALL(call, args, what)            \
  do {                                                  \
    int rc = call args;                                 \
    if (rc != 0) {                                      \
      errno = rc;                                       \
      ABORT_AFTER_LOG_FATAL                             \
      PLOG(FATAL) << #call << " failed for " << (what); \
    }                                                   \
  } while (false)

// DCHECKs are debug variants of CHECKs only enabled in debug builds. Generally
// CHECK should be used unless profiling identifies a CHECK as being in
// performance critical code.
#if defined(NDEBUG) && !defined(__clang_analyzer__)
static constexpr bool kEnableDChecks = false;
#else
static constexpr bool kEnableDChecks = true;
#endif

#define DCHECK(x) \
  if (::ndksamples::base::kEnableDChecks) CHECK(x)
#define DCHECK_EQ(x, y) \
  if (::ndksamples::base::kEnableDChecks) CHECK_EQ(x, y)
#define DCHECK_NE(x, y) \
  if (::ndksamples::base::kEnableDChecks) CHECK_NE(x, y)
#define DCHECK_LE(x, y) \
  if (::ndksamples::base::kEnableDChecks) CHECK_LE(x, y)
#define DCHECK_LT(x, y) \
  if (::ndksamples::base::kEnableDChecks) CHECK_LT(x, y)
#define DCHECK_GE(x, y) \
  if (::ndksamples::base::kEnableDChecks) CHECK_GE(x, y)
#define DCHECK_GT(x, y) \
  if (::ndksamples::base::kEnableDChecks) CHECK_GT(x, y)
#define DCHECK_STREQ(s1, s2) \
  if (::ndksamples::base::kEnableDChecks) CHECK_STREQ(s1, s2)
#define DCHECK_STRNE(s1, s2) \
  if (::ndksamples::base::kEnableDChecks) CHECK_STRNE(s1, s2)

namespace log_detail {

// Temporary storage for a single eagerly evaluated check expression operand.
template <typename T>
struct Storage {
  template <typename U>
  explicit constexpr Storage(U&& u) : v(std::forward<U>(u)) {}
  explicit Storage(const Storage& t) = delete;
  explicit Storage(Storage&& t) = delete;
  T v;
};

// Partial specialization for smart pointers to avoid copying.
template <typename T>
struct Storage<std::unique_ptr<T>> {
  explicit constexpr Storage(const std::unique_ptr<T>& ptr) : v(ptr.get()) {}
  const T* v;
};
template <typename T>
struct Storage<std::shared_ptr<T>> {
  explicit constexpr Storage(const std::shared_ptr<T>& ptr) : v(ptr.get()) {}
  const T* v;
};

// Type trait that checks if a type is a (potentially const) char pointer.
template <typename T>
struct IsCharPointer {
  using Pointee = std::remove_cv_t<std::remove_pointer_t<T>>;
  static constexpr bool value =
      std::is_pointer_v<T> &&
      (std::is_same_v<Pointee, char> || std::is_same_v<Pointee, signed char> ||
       std::is_same_v<Pointee, unsigned char>);
};

// Counterpart to Storage that depends on both operands. This is used to prevent
// char pointers being treated as strings in the log output - they might point
// to buffers of unprintable binary data.
template <typename LHS, typename RHS>
struct StorageTypes {
  static constexpr bool voidptr =
      IsCharPointer<LHS>::value && IsCharPointer<RHS>::value;
  using LHSType = std::conditional_t<voidptr, const void*, LHS>;
  using RHSType = std::conditional_t<voidptr, const void*, RHS>;
};

// Temporary class created to evaluate the LHS and RHS, used with
// MakeEagerEvaluator to infer the types of LHS and RHS.
template <typename LHS, typename RHS>
struct EagerEvaluator {
  template <typename A, typename B>
  constexpr EagerEvaluator(A&& l, B&& r)
      : lhs(std::forward<A>(l)), rhs(std::forward<B>(r)) {}
  const Storage<typename StorageTypes<LHS, RHS>::LHSType> lhs;
  const Storage<typename StorageTypes<LHS, RHS>::RHSType> rhs;
};

}  // namespace log_detail

// Converts std::nullptr_t and null char pointers to the string "null"
// when writing the failure message.
template <typename T>
struct LogNullGuard {
  static const T& Guard(const T& v) { return v; }
};
template <>
struct LogNullGuard<std::nullptr_t> {
  static const char* Guard(const std::nullptr_t&) { return "(null)"; }
};
template <>
struct LogNullGuard<char*> {
  static const char* Guard(const char* v) { return v ? v : "(null)"; }
};
template <>
struct LogNullGuard<const char*> {
  static const char* Guard(const char* v) { return v ? v : "(null)"; }
};

// Helper function for CHECK_xx.
template <typename LHS, typename RHS>
constexpr auto MakeEagerEvaluator(LHS&& lhs, RHS&& rhs) {
  return log_detail::EagerEvaluator<std::decay_t<LHS>, std::decay_t<RHS>>(
      std::forward<LHS>(lhs), std::forward<RHS>(rhs));
}

// Data for the log message, not stored in LogMessage to avoid increasing the
// stack size.
class LogMessageData;

// A LogMessage is a temporarily scoped object used by LOG and the unlikely part
// of a CHECK. The destructor will abort if the severity is FATAL.
class LogMessage {
 public:
  // LogId has been deprecated, but this constructor must exist for prebuilts.
  LogMessage(const char* file, unsigned int line, LogId, LogSeverity severity,
             const char* tag, int error);
  LogMessage(const char* file, unsigned int line, LogSeverity severity,
             const char* tag, int error);

  DISALLOW_COPY_AND_ASSIGN(LogMessage);

  ~LogMessage();

  // Returns the stream associated with the message, the LogMessage performs
  // output when it goes out of scope.
  std::ostream& stream();

  // The routine that performs the actual logging.
  static void LogLine(const char* file, unsigned int line, LogSeverity severity,
                      const char* tag, const char* msg);

 private:
  const std::unique_ptr<LogMessageData> data_;
};

// Get the minimum severity level for logging.
LogSeverity GetMinimumLogSeverity();

// Set the minimum severity level for logging, returning the old severity.
LogSeverity SetMinimumLogSeverity(LogSeverity new_severity);

// Return whether or not a log message with the associated tag should be logged.
bool ShouldLog(LogSeverity severity, const char* tag);

// Allows to temporarily change the minimum severity level for logging.
class ScopedLogSeverity {
 public:
  explicit ScopedLogSeverity(LogSeverity level);
  ~ScopedLogSeverity();

 private:
  LogSeverity old_;
};

}  // namespace ndksamples::base

namespace std {  // NOLINT(cert-dcl58-cpp)

// Emit a warning of ostream<< with std::string*. The intention was most likely
// to print *string.
//
// Note: for this to work, we need to have this in a namespace.
// Note: using a pragma because "-Wgcc-compat" (included in "-Weverything")
// complains about
//       diagnose_if.
// Note: to print the pointer, use "<< static_cast<const void*>(string_pointer)"
// instead. Note: a not-recommended alternative is to let Clang ignore the
// warning by adding
//       -Wno-user-defined-warnings to CPPFLAGS.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"
#define OSTREAM_STRING_POINTER_USAGE_WARNING \
  __attribute__((                            \
      diagnose_if(true, "Unexpected logging of string pointer", "warning")))
inline OSTREAM_STRING_POINTER_USAGE_WARNING std::ostream& operator<<(
    std::ostream& stream, const std::string* string_pointer) {
  return stream << static_cast<const void*>(string_pointer);
}
#pragma clang diagnostic pop

}  // namespace std


================================================
FILE: base/src/main/cpp/include/base/macros.h
================================================
/*
 * 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.
 */

#pragma once

#include <stddef.h>  // for size_t

#include <utility>

// A macro to disallow the copy constructor and operator= functions
// This must be placed in the private: declarations for a class.
//
// For disallowing only assign or copy, delete the relevant operator or
// constructor, for example:
// void operator=(const TypeName&) = delete;
// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
// semantically, one should either use disallow both or neither. Try to
// avoid these in new code.
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&) = delete;      \
  void operator=(const TypeName&) = delete

// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
  TypeName() = delete;                           \
  DISALLOW_COPY_AND_ASSIGN(TypeName)

// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example.  If you use arraysize on
// a pointer by mistake, you will get a compile-time error.
//
// One caveat is that arraysize() doesn't accept any array of an
// anonymous type or a type defined inside a function.  In these rare
// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below.  This is
// due to a limitation in C++'s template system.  The limitation might
// eventually be removed, but it hasn't happened yet.

// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];  // NOLINT(readability/casting)

#define arraysize(array) (sizeof(ArraySizeHelper(array)))

#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)

// Changing this definition will cause you a lot of pain.  A majority of
// vendor code defines LIKELY and UNLIKELY this way, and includes
// this header through an indirect path.
#define LIKELY(exp) (__builtin_expect((exp) != 0, true))
#define UNLIKELY(exp) (__builtin_expect((exp) != 0, false))

/// True if the (runtime) version of the OS is at least x.
///
/// Clang is very particular about how __builtin_available is used. Logical
/// operations (including negation) may not be combined with
/// __builtin_available, so to negate this check you must do:
///
///     if (API_AT_LEAST(x)) {
///     } else {
///       // do negated stuff
///     }
#define API_AT_LEAST(x) __builtin_available(android x, *)

/// Marks a function as not callable on OS versions older than x.
///
/// This is a minor abuse of Clang's __attribute__((availability)), so the
/// diagnostic for this will be a little odd, but it allows us to extract
/// functions from code that already has an API_AT_LEAST guard without rewriting
/// the guard in every called function.
#define REQUIRES_API(x) __INTRODUCED_IN(x)


================================================
FILE: base/src/main/cpp/logging.cpp
================================================
/*
 * 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.
 */

#include "base/logging.h"

#include <android/log.h>
#include <android/set_abort_message.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <stdlib.h>
#include <time.h>

#include <atomic>
#include <iostream>
#include <limits>
#include <mutex>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/macros.h"
#include "logging_splitters.h"

namespace ndksamples::base {

static const char* GetFileBasename(const char* file) {
  // We can't use basename(3) even on Unix because the Mac doesn't
  // have a non-modifying basename.
  const char* last_slash = strrchr(file, '/');
  if (last_slash != nullptr) {
    return last_slash + 1;
  }
  return file;
}

static int32_t LogIdTolog_id_t(LogId log_id) {
  switch (log_id) {
    case MAIN:
      return LOG_ID_MAIN;
    case SYSTEM:
      return LOG_ID_SYSTEM;
    case RADIO:
      return LOG_ID_RADIO;
    case CRASH:
      return LOG_ID_CRASH;
    case DEFAULT:
    default:
      return LOG_ID_DEFAULT;
  }
}

static int32_t LogSeverityToPriority(LogSeverity severity) {
  switch (severity) {
    case VERBOSE:
      return ANDROID_LOG_VERBOSE;
    case DEBUG:
      return ANDROID_LOG_DEBUG;
    case INFO:
      return ANDROID_LOG_INFO;
    case WARNING:
      return ANDROID_LOG_WARN;
    case ERROR:
      return ANDROID_LOG_ERROR;
    case FATAL_WITHOUT_ABORT:
    case FATAL:
    default:
      return ANDROID_LOG_FATAL;
  }
}

static LogFunction& Logger() {
  static auto& logger = *new LogFunction(LogdLogger());
  return logger;
}

static AbortFunction& Aborter() {
  static auto& aborter = *new AbortFunction(DefaultAborter);
  return aborter;
}

// Only used for Q fallback.
static std::recursive_mutex& TagLock() {
  static auto& tag_lock = *new std::recursive_mutex();
  return tag_lock;
}

static std::string* gDefaultTag;

void SetDefaultTag(const std::string_view tag) {
  std::lock_guard<std::recursive_mutex> lock(TagLock());
  if (gDefaultTag != nullptr) {
    delete gDefaultTag;
    gDefaultTag = nullptr;
  }
  if (!tag.empty()) {
    gDefaultTag = new std::string(tag);
  }
}

static bool gInitialized = false;

// Only used for Q fallback.
static LogSeverity gMinimumLogSeverity = INFO;

void DefaultAborter(const char* abort_message) {
  android_set_abort_message(abort_message);
  abort();
}

static void LogdLogChunk(LogId id, LogSeverity severity, const char* tag,
                         const char* message) {
  int32_t lg_id = LogIdTolog_id_t(id);
  int32_t priority = LogSeverityToPriority(severity);

  __android_log_buf_print(lg_id, priority, tag, "%s", message);
}

LogdLogger::LogdLogger(LogId default_log_id)
    : default_log_id_(default_log_id) {}

void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
                            const char* file, unsigned int line,
                            const char* message) {
  if (id == DEFAULT) {
    id = default_log_id_;
  }

  SplitByLogdChunks(id, severity, tag, file, line, message, LogdLogChunk);
}

void InitLogging(const std::optional<std::string_view> default_tag,
                 std::optional<LogSeverity> log_level, LogFunction&& logger,
                 AbortFunction&& aborter) {
  SetLogger(std::forward<LogFunction>(logger));
  SetAborter(std::forward<AbortFunction>(aborter));

  if (gInitialized) {
    return;
  }

  gInitialized = true;

  if (default_tag.has_value()) {
    SetDefaultTag(default_tag.value());
  }

  const char* tags = getenv("ANDROID_LOG_TAGS");
  if (tags == nullptr) {
    return;
  }

  if (log_level.has_value()) {
    SetMinimumLogSeverity(log_level.value());
  }
}

LogFunction SetLogger(LogFunction&& logger) {
  LogFunction old_logger = std::move(Logger());
  Logger() = std::move(logger);
  return old_logger;
}

AbortFunction SetAborter(AbortFunction&& aborter) {
  AbortFunction old_aborter = std::move(Aborter());
  Aborter() = std::move(aborter);
  return old_aborter;
}

// This indirection greatly reduces the stack impact of having lots of
// checks/logging in a function.
class LogMessageData {
 public:
  LogMessageData(const char* file, unsigned int line, LogSeverity severity,
                 const char* tag, int error)
      : file_(GetFileBasename(file)),
        line_number_(line),
        severity_(severity),
        tag_(tag),
        error_(error) {}

  DISALLOW_COPY_AND_ASSIGN(LogMessageData);

  const char* GetFile() const { return file_; }

  unsigned int GetLineNumber() const { return line_number_; }

  LogSeverity GetSeverity() const { return severity_; }

  const char* GetTag() const { return tag_; }

  int GetError() const { return error_; }

  std::ostream& GetBuffer() { return buffer_; }

  std::string ToString() const { return buffer_.str(); }

 private:
  std::ostringstream buffer_;
  const char* const file_;
  const unsigned int line_number_;
  const LogSeverity severity_;
  const char* const tag_;
  const int error_;
};

LogMessage::LogMessage(const char* file, unsigned int line, LogId,
                       LogSeverity severity, const char* tag, int error)
    : LogMessage(file, line, severity, tag, error) {}

LogMessage::LogMessage(const char* file, unsigned int line,
                       LogSeverity severity, const char* tag, int error)
    : data_(new LogMessageData(file, line, severity, tag, error)) {}

LogMessage::~LogMessage() {
  // Check severity again. This is duplicate work wrt/ LOG macros, but not
  // LOG_STREAM.
  if (!WOULD_LOG(data_->GetSeverity())) {
    return;
  }

  // Finish constructing the message.
  if (data_->GetError() != -1) {
    data_->GetBuffer() << ": " << strerror(data_->GetError());
  }
  std::string msg(data_->ToString());

  if (data_->GetSeverity() == FATAL) {
    // Set the bionic abort message early to avoid liblog doing it
    // with the individual lines, so that we get the whole message.
    android_set_abort_message(msg.c_str());
  }

  LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(),
          data_->GetTag(), msg.c_str());

  // Abort if necessary.
  if (data_->GetSeverity() == FATAL) {
    Aborter()(msg.c_str());
  }
}

std::ostream& LogMessage::stream() { return data_->GetBuffer(); }

void LogMessage::LogLine(const char* file, unsigned int line,
                         LogSeverity severity, const char* tag,
                         const char* message) {
  if (tag == nullptr) {
    std::lock_guard<std::recursive_mutex> lock(TagLock());
    if (gDefaultTag == nullptr) {
      gDefaultTag = new std::string(getprogname());
    }

    Logger()(DEFAULT, severity, gDefaultTag->c_str(), file, line, message);
  } else {
    Logger()(DEFAULT, severity, tag, file, line, message);
  }
}

LogSeverity GetMinimumLogSeverity() { return gMinimumLogSeverity; }

bool ShouldLog(LogSeverity severity, const char*) {
  return severity >= gMinimumLogSeverity;
}

LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
  LogSeverity old_severity = gMinimumLogSeverity;
  gMinimumLogSeverity = new_severity;
  return old_severity;
}

ScopedLogSeverity::ScopedLogSeverity(LogSeverity new_severity) {
  old_ = SetMinimumLogSeverity(new_severity);
}

ScopedLogSeverity::~ScopedLogSeverity() { SetMinimumLogSeverity(old_); }

}  // namespace ndksamples::base


================================================
FILE: base/src/main/cpp/logging_splitters.h
================================================
/*
 * Copyright (C) 2020 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.
 */

#pragma once

#include <inttypes.h>
#include <time.h>

#include <format>

#include "base/logging.h"

#define LOGGER_ENTRY_MAX_PAYLOAD 4068  // This constant is not in the NDK.

namespace ndksamples::base {

// This splits the message up line by line, by calling log_function with a
// pointer to the start of each line and the size up to the newline character.
// It sends size = -1 for the final line.
template <typename F, typename... Args>
static void SplitByLines(const char* msg, const F& log_function,
                         Args&&... args) {
  const char* newline = strchr(msg, '\n');
  while (newline != nullptr) {
    log_function(msg, newline - msg, args...);
    msg = newline + 1;
    newline = strchr(msg, '\n');
  }

  log_function(msg, -1, args...);
}

// This splits the message up into chunks that logs can process delimited by new
// lines.  It calls log_function with the exact null terminated message that
// should be sent to logd. Note, despite the loops and snprintf's, if severity
// is not fatal and there are no new lines, this function simply calls
// log_function with msg without any extra overhead.
template <typename F>
static void SplitByLogdChunks(LogId log_id, LogSeverity severity,
                              const char* tag, const char* file,
                              unsigned int line, const char* msg,
                              const F& log_function) {
  // The maximum size of a payload, after the log header that logd will accept
  // is LOGGER_ENTRY_MAX_PAYLOAD, so subtract the other elements in the payload
  // to find the size of the string that we can log in each pass. The protocol
  // is documented in liblog/README.protocol.md. Specifically we subtract a byte
  // for the priority, the length of the tag + its null terminator, and an
  // additional byte for the null terminator on the payload.  We subtract an
  // additional 32 bytes for slack, similar to java/android/util/Log.java.
  ptrdiff_t max_size = LOGGER_ENTRY_MAX_PAYLOAD - strlen(tag) - 35;
  if (max_size <= 0) {
    abort();
  }
  // If we're logging a fatal message, we'll append the file and line numbers.
  bool add_file =
      file != nullptr && (severity == FATAL || severity == FATAL_WITHOUT_ABORT);

  std::string file_header;
  if (add_file) {
    file_header = std::format("{}:{}]", file, line);
  }
  int file_header_size = file_header.size();

  __attribute__((uninitialized)) char logd_chunk[max_size + 1];
  ptrdiff_t chunk_position = 0;

  auto call_log_function = [&]() {
    log_function(log_id, severity, tag, logd_chunk);
    chunk_position = 0;
  };

  auto write_to_logd_chunk = [&](const char* message, int length) {
    int size_written = 0;
    const char* new_line = chunk_position > 0 ? "\n" : "";
    if (add_file) {
      size_written = snprintf(logd_chunk + chunk_position,
                              sizeof(logd_chunk) - chunk_position, "%s%s%.*s",
                              new_line, file_header.c_str(), length, message);
    } else {
      size_written = snprintf(logd_chunk + chunk_position,
                              sizeof(logd_chunk) - chunk_position, "%s%.*s",
                              new_line, length, message);
    }

    // This should never fail, if it does and we set size_written to 0, which
    // will skip this line and move to the next one.
    if (size_written < 0) {
      size_written = 0;
    }
    chunk_position += size_written;
  };

  const char* newline = strchr(msg, '\n');
  while (newline != nullptr) {
    // If we have data in the buffer and this next line doesn't fit, write the
    // buffer.
    if (chunk_position != 0 &&
        chunk_position + (newline - msg) + 1 + file_header_size > max_size) {
      call_log_function();
    }

    // Otherwise, either the next line fits or we have any empty buffer and too
    // large of a line to ever fit, in both cases, we add it to the buffer and
    // continue.
    write_to_logd_chunk(msg, newline - msg);

    msg = newline + 1;
    newline = strchr(msg, '\n');
  }

  // If we have left over data in the buffer and we can fit the rest of msg, add
  // it to the buffer then write the buffer.
  if (chunk_position != 0 &&
      chunk_position + static_cast<int>(strlen(msg)) + 1 + file_header_size <=
          max_size) {
    write_to_logd_chunk(msg, -1);
    call_log_function();
  } else {
    // If the buffer is not empty and we can't fit the rest of msg into it,
    // write its contents.
    if (chunk_position != 0) {
      call_log_function();
    }
    // Then write the rest of the msg.
    if (add_file) {
      snprintf(logd_chunk, sizeof(logd_chunk), "%s%s", file_header.c_str(),
               msg);
      log_function(log_id, severity, tag, logd_chunk);
    } else {
      log_function(log_id, severity, tag, msg);
    }
  }
}

}  // namespace ndksamples::base


================================================
FILE: bitmap-plasma/README.md
================================================
# Bitmap Plasma

Bitmap Plasma is an Android sample that uses JNI to render a plasma effect in an
Android
[Bitmap](http://developer.android.com/reference/android/graphics/Bitmap.html)
from C code.

## Screenshots

![screenshot](screenshot.png)


================================================
FILE: bitmap-plasma/app/build.gradle
================================================
plugins {
    id "ndksamples.android.application"
}

android {
    namespace 'com.example.plasma'
    defaultConfig {
        applicationId 'com.example.plasma'
    }
    externalNativeBuild {
        cmake {
            path 'src/main/cpp/CMakeLists.txt'
        }
    }

    buildFeatures {
        prefab true
    }
}

dependencies {
    implementation project(":base")
}


================================================
FILE: bitmap-plasma/app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1"
          android:versionName="1.0">
  <application
      android:allowBackup="false"
      android:fullBackupContent="false"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name">
    <activity android:name=".Plasma"
              android:label="@string/app_name"
        android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>
</manifest>


================================================
FILE: bitmap-plasma/app/src/main/cpp/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.22.1)
project(BitmapPlasma LANGUAGES CXX)

include(AppLibrary)
find_package(base CONFIG REQUIRED)

add_app_library(plasma SHARED jni.cpp plasma.cpp)

target_link_libraries(plasma
    base::base
    android
    jnigraphics
    log
    m
)


================================================
FILE: bitmap-plasma/app/src/main/cpp/jni.cpp
================================================
// Copyright (C) 2025 The Android Open Source Project
// SPDX-License-Identifier: Apache-2.0

#include <base/macros.h>
#include <jni.h>

#include "plasma.h"

extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {
  JNIEnv* env;
  if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
    return JNI_ERR;
  }

  jclass c = env->FindClass("com/example/plasma/PlasmaView");
  if (c == nullptr) return JNI_ERR;

  static const JNINativeMethod methods[] = {
      {"renderPlasma", "(Landroid/graphics/Bitmap;J)V",
       reinterpret_cast<void*>(RenderPlasma)},
  };
  int rc = env->RegisterNatives(c, methods, arraysize(methods));
  if (rc != JNI_OK) return rc;

  return JNI_VERSION_1_6;
}

================================================
FILE: bitmap-plasma/app/src/main/cpp/libplasma.map.txt
================================================
LIBPLASMA {
  global:
    JNI_OnLoad;
  local:
    *;
};


================================================
FILE: bitmap-plasma/app/src/main/cpp/plasma.cpp
================================================
/*
 * Copyright (C) 2010 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 <android/bitmap.h>
#include <android/log.h>
#include <jni.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define LOG_TAG "libplasma"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

/* Set to 1 to enable debug log traces. */
#define DEBUG 0

/* Set to 1 to optimize memory stores when generating plasma. */
#define OPTIMIZE_WRITES 1

/* Return current time in milliseconds */
static double now_ms(void) {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec * 1000. + tv.tv_usec / 1000.;
}

/* We're going to perform computations for every pixel of the target
 * bitmap. floating-point operations are very slow on ARMv5, and not
 * too bad on ARMv7 with the exception of trigonometric functions.
 *
 * For better performance on all platforms, we're going to use fixed-point
 * arithmetic and all kinds of tricks
 */

typedef int32_t Fixed;

#define FIXED_BITS 16
#define FIXED_ONE (1 << FIXED_BITS)
#define FIXED_AVERAGE(x, y) (((x) + (y)) >> 1)

#define FIXED_FROM_INT(x) ((x) << FIXED_BITS)
#define FIXED_TO_INT(x) ((x) >> FIXED_BITS)

#define FIXED_FROM_FLOAT(x) ((Fixed)((x) * FIXED_ONE))
#define FIXED_TO_FLOAT(x) ((x) / (1. * FIXED_ONE))

#define FIXED_MUL(x, y) (((int64_t)(x) * (y)) >> FIXED_BITS)
#define FIXED_DIV(x, y) (((int64_t)(x) * FIXED_ONE) / (y))

#define FIXED_DIV2(x) ((x) >> 1)
#define FIXED_AVERAGE(x, y) (((x) + (y)) >> 1)

#define FIXED_FRAC(x) ((x) & ((1 << FIXED_BITS) - 1))
#define FIXED_TRUNC(x) ((x) & ~((1 << FIXED_BITS) - 1))

#define FIXED_FROM_INT_FLOAT(x, f) (Fixed)((x) * (FIXED_ONE * (f)))

typedef int32_t Angle;

#define ANGLE_BITS 9

#if ANGLE_BITS < 8
#error ANGLE_BITS must be at least 8
#endif

#define ANGLE_2PI (1 << ANGLE_BITS)
#define ANGLE_PI (1 << (ANGLE_BITS - 1))
#define ANGLE_PI2 (1 << (ANGLE_BITS - 2))
#define ANGLE_PI4 (1 << (ANGLE_BITS - 3))

#define ANGLE_FROM_FLOAT(x) (Angle)((x) * ANGLE_PI / M_PI)
#define ANGLE_TO_FLOAT(x) ((x) * M_PI / ANGLE_PI)

#if ANGLE_BITS <= FIXED_BITS
#define ANGLE_FROM_FIXED(x) (Angle)((x) >> (FIXED_BITS - ANGLE_BITS))
#define ANGLE_TO_FIXED(x) (Fixed)((x) << (FIXED_BITS - ANGLE_BITS))
#else
#define ANGLE_FROM_FIXED(x) (Angle)((x) << (ANGLE_BITS - FIXED_BITS))
#define ANGLE_TO_FIXED(x) (Fixed)((x) >> (ANGLE_BITS - FIXED_BITS))
#endif

static Fixed angle_sin_tab[ANGLE_2PI + 1];

static void init_angles(void) {
  int nn;
  for (nn = 0; nn < ANGLE_2PI + 1; nn++) {
    double radians = nn * M_PI / ANGLE_PI;
    angle_sin_tab[nn] = FIXED_FROM_FLOAT(sin(radians));
  }
}

static __inline__ Fixed angle_sin(Angle a) {
  return angle_sin_tab[(uint32_t)a & (ANGLE_2PI - 1)];
}

static __inline__ Fixed fixed_sin(Fixed f) {
  return angle_sin(ANGLE_FROM_FIXED(f));
}

/* Color palette used for rendering the plasma */
#define PALETTE_BITS 8
#define PALETTE_SIZE (1 << PALETTE_BITS)

#if PALETTE_BITS > FIXED_BITS
#error PALETTE_BITS must be smaller than FIXED_BITS
#endif

static uint16_t palette[PALETTE_SIZE];

static uint16_t make565(int red, int green, int blue) {
  return (uint16_t)(((red << 8) & 0xf800) | ((green << 3) & 0x07e0) |
                    ((blue >> 3) & 0x001f));
}

static void init_palette(void) {
  int nn, mm = 0;
  /* fun with colors */
  for (nn = 0; nn < PALETTE_SIZE / 4; nn++) {
    int jj = (nn - mm) * 4 * 255 / PALETTE_SIZE;
    palette[nn] = make565(255, jj, 255 - jj);
  }

  for (mm = nn; nn < PALETTE_SIZE / 2; nn++) {
    int jj = (nn - mm) * 4 * 255 / PALETTE_SIZE;
    palette[nn] = make565(255 - jj, 255, jj);
  }

  for (mm = nn; nn < PALETTE_SIZE * 3 / 4; nn++) {
    int jj = (nn - mm) * 4 * 255 / PALETTE_SIZE;
    palette[nn] = make565(0, 255 - jj, 255);
  }

  for (mm = nn; nn < PALETTE_SIZE; nn++) {
    int jj = (nn - mm) * 4 * 255 / PALETTE_SIZE;
    palette[nn] = make565(jj, 0, 255);
  }
}

static __inline__ uint16_t palette_from_fixed(Fixed x) {
  if (x < 0) x = -x;
  if (x >= FIXED_ONE) x = FIXED_ONE - 1;
  int idx = FIXED_FRAC(x) >> (FIXED_BITS - PALETTE_BITS);
  return palette[idx & (PALETTE_SIZE - 1)];
}

/* Angles expressed as fixed point radians */

static void init_tables(void) {
  init_palette();
  init_angles();
}

static void fill_plasma(AndroidBitmapInfo* info, void* pixels, double t) {
  Fixed yt1 = FIXED_FROM_FLOAT(t / 1230.);
  Fixed yt2 = yt1;
  Fixed xt10 = FIXED_FROM_FLOAT(t / 3000.);
  Fixed xt20 = xt10;

#define YT1_INCR FIXED_FROM_FLOAT(1 / 100.)
#define YT2_INCR FIXED_FROM_FLOAT(1 / 163.)

  for (uint32_t yy = 0; yy < info->height; yy++) {
    uint16_t* line = (uint16_t*)pixels;
    Fixed base = fixed_sin(yt1) + fixed_sin(yt2);
    Fixed xt1 = xt10;
    Fixed xt2 = xt20;

    yt1 += YT1_INCR;
    yt2 += YT2_INCR;

#define XT1_INCR FIXED_FROM_FLOAT(1 / 173.)
#define XT2_INCR FIXED_FROM_FLOAT(1 / 242.)

#if OPTIMIZE_WRITES
    /* optimize memory writes by generating one aligned 32-bit store
     * for every pair of pixels.
     */
    uint16_t* line_end = line + info->width;

    if (line < line_end) {
      if (((uint32_t)(uintptr_t)line & 3) != 0) {
        Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2);

        xt1 += XT1_INCR;
        xt2 += XT2_INCR;

        line[0] = palette_from_fixed(ii >> 2);
        line++;
      }

      while (line + 2 <= line_end) {
        Fixed i1 = base + fixed_sin(xt1) + fixed_sin(xt2);
        xt1 += XT1_INCR;
        xt2 += XT2_INCR;

        Fixed i2 = base + fixed_sin(xt1) + fixed_sin(xt2);
        xt1 += XT1_INCR;
        xt2 += XT2_INCR;

        uint32_t pixel = ((uint32_t)palette_from_fixed(i1 >> 2) << 16) |
                         (uint32_t)palette_from_fixed(i2 >> 2);

        ((uint32_t*)line)[0] = pixel;
        line += 2;
      }

      if (line < line_end) {
        Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2);
        line[0] = palette_from_fixed(ii >> 2);
        line++;
      }
    }
#else  /* !OPTIMIZE_WRITES */
    int xx;
    for (xx = 0; xx < info->width; xx++) {
      Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2);

      xt1 += XT1_INCR;
      xt2 += XT2_INCR;

      line[xx] = palette_from_fixed(ii / 4);
    }
#endif /* !OPTIMIZE_WRITES */

    // go to next line
    pixels = (char*)pixels + info->stride;
  }
}

/* simple stats management */
typedef struct {
  double renderTime;
  double frameTime;
} FrameStats;

#define MAX_FRAME_STATS 200
#define MAX_PERIOD_MS 1500

typedef struct {
  double firstTime;
  double lastTime;
  double frameTime;

  int firstFrame;
  int numFrames;
  FrameStats frames[MAX_FRAME_STATS];
} Stats;

static void stats_init(Stats* s) {
  s->lastTime = now_ms();
  s->firstTime = 0.;
  s->firstFrame = 0;
  s->numFrames = 0;
}

static void stats_startFrame(Stats* s) { s->frameTime = now_ms(); }

static void stats_endFrame(Stats* s) {
  double now = now_ms();
  double renderTime = now - s->frameTime;
  double frameTime = now - s->lastTime;
  int nn;

  if (now - s->firstTime >= MAX_PERIOD_MS) {
    if (s->numFrames > 0) {
      double minRender, maxRender, avgRender;
      double minFrame, maxFrame, avgFrame;
      int count;

      nn = s->firstFrame;
      minRender = maxRender = avgRender = s->frames[nn].renderTime;
      minFrame = maxFrame = avgFrame = s->frames[nn].frameTime;
      for (count = s->numFrames; count > 0; count--) {
        nn += 1;
        if (nn >= MAX_FRAME_STATS) nn -= MAX_FRAME_STATS;
        double render = s->frames[nn].renderTime;
        if (render < minRender) minRender = render;
        if (render > maxRender) maxRender = render;
        double frame = s->frames[nn].frameTime;
        if (frame < minFrame) minFrame = frame;
        if (frame > maxFrame) maxFrame = frame;
        avgRender += render;
        avgFrame += frame;
      }
      avgRender /= s->numFrames;
      avgFrame /= s->numFrames;

      LOGI(
          "frame/s (avg,min,max) = (%.1f,%.1f,%.1f) "
          "render time ms (avg,min,max) = (%.1f,%.1f,%.1f)\n",
          1000. / avgFrame, 1000. / maxFrame, 1000. / minFrame, avgRender,
          minRender, maxRender);
    }
    s->numFrames = 0;
    s->firstFrame = 0;
    s->firstTime = now;
  }

  nn = s->firstFrame + s->numFrames;
  if (nn >= MAX_FRAME_STATS) nn -= MAX_FRAME_STATS;

  s->frames[nn].renderTime = renderTime;
  s->frames[nn].frameTime = frameTime;

  if (s->numFrames < MAX_FRAME_STATS) {
    s->numFrames += 1;
  } else {
    s->firstFrame += 1;
    if (s->firstFrame >= MAX_FRAME_STATS) s->firstFrame -= MAX_FRAME_STATS;
  }

  s->lastTime = now;
}

void RenderPlasma(JNIEnv* env, jclass, jobject bitmap, jlong time_ms) {
  AndroidBitmapInfo info;
  void* pixels;
  int ret;
  static Stats stats;
  static int init;

  if (!init) {
    init_tables();
    stats_init(&stats);
    init = 1;
  }

  if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
    LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
    return;
  }

  if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) {
    LOGE("Bitmap format is not RGB_565 !");
    return;
  }

  if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
  }

  stats_startFrame(&stats);

  /* Now fill the values with a nice little plasma */
  fill_plasma(&info, pixels, time_ms);

  AndroidBitmap_unlockPixels(env, bitmap);

  stats_endFrame(&stats);
}


================================================
FILE: bitmap-plasma/app/src/main/cpp/plasma.h
================================================
// Copyright (C) 2025 The Android Open Source Project
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <jni.h>

void RenderPlasma(JNIEnv* env, jclass, jobject bitmap, jlong time_ms);


================================================
FILE: bitmap-plasma/app/src/main/java/com/example/plasma/Plasma.java
================================================
/*
 * Copyright (C) 2010 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.
 */
package com.example.plasma;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Point;
import android.os.Bundle;
import android.content.Context;
import android.view.View;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.Display;
import android.view.WindowManager;

public class Plasma extends Activity
{
    // Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Display display = getWindowManager().getDefaultDisplay();
        Point displaySize = new Point();
        display.getSize(displaySize);
        setContentView(new PlasmaView(this, displaySize.x, displaySize.y));
    }

    // load our native library
    static {
        System.loadLibrary("plasma");
    }
}

// Custom view for rendering plasma.
//
// Note: suppressing lint wrarning for ViewConstructor since it is
//       manually set from the activity and not used in any layout.
@SuppressLint("ViewConstructor")
class PlasmaView extends View {
    private Bitmap mBitmap;
    private long mStartTime;

    // implementend by libplasma.so
    private static native void renderPlasma(Bitmap  bitmap, long time_ms);

    public PlasmaView(Context context, int width, int height) {
        super(context);
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        mStartTime = System.currentTimeMillis();
    }

    @Override protected void onDraw(Canvas canvas) {
        renderPlasma(mBitmap, System.currentTimeMillis() - mStartTime);
        canvas.drawBitmap(mBitmap, 0, 0, null);
        // force a redraw, with a different time-based pattern.
        invalidate();
    }

    @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
    }

}


================================================
FILE: bitmap-plasma/app/src/main/res/values/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Plasma</string>
</resources>


================================================
FILE: build-logic/.gitignore
================================================
/bin


================================================
FILE: build-logic/README.md
================================================
# Convention plugins

This directory contains [convention plugins] used by the NDK samples. These are
used to remove Gradle boiler plate from individual samples in favor of common
configuration here. Using convention plugins for single module projects is
overkill, but any non-trivial app will likely need their own eventually. See
[Now In Android's build-logic][nia-build-logic] for a more thorough example of
building convention plugins for Android projects.

[convention plugins]: https://docs.gradle.org/current/samples/sample_convention_plugins.html
[nia-build-logic]: https://github.com/android/nowinandroid/blob/main/build-logic/README.md


================================================
FILE: build-logic/build.gradle.kts
================================================
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("java-gradle-plugin")
    `kotlin-dsl`
    alias(libs.plugins.jetbrains.kotlin.jvm)
}

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

tasks.withType<KotlinCompile>().configureEach {
    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_17.toString()
    }
}

dependencies {
    compileOnly(libs.android.gradlePlugin)
    compileOnly(libs.kotlin.gradlePlugin)
}

gradlePlugin {
    plugins {
        register("androidApplication") {
            id = "ndksamples.android.application"
            implementationClass = "com.android.ndk.samples.buildlogic.AndroidApplicationConventionPlugin"
        }
        register("androidLibrary") {
            id = "ndksamples.android.library"
            implementationClass = "com.android.ndk.samples.buildlogic.AndroidLibraryConventionPlugin"
        }
        register("kotlinAndroid") {
            id = "ndksamples.android.kotlin"
            implementationClass = "com.android.ndk.samples.buildlogic.KotlinConventionPlugin"
        }
    }
}


================================================
FILE: build-logic/settings.gradle.kts
================================================
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

rootProject.name = "build-logic"


================================================
FILE: build-logic/src/main/java/com/android/ndk/samples/buildlogic/AndroidApplicationConventionPlugin.kt
================================================
package com.android.ndk.samples.buildlogic

import com.android.build.api.dsl.ApplicationExtension

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

class AndroidApplicationConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            with(pluginManager) {
                apply("com.android.application")
            }

            extensions.configure<ApplicationExtension> {
                compileSdk = Versions.COMPILE_SDK
                ndkVersion = Versions.NDK

                externalNativeBuild {
                    cmake {
                        version = Versions.CMAKE
                    }
                }

                defaultConfig {
                    minSdk = Versions.MIN_SDK
                    targetSdk = Versions.TARGET_SDK

                    externalNativeBuild {
                        cmake {
                            arguments.add("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
                            arguments.add("-DCMAKE_MODULE_PATH=${rootDir.resolve("cmake")}")
                        }
                    }

                    ndk {
                        // riscv64 isn't a supported Android ABI yet (August 2025), but we're
                        // enabling it here as part of that experiment. Until it's a supported ABI,
                        // don't include this in your app, as Play will block uploads of APKs which
                        // contain riscv64 libraries.
                        abiFilters.addAll(
                            listOf(
                                "arm64-v8a",
                                "armeabi-v7a",
                                "riscv64",
                                "x86",
                                "x86_64",
                            )
                        )
                    }
                }
                compileOptions {
                    sourceCompatibility = Versions.JAVA
                    targetCompatibility = Versions.JAVA
                }

                // Studio will not automatically pass logcat through ndk-stack, so we need to avoid
                // stripping debug binaries if we want the crash trace to be readable.
                buildTypes {
                    debug {
                        packaging {
                            jniLibs {
                                keepDebugSymbols += "**/*.so"
                            }
                        }
                    }
                }
            }
        }
    }
}


================================================
FILE: build-logic/src/main/java/com/android/ndk/samples/buildlogic/AndroidLibraryConventionPlugin.kt
================================================
package com.android.ndk.samples.buildlogic

import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

class AndroidLibraryConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            with(pluginManager) {
                apply("com.android.library")
            }

            extensions.configure<LibraryExtension> {
                compileSdk = Versions.COMPILE_SDK
                ndkVersion = Versions.NDK

                externalNativeBuild {
                    cmake {
                        version = Versions.CMAKE
                    }
                }

                defaultConfig {
                    minSdk = Versions.MIN_SDK
                    lint {
                        targetSdk = Versions.TARGET_SDK
                    }
                    testOptions {
                        targetSdk = Versions.TARGET_SDK
                    }
                    externalNativeBuild {
                        cmake {
                            arguments.add("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
                            arguments.add("-DCMAKE_MODULE_PATH=${rootDir.resolve("cmake")}")
                        }
                    }
                    ndk {
                        // riscv64 isn't a supported Android ABI yet (August 2025), but we're
                        // enabling it here as part of that experiment. Until it's a supported ABI,
                        // don't include this in your app, as Play will block uploads of APKs which
                        // contain riscv64 libraries.
                        abiFilters.addAll(
                            listOf(
                                "arm64-v8a",
                                "armeabi-v7a",
                                "riscv64",
                                "x86",
                                "x86_64",
                            )
                        )
                    }
                }
                compileOptions {
                    sourceCompatibility = Versions.JAVA
                    targetCompatibility = Versions.JAVA
                }

                // Studio will not automatically pass logcat through ndk-stack, so we need to avoid
                // stripping debug binaries if we want the crash trace to be readable.
                buildTypes {
                    debug {
                        packaging {
                            jniLibs {
                                keepDebugSymbols += "**/*.so"
                            }
                        }
                    }
                }
            }
        }
    }
}


================================================
FILE: build-logic/src/main/java/com/android/ndk/samples/buildlogic/KotlinConventionPlugin.kt
================================================
package com.android.ndk.samples.buildlogic

import com.android.build.api.dsl.ApplicationExtension

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

class KotlinConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            with(pluginManager) {
                apply("org.jetbrains.kotlin.android")
            }

            extensions.configure<ApplicationExtension> {
                tasks.withType<KotlinCompile>().configureEach {
                    kotlinOptions {
                        jvmTarget = Versions.JAVA.toString()
                    }
                }
            }
        }
    }
}


================================================
FILE: build-logic/src/main/java/com/android/ndk/samples/buildlogic/Versions.kt
================================================
package com.android.ndk.samples.buildlogic

import org.gradle.api.JavaVersion

object Versions {
    const val COMPILE_SDK = 35
    const val TARGET_SDK = 35
    const val MIN_SDK = 21
    const val NDK = "29.0.14206865" // r29
    const val CMAKE = "4.1.0"
    val JAVA = JavaVersion.VERSION_1_8
}


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
    alias(libs.plugins.jetbrainsKotlinAndroid) apply false
}


================================================
FILE: camera/README.md
================================================
# NdkCamera Sample

Two API samples:

- texture-view: Preview NDK camera image with
  [Android TextureView](https://developer.android.com/reference/android/view/TextureView.html)
- basic: A basic NdkCamera sample to preview camera images with AReadImage and
  take jpeg photos. Exposure and sensitivity are adjustable for preview, however
  capturing photos is in auto mode (it could be adjustable with similar method
  as used for preview).

## Other Resources

- Getting familiar with the 5 Camera2 objects
  ![Camera2 API Model](Camera2ProgrammingModel.png)

- [Camera2 blogs](https://medium.com/androiddevelopers/camera-enumeration-on-android-9a053b910cb5)

- [Camera2 Java documentation](https://developer.android.com/reference/android/hardware/camera2/package-summary)

## Screenshots

![screenshot](ndkCamera.png)


================================================
FILE: camera/basic/build.gradle
================================================
plugins {
    id "ndksamples.android.application"
}

android {
    namespace 'com.sample.camera.basic'
    defaultConfig {
        applicationId 'com.sample.camera.basic'
        minSdkVersion 24
        externalNativeBuild {
            cmake {
                arguments '-DANDROID_STL=c++_static'
            }
        }
    }
    externalNativeBuild {
        cmake {
            path 'src/main/cpp/CMakeLists.txt'
        }
    }

    buildFeatures {
        prefab true
    }
}

dependencies {
    implementation project(":base")
    implementation libs.appcompat
    implementation project(":camera:camera-utils")
}


================================================
FILE: camera/basic/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1"
          android:versionName="1.0">
  <uses-feature android:name="android.hardware.camera" />
  <uses-permission android:name="android.permission.CAMERA" />
  <application
      android:allowBackup="false"
      android:fullBackupContent="false"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:screenOrientation="sensorLandscape"
      android:configChanges="keyboardHidden|orientation|screenSize"
      android:hasCode="true">
    <activity android:name="com.sample.camera.basic.CameraActivity"
              android:label="@string/app_name"
        android:exported="true">
      <meta-data android:name="android.app.lib_name"
                 android:value="ndk_camera" />
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>
</manifest>


================================================
FILE: camera/basic/src/main/cpp/CMakeLists.txt
================================================
#
# Copyright (C)  2017 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.
#

cmake_minimum_required(VERSION 3.22.1)
project(CameraBasic LANGUAGES C CXX)

include(AppLibrary)
include(AndroidNdkModules)
find_package(base REQUIRED CONFIG)
find_package(camera-utils REQUIRED CONFIG)

android_ndk_import_module_native_app_glue()

add_app_library(ndk_camera SHARED
    ${CMAKE_CURRENT_SOURCE_DIR}/android_main.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/camera_engine.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/camera_manager.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/camera_listeners.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/image_reader.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/camera_ui.cpp
)

target_link_libraries(ndk_camera
    PRIVATE
    base::base
    camera-utils::camera-utils
    android
    log
    m
    $<LINK_LIBRARY:WHOLE_ARCHIVE,native_app_glue>
    camera2ndk
    mediandk
)


================================================
FILE: camera/basic/src/main/cpp/android_main.cpp
================================================
/*
 * Copyright (C) 2017 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 <ndksamples/camera/native_debug.h>

#include "camera_engine.h"

/*
 * SampleEngine global object
 */
static CameraEngine* pEngineObj = nullptr;
CameraEngine* GetAppEngine(void) {
  ASSERT(pEngineObj, "AppEngine has not initialized");
  return pEngineObj;
}

/**
 * Teamplate function for NativeActivity derived applications
 *   Create/Delete camera object with
 *   INIT_WINDOW/TERM_WINDOW command, ignoring other event.
 */
static void ProcessAndroidCmd(struct android_app* app, int32_t cmd) {
  CameraEngine* engine = reinterpret_cast<CameraEngine*>(app->userData);
  switch (cmd) {
    case APP_CMD_INIT_WINDOW:
      if (engine->AndroidApp()->window != NULL) {
        engine->SaveNativeWinRes(ANativeWindow_getWidth(app->window),
                                 ANativeWindow_getHeight(app->window),
                                 ANativeWindow_getFormat(app->window));
        engine->OnAppInitWindow();
      }
      break;
    case APP_CMD_TERM_WINDOW:
      engine->OnAppTermWindow();
      ANativeWindow_setBuffersGeometry(
          app->window, engine->GetSavedNativeWinWidth(),
          engine->GetSavedNativeWinHeight(), engine->GetSavedNativeWinFormat());
      break;
    case APP_CMD_CONFIG_CHANGED:
      engine->OnAppConfigChange();
      break;
    case APP_CMD_LOST_FOCUS:
      break;
  }
}

extern "C" void android_main(struct android_app* state) {
  CameraEngine engine(state);
  pEngineObj = &engine;

  state->userData = reinterpret_cast<void*>(&engine);
  state->onAppCmd = ProcessAndroidCmd;

  // loop waiting for stuff to do.
  while (!state->destroyRequested) {
    struct android_poll_source* source = nullptr;
    auto result = ALooper_pollOnce(0, NULL, nullptr, (void**)&source);
    ASSERT(result != ALOOPER_POLL_ERROR, "ALooper_pollOnce returned an error");
    if (source != NULL) {
      source->process(state, source);
    }
    pEngineObj->DrawFrame();
  }

  LOGI("CameraEngine thread destroy requested!");
  engine.DeleteCamera();
  pEngineObj = nullptr;
}

/**
 * Handle Android System APP_CMD_INIT_WINDOW message
 *   Request camera persmission from Java side
 *   Create camera object if camera has been granted
 */
void CameraEngine::OnAppInitWindow(void) {
  if (!cameraGranted_) {
    // Not permitted to use camera yet, ask(again) and defer other events
    RequestCameraPermission();
    return;
  }

  rotation_ = GetDisplayRotation();

  CreateCamera();
  ASSERT(camera_, "CameraCreation Failed");

  EnableUI();

  // NativeActivity end is ready to display, start pulling images
  cameraReady_ = true;
  camera_->StartPreview(true);
}

/**
 * Handle APP_CMD_TEMR_WINDOW
 */
void CameraEngine::OnAppTermWindow(void) {
  cameraReady_ = false;
  DeleteCamera();
}

/**
 * Handle APP_CMD_CONFIG_CHANGED
 */
void CameraEngine::OnAppConfigChange(void) {
  int newRotation = GetDisplayRotation();

  if (newRotation != rotation_) {
    OnAppTermWindow();

    rotation_ = newRotation;
    OnAppInitWindow();
  }
}

/**
 * Retrieve saved native window width.
 * @return width of native window
 */
int32_t CameraEngine::GetSavedNativeWinWidth(void) {
  return savedNativeWinRes_.width;
}

/**
 * Retrieve saved native window height.
 * @return height of native window
 */
int32_t CameraEngine::GetSavedNativeWinHeight(void) {
  return savedNativeWinRes_.height;
}

/**
 * Retrieve saved native window format
 * @return format of native window
 */
int32_t CameraEngine::GetSavedNativeWinFormat(void) {
  return savedNativeWinRes_.format;
}

/**
 * Save original NativeWindow Resolution
 * @param w width of native window in pixel
 * @param h height of native window in pixel
 * @param format
 */
void CameraEngine::SaveNativeWinRes(int32_t w, int32_t h, int32_t format) {
  savedNativeWinRes_.width = w;
  savedNativeWinRes_.height = h;
  savedNativeWinRes_.format = format;
}


================================================
FILE: camera/basic/src/main/cpp/camera_engine.cpp
================================================
/**
 * Copyright (C) 2017 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.
 */

/** Description
 *   Demonstrate NDK Camera interface added to android-24
 */

#include "camera_engine.h"

#include <ndksamples/camera/native_debug.h>

#include <cstdio>

/**
 * constructor and destructor for main application class
 * @param app native_app_glue environment
 * @return none
 */
CameraEngine::CameraEngine(android_app* app)
    : app_(app),
      cameraGranted_(false),
      rotation_(0),
      cameraReady_(false),
      camera_(nullptr),
      yuvReader_(nullptr),
      jpgReader_(nullptr) {
  memset(&savedNativeWinRes_, 0, sizeof(savedNativeWinRes_));
}

CameraEngine::~CameraEngine() {
  cameraReady_ = false;
  DeleteCamera();
}

struct android_app* CameraEngine::AndroidApp(void) const { return app_; }

/**
 * Create a camera object for onboard BACK_FACING camera
 */
void CameraEngine::CreateCamera(void) {
  // Camera needed to be requested at the run-time from Java SDK
  // if Not granted, do nothing.
  if (!cameraGranted_ || !app_->window) {
    LOGW("Camera Sample requires Full Camera access");
    return;
  }

  int32_t displayRotation = GetDisplayRotation();
  rotation_ = displayRotation;

  camera_ = new NDKCamera();
  ASSERT(camera_, "Failed to Create CameraObject");

  int32_t facing = 0, angle = 0, imageRotation = 0;
  if (camera_->GetSensorOrientation(&facing, &angle)) {
    if (facing == ACAMERA_LENS_FACING_FRONT) {
      imageRotation = (angle + rotation_) % 360;
      imageRotation = (360 - imageRotation) % 360;
    } else {
      imageRotation = (angle - rotation_ + 360) % 360;
    }
  }
  LOGI("Phone Rotation: %d, Present Rotation Angle: %d", rotation_,
       imageRotation);
  ImageFormat view{0, 0, 0}, capture{0, 0, 0};
  camera_->MatchCaptureSizeRequest(app_->window, &view, &capture);

  ASSERT(view.width && view.height, "Could not find supportable resolution");

  // Request the necessary nativeWindow to OS
  bool portraitNativeWindow =
      (savedNativeWinRes_.width < savedNativeWinRes_.height);
  ANativeWindow_setBuffersGeometry(
      app_->window, portraitNativeWindow ? view.height : view.width,
      portraitNativeWindow ? view.width : view.height, WINDOW_FORMAT_RGBA_8888);

  yuvReader_ = new ImageReader(&view, AIMAGE_FORMAT_YUV_420_888);
  yuvReader_->SetPresentRotation(imageRotation);
  jpgReader_ = new ImageReader(&capture, AIMAGE_FORMAT_JPEG);
  jpgReader_->SetPresentRotation(imageRotation);
  jpgReader_->RegisterCallback(this, [](void* ctx, const char* str) -> void {
    reinterpret_cast<CameraEngine*>(ctx)->OnPhotoTaken(str);
  });

  // now we could create session
  camera_->CreateSession(yuvReader_->GetNativeWindow(),
                         jpgReader_->GetNativeWindow(), imageRotation);
}

void CameraEngine::DeleteCamera(void) {
  cameraReady_ = false;
  if (camera_) {
    delete camera_;
    camera_ = nullptr;
  }
  if (yuvReader_) {
    delete yuvReader_;
    yuvReader_ = nullptr;
  }
  if (jpgReader_) {
    delete jpgReader_;
    jpgReader_ = nullptr;
  }
}

/**
 * Initiate a Camera Run-time usage request to Java side implementation
 *  [ The request result will be passed back in function
 *    notifyCameraPermission()]
 */
void CameraEngine::RequestCameraPermission() {
  if (!app_) return;

  JNIEnv* env;
  ANativeActivity* activity = app_->activity;
  activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6);

  activity->vm->AttachCurrentThread(&env, NULL);

  jobject activityObj = env->NewGlobalRef(activity->clazz);
  jclass clz = env->GetObjectClass(activityObj);
  env->CallVoidMethod(activityObj,
                      env->GetMethodID(clz, "RequestCamera", "()V"));
  env->DeleteGlobalRef(activityObj);

  activity->vm->DetachCurrentThread();
}
/**
 * Process to user's sensitivity and exposure value change
 * all values are represented in int64_t even exposure is just int32_t
 * @param code ACAMERA_SENSOR_EXPOSURE_TIME or ACAMERA_SENSOR_SENSITIVITY
 * @param val corresponding value from user
 */
void CameraEngine::OnCameraParameterChanged(int32_t code, int64_t val) {
  camera_->UpdateCameraRequestParameter(code, val);
}

/**
 * The main function rendering a frame. In our case, it is yuv to RGBA8888
 * converter
 */
void CameraEngine::DrawFrame(void) {
  if (!cameraReady_ || !yuvReader_) return;
  AImage* image = yuvReader_->GetNextImage();
  if (!image) {
    return;
  }

  ANativeWindow_acquire(app_->window);
  ANativeWindow_Buffer buf;
  if (ANativeWindow_lock(app_->window, &buf, nullptr) < 0) {
    yuvReader_->DeleteImage(image);
    return;
  }

  yuvReader_->DisplayImage(&buf, image);
  ANativeWindow_unlockAndPost(app_->window);
  ANativeWindow_release(app_->window);
}


================================================
FILE: camera/basic/src/main/cpp/camera_engine.h
================================================

/*
 * Copyright (C) 2017 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 __CAMERA_ENGINE_H__
#define __CAMERA_ENGINE_H__

#include <android/native_window.h>
#include <android_native_app_glue.h>

#include <functional>
#include <thread>

#include "camera_manager.h"

/**
 * basic CameraAppEngine
 */
class CameraEngine {
 public:
  explicit CameraEngine(android_app* app);
  ~CameraEngine();

  // Interfaces to android application framework
  struct android_app* AndroidApp(void) const;
  void OnAppInitWindow(void);
  void DrawFrame(void);
  void OnAppConfigChange(void);
  void OnAppTermWindow(void);

  // Native Window handlers
  int32_t GetSavedNativeWinWidth(void);
  int32_t GetSavedNativeWinHeight(void);
  int32_t GetSavedNativeWinFormat(void);
  void SaveNativeWinRes(int32_t w, int32_t h, int32_t format);

  // UI handlers
  void RequestCameraPermission();
  void OnCameraPermission(jboolean granted);
  void EnableUI(void);
  void OnTakePhoto(void);
  void OnCameraParameterChanged(int32_t code, int64_t val);

  // Manage NDKCamera Object
  void CreateCamera(void);
  void DeleteCamera(void);

 private:
  void OnPhotoTaken(const char* fileName);
  int GetDisplayRotation(void);

  struct android_app* app_;
  ImageFormat savedNativeWinRes_;
  bool cameraGranted_;
  int rotation_;
  volatile bool cameraReady_;
  NDKCamera* camera_;
  ImageReader* yuvReader_;
  ImageReader* jpgReader_;
};

/**
 * retrieve global singleton CameraEngine instance
 * @return the only instance of CameraEngine in the app
 */
CameraEngine* GetAppEngine(void);

#endif  // __CAMERA_ENGINE_H__


================================================
FILE: camera/basic/src/main/cpp/camera_listeners.cpp
================================================
/*
 * Copyright (C) 2017 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 <camera/NdkCameraManager.h>
#include <ndksamples/camera/camera_utils.h>
#include <ndksamples/camera/native_debug.h>

#include <cinttypes>
#include <queue>
#include <thread>
#include <utility>

#include "camera_manager.h"

/*
 * Camera Manager Listener object
 */
void OnCameraAvailable(void* ctx, const char* id) {
  reinterpret_cast<NDKCamera*>(ctx)->OnCameraStatusChanged(id, true);
}
void OnCameraUnavailable(void* ctx, const char* id) {
  reinterpret_cast<NDKCamera*>(ctx)->OnCameraStatusChanged(id, false);
}

/**
 * OnCameraStatusChanged()
 *  handles Callback from ACameraManager
 */
void NDKCamera::OnCameraStatusChanged(const char* id, bool available) {
  if (valid_) {
    cameras_[std::string(id)].available_ = available ? true : false;
  }
}

/**
 * Construct a camera manager listener on the fly and return to caller
 *
 * @return ACameraManager_AvailabilityCallback
 */
ACameraManager_AvailabilityCallbacks* NDKCamera::GetManagerListener() {
  static ACameraManager_AvailabilityCallbacks cameraMgrListener = {
      .context = this,
      .onCameraAvailable = ::OnCameraAvailable,
      .onCameraUnavailable = ::OnCameraUnavailable,
  };
  return &cameraMgrListener;
}

/*
 * CameraDevice callbacks
 */
void OnDeviceStateChanges(void* ctx, ACameraDevice* dev) {
  reinterpret_cast<NDKCamera*>(ctx)->OnDeviceState(dev);
}

void OnDeviceErrorChanges(void* ctx, ACameraDevice* dev, int err) {
  reinterpret_cast<NDKCamera*>(ctx)->OnDeviceError(dev, err);
}

#if __NDK_MAJOR__ >= 30
void OnClientSharedAccessPriorityChanged(void*,
                                         ACameraDevice*, bool) {
    // TODO: Implement this.
}
#endif

ACameraDevice_stateCallbacks* NDKCamera::GetDeviceListener() {
  static ACameraDevice_stateCallbacks cameraDeviceListener = {
      .context = this,
      .onDisconnected = ::OnDeviceStateChanges,
      .onError = ::OnDeviceErrorChanges,
#if __NDK_MAJOR__ >= 30
      .onClientSharedAccessPriorityChanged = ::OnClientSharedAccessPriorityChanged
#endif
  };
  return &cameraDeviceListener;
}
/**
 * Handle Camera DeviceStateChanges msg, notify device is disconnected
 * simply close the camera
 */
void NDKCamera::OnDeviceState(ACameraDevice* dev) {
  std::string id(ACameraDevice_getId(dev));
  LOGW("device %s is disconnected", id.c_str());

  cameras_[id].available_ = false;
  ACameraDevice_close(cameras_[id].device_);
  cameras_.erase(id);
}
/**
 * Handles Camera's deviceErrorChanges message, no action;
 * mainly debugging purpose
 *
 *
 */
void NDKCamera::OnDeviceError(ACameraDevice* dev, int err) {
  std::string id(ACameraDevice_getId(dev));

  LOGI("CameraDevice %s is in error %#x", id.c_str(), err);
  PrintCameraDeviceError(err);

  CameraId& cam = cameras_[id];

  switch (err) {
    case ERROR_CAMERA_IN_USE:
      cam.available_ = false;
      cam.owner_ = false;
      break;
    case ERROR_CAMERA_SERVICE:
    case ERROR_CAMERA_DEVICE:
    case ERROR_CAMERA_DISABLED:
    case ERROR_MAX_CAMERAS_IN_USE:
      cam.available_ = false;
      cam.owner_ = false;
      break;
    default:
      LOGI("Unknown Camera Device Error: %#x", err);
  }
}

// CaptureSession state callbacks
void OnSessionClosed(void* ctx, ACameraCaptureSession* ses) {
  LOGW("session %p closed", ses);
  reinterpret_cast<NDKCamera*>(ctx)->OnSessionState(
      ses, CaptureSessionState::CLOSED);
}
void OnSessionReady(void* ctx, ACameraCaptureSession* ses) {
  LOGW("session %p ready", ses);
  reinterpret_cast<NDKCamera*>(ctx)->OnSessionState(ses,
                                                    CaptureSessionState::READY);
}
void OnSessionActive(void* ctx, ACameraCaptureSession* ses) {
  LOGW("session %p active", ses);
  reinterpret_cast<NDKCamera*>(ctx)->OnSessionState(
      ses, CaptureSessionState::ACTIVE);
}

ACameraCaptureSession_stateCallbacks* NDKCamera::GetSessionListener() {
  static ACameraCaptureSession_stateCallbacks sessionListener = {
      .context = this,
      .onClosed = ::OnSessionClosed,
      .onReady = ::OnSessionReady,
      .onActive = ::OnSessionActive,
  };
  return &sessionListener;
}

/**
 * Handles capture session state changes.
 *   Update into internal session state.
 */
void NDKCamera::OnSessionState(ACameraCaptureSession* ses,
                               CaptureSessionState state) {
  if (!ses || ses != captureSession_) {
    LOGW("CaptureSession is %s", (ses ? "NOT our session" : "NULL"));
    return;
  }

  ASSERT(state < CaptureSessionState::MAX_STATE, "Wrong state %d",
         static_cast<int>(state));

  captureSessionState_ = state;
}

// Capture callbacks, mostly information purpose
void SessionCaptureCallback_OnFailed(void* context,
                                     ACameraCaptureSession* session,
                                     ACaptureRequest* request,
                                     ACameraCaptureFailure* failure) {
  std::thread captureFailedThread(&NDKCamera::OnCaptureFailed,
                                  static_cast<NDKCamera*>(context), session,
                                  request, failure);
  captureFailedThread.detach();
}

void SessionCaptureCallback_OnSequenceEnd(void* context,
                                          ACameraCaptureSession* session,
                                          int sequenceId, int64_t frameNumber) {
  std::thread sequenceThread(&NDKCamera::OnCaptureSequenceEnd,
                             static_cast<NDKCamera*>(context), session,
                             sequenceId, frameNumber);
  sequenceThread.detach();
}
void SessionCaptureCallback_OnSequenceAborted(void* context,
                                              ACameraCaptureSession* session,
                                              int sequenceId) {
  std::thread sequenceThread(&NDKCamera::OnCaptureSequenceEnd,
                             static_cast<NDKCamera*>(context), session,
                             sequenceId, static_cast<int64_t>(-1));
  sequenceThread.detach();
}

ACameraCaptureSession_captureCallbacks* NDKCamera::GetCaptureCallback() {
  static ACameraCaptureSession_captureCallbacks captureListener{
      .context = this,
      .onCaptureStarted = nullptr,
      .onCaptureProgressed = nullptr,
      .onCaptureCompleted = nullptr,
      .onCaptureFailed = SessionCaptureCallback_OnFailed,
      .onCaptureSequenceCompleted = SessionCaptureCallback_OnSequenceEnd,
      .onCaptureSequenceAborted = SessionCaptureCallback_OnSequenceAborted,
      .onCaptureBufferLost = nullptr,
  };
  return &captureListener;
}

/**
 * Process JPG capture SessionCaptureCallback_OnFailed event
 * If this is current JPG capture session, simply resume preview
 * @param session the capture session that failed
 * @param request the capture request that failed
 * @param failure for additional fail info.
 */
void NDKCamera::OnCaptureFailed(ACameraCaptureSession*,
                                ACaptureRequest* request,
                                ACameraCaptureFailure* failure) {
  if (valid_ && request == requests_[JPG_CAPTURE_REQUEST_IDX].request_) {
    ASSERT(failure->sequenceId ==
               requests_[JPG_CAPTURE_REQUEST_IDX].sessionSequenceId_,
           "Error jpg sequence id")
    StartPreview(true);
  }
}

/**
 * Process event from JPEG capture
 *    SessionCaptureCallback_OnSequenceEnd()
 *    SessionCaptureCallback_OnSequenceAborted()
 *
 * If this is jpg capture, turn back on preview after a catpure.
 */
void NDKCamera::OnCaptureSequenceEnd(ACameraCaptureSession*, int sequenceId,
                                     int64_t) {
  if (sequenceId != requests_[JPG_CAPTURE_REQUEST_IDX].sessionSequenceId_)
    return;

  // resume preview
  CALL_SESSION(setRepeatingRequest(captureSession_, nullptr, 1,
                                   &requests_[PREVIEW_REQUEST_IDX].request_,
                                   nullptr));
}


================================================
FILE: camera/basic/src/main/cpp/camera_manager.cpp
================================================
/*
 * Copyright (C) 2017 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 "camera_manager.h"

#include <camera/NdkCameraManager.h>
#include <ndksamples/camera/camera_utils.h>
#include <ndksamples/camera/native_debug.h>
#include <unistd.h>

#include <cinttypes>
#include <queue>
#include <utility>

/**
 * Range of Camera Exposure Time:
 *     Camera's capability range have a very long range which may be disturbing
 *     on camera. For this sample purpose, clamp to a range showing visible
 *     video on preview: 100000ns ~ 250000000ns
 */
static const int64_t kMinExposureTime = 1000000;
static const int64_t kMaxExposureTime = 250000000;

NDKCamera::NDKCamera()
    : cameraMgr_(nullptr),
      activeCameraId_(""),
      cameraFacing_(ACAMERA_LENS_FACING_BACK),
      cameraOrientation_(0),
      outputContainer_(nullptr),
      captureSessionState_(CaptureSessionState::MAX_STATE),
      exposureTime_(static_cast<int64_t>(0)) {
  valid_ = false;
  requests_.resize(CAPTURE_REQUEST_COUNT);
  memset(requests_.data(), 0, requests_.size() * sizeof(requests_[0]));
  cameras_.clear();
  cameraMgr_ = ACameraManager_create();
  ASSERT(cameraMgr_, "Failed to create cameraManager");

  // Pick up a back-facing camera to preview
  EnumerateCamera();
  ASSERT(activeCameraId_.size(), "Unknown ActiveCameraIdx");

  // Create back facing camera device
  CALL_MGR(openCamera(cameraMgr_, activeCameraId_.c_str(), GetDeviceListener(),
                      &cameras_[activeCameraId_].device_));

  CALL_MGR(registerAvailabilityCallback(cameraMgr_, GetManagerListener()));

  // Initialize camera controls(exposure time and sensitivity), pick
  // up value of 2% * range + min as starting value (just a number, no magic)
  ACameraMetadata* metadataObj;
  CALL_MGR(getCameraCharacteristics(cameraMgr_, activeCameraId_.c_str(),
                                    &metadataObj));
  ACameraMetadata_const_entry val = {};
  camera_status_t status = ACameraMetadata_getConstEntry(
      metadataObj, ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val);
  if (status == ACAMERA_OK) {
    exposureRange_.min_ = val.data.i64[0];
    if (exposureRange_.min_ < kMinExposureTime) {
      exposureRange_.min_ = kMinExposureTime;
    }
    exposureRange_.max_ = val.data.i64[1];
    if (exposureRange_.max_ > kMaxExposureTime) {
      exposureRange_.max_ = kMaxExposureTime;
    }
    exposureTime_ = exposureRange_.value(2);
  } else {
    LOGW("Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE");
    exposureRange_.min_ = exposureRange_.max_ = 0l;
    exposureTime_ = 0l;
  }
  status = ACameraMetadata_getConstEntry(
      metadataObj, ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);

  if (status == ACAMERA_OK) {
    sensitivityRange_.min_ = val.data.i32[0];
    sensitivityRange_.max_ = val.data.i32[1];

    sensitivity_ = sensitivityRange_.value(2);
  } else {
    LOGW("failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE");
    sensitivityRange_.min_ = sensitivityRange_.max_ = 0;
    sensitivity_ = 0;
  }
  valid_ = true;
}

/**
 * A helper class to assist image size comparison, by comparing the absolute
 * size
 * regardless of the portrait or landscape mode.
 */
class DisplayDimension {
 public:
  DisplayDimension(int32_t w, int32_t h) : w_(w), h_(h), portrait_(false) {
    if (h > w) {
      // make it landscape
      w_ = h;
      h_ = w;
      portrait_ = true;
    }
  }
  DisplayDimension(const DisplayDimension& other) {
    w_ = other.w_;
    h_ = other.h_;
    portrait_ = other.portrait_;
  }

  DisplayDimension(void) {
    w_ = 0;
    h_ = 0;
    portrait_ = false;
  }
  DisplayDimension& operator=(const DisplayDimension& other) {
    w_ = other.w_;
    h_ = other.h_;
    portrait_ = other.portrait_;

    return (*this);
  }

  bool IsSameRatio(DisplayDimension& other) {
    return (w_ * other.h_ == h_ * other.w_);
  }
  bool operator>(DisplayDimension& other) {
    return (w_ >= other.w_ & h_ >= other.h_);
  }
  bool operator==(DisplayDimension& other) {
    return (w_ == other.w_ && h_ == other.h_ && portrait_ == other.portrait_);
  }
  DisplayDimension operator-(DisplayDimension& other) {
    DisplayDimension delta(w_ - other.w_, h_ - other.h_);
    return delta;
  }
  void Flip(void) { portrait_ = !portrait_; }
  bool IsPortrait(void) { return portrait_; }
  int32_t width(void) { return w_; }
  int32_t height(void) { return h_; }
  int32_t org_width(void) { return (portrait_ ? h_ : w_); }
  int32_t org_height(void) { return (portrait_ ? w_ : h_); }

 private:
  int32_t w_, h_;
  bool portrait_;
};

/**
 * Find a compatible camera modes:
 *    1) the same aspect ration as the native display window, which should be a
 *       rotated version of the physical device
 *    2) the smallest resolution in the camera mode list
 * This is to minimize the later color space conversion workload.
 */
bool NDKCamera::MatchCaptureSizeRequest(ANativeWindow* display,
                                        ImageFormat* resView,
                                        ImageFormat* resCap) {
  DisplayDimension disp(ANativeWindow_getWidth(display),
                        ANativeWindow_getHeight(display));
  if (cameraOrientation_ == 90 || cameraOrientation_ == 270) {
    disp.Flip();
  }

  ACameraMetadata* metadata;
  CALL_MGR(
      getCameraCharacteristics(cameraMgr_, activeCameraId_.c_str(), &metadata));
  ACameraMetadata_const_entry entry;
  CALL_METADATA(getConstEntry(
      metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry));
  // format of the data: format, width, height, input?, type int32
  bool foundIt = false;
  DisplayDimension foundRes(4000, 4000);
  DisplayDimension maxJPG(0, 0);

  for (uint32_t i = 0; i < entry.count; i += 4) {
    int32_t input = entry.data.i32[i + 3];
    int32_t format = entry.data.i32[i + 0];
    if (input) continue;

    if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) {
      DisplayDimension res(entry.data.i32[i + 1], entry.data.i32[i + 2]);
      if (!disp.IsSameRatio(res)) continue;
      if (format == AIMAGE_FORMAT_YUV_420_888 && foundRes > res) {
        foundIt = true;
        foundRes = res;
      } else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) {
        maxJPG = res;
      }
    }
  }

  if (foundIt) {
    resView->width = foundRes.org_width();
    resView->height = foundRes.org_height();
    resCap->width = maxJPG.org_width();
    resCap->height = maxJPG.org_height();
  } else {
    LOGW("Did not find any compatible camera resolution, taking 640x480");
    if (disp.IsPortrait()) {
      resView->width = 480;
      resView->height = 640;
    } else {
      resView->width = 640;
      resView->height = 480;
    }
    *resCap = *resView;
  }
  resView->format = AIMAGE_FORMAT_YUV_420_888;
  resCap->format = AIMAGE_FORMAT_JPEG;
  return foundIt;
}

void NDKCamera::CreateSession(ANativeWindow* previewWindow,
                              ANativeWindow* jpgWindow, int32_t imageRotation) {
  // Create output from this app's ANativeWindow, and add into output container
  requests_[PREVIEW_REQUEST_IDX].outputNativeWindow_ = previewWindow;
  requests_[PREVIEW_REQUEST_IDX].template_ = TEMPLATE_PREVIEW;
  requests_[JPG_CAPTURE_REQUEST_IDX].outputNativeWindow_ = jpgWindow;
  requests_[JPG_CAPTURE_REQUEST_IDX].template_ = TEMPLATE_STILL_CAPTURE;

  CALL_CONTAINER(create(&outputContainer_));
  for (auto& req : requests_) {
    ANativeWindow_acquire(req.outputNativeWindow_);
    CALL_OUTPUT(create(req.outputNativeWindow_, &req.sessionOutput_));
    CALL_CONTAINER(add(outputContainer_, req.sessionOutput_));
    CALL_TARGET(create(req.outputNativeWindow_, &req.target_));
    CALL_DEV(createCaptureRequest(cameras_[activeCameraId_].device_,
                                  req.template_, &req.request_));
    CALL_REQUEST(addTarget(req.request_, req.target_));
  }

  // Create a capture session for the given preview request
  captureSessionState_ = CaptureSessionState::READY;
  CALL_DEV(createCaptureSession(cameras_[activeCameraId_].device_,
                                outputContainer_, GetSessionListener(),
                                &captureSession_));

  ACaptureRequest_setEntry_i32(requests_[JPG_CAPTURE_REQUEST_IDX].request_,
                               ACAMERA_JPEG_ORIENTATION, 1, &imageRotation);

  /*
   * Only preview request is in manual mode, JPG is always in Auto mode
   * JPG capture mode could also be switch into manual mode and control
   * the capture parameters, this sample leaves JPG capture to be auto mode
   * (auto control has better effect than author's manual control)
   */
  uint8_t aeModeOff = ACAMERA_CONTROL_AE_MODE_OFF;
  CALL_REQUEST(setEntry_u8(requests_[PREVIEW_REQUEST_IDX].request_,
                           ACAMERA_CONTROL_AE_MODE, 1, &aeModeOff));
  CALL_REQUEST(setEntry_i32(requests_[PREVIEW_REQUEST_IDX].request_,
                            ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_));
  CALL_REQUEST(setEntry_i64(requests_[PREVIEW_REQUEST_IDX].request_,
                            ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime_));
}

NDKCamera::~NDKCamera() {
  valid_ = false;
  // stop session if it is on:
  if (captureSessionState_ == CaptureSessionState::ACTIVE) {
    ACameraCaptureSession_stopRepeating(captureSession_);
  }
  ACameraCaptureSession_close(captureSession_);

  for (auto& req : requests_) {
    CALL_REQUEST(removeTarget(req.request_, req.target_));
    ACaptureRequest_free(req.request_);
    ACameraOutputTarget_free(req.target_);

    CALL_CONTAINER(remove(outputContainer_, req.sessionOutput_));
    ACaptureSessionOutput_free(req.sessionOutput_);

    ANativeWindow_release(req.outputNativeWindow_);
  }

  requests_.resize(0);
  ACaptureSessionOutputContainer_free(outputContainer_);

  for (auto& cam : cameras_) {
    if (cam.second.device_) {
      CALL_DEV(close(cam.second.device_));
    }
  }
  cameras_.clear();
  if (cameraMgr_) {
    CALL_MGR(unregisterAvailabilityCallback(cameraMgr_, GetManagerListener()));
    ACameraManager_delete(cameraMgr_);
    cameraMgr_ = nullptr;
  }
}

/**
 * EnumerateCamera()
 *     Loop through cameras on the system, pick up
 *     1) back facing one if available
 *     2) otherwise pick the first one reported to us
 */
void NDKCamera::EnumerateCamera() {
  ACameraIdList* cameraIds = nullptr;
  CALL_MGR(getCameraIdList(cameraMgr_, &cameraIds));

  for (int i = 0; i < cameraIds->numCameras; ++i) {
    const char* id = cameraIds->cameraIds[i];

    ACameraMetadata* metadataObj;
    CALL_MGR(getCameraCharacteristics(cameraMgr_, id, &metadataObj));

    int32_t count = 0;
    const uint32_t* tags = nullptr;
    ACameraMetadata_getAllTags(metadataObj, &count, &tags);
    for (int tagIdx = 0; tagIdx < count; ++tagIdx) {
      if (ACAMERA_LENS_FACING == tags[tagIdx]) {
        ACameraMetadata_const_entry lensInfo = {};
        CALL_METADATA(getConstEntry(metadataObj, tags[tagIdx], &lensInfo));
        CameraId cam(id);
        cam.facing_ = static_cast<acamera_metadata_enum_android_lens_facing_t>(
            lensInfo.data.u8[0]);
        cam.owner_ = false;
        cam.device_ = nullptr;
        cameras_[cam.id_] = cam;
        if (cam.facing_ == ACAMERA_LENS_FACING_BACK) {
          activeCameraId_ = cam.id_;
        }
        break;
      }
    }
    ACameraMetadata_free(metadataObj);
  }

  ASSERT(cameras_.size(), "No Camera Available on the device");
  if (activeCameraId_.length() == 0) {
    // if no back facing camera found, pick up the first one to use...
    activeCameraId_ = cameras_.begin()->second.id_;
  }
  ACameraManager_deleteCameraIdList(cameraIds);
}

/**
 * GetSensorOrientation()
 *     Retrieve current sensor orientation regarding to the phone device
 * orientation
 *     SensorOrientation is NOT settable.
 */
bool NDKCamera::GetSensorOrientation(int32_t* facing, int32_t* angle) {
  if (!cameraMgr_) {
    return false;
  }

  ACameraMetadata* metadataObj;
  ACameraMetadata_const_entry face, orientation;
  CALL_MGR(getCameraCharacteristics(cameraMgr_, activeCameraId_.c_str(),
                                    &metadataObj));
  CALL_METADATA(getConstEntry(metadataObj, ACAMERA_LENS_FACING, &face));
  cameraFacing_ = static_cast<int32_t>(face.data.u8[0]);

  CALL_METADATA(
      getConstEntry(metadataObj, ACAMERA_SENSOR_ORIENTATION, &orientation));

  LOGI("====Current SENSOR_ORIENTATION: %8d", orientation.data.i32[0]);

  ACameraMetadata_free(metadataObj);
  cameraOrientation_ = orientation.data.i32[0];

  if (facing) *facing = cameraFacing_;
  if (angle) *angle = cameraOrientation_;
  return true;
}

/**
 * StartPreview()
 *   Toggle preview start/stop
 */
void NDKCamera::StartPreview(bool start) {
  if (start) {
    CALL_SESSION(setRepeatingRequest(captureSession_, nullptr, 1,
                                     &requests_[PREVIEW_REQUEST_IDX].request_,
                                     nullptr));
  } else if (!start && captureSessionState_ == CaptureSessionState::ACTIVE) {
    ACameraCaptureSession_stopRepeating(captureSession_);
  } else {
    ASSERT(false, "Conflict states(%s, %d)", (start ? "true" : "false"),
           static_cast<int>(captureSessionState_));
  }
}

/**
 * Capture one jpg photo into
 *     /sdcard/DCIM/Camera
 * refer to WriteFile() for details
 */
bool NDKCamera::TakePhoto(void) {
  if (captureSessionState_ == CaptureSessionState::ACTIVE) {
    ACameraCaptureSession_stopRepeating(captureSession_);
  }

  CALL_SESSION(capture(captureSession_, GetCaptureCallback(), 1,
                       &requests_[JPG_CAPTURE_REQUEST_IDX].request_,
                       &requests_[JPG_CAPTURE_REQUEST_IDX].sessionSequenceId_));
  return true;
}

void NDKCamera::UpdateCameraRequestParameter(int32_t code, int64_t val) {
  ACaptureRequest* request = requests_[PREVIEW_REQUEST_IDX].request_;
  switch (code) {
    case ACAMERA_SENSOR_EXPOSURE_TIME:
      if (exposureRange_.Supported()) {
        exposureTime_ = val;
        CALL_REQUEST(setEntry_i64(request, ACAMERA_SENSOR_EXPOSURE_TIME, 1,
                                  &exposureTime_));
      }
      break;

    case ACAMERA_SENSOR_SENSITIVITY:
      if (sensitivityRange_.Supported()) {
        sensitivity_ = val;
        CALL_REQUEST(setEntry_i32(request, ACAMERA_SENSOR_SENSITIVITY, 1,
                                  &sensitivity_));
      }
      break;
    default:
      ASSERT(false, "==ERROR==: error code for CameraParameterChange: %d",
             code);
      return;
  }

  uint8_t aeModeOff = ACAMERA_CONTROL_AE_MODE_OFF;
  CALL_REQUEST(setEntry_u8(request, ACAMERA_CONTROL_AE_MODE, 1, &aeModeOff));
  CALL_SESSION(
      setRepeatingRequest(captureSession_, nullptr, 1, &request,
                          &requests_[PREVIEW_REQUEST_IDX].sessionSequenceId_));
}

/**
 * Retrieve Camera Exposure adjustable range.
 *
 * @param min Camera minimium exposure time in nanoseconds
 * @param max Camera maximum exposure tiem in nanoseconds
 *
 * @return true  min and max are loaded with the camera's exposure values
 *         false camera has not initialized, no value available
 */
bool NDKCamera::GetExposureRange(int64_t* min, int64_t* max, int64_t* curVal) {
  if (!exposureRange_.Supported() || !exposureTime_ || !min || !max ||
      !curVal) {
    return false;
  }
  *min = exposureRange_.min_;
  *max = exposureRange_.max_;
  *curVal = exposureTime_;

  return true;
}

/**
 * Retrieve Camera sensitivity range.
 *
 * @param min Camera minimium sensitivity
 * @param max Camera maximum sensitivity
 *
 * @return true  min and max are loaded with the camera's sensitivity values
 *         false camera has not initialized, no value available
 */
bool NDKCamera::GetSensitivityRange(int64_t* min, int64_t* max,
                                    int64_t* curVal) {
  if (!sensitivityRange_.Supported() || !sensitivity_ || !min || !max ||
      !curVal) {
    return false;
  }
  *min = static_cast<int64_t>(sensitivityRange_.min_);
  *max = static_cast<int64_t>(sensitivityRange_.max_);
  *curVal = sensitivity_;
  return true;
}


================================================
FILE: camera/basic/src/main/cpp/camera_manager.h
================================================
/*
 * Copyright (C) 2017 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 CAMERA_NATIVE_CAMERA_H
#define CAMERA_NATIVE_CAMERA_H
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraMetadataTags.h>

#include <map>
#include <string>
#include <vector>

#include "image_reader.h"

enum class CaptureSessionState : int32_t {
  READY = 0,  // session is ready
  ACTIVE,     // session is busy
  CLOSED,     // session is closed(by itself or a new session evicts)
  MAX_STATE
};

template <typename T>
class RangeValue {
 public:
  T min_, max_;
  /**
   * return absolute value from relative value
   * value: in percent (50 for 50%)
   */
  T value(int percent) {
    return static_cast<T>(min_ + (max_ - min_) * percent / 100);
  }
  RangeValue() { min_ = max_ = static_cast<T>(0); }

  bool Supported(void) const { return (min_ != max_); }
};

enum PREVIEW_INDICES {
  PREVIEW_REQUEST_IDX = 0,
  JPG_CAPTURE_REQUEST_IDX,
  CAPTURE_REQUEST_COUNT,
};

struct CaptureRequestInfo {
  ANativeWindow* outputNativeWindow_;
  ACaptureSessionOutput* sessionOutput_;
  ACameraOutputTarget* target_;
  ACaptureRequest* request_;
  ACameraDevice_request_template template_;
  int sessionSequenceId_;
};

class CameraId;
class NDKCamera {
 private:
  ACameraManager* cameraMgr_;
  std::map<std::string, CameraId> cameras_;
  std::string activeCameraId_;
  uint32_t cameraFacing_;
  uint32_t cameraOrientation_;

  std::vector<CaptureRequestInfo> requests_;

  ACaptureSessionOutputContainer* outputContainer_;
  ACameraCaptureSession* captureSession_;
  CaptureSessionState captureSessionState_;

  // set up exposure control
  int64_t exposureTime_;
  RangeValue<int64_t> exposureRange_;
  int32_t sensitivity_;
  RangeValue<int32_t> sensitivityRange_;
  volatile bool valid_;

  ACameraManager_AvailabilityCallbacks* GetManagerListener();
  ACameraDevice_stateCallbacks* GetDeviceListener();
  ACameraCaptureSession_stateCallbacks* GetSessionListener();
  ACameraCaptureSession_captureCallbacks* GetCaptureCallback();

 public:
  NDKCamera();
  ~NDKCamera();
  void EnumerateCamera(void);
  bool MatchCaptureSizeRequest(ANativeWindow* display, ImageFormat* view,
                               ImageFormat* capture);
  void CreateSession(ANativeWindow* previewWindow, ANativeWindow* jpgWindow,
                     int32_t imageRotation);
  bool GetSensorOrientation(int32_t* facing, int32_t* angle);
  void OnCameraStatusChanged(const char* id, bool available);
  void OnDeviceState(ACameraDevice* dev);
  void OnDeviceError(ACameraDevice* dev, int err);
  void OnSessionState(ACameraCaptureSession* ses, CaptureSessionState state);
  void OnCaptureSequenceEnd(ACameraCaptureSession* session, int sequenceId,
                            int64_t frameNumber);
  void OnCaptureFailed(ACameraCaptureSession* session, ACaptureRequest* request,
                       ACameraCaptureFailure* failure);
  void StartPreview(bool start);
  bool TakePhoto(void);
  bool GetExposureRange(int64_t* min, int64_t* max, int64_t* curVal);
  bool GetSensitivityRange(int64_t* min, int64_t* max, int64_t* curVal);

  void UpdateCameraRequestParameter(int32_t code, int64_t val);
};

// helper classes to hold enumerated camera
class CameraId {
 public:
  ACameraDevice* device_;
  std::string id_;
  acamera_metadata_enum_android_lens_facing_t facing_;
  bool available_;  // free to use ( no other apps are using
  bool owner_;      // we are the owner of the camera
  explicit CameraId(const char* id)
      : device_(nullptr),
        facing_(ACAMERA_LENS_FACING_FRONT),
        available_(false),
        owner_(false) {
    id_ = id;
  }

  explicit CameraId(void) { CameraId(""); }
};

#endif  // CAMERA_NATIVE_CAMERA_H


================================================
FILE: camera/basic/src/main/cpp/camera_ui.cpp
================================================

/*
 * Copyright (C) 2017 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 <base/macros.h>
#include <ndksamples/camera/native_debug.h>

#include "camera_engine.h"

/**
 * Retrieve current rotation from Java side
 *
 * @return current rotation angle
 */
int CameraEngine::GetDisplayRotation() {
  ASSERT(app_, "Application is not initialized");

  JNIEnv* env;
  ANativeActivity* activity = app_->activity;
  activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6);

  activity->vm->AttachCurrentThread(&env, NULL);

  jobject activityObj = env->NewGlobalRef(activity->clazz);
  jclass clz = env->GetObjectClass(activityObj);
  jint newOrientation = env->CallIntMethod(
      activityObj, env->GetMethodID(clz, "getRotationDegree", "()I"));
  env->DeleteGlobalRef(activityObj);

  activity->vm->DetachCurrentThread();
  return newOrientation;
}

/**
 * Initializate UI on Java side. The 2 seekBars' values are passed in
 * array in the tuple of ( min, max, curVal )
 *   0: exposure min
 *   1: exposure max
 *   2: exposure val
 *   3: sensitivity min
 *   4: sensitivity max
 *   5: sensitivity val
 */
const int kInitDataLen = 6;
void CameraEngine::EnableUI(void) {
  JNIEnv* jni;
  app_->activity->vm->AttachCurrentThread(&jni, NULL);
  int64_t range[3];

  // Default class retrieval
  jclass clazz = jni->GetObjectClass(app_->activity->clazz);
  jmethodID methodID = jni->GetMethodID(clazz, "EnableUI", "([J)V");
  jlongArray initData = jni->NewLongArray(kInitDataLen);

  ASSERT(initData && methodID, "JavaUI interface Object failed(%p, %p)",
         methodID, initData);

  if (!camera_->GetExposureRange(&range[0], &range[1], &range[2])) {
    memset(range, 0, sizeof(int64_t) * 3);
  }

  jni->SetLongArrayRegion(initData, 0, 3, range);

  if (!camera_->GetSensitivityRange(&range[0], &range[1], &range[2])) {
    memset(range, 0, sizeof(int64_t) * 3);
  }
  jni->SetLongArrayRegion(initData, 3, 3, range);
  jni->CallVoidMethod(app_->activity->clazz, methodID, initData);
  app_->activity->vm->DetachCurrentThread();
}

/**
 * Handles UI request to take a photo into
 *   /sdcard/DCIM/Camera
 */
void CameraEngine::OnTakePhoto() {
  if (camera_) {
    camera_->TakePhoto();
  }
}

void CameraEngine::OnPhotoTaken(const char* fileName) {
  JNIEnv* jni;
  app_->activity->vm->AttachCurrentThread(&jni, NULL);

  // Default class retrieval
  jclass clazz = jni->GetObjectClass(app_->activity->clazz);
  jmethodID methodID =
      jni->GetMethodID(clazz, "OnPhotoTaken", "(Ljava/lang/String;)V");
  jstring javaName = jni->NewStringUTF(fileName);

  jni->CallVoidMethod(app_->activity->clazz, methodID, javaName);
  app_->activity->vm->DetachCurrentThread();
}
/**
 * Process user camera and disk writing permission
 * Resume application initialization after user granted camera and disk usage
 * If user denied permission, do nothing: no camera
 *
 * @param granted user's authorization for camera and disk usage.
 * @return none
 */
void CameraEngine::OnCameraPermission(jboolean granted) {
  cameraGranted_ = (granted != JNI_FALSE);

  // TODO: Fail gracefully.
  ASSERT(cameraGranted_, "required app permissions were not granted");
  OnAppInitWindow();
}

/**
 *  A couple UI handles ( from UI )
 *      user camera and disk permission
 *      exposure and sensitivity SeekBars
 *      takePhoto button
 */
void notifyCameraPermission(JNIEnv*, jclass, jboolean permission) {
  std::thread permissionHandler(&CameraEngine::OnCameraPermission,
                                GetAppEngine(), permission);
  permissionHandler.detach();
}

void TakePhoto(JNIEnv*, jclass) {
  std::thread takePhotoHandler(&CameraEngine::OnTakePhoto, GetAppEngine());
  takePhotoHandler.detach();
}

void OnExposureChanged(JNIEnv*, jobject, jlong exposurePercent) {
  GetAppEngine()->OnCameraParameterChanged(ACAMERA_SENSOR_EXPOSURE_TIME,
                                           exposurePercent);
}

void OnSensitivityChanged(JNIEnv*, jobject, jlong sensitivity) {
  GetAppEngine()->OnCameraParameterChanged(ACAMERA_SENSOR_SENSITIVITY,
                                           sensitivity);
}

extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {
  JNIEnv* env;
  if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
    return JNI_ERR;
  }

  jclass c = env->FindClass("com/sample/camera/basic/CameraActivity");
  if (c == nullptr) return JNI_ERR;

  static const JNINativeMethod methods[] = {
      {"notifyCameraPermission", "(Z)V",
       reinterpret_cast<void*>(notifyCameraPermission)},
      {"TakePhoto", "()V", reinterpret_cast<void*>(TakePhoto)},
      {"OnExposureChanged", "(J)V", reinterpret_cast<void*>(OnExposureChanged)},
      {"OnSensitivityChanged", "(J)V",
       reinterpret_cast<void*>(OnSensitivityChanged)},
  };
  int rc = env->RegisterNatives(c, methods, arraysize(methods));
  if (rc != JNI_OK) return rc;

  return JNI_VERSION_1_6;
}


================================================
FILE: camera/basic/src/main/cpp/image_reader.cpp
================================================
/*
 * Copyright (C) 2017 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 "image_reader.h"

#include <dirent.h>
#include <ndksamples/camera/native_debug.h>

#include <cstdlib>
#include <ctime>
#include <functional>
#include <string>
#include <thread>

/*
 * For JPEG capture, captured files are saved under
 *     DirName
 * File names are incrementally appended an index number as
 *     capture0.jpg, capture1.jpg, capture2.jpg
 */
static const char* kDirName = "/sdcard/DCIM/Camera/";
static const char* kFileName = "capture";

/**
 * MAX_BUF_COUNT:
 *   Max buffers in this ImageReader.
 */
#define MAX_BUF_COUNT 4

/**
 * ImageReader listener: called by AImageReader for every frame captured
 * We pass the event to ImageReader class, so it could do some housekeeping
 * about
 * the loaded queue. For example, we could keep a counter to track how many
 * buffers are full and idle in the queue. If camera almost has no buffer to
 * capture
 * we could release ( skip ) some frames by AImageReader_getNextImage() and
 * AImageReader_delete().
 */
void OnImageCallback(void* ctx, AImageReader* reader) {
  reinterpret_cast<ImageReader*>(ctx)->ImageCallback(reader);
}

/**
 * Constructor
 */
ImageReader::ImageReader(ImageFormat* res, enum AIMAGE_FORMATS format)
    : presentRotation_(0), reader_(nullptr) {
  callback_ = nullptr;
  callbackCtx_ = nullptr;

  media_status_t status = AImageReader_new(res->width, res->height, format,
                                           MAX_BUF_COUNT, &reader_);
  ASSERT(reader_ && status == AMEDIA_OK, "Failed to create AImageReader");

  AImageReader_ImageListener listener{
      .context = this,
      .onImageAvailable = OnImageCallback,
  };
  AImageReader_setImageListener(reader_, &listener);
}

ImageReader::~ImageReader() {
  ASSERT(reader_, "NULL Pointer to %s", __FUNCTION__);
  AImageReader_delete(reader_);
}

void ImageReader::RegisterCallback(
    void* ctx, std::function<void(void* ctx, const char* fileName)> func) {
  callbackCtx_ = ctx;
  callback_ = func;
}

void ImageReader::ImageCallback(AImageReader* reader) {
  int32_t format;
  media_status_t status = AImageReader_getFormat(reader, &format);
  ASSERT(status == AMEDIA_OK, "Failed to get the media format");
  if (format == AIMAGE_FORMAT_JPEG) {
    AImage* image = nullptr;
    media_status_t status = AImageReader_acquireNextImage(reader, &image);
    ASSERT(status == AMEDIA_OK && image, "Image is not available");

    // Create a thread and write out the jpeg files
    std::thread writeFileHandler(&ImageReader::WriteFile, this, image);
    writeFileHandler.detach();
  }
}

ANativeWindow* ImageReader::GetNativeWindow(void) {
  if (!reader_) return nullptr;
  ANativeWindow* nativeWindow;
  media_status_t status = AImageReader_getWindow(reader_, &nativeWindow);
  ASSERT(status == AMEDIA_OK, "Could not get ANativeWindow");

  return nativeWindow;
}

/**
 * GetNextImage()
 *   Retrieve the next image in ImageReader's bufferQueue, NOT the last image so
 * no image is skipped. Recommended for batch/background processing.
 */
AImage* ImageReader::GetNextImage(void) {
  AImage* image;
  media_status_t status = AImageReader_acquireNextImage(reader_, &image);
  if (status != AMEDIA_OK) {
    return nullptr;
  }
  return image;
}

/**
 * GetLatestImage()
 *   Retrieve the last image in ImageReader's bufferQueue, deleting images in
 * in front of it on the queue. Recommended for real-time processing.
 */
AImage* ImageReader::GetLatestImage(void) {
  AImage* image;
  media_status_t status = AImageReader_acquireLatestImage(reader_, &image);
  if (status != AMEDIA_OK) {
    return nullptr;
  }
  return image;
}

/**
 * Delete Image
 * @param image {@link AImage} instance to be deleted
 */
void ImageReader::DeleteImage(AImage* image) {
  if (image) AImage_delete(image);
}

/**
 * Helper function for YUV_420 to RGB conversion. Courtesy of Tensorflow
 * ImageClassifier Sample:
 * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/android/jni/yuv2rgb.cc
 * The difference is that here we have to swap UV plane when calling it.
 */
#ifndef MAX
#define MAX(a, b)           \
  ({                        \
    __typeof__(a) _a = (a); \
    __typeof__(b) _b = (b); \
    _a > _b ? _a : _b;      \
  })
#define MIN(a, b)           \
  ({                        \
    __typeof__(a) _a = (a); \
    __typeof__(b) _b = (b); \
    _a < _b ? _a : _b;      \
  })
#endif

// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
// ranges
// are normalized to eight bits.
static const int kMaxChannelValue = 262143;

static inline uint32_t YUV2RGB(int nY, int nU, int nV) {
  nY -= 16;
  nU -= 128;
  nV -= 128;
  if (nY < 0) nY = 0;

  // This is the floating point equivalent. We do the conversion in integer
  // because some Android devices do not have floating point in hardware.
  // nR = (int)(1.164 * nY + 1.596 * nV);
  // nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU);
  // nB = (int)(1.164 * nY + 2.018 * nU);

  int nR = (int)(1192 * nY + 1634 * nV);
  int nG = (int)(1192 * nY - 833 * nV - 400 * nU);
  int nB = (int)(1192 * nY + 2066 * nU);

  nR = MIN(kMaxChannelValue, MAX(0, nR));
  nG = MIN(kMaxChannelValue, MAX(0, nG));
  nB = MIN(kMaxChannelValue, MAX(0, nB));

  nR = (nR >> 10) & 0xff;
  nG = (nG >> 10) & 0xff;
  nB = (nB >> 10) & 0xff;

  return 0xff000000 | (nB << 16) | (nG << 8) | nR;
}

/**
 * Convert yuv image inside AImage into ANativeWindow_Buffer
 * ANativeWindow_Buffer format is guaranteed to be
 *      WINDOW_FORMAT_RGBX_8888
 *      WINDOW_FORMAT_RGBA_8888
 * @param buf a {@link ANativeWindow_Buffer } instance, destination of
 *            image conversion
 * @param image a {@link AImage} instance, source of image conversion.
 *            it will be deleted via {@link AImage_delete}
 */
bool ImageReader::DisplayImage(ANativeWindow_Buffer* buf, AImage* image) {
  ASSERT(buf->format == WINDOW_FORMAT_RGBX_8888 ||
             buf->format == WINDOW_FORMAT_RGBA_8888,
         "Not supported buffer format");

  int32_t srcFormat = -1;
  AImage_getFormat(image, &srcFormat);
  ASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
  int32_t srcPlanes = 0;
  AImage_getNumberOfPlanes(image, &srcPlanes);
  ASSERT(srcPlanes == 3, "Is not 3 planes");

  switch (presentRotation_) {
    case 0:
      PresentImage(buf, image);
      break;
    case 90:
      PresentImage90(buf, image);
      break;
    case 180:
      PresentImage180(buf, image);
      break;
    case 270:
      PresentImage270(buf, image);
      break;
    default:
      ASSERT(0, "NOT recognized display rotation: %d", presentRotation_);
  }

  AImage_delete(image);

  return true;
}

/*
 * PresentImage()
 *   Converting yuv to RGB
 *   No rotation: (x,y) --> (x, y)
 *   Refer to:
 * https://mathbits.com/MathBits/TISection/Geometry/Transformations2.htm
 */
void ImageReader::PresentImage(ANativeWindow_Buffer* buf, AImage* image) {
  AImageCropRect srcRect;
  AImage_getCropRect(image, &srcRect);

  int32_t yStride, uvStride;
  uint8_t *yPixel, *uPixel, *vPixel;
  int32_t yLen, uLen, vLen;
  AImage_getPlaneRowStride(image, 0, &yStride);
  AImage_getPlaneRowStride(image, 1, &uvStride);
  AImage_getPlaneData(image, 0, &yPixel, &yLen);
  AImage_getPlaneData(image, 1, &uPixel, &uLen);
  AImage_getPlaneData(image, 2, &vPixel, &vLen);
  int32_t uvPixelStride;
  AImage_getPlanePixelStride(image, 1, &uvPixelStride);

  int32_t height = MIN(buf->height, (srcRect.bottom - srcRect.top));
  int32_t width = MIN(buf->width, (srcRect.right - srcRect.left));

  uint32_t* out = static_cast<uint32_t*>(buf->bits);
  for (int32_t y = 0; y < height; y++) {
    const uint8_t* pY = yPixel + yStride * (y + srcRect.top) + srcRect.left;

    int32_t uv_row_start = uvStride * ((y + srcRect.top) >> 1);
    const uint8_t* pU = uPixel + uv_row_start + (srcRect.left >> 1);
    const uint8_t* pV = vPixel + uv_row_start + (srcRect.left >> 1);

    for (int32_t x = 0; x < width; x++) {
      const int32_t uv_offset = (x >> 1) * uvPixelStride;
      out[x] = YUV2RGB(pY[x], pU[uv_offset], pV[uv_offset]);
    }
    out += buf->stride;
  }
}

/*
 * PresentImage90()
 *   Converting YUV to RGB
 *   Rotation image anti-clockwise 90 degree -- (x, y) --> (-y, x)
 */
void ImageReader::PresentImage90(ANativeWindow_Buffer* buf, AImage* image) {
  AImageCropRect srcRect;
  AImage_getCropRect(image, &srcRect);

  int32_t yStride, uvStride;
  uint8_t *yPixel, *uPixel, *vPixel;
  int32_t yLen, uLen, vLen;
  AImage_getPlaneRowStride(image, 0, &yStride);
  AImage_getPlaneRowStride(image, 1, &uvStride);
  AImage_getPlaneData(image, 0, &yPixel, &yLen);
  AImage_getPlaneData(image, 1, &uPixel, &uLen);
  AImage_getPlaneData(image, 2, &vPixel, &vLen);
  int32_t uvPixelStride;
  AImage_getPlanePixelStride(image, 1, &uvPixelStride);

  int32_t height = MIN(buf->width, (srcRect.bottom - srcRect.top));
  int32_t width = MIN(buf->height, (srcRect.right - srcRect.left));

  uint32_t* out = static_cast<uint32_t*>(buf->bits);
  out += height - 1;
  for (int32_t y = 0; y < height; y++) {
    const uint8_t* pY = yPixel + yStride * (y + srcRect.top) + srcRect.left;

    int32_t uv_row_start = uvStride * ((y + srcRect.top) >> 1);
    const uint8_t* pU = uPixel + uv_row_start + (srcRect.left >> 1);
    const uint8_t* pV = vPixel + uv_row_start + (srcRect.left >> 1);

    for (int32_t x = 0; x < width; x++) {
      const int32_t uv_offset = (x >> 1) * uvPixelStride;
      // [x, y]--> [-y, x]
      out[x * buf->stride] = YUV2RGB(pY[x], pU[uv_offset], pV[uv_offset]);
    }
    out -= 1;  // move to the next column
  }
}

/*
 * PresentImage180()
 *   Converting yuv to RGB
 *   Rotate image 180 degree: (x, y) --> (-x, -y)
 */
void ImageReader::PresentImage180(ANativeWindow_Buffer* buf, AImage* image) {
  AImageCropRect srcRect;
  AImage_getCropRect(image, &srcRect);

  int32_t yStride, uvStride;
  uint8_t *yPixel, *uPixel, *vPixel;
  int32_t yLen, uLen, vLen;
  AImage_getPlaneRowStride(image, 0, &yStride);
  AImage_getPlaneRowStride(image, 1, &uvStride);
  AImage_getPlaneData(image, 0, &yPixel, &yLen);
  AImage_getPlaneData(image, 1, &uPixel, &uLen);
  AImage_getPlaneData(image, 2, &vPixel, &vLen);
  int32_t uvPixelStride;
  AImage_getPlanePixelStride(image, 1, &uvPixelStride);

  int32_t height = MIN(buf->height, (srcRect.bottom - srcRect.top));
  int32_t width = MIN(buf->width, (srcRect.right - srcRect.left));

  uint32_t* out = static_cast<uint32_t*>(buf->bits);
  out += (height - 1) * buf->stride;
  for (int32_t y = 0; y < height; y++) {
    const uint8_t* pY = yPixel + yStride * (y + srcRect.top) + srcRect.left;

    int32_t uv_row_start = uvStride * ((y + srcRect.top) >> 1);
    const uint8_t* pU = uPixel + uv_row_start + (srcRect.left >> 1);
    const uint8_t* pV = vPixel + uv_row_start + (srcRect.left >> 1);

    for (int32_t x = 0; x < width; x++) {
      const int32_t uv_offset = (x >> 1) * uvPixelStride;
      // mirror image since we are using front camera
      out[width - 1 - x] = YUV2RGB(pY[x], pU[uv_offset], pV[uv_offset]);
      // out[x] = YUV2RGB(pY[x], pU[uv_offset], pV[uv_offset]);
    }
    out -= buf->stride;
  }
}

/*
 * PresentImage270()
 *   Converting image from YUV to RGB
 *   Rotate Image counter-clockwise 270 degree: (x, y) --> (y, x)
 */
void ImageReader::PresentImage270(ANativeWindow_Buffer* buf, AImage* image) {
  AImageCropRect srcRect;
  AImage_getCropRect(image, &srcRect);

  int32_t yStride, uvStride;
  uint8_t *yPixel, *uPixel, *vPixel;
  int32_t yLen, uLen, vLen;
  AImage_getPlaneRowStride(image, 0, &yStride);
  AImage_getPlaneRowStride(image, 1, &uvStride);
  AImage_getPlaneData(image, 0, &yPixel, &yLen);
  AImage_getPlaneData(image, 1, &uPixel, &uLen);
  AImage_getPlaneData(image, 2, &vPixel, &vLen);
  int32_t uvPixelStride;
  AImage_getPlanePixelStride(image, 1, &uvPixelStride);

  int32_t height = MIN(buf->width, (srcRect.bottom - srcRect.top));
  int32_t width = MIN(buf->height, (srcRect.right - srcRect.left));

  uint32_t* out = static_cast<uint32_t*>(buf->bits);
  for (int32_t y = 0; y < height; y++) {
    const uint8_t* pY = yPixel + yStride * (y + srcRect.top) + srcRect.left;

    int32_t uv_row_start = uvStride * ((y + srcRect.top) >> 1);
    const uint8_t* pU = uPixel + uv_row_start + (srcRect.left >> 1);
    const uint8_t* pV = vPixel + uv_row_start + (srcRect.left >> 1);

    for (int32_t x = 0; x < width; x++) {
      const int32_t uv_offset = (x >> 1) * uvPixelStride;
      out[(width - 1 - x) * buf->stride] =
          YUV2RGB(pY[x], pU[uv_offset], pV[uv_offset]);
    }
    out += 1;  // move to the next column
  }
}
void ImageReader::SetPresentRotation(int32_t angle) {
  presentRotation_ = angle;
}

/**
 * Write out jpeg files to kDirName directory
 * @param image point capture jpg image
 */
void ImageReader::WriteFile(AImage* image) {
  int planeCount;
  media_status_t status = AImage_getNumberOfPlanes(image, &planeCount);
  ASSERT(status == AMEDIA_OK && planeCount == 1,
         "Error: getNumberOfPlanes() planeCount = %d", planeCount);
  uint8_t* data = nullptr;
  int len = 0;
  AImage_getPlaneData(image, 0, &data, &len);

  DIR* dir = opendir(kDirName);
  if (dir) {
    closedir(dir);
  } else {
    std::string cmd = "mkdir -p ";
    cmd += kDirName;
    system(cmd.c_str());
  }

  struct timespec ts {
    0, 0
  };
  clock_gettime(CLOCK_REALTIME, &ts);
  struct tm localTime;
  localtime_r(&ts.tv_sec, &localTime);

  std::string fileName = kDirName;
  std::string dash("-");
  fileName += kFileName + std::to_string(localTime.tm_mon) +
              std::to_string(localTime.tm_mday) + dash +
              std::to_string(localTime.tm_hour) +
              std::to_string(localTime.tm_min) +
              std::to_string(localTime.tm_sec) + ".jpg";
  FILE* file = fopen(fileName.c_str(), "wb");
  if (file && data && len) {
    fwrite(data, 1, len, file);
    fclose(file);

    if (callback_) {
      callback_(callbackCtx_, fileName.c_str());
    }
  } else {
    if (file) fclose(file);
  }
  AImage_delete(image);
}


================================================
FILE: camera/basic/src/main/cpp/image_reader.h
================================================
/*
 * Copyright (C) 2017 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 CAMERA_IMAGE_READER_H
#define CAMERA_IMAGE_READER_H
#include <media/NdkImageReader.h>

#include <functional>
/*
 * ImageFormat:
 *     A Data Structure to communicate resolution between camera and ImageReader
 */
struct ImageFormat {
  int32_t width;
  int32_t height;

  int32_t format;  // Through out this demo, the format is fixed to
                   // YUV_420 format
};

class ImageReader {
 public:
  /**
   * Ctor and Dtor()
   */
  explicit ImageReader(ImageFormat* res, enum AIMAGE_FORMATS format);

  ~ImageReader();

  /**
   * Report cached ANativeWindow, which was used to create camera's capture
   * session output.
   */
  ANativeWindow* GetNativeWindow(void);

  /**
   * Retrieve Image on the top of Reader's queue
   */
  AImage* GetNextImage(void);

  /**
   * Retrieve Image on the back of Reader's queue, dropping older images
   */
  AImage* GetLatestImage(void);

  /**
   * Delete Image
   * @param image {@link AImage} instance to be deleted
   */
  void DeleteImage(AImage* image);

  /**
   * AImageReader callback handler. Called by AImageReader when a frame is
   * captured
   * (Internal function, not to be called by clients)
   */
  void ImageCallback(AImageReader* reader);

  /**
   * DisplayImage()
   *   Present camera image to the given display buffer. Avaliable image is
   * converted
   *   to display buffer format. Supported display format:
   *      WINDOW_FORMAT_RGBX_8888
   *      WINDOW_FORMAT_RGBA_8888
   *   @param buf {@link ANativeWindow_Buffer} for image to display to.
   *   @param image a {@link AImage} instance, source of image conversion.
   *            it will be deleted via {@link AImage_delete}
   *   @return true on success, false on failure
   */
  bool DisplayImage(ANativeWindow_Buffer* buf, AImage* image);
  /**
   * Configure the rotation angle necessary to apply to
   * Camera image when presenting: all rotations should be accumulated:
   *    CameraSensorOrientation + Android Device Native Orientation +
   *    Human Rotation (rotated degree related to Phone native orientation
   */
  void SetPresentRotation(int32_t angle);

  /**
   * regsiter a callback function for client to be notified that jpeg already
   * written out.
   * @param ctx is client context when callback is invoked
   * @param callback is the actual callback function
   */
  void RegisterCallback(void* ctx,
                        std::function<void(void* ctx, const char* fileName)>);

 private:
  int32_t presentRotation_;
  AImageReader* reader_;

  std::function<void(void* ctx, const char* fileName)> callback_;
  void* callbackCtx_;

  void PresentImage(ANativeWindow_Buffer* buf, AImage* image);
  void PresentImage90(ANativeWindow_Buffer* buf, AImage* image);
  void PresentImage180(ANativeWindow_Buffer* buf, AImage* image);
  void PresentImage270(ANativeWindow_Buffer* buf, AImage* image);

  void WriteFile(AImage* image);
};

#endif  // CAMERA_IMAGE_READER_H


================================================
FILE: camera/basic/src/main/cpp/libndk_camera.map.txt
================================================
LIBNDK_CAMERA {
  global:
    ANativeActivity_onCreate;
    JNI_OnLoad;
  local:
    *;
};


================================================
FILE: camera/basic/src/main/java/com/sample/camera/basic/CameraActivity.java
================================================
/*
 * Copyright (C) 2017 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.
 */
package com.sample.camera.basic;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.NativeActivity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import static android.hardware.camera2.CameraMetadata.LENS_FACING_BACK;

import java.util.Arrays;

class CameraSeekBar {
    int _progress;
    long _min, _max, _absVal;
    SeekBar _seekBar;
    TextView _sliderPrompt;
    CameraSeekBar() {
        _progress = 0;
        _min = _max = _absVal  = 0;
    }

    CameraSeekBar(SeekBar seekBar, TextView textView, long min, long max, long val) {
        _seekBar = seekBar;
        _sliderPrompt = textView;
        _min = min;
        _max = max;
        _absVal = val;

        if(_min != _max) {
            _progress = (int) ((_absVal - _min) * _seekBar.getMax() / (_max - _min));
            seekBar.setProgress(_progress);
            updateProgress(_progress);
        } else {
            _progress = 0;
            seekBar.setEnabled(false);
        }
    }

    public boolean isSupported() {
        return (_min != _max);
    }
    public void updateProgress(int progress) {
        if (!isSupported())
            return;

        _progress = progress;
        _absVal = (progress * ( _max - _min )) / _seekBar.getMax() + _min;
        int val = (progress * (_seekBar.getWidth() - 2 * _seekBar.getThumbOffset())) / _seekBar.getMax();
        _sliderPrompt.setText("" + _absVal);
        _sliderPrompt.setX(_seekBar.getX() + val + _seekBar.getThumbOffset() / 2);
    }
    public int getProgress() {
        return _progress;
    }
    public void updateAbsProgress(long val) {
        if (!isSupported())
            return;
        int progress = (int)((val - _min) * _seekBar.getMax() / (_max - _min));
        updateProgress(progress);
    }
    public long getAbsProgress() {
        return _absVal;
    }
}

public class CameraActivity extends NativeActivity
        implements ActivityCompat.OnRequestPermissionsResultCallback {
    volatile CameraActivity _savedInstance;
    PopupWindow _popupWindow;
    ImageButton _takePhoto;
    CameraSeekBar _exposure, _sensitivity;
    long[] _initParams;

    private final String DBG_TAG = "NDK-CAMERA-BASIC";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(DBG_TAG, "OnCreate()");
        // new initialization here... request for permission
        _savedInstance  = this;

        setImmersiveSticky();
        View decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener
                (new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        setImmersiveSticky();
                    }
                });
    }

    private boolean isCamera2Device() {
        CameraManager camMgr = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
        boolean camera2Dev = true;
        try {
            String[] cameraIds = camMgr.getCameraIdList();
            if (cameraIds.length != 0 ) {
                for (String id : cameraIds) {
                    CameraCharacteristics characteristics = camMgr.getCameraCharacteristics(id);
                    int deviceLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                    int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
                    if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY &&
                        facing == LENS_FACING_BACK) {
                        camera2Dev =  false;
                    }
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
            camera2Dev = false;
        }
        return camera2Dev;
    }

    // get current rotation method
    int getRotationDegree() {
        return 90 * ((WindowManager)(getSystemService(WINDOW_SERVICE)))
                .getDefaultDisplay()
                .getRotation();
    }
    @Override
    protected void onResume() {
        super.onResume();
        setImmersiveSticky();
    }
    void setImmersiveSticky() {
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    }

    @Override
    protected void onPause() {
        if (_popupWindow != null && _popupWindow.isShowing()) {
            _popupWindow.dismiss();
            _popupWindow = null;
        }
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private static final int PERMISSION_REQUEST_CODE_CAMERA = 1;
    public void RequestCamera() {
        if(!isCamera2Device()) {
            Log.e(DBG_TAG, "Found legacy camera Device, this sample needs camera2 device");
            return;
        }
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.CAMERA
        ) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.CAMERA},
                    PERMISSION_REQUEST_CODE_CAMERA
            );
            return;
        }
        notifyCameraPermission(true);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (requestCode != PERMISSION_REQUEST_CODE_CAMERA) {
            // The permissions request isn't ours.
            super.onRequestPermissionsResult(requestCode,
                                             permissions,
                                             grantResults);
            return;
        }

        if (permissions.length == 0) {
            // https://developer.android.com/reference/androidx/core/app/ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(int,java.lang.String[],int[])
            //
            // Note: It is possible that the permissions request interaction with the user is
            // interrupted. In this case you will receive empty permissions and results arrays which
            // should be treated as a cancellation.
            //
            // The docs aren't clear about *why* it might be canceled, so it's not clear what we
            // should do here other than restart the request.
            RequestCamera();
            return;
        }

        boolean granted = Arrays.stream(grantResults)
                .allMatch(element -> element == PackageManager.PERMISSION_GRANTED);
        if (!granted) {
            logDeniedPermissions(permissions, grantResults);
        }
        notifyCameraPermission(granted);
    }

    private void logDeniedPermissions(
            @NonNull String[] requestedPermissions,
            @NonNull int[] grantResults
    ) {
        if (requestedPermissions.length != grantResults.length) {
            throw new IllegalArgumentException(
                    String.format(
                            "requestedPermissions.length (%d) != grantResults.length (%d)",
                            requestedPermissions.length,
                            grantResults.length
                    )
            );
        }

        for (int i = 0; i < requestedPermissions.length; i++) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                Log.i(DBG_TAG, requestedPermissions[i] + " DENIED");
            }
        }
    }

    /**
     * params[] exposure and sensitivity init values in (min, max, curVa) tuple
     *   0: exposure min
     *   1: exposure max
     *   2: exposure val
     *   3: sensitivity min
     *   4: sensitivity max
     *   5: sensitivity val
     */
    @SuppressLint("InflateParams")
    public void EnableUI(final long[] params)
    {
        // make our own copy
        _initParams = new long[params.length];
        System.arraycopy(params, 0, _initParams, 0, params.length);

        runOnUiThread(new Runnable()  {
            @Override
            public void run()  {
                try {
                    if (_popupWindow != null) {
                        _popupWindow.dismiss();
                    }
                    LayoutInflater layoutInflater
                            = (LayoutInflater) getBaseContext()
                            .getSystemService(LAYOUT_INFLATER_SERVICE);
                    View popupView = layoutInflater.inflate(R.layout.widgets, null);
                    _popupWindow = new PopupWindow(
                            popupView,
                            WindowManager.LayoutParams.MATCH_PARENT,
                            WindowManager.LayoutParams.WRAP_CONTENT);

                    RelativeLayout mainLayout = new RelativeLayout(_savedInstance);
                    ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(
                            -1, -1);
                    params.setMargins(0, 0, 0, 0);
                    _savedInstance.setContentView(mainLayout, params);

                    // Show our UI over NativeActivity window
                    _popupWindow.showAtLocation(mainLayout, Gravity.BOTTOM | Gravity.START, 0, 0);
                    _popupWindow.update();

                    _takePhoto = (ImageButton) popupView.findViewById(R.id.takePhoto);
                    _takePhoto.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            TakePhoto();
                        }
                    });
                    _takePhoto.setEnabled(true);
                    (popupView.findViewById(R.id.exposureLabel)).setEnabled(true);
                    (popupView.findViewById(R.id.sensitivityLabel)).setEnabled(true);

                    SeekBar seekBar = (SeekBar) popupView.findViewById(R.id.exposure_seekbar);
                    _exposure = new CameraSeekBar(seekBar,
                            (TextView) popupView.findViewById(R.id.exposureVal),
                            _initParams[0], _initParams[1], _initParams[2]);
                    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                        @Override
                        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                            _exposure.updateProgress(progress);
                            OnExposureChanged(_exposure.getAbsProgress());
                        }

                        @Override
                        public void onStartTrackingTouch(SeekBar seekBar) {
                        }

                        @Override
                        public void onStopTrackingTouch(SeekBar seekBar) {
                        }
                    });
                    seekBar = ((SeekBar) popupView.findViewById(R.id.sensitivity_seekbar));
                    _sensitivity = new CameraSeekBar(seekBar,
                            (TextView) popupView.findViewById(R.id.sensitivityVal),
                            _initParams[3], _initParams[4], _initParams[5]);
                    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                        @Override
                        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                            _sensitivity.updateProgress(progress);
                            OnSensitivityChanged(_sensitivity.getAbsProgress());
                        }

                        @Override
                        public void onStartTrackingTouch(SeekBar seekBar) {
                        }

                        @Override
                        public void onStopTrackingTouch(SeekBar seekBar) {
                        }
                    });
                } catch (WindowManager.BadTokenException e) {
                    // UI error out, ignore and continue
                    Log.e(DBG_TAG, "UI Exception Happened: " + e.getMessage());
                }
            }});
    }
    /**
      Called from Native side to notify that a photo is taken
     */
    public void OnPhotoTaken(String fileName) {
        final String name = fileName;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(),
                        "Photo saved to " + name, Toast.LENGTH_SHORT).show();
            }
        });
    }

    native static void notifyCameraPermission(boolean granted);
    native static void TakePhoto();
    native void OnExposureChanged(long exposure);
    native void OnSensitivityChanged(long sensitivity);

    static {
        System.loadLibrary("ndk_camera");
    }
}



================================================
FILE: camera/basic/src/main/res/layout/widgets.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    android:orientation="vertical" >


    <TextView
        android:id="@+id/exposureLabel"
        android:text="Exposure"
        android:textColor="#FFFF00"
        android:textSize="20sp"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="60dp"
        android:layout_above="@+id/sensitivityLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/exposureVal"
        android:text="0"
        android:textColor="#FFFF00"
        android:textSize="16sp"
        android:layout_toRightOf="@+id/exposureLabel"
        android:layout_above="@+id/exposureLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <SeekBar
        android:id="@+id/exposure_seekbar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/exposureLabel"
        android:layout_toRightOf="@+id/exposureLabel"
        android:minHeight="2dip"
        android:maxHeight="2dip"
        android:max="100" />
    <TextView
        android:id="@+id/sensitivityLabel"
        android:text="Sensitivity"
        android:textColor="#FFFF00"
        android:textSize="20sp"
        android:layout_alignParentLeft="true"
        android:layout_above="@+id/takePhoto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/sensitivityVal"
        android:text="0"
        android:textColor="#FFFF00"
        android:textSize="16sp"
        android:layout_toRightOf="@+id/sensitivityLabel"
        android:layout_above="@+id/sensitivityLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <SeekBar
        android:id="@+id/sensitivity_seekbar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/sensitivityLabel"
        android:layout_alignTop="@+id/sensitivityLabel"
        android:minHeight="2dip"
        android:maxHeight="2dip"
        android:max="100"/>
    <ImageButton
        android:id="@+id/takePhoto"
        android:layout_width="80dp"
        android:layout_height="60dp"
        android:layout_gravity="center_horizontal"
        android:src = "@drawable/camera_button"
        android:background="@android:color/transparent"
        android:adjustViewBounds ="true"
        android:scaleType="fitCenter"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="60dp"/>
</RelativeLayout>


================================================
FILE: camera/basic/src/main/res/values/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">NDKCamera</string>
</resources>


================================================
FILE: camera/camera-utils/build.gradle.kts
================================================
plugins {
    id("ndksamples.android.library")
}

android {
    namespace = "com.android.ndk.samples.camera.utils"

    defaultConfig {
        minSdk = 24
    }

    externalNativeBuild {
        cmake {
            path = file("src/main/cpp/CMakeLists.txt")
        }
    }

    buildFeatures {
        prefabPublishing = true
    }

    prefab {
        create("camera-utils") {
            headers = "src/main/cpp/include"
        }
    }
}


================================================
FILE: camera/camera-utils/src/main/cpp/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.22.1)
project(CameraCommon LANGUAGES CXX)

include(AppLibrary)

add_app_library(camera-utils
    STATIC
    camera_utils.cpp
)

target_include_directories(camera-utils PUBLIC include)
target_link_libraries(camera-utils PUBLIC log)


================================================
FILE: camera/camera-utils/src/main/cpp/camera_utils.cpp
================================================
/*
 * Copyright (C) 2017 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 "ndksamples/camera/camera_utils.h"

#include <camera/NdkCameraManager.h>
#include <media/NdkImage.h>

#include <cinttypes>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>

#include "ndksamples/camera/native_debug.h"

#define UKNOWN_TAG "UNKNOW_TAG"
#define MAKE_PAIR(val) std::make_pair(val, #val)
template <typename T>
const char* GetPairStr(T key, std::vector<std::pair<T, const char*>>& store) {
  typedef typename std::vector<std::pair<T, const char*>>::iterator iterator;
  for (iterator it = store.begin(); it != store.end(); ++it) {
    if (it->first == key) {
      return it->second;
    }
  }
  LOGW("(%#08x) : UNKNOWN_TAG for %s", key, typeid(store[0].first).name());
  return UKNOWN_TAG;
}

/*
 * camera_status_t error translation
 */
using ERROR_PAIR = std::pair<camera_status_t, const char*>;
static std::vector<ERROR_PAIR> errorInfo{
    MAKE_PAIR(ACAMERA_OK),
    MAKE_PAIR(ACAMERA_ERROR_UNKNOWN),
    MAKE_PAIR(ACAMERA_ERROR_INVALID_PARAMETER),
    MAKE_PAIR(ACAMERA_ERROR_CAMERA_DISCONNECTED),
    MAKE_PAIR(ACAMERA_ERROR_NOT_ENOUGH_MEMORY),
    MAKE_PAIR(ACAMERA_ERROR_METADATA_NOT_FOUND),
    MAKE_PAIR(ACAMERA_ERROR_CAMERA_DEVICE),
    MAKE_PAIR(ACAMERA_ERROR_CAMERA_SERVICE),
    MAKE_PAIR(ACAMERA_ERROR_SESSION_CLOSED),
    MAKE_PAIR(ACAMERA_ERROR_INVALID_OPERATION),
    MAKE_PAIR(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL),
    MAKE_PAIR(ACAMERA_ERROR_CAMERA_IN_USE),
    MAKE_PAIR(ACAMERA_ERROR_MAX_CAMERA_IN_USE),
    MAKE_PAIR(ACAMERA_ERROR_CAMERA_DISABLED),
    MAKE_PAIR(ACAMERA_ERROR_PERMISSION_DENIED),
};
const char* GetErrorStr(camera_status_t err) {
  return GetPairStr<camera_status_t>(err, errorInfo);
}

/*
 * camera_metadata_tag_t translation. Useful to look at available tags
 * on the underneath platform
 */
using TAG_PAIR = std::pair<acamera_metadata_tag_t, const char*>;
static std::vector<TAG_PAIR> tagInfo{
    MAKE_PAIR(ACAMERA_COLOR_CORRECTION_MODE),
    MAKE_PAIR(ACAMERA_COLOR_CORRECTION_TRANSFORM),
    MAKE_PAIR(ACAMERA_COLOR_CORRECTION_GAINS),
    MAKE_PAIR(ACAMERA_COLOR_CORRECTION_ABERRATION_MODE),
    MAKE_PAIR(ACAMERA_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES),
    MAKE_PAIR(ACAMERA_COLOR_CORRECTION_END),
    MAKE_PAIR(ACAMERA_CONTROL_AE_ANTIBANDING_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_AE_EXPOSURE_COMPENSATION),
    MAKE_PAIR(ACAMERA_CONTROL_AE_LOCK),
    MAKE_PAIR(ACAMERA_CONTROL_AE_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_AE_REGIONS),
    MAKE_PAIR(ACAMERA_CONTROL_AE_TARGET_FPS_RANGE),
    MAKE_PAIR(ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER),
    MAKE_PAIR(ACAMERA_CONTROL_AF_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_AF_REGIONS),
    MAKE_PAIR(ACAMERA_CONTROL_AF_TRIGGER),
    MAKE_PAIR(ACAMERA_CONTROL_AWB_LOCK),
    MAKE_PAIR(ACAMERA_CONTROL_AWB_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_AWB_REGIONS),
    MAKE_PAIR(ACAMERA_CONTROL_CAPTURE_INTENT),
    MAKE_PAIR(ACAMERA_CONTROL_EFFECT_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_SCENE_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE),
    MAKE_PAIR(ACAMERA_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_AE_AVAILABLE_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES),
    MAKE_PAIR(ACAMERA_CONTROL_AE_COMPENSATION_RANGE),
    MAKE_PAIR(ACAMERA_CONTROL_AE_COMPENSATION_STEP),
    MAKE_PAIR(ACAMERA_CONTROL_AF_AVAILABLE_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_AVAILABLE_EFFECTS),
    MAKE_PAIR(ACAMERA_CONTROL_AVAILABLE_SCENE_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_AWB_AVAILABLE_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_MAX_REGIONS),
    MAKE_PAIR(ACAMERA_CONTROL_AE_STATE),
    MAKE_PAIR(ACAMERA_CONTROL_AF_STATE),
    MAKE_PAIR(ACAMERA_CONTROL_AWB_STATE),
    MAKE_PAIR(ACAMERA_CONTROL_AE_LOCK_AVAILABLE),
    MAKE_PAIR(ACAMERA_CONTROL_AWB_LOCK_AVAILABLE),
    MAKE_PAIR(ACAMERA_CONTROL_AVAILABLE_MODES),
    MAKE_PAIR(ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE),
    MAKE_PAIR(ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST),
    MAKE_PAIR(ACAMERA_CONTROL_END),
    MAKE_PAIR(ACAMERA_EDGE_MODE),
    MAKE_PAIR(ACAMERA_EDGE_AVAILABLE_EDGE_MODES),
    MAKE_PAIR(ACAMERA_EDGE_END),
    MAKE_PAIR(ACAMERA_FLASH_MODE),
    MAKE_PAIR(ACAMERA_FLASH_STATE),
    MAKE_PAIR(ACAMERA_FLASH_END),
    MAKE_PAIR(ACAMERA_FLASH_INFO_AVAILABLE),
    MAKE_PAIR(ACAMERA_FLASH_INFO_END),
    MAKE_PAIR(ACAMERA_HOT_PIXEL_MODE),
    MAKE_PAIR(ACAMERA_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES),
    MAKE_PAIR(ACAMERA_HOT_PIXEL_END),
    MAKE_PAIR(ACAMERA_JPEG_GPS_COORDINATES),
    MAKE_PAIR(ACAMERA_JPEG_GPS_PROCESSING_METHOD),
    MAKE_PAIR(ACAMERA_JPEG_GPS_TIMESTAMP),
    MAKE_PAIR(ACAMERA_JPEG_ORIENTATION),
    MAKE_PAIR(ACAMERA_JPEG_QUALITY),
    MAKE_PAIR(ACAMERA_JPEG_THUMBNAIL_QUALITY),
    MAKE_PAIR(ACAMERA_JPEG_THUMBNAIL_SIZE),
    MAKE_PAIR(ACAMERA_JPEG_AVAILABLE_THUMBNAIL_SIZES),
    MAKE_PAIR(ACAMERA_JPEG_END),
    MAKE_PAIR(ACAMERA_LENS_APERTURE),
    MAKE_PAIR(ACAMERA_LENS_FILTER_DENSITY),
    MAKE_PAIR(ACAMERA_LENS_FOCAL_LENGTH),
    MAKE_PAIR(ACAMERA_LENS_FOCUS_DISTANCE),
    MAKE_PAIR(ACAMERA_LENS_OPTICAL_STABILIZATION_MODE),
    MAKE_PAIR(ACAMERA_LENS_FACING),
    MAKE_PAIR(ACAMERA_LENS_POSE_ROTATION),
    MAKE_PAIR(ACAMERA_LENS_POSE_TRANSLATION),
    MAKE_PAIR(ACAMERA_LENS_FOCUS_RANGE),
    MAKE_PAIR(ACAMERA_LENS_STATE),
    MAKE_PAIR(ACAMERA_LENS_INTRINSIC_CALIBRATION),
    MAKE_PAIR(ACAMERA_LENS_RADIAL_DISTORTION),
    MAKE_PAIR(ACAMERA_LENS_END),

    MAKE_PAIR(ACAMERA_LENS_INFO_AVAILABLE_APERTURES),
    MAKE_PAIR(ACAMERA_LENS_INFO_AVAILABLE_FILTER_DENSITIES),
    MAKE_PAIR(ACAMERA_LENS_INFO_AVAILABLE_FOCAL_LENGTHS),
    MAKE_PAIR(ACAMERA_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION),
    MAKE_PAIR(ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE),
    MAKE_PAIR(ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE),
    MAKE_PAIR(ACAMERA_LENS_INFO_SHADING_MAP_SIZE),
    MAKE_PAIR(ACAMERA_LENS_INFO_FOCUS_DISTANCE_CALIBRATION),
    MAKE_PAIR(ACAMERA_LENS_INFO_END),

    MAKE_PAIR(ACAMERA_NOISE_REDUCTION_MODE),
    MAKE_PAIR(ACAMERA_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES),
    MAKE_PAIR(ACAMERA_NOISE_REDUCTION_END),

    MAKE_PAIR(ACAMERA_REQUEST_MAX_NUM_OUTPUT_STREAMS),
    MAKE_PAIR(ACAMERA_REQUEST_PIPELINE_DEPTH),
    MAKE_PAIR(ACAMERA_REQUEST_PIPELINE_MAX_DEPTH),
    MAKE_PAIR(ACAMERA_REQUEST_PARTIAL_RESULT_COUNT),
    MAKE_PAIR(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES),
    MAKE_PAIR(ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS),
    MAKE_PAIR(ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS),
    MAKE_PAIR(ACAMERA_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS),
    MAKE_PAIR(ACAMERA_REQUEST_END),

    MAKE_PAIR(ACAMERA_SCALER_CROP_REGION),
    MAKE_PAIR(ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM),
    MAKE_PAIR(ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS),
    MAKE_PAIR(ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS),
    MAKE_PAIR(ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS),
    MAKE_PAIR(ACAMERA_SCALER_CROPPING_TYPE),
    MAKE_PAIR(ACAMERA_SCALER_END),

    MAKE_PAIR(ACAMERA_SENSOR_EXPOSURE_TIME),
    MAKE_PAIR(ACAMERA_SENSOR_FRAME_DURATION),
    MAKE_PAIR(ACAMERA_SENSOR_SENSITIVITY),
    MAKE_PAIR(ACAMERA_SENSOR_REFERENCE_ILLUMINANT1),
    MAKE_PAIR(ACAMERA_SENSOR_REFERENCE_ILLUMINANT2),
    MAKE_PAIR(ACAMERA_SENSOR_CALIBRATION_TRANSFORM1),
    MAKE_PAIR(ACAMERA_SENSOR_CALIBRATION_TRANSFORM2),
    MAKE_PAIR(ACAMERA_SENSOR_COLOR_TRANSFORM1),
    MAKE_PAIR(ACAMERA_SENSOR_COLOR_TRANSFORM2),
    MAKE_PAIR(ACAMERA_SENSOR_FORWARD_MATRIX1),
    MAKE_PAIR(ACAMERA_SENSOR_FORWARD_MATRIX2),
    MAKE_PAIR(ACAMERA_SENSOR_BLACK_LEVEL_PATTERN),
    MAKE_PAIR(ACAMERA_SENSOR_MAX_ANALOG_SENSITIVITY),
    MAKE_PAIR(ACAMERA_SENSOR_ORIENTATION),
    MAKE_PAIR(ACAMERA_SENSOR_TIMESTAMP),
    MAKE_PAIR(ACAMERA_SENSOR_NEUTRAL_COLOR_POINT),
    MAKE_PAIR(ACAMERA_SENSOR_NOISE_PROFILE),
    MAKE_PAIR(ACAMERA_SENSOR_GREEN_SPLIT),
    MAKE_PAIR(ACAMERA_SENSOR_TEST_PATTERN_DATA),
    MAKE_PAIR(ACAMERA_SENSOR_TEST_PATTERN_MODE),
    MAKE_PAIR(ACAMERA_SENSOR_AVAILABLE_TEST_PATTERN_MODES),
    MAKE_PAIR(ACAMERA_SENSOR_ROLLING_SHUTTER_SKEW),
    MAKE_PAIR(ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS),
    MAKE_PAIR(ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL),
    MAKE_PAIR(ACAMERA_SENSOR_DYNAMIC_WHITE_LEVEL),
    MAKE_PAIR(ACAMERA_SENSOR_END),

    MAKE_PAIR(ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_PHYSICAL_SIZE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_WHITE_LEVEL),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_LENS_SHADING_APPLIED),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE),
    MAKE_PAIR(ACAMERA_SENSOR_INFO_END),

    MAKE_PAIR(ACAMERA_SHADING_MODE),
    MAKE_PAIR(ACAMERA_SHADING_AVAILABLE_MODES),
    MAKE_PAIR(ACAMERA_SHADING_END),

    MAKE_PAIR(ACAMERA_STATISTICS_FACE_DETECT_MODE),
    MAKE_PAIR(ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE),
    MAKE_PAIR(ACAMERA_STATISTICS_FACE_IDS),
    MAKE_PAIR(ACAMERA_STATISTICS_FACE_LANDMARKS),
    MAKE_PAIR(ACAMERA_STATISTICS_FACE_RECTANGLES),
    MAKE_PAIR(ACAMERA_STATISTICS_FACE_SCORES),
    MAKE_PAIR(ACAMERA_STATISTICS_LENS_SHADING_MAP),
    MAKE_PAIR(ACAMERA_STATISTICS_SCENE_FLICKER),
    MAKE_PAIR(ACAMERA_STATISTICS_HOT_PIXEL_MAP),
    MAKE_PAIR(ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE),
    MAKE_PAIR(ACAMERA_STATISTICS_END),

    MAKE_PAIR(ACAMERA_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES),
    MAKE_PAIR(ACAMERA_STATISTICS_INFO_MAX_FACE_COUNT),
    MAKE_PAIR(ACAMERA_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES),
    MAKE_PAIR(ACAMERA_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES),
    MAKE_PAIR(ACAMERA_STATISTICS_INFO_END),

    MAKE_PAIR(ACAMERA_TONEMAP_CURVE_BLUE),
    MAKE_PAIR(ACAMERA_TONEMAP_CURVE_GREEN),
    MAKE_PAIR(ACAMERA_TONEMAP_CURVE_RED),
    MAKE_PAIR(ACAMERA_TONEMAP_MODE),
    MAKE_PAIR(ACAMERA_TONEMAP_MAX_CURVE_POINTS),
    MAKE_PAIR(ACAMERA_TONEMAP_AVAILABLE_TONE_MAP_MODES),
    MAKE_PAIR(ACAMERA_TONEMAP_GAMMA),
    MAKE_PAIR(ACAMERA_TONEMAP_PRESET_CURVE),
    MAKE_PAIR(ACAMERA_TONEMAP_END),

    MAKE_PAIR(ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL),
    MAKE_PAIR(ACAMERA_INFO_END),
    MAKE_PAIR(ACAMERA_BLACK_LEVEL_LOCK),
    MAKE_PAIR(ACAMERA_BLACK_LEVEL_END),
    MAKE_PAIR(ACAMERA_SYNC_FRAME_NUMBER),
    MAKE_PAIR(ACAMERA_SYNC_MAX_LATENCY),
    MAKE_PAIR(ACAMERA_SYNC_END),
    MAKE_PAIR(ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS),

    MAKE_PAIR(ACAMERA_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS),
    MAKE_PAIR(ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS),
    MAKE_PAIR(ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE),
    MAKE_PAIR(ACAMERA_DEPTH_END),
};
const char* GetTagStr(acamera_metadata_tag_t tag) {
  return GetPairStr<acamera_metadata_tag_t>(tag, tagInfo);
}

using FORMAT_PAIR = std::pair<int, const char*>;
static std::vector<FORMAT_PAIR> formatInfo{
    MAKE_PAIR(AIMAGE_FORMAT_YUV_420_888),
    MAKE_PAIR(AIMAGE_FORMAT_JPEG),
    MAKE_PAIR(AIMAGE_FORMAT_RAW16),
    MAKE_PAIR(AIMAGE_FORMAT_RAW_PRIVATE),
    MAKE_PAIR(AIMAGE_FORMAT_RAW10),
    MAKE_PAIR(AIMAGE_FORMAT_RAW12),
    MAKE_PAIR(AIMAGE_FORMAT_DEPTH16),
    MAKE_PAIR(AIMAGE_FORMAT_DEPTH_POINT_CLOUD),
    MAKE_PAIR(AIMAGE_FORMAT_PRIVATE),
};
const char* GetFormatStr(int fmt) { return GetPairStr<int>(fmt, formatInfo); }

void PrintMetadataTags(int32_t entries, const uint32_t* pTags) {
  LOGI("MetadataTag (start):");
  for (int32_t idx = 0; idx < entries; ++idx) {
    const char* name =
        GetTagStr(static_cast<acamera_metadata_tag_t>(pTags[idx]));
    LOGI("(%#08x) : %s", pTags[idx], name);
  }
  LOGI("MetadataTag (end)");
}

void PrintLensFacing(ACameraMetadata_const_entry& lens) {
  ASSERT(lens.tag == ACAMERA_LENS_FACING, "Wrong tag(%#x) of %s to %s",
         lens.tag, GetTagStr((acamera_metadata_tag_t)lens.tag), __FUNCTION__);
  LOGI("LensFacing: tag(%#x), type(%d), count(%d), val(%#x)", lens.tag,
       lens.type, lens.count, lens.data.u8[0]);
}

/*
 * Stream_Configuration is in format of:
 *    format, width, height, input?
 *    ACAMERA_TYPE_INT32 type
 */
void PrintStreamConfigurations(ACameraMetadata_const_entry& val) {
#define MODE_LABLE "ModeInfo:"
  const char* tagName = GetTagStr(static_cast<acamera_metadata_tag_t>(val.tag));
  ASSERT(!(val.count & 0x3), "STREAM_CONFIGURATION (%d) should multiple of 4",
         val.count);
  ASSERT(val.type == ACAMERA_TYPE_INT32,
         "STREAM_CONFIGURATION TYPE(%d) is not ACAMERA_TYPE_INT32(1)",
         val.type);
  LOGI("%s -- %s:", tagName, MODE_LABLE);
  for (uint32_t i = 0; i < val.count; i += 4) {
    LOGI("%s: %08d x %08d  %s", GetFormatStr(val.data.i32[i]),
         val.data.i32[i + 1], val.data.i32[i + 2],
         val.data.i32[i + 3] ? "INPUT" : "OUTPUT");
  }
#undef MODE_LABLE
}
void PrintTagVal(const char* printLabel, ACameraMetadata_const_entry& val) {
  if (val.tag == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS) {
    PrintStreamConfigurations(val);
    return;
  }
  const char* name = GetTagStr(static_cast<acamera_metadata_tag_t>(val.tag));
  for (uint32_t i = 0; i < val.count; ++i) {
    switch (val.type) {
      case ACAMERA_TYPE_INT32:
        LOGI("%s %s: %08d", printLabel, name, val.data.i32[i]);
        break;
      case ACAMERA_TYPE_BYTE:
        LOGI("%s %s: %#02x", printLabel, name, val.data.u8[i]);
        break;
      case ACAMERA_TYPE_INT64:
        LOGI("%s %s: %" PRIu64, printLabel, name, (int64_t)val.data.i64[i]);
        break;
      case ACAMERA_TYPE_FLOAT:
        LOGI("%s %s: %f", printLabel, name, val.data.f[i]);
        break;
      case ACAMERA_TYPE_DOUBLE:
        LOGI("%s %s: %" PRIx64, printLabel, name, val.data.i64[i]);
        break;
      case ACAMERA_TYPE_RATIONAL:
        LOGI("%s %s: %08x, %08x", printLabel, name, val.data.r[i].numerator,
             val.data.r[i].denominator);
        break;
      default:
        ASSERT(false, "Unknown tag value type: %d", val.type);
    }
  }
}

/*
 * PrintCamera():
 *   Enumerate existing camera and its metadata.
 */
void PrintCameras(ACameraManager* cmrMgr) {
  if (!cmrMgr) return;

  ACameraIdList* cameraIds = nullptr;
  camera_status_t status = ACameraManager_getCameraIdList(cmrMgr, &cameraIds);
  LOGI("camera Status = %d, %s", status, GetErrorStr(status));

  for (int i = 0; i < cameraIds->numCameras; ++i) {
    const char* id = cameraIds->cameraIds[i];
    LOGI("=====cameraId = %d, cameraName = %s=====", i, id);
    ACameraMetadata* metadataObj;
    CALL_MGR(getCameraCharacteristics(cmrMgr, id, &metadataObj));

    int32_t count = 0;
    const uint32_t* tags = nullptr;
    ACameraMetadata_getAllTags(metadataObj, &count, &tags);

    for (int tagIdx = 0; tagIdx < count; ++tagIdx) {
      ACameraMetadata_const_entry val = {};
      camera_status_t status =
          ACameraMetadata_getConstEntry(metadataObj, tags[tagIdx], &val);
      if (status != ACAMERA_OK) {
        LOGW("Unsupported Tag: %s",
             GetTagStr(static_cast<acamera_metadata_tag_t>(tags[tagIdx])));
        continue;
      }

      PrintTagVal("Camera Tag:", val);

      if (ACAMERA_LENS_FACING == tags[tagIdx]) {
        PrintLensFacing(val);
      }
    }
    ACameraMetadata_free(metadataObj);
  }

  ACameraManager_deleteCameraIdList(cameraIds);
}

void PrintRequestMetadata(ACaptureRequest* req) {
  if (!req) return;
  int32_t count;
  const uint32_t* tags;
  CALL_REQUEST(getAllTags(req, &count, &tags));
  for (int32_t idx = 0; idx < count; ++idx) {
    ACameraMetadata_const_entry val;
    CALL_REQUEST(getConstEntry(req, tags[idx], &val));
    const char* name =
        GetTagStr(static_cast<acamera_metadata_tag_t>(tags[idx]));

    for (uint32_t i = 0; i < val.count; ++i) {
      switch (val.type) {
        case ACAMERA_TYPE_INT32:
          LOGI("Capture Tag %s: %08d", name, val.data.i32[i]);
          break;
        case ACAMERA_TYPE_BYTE:
          LOGI("Capture Tag %s: %#08x", name, val.data.u8[i]);
          break;
        case ACAMERA_TYPE_INT64:
          LOGI("Capture Tag %s: %" PRIu64, name, (int64_t)val.data.i64[i]);
          break;
        case ACAMERA_TYPE_FLOAT:
          LOGI("Capture Tag %s: %f", name, val.data.f[i]);
          break;
        case ACAMERA_TYPE_DOUBLE:
          LOGI("Capture Tag %s: %" PRIx64, name, val.data.i64[i]);
          break;
        case ACAMERA_TYPE_RATIONAL:
          LOGI("Capture Tag %s: %08x, %08x", name, val.data.r[i].numerator,
               val.data.r[i].denominator);
          break;
        default:
          ASSERT(false, "Unknown tag value type: %d", val.type);
      }
    }
  }
}

/*
 * CameraDevice error state translation, used in
 *     ACameraDevice_ErrorStateCallback
 */
using DEV_ERROR_PAIR = std::pair<int, const char*>;
static std::vector<DEV_ERROR_PAIR> devErrors{
    MAKE_PAIR(ERROR_CAMERA_IN_USE),   MAKE_PAIR(ERROR_MAX_CAMERAS_IN_USE),
    MAKE_PAIR(ERROR_CAMERA_DISABLED), MAKE_PAIR(ERROR_CAMERA_DEVICE),
    MAKE_PAIR(ERROR_CAMERA_SERVICE),
};

const char* GetCameraDeviceErrorStr(int err) {
  return GetPairStr<int>(err, devErrors);
}
void PrintCameraDeviceError(int err) {
  LOGI("CameraDeviceError(%#x): %s", err, GetCameraDeviceErrorStr(err));
}


================================================
FILE: camera/camera-utils/src/main/cpp/include/ndksamples/camera/camera_utils.h
================================================
/*
 * Copyright (C) 2017 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 __CAMERA_CAMERA_UT
Download .txt
gitextract_om9grlgx/

├── .clang-format
├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .google/
│   └── packaging.yaml
├── .pre-commit-config.yaml
├── ARCHITECTURE.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── REFERENCE.md
├── audio-echo/
│   └── README.md
├── base/
│   ├── .gitignore
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── cpp/
│               ├── CMakeLists.txt
│               ├── include/
│               │   └── base/
│               │       ├── errno_restorer.h
│               │       ├── logging.h
│               │       └── macros.h
│               ├── logging.cpp
│               └── logging_splitters.h
├── bitmap-plasma/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── jni.cpp
│               │   ├── libplasma.map.txt
│               │   ├── plasma.cpp
│               │   └── plasma.h
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── plasma/
│               │               └── Plasma.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── build-logic/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── android/
│                       └── ndk/
│                           └── samples/
│                               └── buildlogic/
│                                   ├── AndroidApplicationConventionPlugin.kt
│                                   ├── AndroidLibraryConventionPlugin.kt
│                                   ├── KotlinConventionPlugin.kt
│                                   └── Versions.kt
├── build.gradle
├── camera/
│   ├── README.md
│   ├── basic/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── android_main.cpp
│   │           │   ├── camera_engine.cpp
│   │           │   ├── camera_engine.h
│   │           │   ├── camera_listeners.cpp
│   │           │   ├── camera_manager.cpp
│   │           │   ├── camera_manager.h
│   │           │   ├── camera_ui.cpp
│   │           │   ├── image_reader.cpp
│   │           │   ├── image_reader.h
│   │           │   └── libndk_camera.map.txt
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           └── camera/
│   │           │               └── basic/
│   │           │                   └── CameraActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               └── values/
│   │                   └── strings.xml
│   ├── camera-utils/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── cpp/
│   │               ├── CMakeLists.txt
│   │               ├── camera_utils.cpp
│   │               └── include/
│   │                   └── ndksamples/
│   │                       └── camera/
│   │                           ├── camera_utils.h
│   │                           └── native_debug.h
│   └── texture-view/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── android_main.cpp
│               │   ├── camera_engine.cpp
│               │   ├── camera_engine.h
│               │   ├── camera_listeners.cpp
│               │   ├── camera_manager.cpp
│               │   ├── camera_manager.h
│               │   └── libcamera_textureview.map.txt
│               ├── java/
│               │   └── com/
│               │       └── sample/
│               │           └── textureview/
│               │               └── ViewActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── activity_main.xml
│                   └── values/
│                       └── strings.xml
├── cmake/
│   └── AppLibrary.cmake
├── endless-tunnel/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── android_main.cpp
│               │   ├── anim.cpp
│               │   ├── anim.hpp
│               │   ├── ascii_to_geom.cpp
│               │   ├── ascii_to_geom.hpp
│               │   ├── common.hpp
│               │   ├── data/
│               │   │   ├── alphabet.inl
│               │   │   ├── ascii_art.inl
│               │   │   ├── blurb.inl
│               │   │   ├── cube_geom.inl
│               │   │   ├── our_shader.inl
│               │   │   ├── strings.inl
│               │   │   └── tunnel_geom.inl
│               │   ├── dialog_scene.cpp
│               │   ├── dialog_scene.hpp
│               │   ├── engine.hpp
│               │   ├── game_consts.hpp
│               │   ├── glm/
│               │   │   ├── CMakeLists.txt
│               │   │   ├── common.hpp
│               │   │   ├── detail/
│               │   │   │   ├── _features.hpp
│               │   │   │   ├── _fixes.hpp
│               │   │   │   ├── _literals.hpp
│               │   │   │   ├── _noise.hpp
│               │   │   │   ├── _swizzle.hpp
│               │   │   │   ├── _swizzle_func.hpp
│               │   │   │   ├── _vectorize.hpp
│               │   │   │   ├── func_common.hpp
│               │   │   │   ├── func_common.inl
│               │   │   │   ├── func_exponential.hpp
│               │   │   │   ├── func_exponential.inl
│               │   │   │   ├── func_geometric.hpp
│               │   │   │   ├── func_geometric.inl
│               │   │   │   ├── func_integer.hpp
│               │   │   │   ├── func_integer.inl
│               │   │   │   ├── func_matrix.hpp
│               │   │   │   ├── func_matrix.inl
│               │   │   │   ├── func_noise.hpp
│               │   │   │   ├── func_noise.inl
│               │   │   │   ├── func_packing.hpp
│               │   │   │   ├── func_packing.inl
│               │   │   │   ├── func_trigonometric.hpp
│               │   │   │   ├── func_trigonometric.inl
│               │   │   │   ├── func_vector_relational.hpp
│               │   │   │   ├── func_vector_relational.inl
│               │   │   │   ├── glm.cpp
│               │   │   │   ├── hint.hpp
│               │   │   │   ├── intrinsic_common.hpp
│               │   │   │   ├── intrinsic_common.inl
│               │   │   │   ├── intrinsic_exponential.hpp
│               │   │   │   ├── intrinsic_exponential.inl
│               │   │   │   ├── intrinsic_geometric.hpp
│               │   │   │   ├── intrinsic_geometric.inl
│               │   │   │   ├── intrinsic_integer.hpp
│               │   │   │   ├── intrinsic_integer.inl
│               │   │   │   ├── intrinsic_matrix.hpp
│               │   │   │   ├── intrinsic_matrix.inl
│               │   │   │   ├── intrinsic_trigonometric.hpp
│               │   │   │   ├── intrinsic_trigonometric.inl
│               │   │   │   ├── intrinsic_vector_relational.hpp
│               │   │   │   ├── intrinsic_vector_relational.inl
│               │   │   │   ├── precision.hpp
│               │   │   │   ├── precision.inl
│               │   │   │   ├── setup.hpp
│               │   │   │   ├── type_float.hpp
│               │   │   │   ├── type_gentype.hpp
│               │   │   │   ├── type_gentype.inl
│               │   │   │   ├── type_half.hpp
│               │   │   │   ├── type_half.inl
│               │   │   │   ├── type_int.hpp
│               │   │   │   ├── type_mat.hpp
│               │   │   │   ├── type_mat.inl
│               │   │   │   ├── type_mat2x2.hpp
│               │   │   │   ├── type_mat2x2.inl
│               │   │   │   ├── type_mat2x3.hpp
│               │   │   │   ├── type_mat2x3.inl
│               │   │   │   ├── type_mat2x4.hpp
│               │   │   │   ├── type_mat2x4.inl
│               │   │   │   ├── type_mat3x2.hpp
│               │   │   │   ├── type_mat3x2.inl
│               │   │   │   ├── type_mat3x3.hpp
│               │   │   │   ├── type_mat3x3.inl
│               │   │   │   ├── type_mat3x4.hpp
│               │   │   │   ├── type_mat3x4.inl
│               │   │   │   ├── type_mat4x2.hpp
│               │   │   │   ├── type_mat4x2.inl
│               │   │   │   ├── type_mat4x3.hpp
│               │   │   │   ├── type_mat4x3.inl
│               │   │   │   ├── type_mat4x4.hpp
│               │   │   │   ├── type_mat4x4.inl
│               │   │   │   ├── type_vec.hpp
│               │   │   │   ├── type_vec.inl
│               │   │   │   ├── type_vec1.hpp
│               │   │   │   ├── type_vec1.inl
│               │   │   │   ├── type_vec2.hpp
│               │   │   │   ├── type_vec2.inl
│               │   │   │   ├── type_vec3.hpp
│               │   │   │   ├── type_vec3.inl
│               │   │   │   ├── type_vec4.hpp
│               │   │   │   └── type_vec4.inl
│               │   │   ├── exponential.hpp
│               │   │   ├── ext.hpp
│               │   │   ├── fwd.hpp
│               │   │   ├── geometric.hpp
│               │   │   ├── glm.hpp
│               │   │   ├── gtc/
│               │   │   │   ├── constants.hpp
│               │   │   │   ├── constants.inl
│               │   │   │   ├── epsilon.hpp
│               │   │   │   ├── epsilon.inl
│               │   │   │   ├── matrix_access.hpp
│               │   │   │   ├── matrix_access.inl
│               │   │   │   ├── matrix_integer.hpp
│               │   │   │   ├── matrix_inverse.hpp
│               │   │   │   ├── matrix_inverse.inl
│               │   │   │   ├── matrix_transform.hpp
│               │   │   │   ├── matrix_transform.inl
│               │   │   │   ├── noise.hpp
│               │   │   │   ├── noise.inl
│               │   │   │   ├── packing.hpp
│               │   │   │   ├── packing.inl
│               │   │   │   ├── quaternion.hpp
│               │   │   │   ├── quaternion.inl
│               │   │   │   ├── random.hpp
│               │   │   │   ├── random.inl
│               │   │   │   ├── reciprocal.hpp
│               │   │   │   ├── reciprocal.inl
│               │   │   │   ├── type_precision.hpp
│               │   │   │   ├── type_precision.inl
│               │   │   │   ├── type_ptr.hpp
│               │   │   │   ├── type_ptr.inl
│               │   │   │   ├── ulp.hpp
│               │   │   │   └── ulp.inl
│               │   │   ├── gtx/
│               │   │   │   ├── associated_min_max.hpp
│               │   │   │   ├── associated_min_max.inl
│               │   │   │   ├── bit.hpp
│               │   │   │   ├── bit.inl
│               │   │   │   ├── closest_point.hpp
│               │   │   │   ├── closest_point.inl
│               │   │   │   ├── color_space.hpp
│               │   │   │   ├── color_space.inl
│               │   │   │   ├── color_space_YCoCg.hpp
│               │   │   │   ├── color_space_YCoCg.inl
│               │   │   │   ├── compatibility.hpp
│               │   │   │   ├── compatibility.inl
│               │   │   │   ├── component_wise.hpp
│               │   │   │   ├── component_wise.inl
│               │   │   │   ├── constants.hpp
│               │   │   │   ├── dual_quaternion.hpp
│               │   │   │   ├── dual_quaternion.inl
│               │   │   │   ├── epsilon.hpp
│               │   │   │   ├── euler_angles.hpp
│               │   │   │   ├── euler_angles.inl
│               │   │   │   ├── extend.hpp
│               │   │   │   ├── extend.inl
│               │   │   │   ├── extented_min_max.hpp
│               │   │   │   ├── extented_min_max.inl
│               │   │   │   ├── fast_exponential.hpp
│               │   │   │   ├── fast_exponential.inl
│               │   │   │   ├── fast_square_root.hpp
│               │   │   │   ├── fast_square_root.inl
│               │   │   │   ├── fast_trigonometry.hpp
│               │   │   │   ├── fast_trigonometry.inl
│               │   │   │   ├── gradient_paint.hpp
│               │   │   │   ├── gradient_paint.inl
│               │   │   │   ├── handed_coordinate_space.hpp
│               │   │   │   ├── handed_coordinate_space.inl
│               │   │   │   ├── inertia.hpp
│               │   │   │   ├── inertia.inl
│               │   │   │   ├── int_10_10_10_2.hpp
│               │   │   │   ├── int_10_10_10_2.inl
│               │   │   │   ├── integer.hpp
│               │   │   │   ├── integer.inl
│               │   │   │   ├── intersect.hpp
│               │   │   │   ├── intersect.inl
│               │   │   │   ├── io.hpp
│               │   │   │   ├── io.inl
│               │   │   │   ├── log_base.hpp
│               │   │   │   ├── log_base.inl
│               │   │   │   ├── matrix_cross_product.hpp
│               │   │   │   ├── matrix_cross_product.inl
│               │   │   │   ├── matrix_interpolation.hpp
│               │   │   │   ├── matrix_interpolation.inl
│               │   │   │   ├── matrix_major_storage.hpp
│               │   │   │   ├── matrix_major_storage.inl
│               │   │   │   ├── matrix_operation.hpp
│               │   │   │   ├── matrix_operation.inl
│               │   │   │   ├── matrix_query.hpp
│               │   │   │   ├── matrix_query.inl
│               │   │   │   ├── matrix_transform_2d.hpp
│               │   │   │   ├── matrix_transform_2d.inl
│               │   │   │   ├── mixed_product.hpp
│               │   │   │   ├── mixed_product.inl
│               │   │   │   ├── multiple.hpp
│               │   │   │   ├── multiple.inl
│               │   │   │   ├── noise.hpp
│               │   │   │   ├── norm.hpp
│               │   │   │   ├── norm.inl
│               │   │   │   ├── normal.hpp
│               │   │   │   ├── normal.inl
│               │   │   │   ├── normalize_dot.hpp
│               │   │   │   ├── normalize_dot.inl
│               │   │   │   ├── number_precision.hpp
│               │   │   │   ├── number_precision.inl
│               │   │   │   ├── optimum_pow.hpp
│               │   │   │   ├── optimum_pow.inl
│               │   │   │   ├── orthonormalize.hpp
│               │   │   │   ├── orthonormalize.inl
│               │   │   │   ├── perpendicular.hpp
│               │   │   │   ├── perpendicular.inl
│               │   │   │   ├── polar_coordinates.hpp
│               │   │   │   ├── polar_coordinates.inl
│               │   │   │   ├── projection.hpp
│               │   │   │   ├── projection.inl
│               │   │   │   ├── quaternion.hpp
│               │   │   │   ├── quaternion.inl
│               │   │   │   ├── random.hpp
│               │   │   │   ├── raw_data.hpp
│               │   │   │   ├── raw_data.inl
│               │   │   │   ├── reciprocal.hpp
│               │   │   │   ├── rotate_normalized_axis.hpp
│               │   │   │   ├── rotate_normalized_axis.inl
│               │   │   │   ├── rotate_vector.hpp
│               │   │   │   ├── rotate_vector.inl
│               │   │   │   ├── scalar_relational.hpp
│               │   │   │   ├── scalar_relational.inl
│               │   │   │   ├── simd_mat4.hpp
│               │   │   │   ├── simd_mat4.inl
│               │   │   │   ├── simd_quat.hpp
│               │   │   │   ├── simd_quat.inl
│               │   │   │   ├── simd_vec4.hpp
│               │   │   │   ├── simd_vec4.inl
│               │   │   │   ├── spline.hpp
│               │   │   │   ├── spline.inl
│               │   │   │   ├── std_based_type.hpp
│               │   │   │   ├── std_based_type.inl
│               │   │   │   ├── string_cast.hpp
│               │   │   │   ├── string_cast.inl
│               │   │   │   ├── transform.hpp
│               │   │   │   ├── transform.inl
│               │   │   │   ├── transform2.hpp
│               │   │   │   ├── transform2.inl
│               │   │   │   ├── ulp.hpp
│               │   │   │   ├── unsigned_int.hpp
│               │   │   │   ├── unsigned_int.inl
│               │   │   │   ├── vec1.hpp
│               │   │   │   ├── vec1.inl
│               │   │   │   ├── vector_angle.hpp
│               │   │   │   ├── vector_angle.inl
│               │   │   │   ├── vector_query.hpp
│               │   │   │   ├── vector_query.inl
│               │   │   │   ├── wrap.hpp
│               │   │   │   └── wrap.inl
│               │   │   ├── integer.hpp
│               │   │   ├── mat2x2.hpp
│               │   │   ├── mat2x3.hpp
│               │   │   ├── mat2x4.hpp
│               │   │   ├── mat3x2.hpp
│               │   │   ├── mat3x3.hpp
│               │   │   ├── mat3x4.hpp
│               │   │   ├── mat4x2.hpp
│               │   │   ├── mat4x3.hpp
│               │   │   ├── mat4x4.hpp
│               │   │   ├── matrix.hpp
│               │   │   ├── packing.hpp
│               │   │   ├── trigonometric.hpp
│               │   │   ├── vec2.hpp
│               │   │   ├── vec3.hpp
│               │   │   ├── vec4.hpp
│               │   │   ├── vector_relational.hpp
│               │   │   └── virtrev/
│               │   │       └── xstream.hpp
│               │   ├── indexbuf.cpp
│               │   ├── indexbuf.hpp
│               │   ├── input_util.cpp
│               │   ├── input_util.hpp
│               │   ├── jni_util.cpp
│               │   ├── jni_util.hpp
│               │   ├── joystick-support.hpp
│               │   ├── libgame.map.txt
│               │   ├── native_engine.cpp
│               │   ├── native_engine.hpp
│               │   ├── obstacle.cpp
│               │   ├── obstacle.hpp
│               │   ├── obstacle_generator.cpp
│               │   ├── obstacle_generator.hpp
│               │   ├── our_key_codes.hpp
│               │   ├── our_shader.cpp
│               │   ├── our_shader.hpp
│               │   ├── play_scene.cpp
│               │   ├── play_scene.hpp
│               │   ├── scene.cpp
│               │   ├── scene.hpp
│               │   ├── scene_manager.cpp
│               │   ├── scene_manager.hpp
│               │   ├── sfxman.cpp
│               │   ├── sfxman.hpp
│               │   ├── shader.cpp
│               │   ├── shader.hpp
│               │   ├── shape_renderer.cpp
│               │   ├── shape_renderer.hpp
│               │   ├── simplegeom.hpp
│               │   ├── tex_quad.cpp
│               │   ├── tex_quad.hpp
│               │   ├── text_renderer.cpp
│               │   ├── text_renderer.hpp
│               │   ├── texture.cpp
│               │   ├── texture.hpp
│               │   ├── ui_scene.cpp
│               │   ├── ui_scene.hpp
│               │   ├── util.cpp
│               │   ├── util.hpp
│               │   ├── vertexbuf.cpp
│               │   ├── vertexbuf.hpp
│               │   ├── welcome_scene.cpp
│               │   └── welcome_scene.hpp
│               └── res/
│                   └── values/
│                       ├── strings.xml
│                       └── styles.xml
├── exceptions/
│   ├── .gitignore
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── exception_helper.cpp
│               │   ├── exception_helper.h
│               │   ├── libexceptions.map.txt
│               │   └── native-lib.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── exceptions/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   ├── values-night/
│                   │   └── themes.xml
│                   └── xml/
│                       ├── backup_rules.xml
│                       └── data_extraction_rules.xml
├── gles3jni/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── RendererES2.cpp
│               │   ├── RendererES3.cpp
│               │   ├── gles3jni.cpp
│               │   ├── gles3jni.h
│               │   └── libgles3jni.map.txt
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── gles3jni/
│               │               ├── GLES3JNIActivity.java
│               │               ├── GLES3JNILib.java
│               │               └── GLES3JNIView.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── gradle/
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── hello-gl2/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── gl_code.cpp
│               │   └── libgl2jni.map.txt
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── gl2jni/
│               │               ├── GL2JNIActivity.java
│               │               ├── GL2JNILib.java
│               │               └── GL2JNIView.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── hello-jni/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── hello-jni.cpp
│               │   └── libhello-jni.map.txt
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── hellojni/
│               │               └── HelloJni.kt
│               └── res/
│                   ├── layout/
│                   │   └── activity_hello_jni.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
├── hello-jniCallback/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── hello-jnicallback.cpp
│               │   └── libhello-jnicallback.map.txt
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── hellojnicallback/
│               │               ├── JniHandler.java
│               │               └── MainActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
├── hello-oboe/
│   └── README.md
├── hello-vulkan/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── hellovk.h
│               │   ├── libhellovkjni.map.txt
│               │   └── vk_main.cpp
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── hellovk/
│               │               └── VulkanActivity.kt
│               ├── res/
│               │   └── values/
│               │       ├── strings.xml
│               │       └── themes.xml
│               └── shaders/
│                   ├── shader.frag
│                   └── shader.vert
├── native-activity/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libnative-activity.map.txt
│               │   └── main.cpp
│               └── res/
│                   └── values/
│                       └── strings.xml
├── native-audio/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── assets/
│               │   └── README.txt
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── android_clip.h
│               │   ├── hello_clip.h
│               │   ├── libnative-audio-jni.map.txt
│               │   └── native-audio-jni.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── nativeaudio/
│               │               └── NativeAudio.java
│               └── res/
│                   ├── layout/
│                   │   └── main.xml
│                   └── values/
│                       └── strings.xml
├── native-codec/
│   ├── README.md
│   └── app/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libnative-codec-jni.map.txt
│               │   ├── looper.cpp
│               │   ├── looper.h
│               │   └── native-codec-jni.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── nativecodec/
│               │               ├── MyGLSurfaceView.java
│               │               └── NativeCodec.java
│               └── res/
│                   ├── layout/
│                   │   └── main.xml
│                   └── values/
│                       └── strings.xml
├── native-media/
│   └── README.md
├── native-midi/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── AndroidDebug.h
│               │   ├── AppMidiManager.cpp
│               │   ├── CMakeLists.txt
│               │   ├── MainActivity.cpp
│               │   ├── MidiSpec.h
│               │   └── libnative_midi.map.txt
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── nativemidi/
│               │               ├── AppMidiManager.java
│               │               ├── MainActivity.java
│               │               ├── MidiDataHelper.java
│               │               └── MidiSpec.java
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
├── nn-samples/
│   └── README.md
├── orderfile/
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── demo.orderfile
│               │   ├── liborderfiledemo.map.txt
│               │   └── orderfile.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── orderfiledemo/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   └── values-night/
│                       └── themes.xml
├── prefab/
│   └── README.md
├── san-angeles/
│   └── README.md
├── sanitizers/
│   ├── .gitignore
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           ├── asan/
│           │   └── resources/
│           │       └── .gitignore
│           ├── hwasan/
│           │   └── resources/
│           │       └── lib/
│           │           └── arm64-v8a/
│           │               └── wrap.sh
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libsanitizers.map.txt
│               │   └── native-lib.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── sanitizers/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   ├── values-night/
│                   │   └── themes.xml
│                   └── xml/
│                       ├── backup_rules.xml
│                       └── data_extraction_rules.xml
├── sensor-graph/
│   ├── README.md
│   └── accelerometer/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── assets/
│               │   ├── shader.glslf
│               │   └── shader.glslv
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── libaccelerometergraph.map.txt
│               │   └── sensorgraph.cpp
│               ├── java/
│               │   └── com/
│               │       └── android/
│               │           └── accelerometergraph/
│               │               ├── AccelerometerGraphActivity.java
│               │               └── AccelerometerGraphJNI.java
│               └── res/
│                   └── values/
│                       └── strings.xml
├── settings.gradle
├── teapots/
│   ├── .gitignore
│   ├── README.md
│   ├── choreographer-30fps/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── ShaderPlain.fsh
│   │           │       └── VS_ShaderPlain.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── ChoreographerNativeActivity.cpp
│   │           │   ├── TeapotRenderer.cpp
│   │           │   ├── TeapotRenderer.h
│   │           │   ├── libChoreographerNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── choreographer/
│   │           │           │   ├── ChoreographerApplication.java
│   │           │           │   └── ChoreographerNativeActivity.java
│   │           │           └── helper/
│   │           │               └── NDKHelper.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   ├── classic-teapot/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── ShaderPlain.fsh
│   │           │       └── VS_ShaderPlain.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── TeapotNativeActivity.cpp
│   │           │   ├── TeapotRenderer.cpp
│   │           │   ├── TeapotRenderer.h
│   │           │   ├── libTeapotNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── helper/
│   │           │           │   └── NDKHelper.java
│   │           │           └── teapot/
│   │           │               ├── TeapotApplication.java
│   │           │               └── TeapotNativeActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   ├── common/
│   │   └── ndk_helper/
│   │       ├── CMakeLists.txt
│   │       ├── GLContext.cpp
│   │       ├── GLContext.h
│   │       ├── JNIHelper.cpp
│   │       ├── JNIHelper.h
│   │       ├── NDKHelper.h
│   │       ├── gestureDetector.cpp
│   │       ├── gestureDetector.h
│   │       ├── gl3stub.c
│   │       ├── gl3stub.cpp
│   │       ├── gl3stub.h
│   │       ├── interpolator.cpp
│   │       ├── interpolator.h
│   │       ├── perfMonitor.cpp
│   │       ├── perfMonitor.h
│   │       ├── sensorManager.cpp
│   │       ├── sensorManager.h
│   │       ├── shader.cpp
│   │       ├── shader.h
│   │       ├── tapCamera.cpp
│   │       ├── tapCamera.h
│   │       ├── vecmath.cpp
│   │       └── vecmath.h
│   ├── image-decoder/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── 2DTexture.fsh
│   │           │       ├── 2DTexture.vsh
│   │           │       ├── Cubemap.fsh
│   │           │       ├── Cubemap.vsh
│   │           │       ├── ShaderPlain.fsh
│   │           │       └── VS_ShaderPlain.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── ImageDecoderRender.cpp
│   │           │   ├── ImageDecoderRender.h
│   │           │   ├── TeapotNativeActivity.cpp
│   │           │   ├── TeapotRenderer.cpp
│   │           │   ├── TeapotRenderer.h
│   │           │   ├── Texture.cpp
│   │           │   ├── Texture.h
│   │           │   ├── android_debug.h
│   │           │   ├── libImageDecoderNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── helper/
│   │           │           │   └── NDKHelper.java
│   │           │           └── imagedecoder/
│   │           │               ├── TeapotApplication.java
│   │           │               └── TeapotNativeActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   ├── more-teapots/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── Shaders/
│   │           │       ├── ShaderPlain.fsh
│   │           │       ├── ShaderPlainES3.fsh
│   │           │       ├── VS_ShaderPlain.vsh
│   │           │       └── VS_ShaderPlainES3.vsh
│   │           ├── cpp/
│   │           │   ├── CMakeLists.txt
│   │           │   ├── MoreTeapotsNativeActivity.cpp
│   │           │   ├── MoreTeapotsRenderer.cpp
│   │           │   ├── MoreTeapotsRenderer.h
│   │           │   ├── libMoreTeapotsNativeActivity.map.txt
│   │           │   └── teapot.inl
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── sample/
│   │           │           ├── helper/
│   │           │           │   └── NDKHelper.java
│   │           │           └── moreteapots/
│   │           │               ├── MoreTeapotsApplication.java
│   │           │               └── MoreTeapotsNativeActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── widgets.xml
│   │               ├── values/
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               ├── values-v11/
│   │               │   └── styles.xml
│   │               └── values-v14/
│   │                   └── styles.xml
│   └── textured-teapot/
│       ├── README.md
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── assets/
│               │   ├── Shaders/
│               │   │   ├── 2DTexture.fsh
│               │   │   ├── 2DTexture.vsh
│               │   │   ├── Cubemap.fsh
│               │   │   ├── Cubemap.vsh
│               │   │   ├── ShaderPlain.fsh
│               │   │   └── VS_ShaderPlain.vsh
│               │   └── Textures/
│               │       ├── back.tga
│               │       ├── bottom.tga
│               │       ├── front.tga
│               │       ├── left.tga
│               │       ├── right.tga
│               │       └── top.tga
│               ├── cpp/
│               │   ├── AssetUtil.cpp
│               │   ├── AssetUtil.h
│               │   ├── CMakeLists.txt
│               │   ├── TeapotNativeActivity.cpp
│               │   ├── TeapotRenderer.cpp
│               │   ├── TeapotRenderer.h
│               │   ├── Texture.cpp
│               │   ├── Texture.h
│               │   ├── TexturedTeapotRender.cpp
│               │   ├── TexturedTeapotRender.h
│               │   ├── android_debug.h
│               │   ├── libTexturedTeapotNativeActivity.map.txt
│               │   └── teapot.inl
│               ├── java/
│               │   └── com/
│               │       └── sample/
│               │           ├── helper/
│               │           │   └── NDKHelper.java
│               │           └── texturedteapot/
│               │               ├── TeapotApplication.java
│               │               └── TeapotNativeActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── widgets.xml
│                   ├── values/
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   ├── values-v11/
│                   │   └── styles.xml
│                   └── values-v14/
│                       └── styles.xml
├── unit-test/
│   ├── .gitignore
│   ├── README.md
│   └── app/
│       ├── .gitignore
│       ├── build.gradle
│       ├── proguard-rules.pro
│       └── src/
│           ├── androidTest/
│           │   └── java/
│           │       └── com/
│           │           └── example/
│           │               └── unittest/
│           │                   └── NativeTests.kt
│           └── main/
│               ├── AndroidManifest.xml
│               ├── cpp/
│               │   ├── CMakeLists.txt
│               │   ├── adder.cpp
│               │   ├── adder.h
│               │   ├── adder_test.cpp
│               │   ├── libunittest.map.txt
│               │   └── native-lib.cpp
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── unittest/
│               │               └── MainActivity.kt
│               └── res/
│                   ├── drawable/
│                   │   └── ic_launcher_background.xml
│                   ├── drawable-v24/
│                   │   └── ic_launcher_foreground.xml
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── mipmap-anydpi-v26/
│                   │   ├── ic_launcher.xml
│                   │   └── ic_launcher_round.xml
│                   ├── values/
│                   │   ├── colors.xml
│                   │   ├── strings.xml
│                   │   └── themes.xml
│                   ├── values-night/
│                   │   └── themes.xml
│                   └── xml/
│                       ├── backup_rules.xml
│                       └── data_extraction_rules.xml
└── vectorization/
    ├── .gitignore
    ├── README.md
    ├── build.gradle.kts
    └── src/
        └── main/
            ├── AndroidManifest.xml
            ├── cpp/
            │   ├── CMakeLists.txt
            │   ├── auto_vectorization.h
            │   ├── benchmark.cpp
            │   ├── benchmark.h
            │   ├── clang_vector.h
            │   ├── jni.cpp
            │   ├── libapp.map.txt
            │   ├── matrix.h
            │   └── omp_simd.h
            ├── java/
            │   └── com/
            │       └── android/
            │           └── ndk/
            │               └── samples/
            │                   └── vectorization/
            │                       ├── VectorizationActivity.kt
            │                       └── ui/
            │                           └── theme/
            │                               ├── Color.kt
            │                               ├── Theme.kt
            │                               └── Type.kt
            └── res/
                ├── drawable/
                │   └── ic_launcher_background.xml
                ├── drawable-v24/
                │   └── ic_launcher_foreground.xml
                ├── mipmap-anydpi-v26/
                │   ├── ic_launcher.xml
                │   └── ic_launcher_round.xml
                └── values/
                    ├── colors.xml
                    ├── strings.xml
                    └── themes.xml
Download .txt
SYMBOL INDEX (1555 symbols across 287 files)

FILE: base/src/main/cpp/include/base/errno_restorer.h
  function namespace (line 21) | namespace ndksamples::base {

FILE: base/src/main/cpp/include/base/logging.h
  function namespace (line 92) | namespace ndksamples::base {
  function namespace (line 459) | namespace std {  // NOLINT(cert-dcl58-cpp)

FILE: base/src/main/cpp/logging.cpp
  type ndksamples::base (line 41) | namespace ndksamples::base {
    function LogIdTolog_id_t (line 53) | static int32_t LogIdTolog_id_t(LogId log_id) {
    function LogSeverityToPriority (line 69) | static int32_t LogSeverityToPriority(LogSeverity severity) {
    function LogFunction (line 88) | static LogFunction& Logger() {
    function AbortFunction (line 93) | static AbortFunction& Aborter() {
    function SetDefaultTag (line 106) | void SetDefaultTag(const std::string_view tag) {
    function DefaultAborter (line 122) | void DefaultAborter(const char* abort_message) {
    function LogdLogChunk (line 127) | static void LogdLogChunk(LogId id, LogSeverity severity, const char* tag,
    function InitLogging (line 148) | void InitLogging(const std::optional<std::string_view> default_tag,
    function LogFunction (line 174) | LogFunction SetLogger(LogFunction&& logger) {
    function AbortFunction (line 180) | AbortFunction SetAborter(AbortFunction&& aborter) {
    class LogMessageData (line 188) | class LogMessageData {
      method LogMessageData (line 190) | LogMessageData(const char* file, unsigned int line, LogSeverity seve...
      method GetLineNumber (line 202) | unsigned int GetLineNumber() const { return line_number_; }
      method LogSeverity (line 204) | LogSeverity GetSeverity() const { return severity_; }
      method GetError (line 208) | int GetError() const { return error_; }
      method ToString (line 212) | std::string ToString() const { return buffer_.str(); }
    function LogSeverity (line 276) | LogSeverity GetMinimumLogSeverity() { return gMinimumLogSeverity; }
    function ShouldLog (line 278) | bool ShouldLog(LogSeverity severity, const char*) {
    function LogSeverity (line 282) | LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {

FILE: base/src/main/cpp/logging_splitters.h
  function namespace (line 28) | namespace ndksamples::base {

FILE: bitmap-plasma/app/src/main/cpp/jni.cpp
  function JNIEXPORT (line 9) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: bitmap-plasma/app/src/main/cpp/plasma.cpp
  function now_ms (line 36) | static double now_ms(void) {
  function init_angles (line 99) | static void init_angles(void) {
  function Fixed (line 107) | static __inline__ Fixed angle_sin(Angle a) {
  function Fixed (line 111) | static __inline__ Fixed fixed_sin(Fixed f) {
  function make565 (line 125) | static uint16_t make565(int red, int green, int blue) {
  function init_palette (line 130) | static void init_palette(void) {
  function palette_from_fixed (line 154) | static __inline__ uint16_t palette_from_fixed(Fixed x) {
  function init_tables (line 163) | static void init_tables(void) {
  function fill_plasma (line 168) | static void fill_plasma(AndroidBitmapInfo* info, void* pixels, double t) {
  function stats_init (line 264) | static void stats_init(Stats* s) {
  function stats_startFrame (line 271) | static void stats_startFrame(Stats* s) { s->frameTime = now_ms(); }
  function stats_endFrame (line 273) | static void stats_endFrame(Stats* s) {
  function RenderPlasma (line 330) | void RenderPlasma(JNIEnv* env, jclass, jobject bitmap, jlong time_ms) {

FILE: bitmap-plasma/app/src/main/java/com/example/plasma/Plasma.java
  class Plasma (line 29) | public class Plasma extends Activity
    method onCreate (line 32) | @Override
  class PlasmaView (line 52) | @SuppressLint("ViewConstructor")
    method renderPlasma (line 58) | private static native void renderPlasma(Bitmap  bitmap, long time_ms);
    method PlasmaView (line 60) | public PlasmaView(Context context, int width, int height) {
    method onDraw (line 66) | @Override protected void onDraw(Canvas canvas) {
    method onSizeChanged (line 73) | @Override protected void onSizeChanged(int w, int h, int oldw, int old...

FILE: camera/basic/src/main/cpp/android_main.cpp
  function CameraEngine (line 25) | CameraEngine* GetAppEngine(void) {
  function ProcessAndroidCmd (line 35) | static void ProcessAndroidCmd(struct android_app* app, int32_t cmd) {
  function android_main (line 60) | void android_main(struct android_app* state) {

FILE: camera/basic/src/main/cpp/camera_engine.cpp
  type android_app (line 48) | struct android_app

FILE: camera/basic/src/main/cpp/camera_engine.h
  function class (line 32) | class CameraEngine {

FILE: camera/basic/src/main/cpp/camera_listeners.cpp
  function OnCameraAvailable (line 30) | void OnCameraAvailable(void* ctx, const char* id) {
  function OnCameraUnavailable (line 33) | void OnCameraUnavailable(void* ctx, const char* id) {
  function ACameraManager_AvailabilityCallbacks (line 52) | ACameraManager_AvailabilityCallbacks* NDKCamera::GetManagerListener() {
  function OnDeviceStateChanges (line 64) | void OnDeviceStateChanges(void* ctx, ACameraDevice* dev) {
  function OnDeviceErrorChanges (line 68) | void OnDeviceErrorChanges(void* ctx, ACameraDevice* dev, int err) {
  function OnClientSharedAccessPriorityChanged (line 73) | void OnClientSharedAccessPriorityChanged(void*,
  function ACameraDevice_stateCallbacks (line 79) | ACameraDevice_stateCallbacks* NDKCamera::GetDeviceListener() {
  function OnSessionClosed (line 134) | void OnSessionClosed(void* ctx, ACameraCaptureSession* ses) {
  function OnSessionReady (line 139) | void OnSessionReady(void* ctx, ACameraCaptureSession* ses) {
  function OnSessionActive (line 144) | void OnSessionActive(void* ctx, ACameraCaptureSession* ses) {
  function ACameraCaptureSession_stateCallbacks (line 150) | ACameraCaptureSession_stateCallbacks* NDKCamera::GetSessionListener() {
  function SessionCaptureCallback_OnFailed (line 178) | void SessionCaptureCallback_OnFailed(void* context,
  function SessionCaptureCallback_OnSequenceEnd (line 188) | void SessionCaptureCallback_OnSequenceEnd(void* context,
  function SessionCaptureCallback_OnSequenceAborted (line 196) | void SessionCaptureCallback_OnSequenceAborted(void* context,
  function ACameraCaptureSession_captureCallbacks (line 205) | ACameraCaptureSession_captureCallbacks* NDKCamera::GetCaptureCallback() {

FILE: camera/basic/src/main/cpp/camera_manager.cpp
  class DisplayDimension (line 105) | class DisplayDimension {
    method DisplayDimension (line 107) | DisplayDimension(int32_t w, int32_t h) : w_(w), h_(h), portrait_(false) {
    method DisplayDimension (line 115) | DisplayDimension(const DisplayDimension& other) {
    method DisplayDimension (line 121) | DisplayDimension(void) {
    method DisplayDimension (line 126) | DisplayDimension& operator=(const DisplayDimension& other) {
    method IsSameRatio (line 134) | bool IsSameRatio(DisplayDimension& other) {
    method DisplayDimension (line 143) | DisplayDimension operator-(DisplayDimension& other) {
    method Flip (line 147) | void Flip(void) { portrait_ = !portrait_; }
    method IsPortrait (line 148) | bool IsPortrait(void) { return portrait_; }
    method width (line 149) | int32_t width(void) { return w_; }
    method height (line 150) | int32_t height(void) { return h_; }
    method org_width (line 151) | int32_t org_width(void) { return (portrait_ ? h_ : w_); }
    method org_height (line 152) | int32_t org_height(void) { return (portrait_ ? w_ : h_); }

FILE: camera/basic/src/main/cpp/camera_manager.h
  function CaptureSessionState (line 30) | enum class CaptureSessionState : int32_t {

FILE: camera/basic/src/main/cpp/camera_ui.cpp
  function notifyCameraPermission (line 130) | void notifyCameraPermission(JNIEnv*, jclass, jboolean permission) {
  function TakePhoto (line 136) | void TakePhoto(JNIEnv*, jclass) {
  function OnExposureChanged (line 141) | void OnExposureChanged(JNIEnv*, jobject, jlong exposurePercent) {
  function OnSensitivityChanged (line 146) | void OnSensitivityChanged(JNIEnv*, jobject, jlong sensitivity) {
  function JNIEXPORT (line 151) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: camera/basic/src/main/cpp/image_reader.cpp
  function OnImageCallback (line 52) | void OnImageCallback(void* ctx, AImageReader* reader) {
  type AIMAGE_FORMATS (line 59) | enum AIMAGE_FORMATS
  function ANativeWindow (line 101) | ANativeWindow* ImageReader::GetNativeWindow(void) {
  function AImage (line 115) | AImage* ImageReader::GetNextImage(void) {
  function AImage (line 129) | AImage* ImageReader::GetLatestImage(void) {
  function YUV2RGB (line 172) | static inline uint32_t YUV2RGB(int nY, int nU, int nV) {
  type timespec (line 432) | struct timespec
  type tm (line 436) | struct tm

FILE: camera/basic/src/main/cpp/image_reader.h
  type ImageFormat (line 26) | struct ImageFormat {
  function class (line 34) | class ImageReader {

FILE: camera/basic/src/main/java/com/sample/camera/basic/CameraActivity.java
  class CameraSeekBar (line 46) | class CameraSeekBar {
    method CameraSeekBar (line 51) | CameraSeekBar() {
    method CameraSeekBar (line 56) | CameraSeekBar(SeekBar seekBar, TextView textView, long min, long max, ...
    method isSupported (line 73) | public boolean isSupported() {
    method updateProgress (line 76) | public void updateProgress(int progress) {
    method getProgress (line 86) | public int getProgress() {
    method updateAbsProgress (line 89) | public void updateAbsProgress(long val) {
    method getAbsProgress (line 95) | public long getAbsProgress() {
  class CameraActivity (line 100) | public class CameraActivity extends NativeActivity
    method onCreate (line 109) | @Override
    method isCamera2Device (line 127) | private boolean isCamera2Device() {
    method getRotationDegree (line 151) | int getRotationDegree() {
    method onResume (line 156) | @Override
    method setImmersiveSticky (line 161) | void setImmersiveSticky() {
    method onPause (line 171) | @Override
    method onDestroy (line 180) | @Override
    method RequestCamera (line 186) | public void RequestCamera() {
    method onRequestPermissionsResult (line 205) | @Override
    method logDeniedPermissions (line 238) | private void logDeniedPermissions(
    method EnableUI (line 268) | @SuppressLint("InflateParams")
    method OnPhotoTaken (line 359) | public void OnPhotoTaken(String fileName) {
    method notifyCameraPermission (line 370) | native static void notifyCameraPermission(boolean granted);
    method TakePhoto (line 371) | native static void TakePhoto();
    method OnExposureChanged (line 372) | native void OnExposureChanged(long exposure);
    method OnSensitivityChanged (line 373) | native void OnSensitivityChanged(long sensitivity);

FILE: camera/camera-utils/src/main/cpp/camera_utils.cpp
  function PrintMetadataTags (line 288) | void PrintMetadataTags(int32_t entries, const uint32_t* pTags) {
  function PrintLensFacing (line 298) | void PrintLensFacing(ACameraMetadata_const_entry& lens) {
  function PrintStreamConfigurations (line 310) | void PrintStreamConfigurations(ACameraMetadata_const_entry& val) {
  function PrintTagVal (line 326) | void PrintTagVal(const char* printLabel, ACameraMetadata_const_entry& va...
  function PrintCameras (line 363) | void PrintCameras(ACameraManager* cmrMgr) {
  function PrintRequestMetadata (line 402) | void PrintRequestMetadata(ACaptureRequest* req) {
  function PrintCameraDeviceError (line 455) | void PrintCameraDeviceError(int err) {

FILE: camera/texture-view/src/main/cpp/android_main.cpp
  function jlong (line 53) | jlong CreateCamera(JNIEnv* env, jobject, jint width, jint height) {
  function DeleteCamera (line 63) | void DeleteCamera(JNIEnv*, jobject, jlong ndkCameraObj) {
  function jobject (line 87) | jobject GetMinimumCompatiblePreviewSize(JNIEnv* env, jobject,
  function OnPreviewSurfaceCreated (line 107) | void OnPreviewSurfaceCreated(JNIEnv*, jobject, jlong ndkCameraObj,
  function OnPreviewSurfaceDestroyed (line 122) | void OnPreviewSurfaceDestroyed(JNIEnv* env, jobject, jlong ndkCameraObj,
  function JNIEXPORT (line 147) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: camera/texture-view/src/main/cpp/camera_engine.cpp
  function jobject (line 65) | jobject CameraAppEngine::GetSurfaceObject() { return surface_; }
  function ImageFormat (line 71) | const ImageFormat& CameraAppEngine::GetCompatibleCameraRes() const {

FILE: camera/texture-view/src/main/cpp/camera_engine.h
  function class (line 33) | class CameraAppEngine {

FILE: camera/texture-view/src/main/cpp/camera_listeners.cpp
  function OnCameraAvailable (line 30) | void OnCameraAvailable(void* ctx, const char* id) {
  function OnCameraUnavailable (line 33) | void OnCameraUnavailable(void* ctx, const char* id) {
  function ACameraManager_AvailabilityCallbacks (line 52) | ACameraManager_AvailabilityCallbacks* NDKCamera::GetManagerListener() {
  function OnDeviceStateChanges (line 64) | void OnDeviceStateChanges(void* ctx, ACameraDevice* dev) {
  function OnDeviceErrorChanges (line 68) | void OnDeviceErrorChanges(void* ctx, ACameraDevice* dev, int err) {
  function OnClientSharedAccessPriorityChanged (line 73) | void OnClientSharedAccessPriorityChanged(void*,
  function ACameraDevice_stateCallbacks (line 79) | ACameraDevice_stateCallbacks* NDKCamera::GetDeviceListener() {
  function OnSessionClosed (line 134) | void OnSessionClosed(void* ctx, ACameraCaptureSession* ses) {
  function OnSessionReady (line 139) | void OnSessionReady(void* ctx, ACameraCaptureSession* ses) {
  function OnSessionActive (line 144) | void OnSessionActive(void* ctx, ACameraCaptureSession* ses) {
  function ACameraCaptureSession_stateCallbacks (line 150) | ACameraCaptureSession_stateCallbacks* NDKCamera::GetSessionListener() {
  function SessionCaptureCallback_OnFailed (line 178) | void SessionCaptureCallback_OnFailed(void* context,
  function SessionCaptureCallback_OnSequenceEnd (line 188) | void SessionCaptureCallback_OnSequenceEnd(void* context,
  function SessionCaptureCallback_OnSequenceAborted (line 196) | void SessionCaptureCallback_OnSequenceAborted(void* context,
  function ACameraCaptureSession_captureCallbacks (line 205) | ACameraCaptureSession_captureCallbacks* NDKCamera::GetCaptureCallback() {

FILE: camera/texture-view/src/main/cpp/camera_manager.cpp
  class DisplayDimension (line 107) | class DisplayDimension {
    method DisplayDimension (line 109) | DisplayDimension(int32_t w, int32_t h) : w_(w), h_(h), portrait_(false) {
    method DisplayDimension (line 117) | DisplayDimension(const DisplayDimension& other) {
    method DisplayDimension (line 123) | DisplayDimension(void) {
    method DisplayDimension (line 128) | DisplayDimension& operator=(const DisplayDimension& other) {
    method IsSameRatio (line 136) | bool IsSameRatio(DisplayDimension& other) {
    method DisplayDimension (line 145) | DisplayDimension operator-(DisplayDimension& other) {
    method Flip (line 149) | void Flip(void) { portrait_ = !portrait_; }
    method IsPortrait (line 150) | bool IsPortrait(void) { return portrait_; }
    method width (line 151) | int32_t width(void) { return w_; }
    method height (line 152) | int32_t height(void) { return h_; }
    method org_width (line 153) | int32_t org_width(void) { return (portrait_ ? h_ : w_); }
    method org_height (line 154) | int32_t org_height(void) { return (portrait_ ? w_ : h_); }

FILE: camera/texture-view/src/main/cpp/camera_manager.h
  function CaptureSessionState (line 28) | enum class CaptureSessionState : int32_t {

FILE: camera/texture-view/src/main/java/com/sample/textureview/ViewActivity.java
  class ViewActivity (line 42) | public class ViewActivity extends Activity
    method onCreate (line 50) | @Override
    method onWindowFocusChanged (line 62) | @Override
    method isCamera2Device (line 75) | private boolean isCamera2Device() {
    method createTextureView (line 97) | private void createTextureView() {
    method onSurfaceTextureAvailable (line 106) | public void onSurfaceTextureAvailable(SurfaceTexture surface,
    method resizeTextureView (line 117) | private void resizeTextureView(int textureWidth, int textureHeight) {
    method configureTransform (line 137) | void configureTransform(int width, int height) {
    method onSurfaceTextureSizeChanged (line 173) | public void onSurfaceTextureSizeChanged(SurfaceTexture surface,
    method onSurfaceTextureDestroyed (line 177) | public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    method onSurfaceTextureUpdated (line 185) | public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    method RequestCamera (line 190) | public void RequestCamera() {
    method onRequestPermissionsResult (line 202) | @Override
    method createNativeCamera (line 232) | private void createNativeCamera() {
    method createCamera (line 249) | private native long createCamera(int width, int height);
    method getMinimumCompatiblePreviewSize (line 251) | private native Size getMinimumCompatiblePreviewSize(long ndkCamera);
    method onPreviewSurfaceCreated (line 253) | private native void onPreviewSurfaceCreated(long ndkCamera, Surface su...
    method onPreviewSurfaceDestroyed (line 255) | private native void onPreviewSurfaceDestroyed(long ndkCamera, Surface ...
    method deleteCamera (line 257) | private native void deleteCamera(long ndkCamera, Surface surface);

FILE: endless-tunnel/app/src/main/cpp/android_main.cpp
  type android_app (line 20) | struct android_app
  function android_main (line 23) | void android_main(struct android_app* app) {

FILE: endless-tunnel/app/src/main/cpp/anim.cpp
  function RenderBackgroundAnimation (line 20) | void RenderBackgroundAnimation(ShapeRenderer* r) {

FILE: endless-tunnel/app/src/main/cpp/ascii_to_geom.cpp
  function SimpleGeom (line 21) | SimpleGeom* AsciiArtToGeom(const char* art, float scale) {

FILE: endless-tunnel/app/src/main/cpp/dialog_scene.hpp
  class DialogScene (line 25) | class DialogScene : public UiScene {
    method DialogScene (line 65) | DialogScene *SetText(const char *text) {
    method DialogScene (line 70) | DialogScene *SetSingleButton(const char *text, int action) {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/_literals.hpp
  type glm (line 32) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/_noise.hpp
  type glm (line 32) | namespace glm {
    type detail (line 33) | namespace detail {
      function GLM_FUNC_QUALIFIER (line 35) | GLM_FUNC_QUALIFIER T mod289(T const& x) {
      function GLM_FUNC_QUALIFIER (line 41) | GLM_FUNC_QUALIFIER T permute(T const& x) {
      function GLM_FUNC_QUALIFIER (line 46) | GLM_FUNC_QUALIFIER tvec2<T, P> permute(tvec2<T, P> const& x) {
      function GLM_FUNC_QUALIFIER (line 51) | GLM_FUNC_QUALIFIER tvec3<T, P> permute(tvec3<T, P> const& x) {
      function GLM_FUNC_QUALIFIER (line 56) | GLM_FUNC_QUALIFIER tvec4<T, P> permute(tvec4<T, P> const& x) {
      function GLM_FUNC_QUALIFIER (line 67) | GLM_FUNC_QUALIFIER T taylorInvSqrt(T const& r) {
      function GLM_FUNC_QUALIFIER (line 72) | GLM_FUNC_QUALIFIER detail::tvec2<T, P> taylorInvSqrt(
      function GLM_FUNC_QUALIFIER (line 78) | GLM_FUNC_QUALIFIER detail::tvec3<T, P> taylorInvSqrt(
      function GLM_FUNC_QUALIFIER (line 84) | GLM_FUNC_QUALIFIER detail::tvec4<T, P> taylorInvSqrt(
      function GLM_FUNC_QUALIFIER (line 97) | GLM_FUNC_QUALIFIER detail::tvec2<T, P> fade(detail::tvec2<T, P> cons...
      function GLM_FUNC_QUALIFIER (line 102) | GLM_FUNC_QUALIFIER detail::tvec3<T, P> fade(detail::tvec3<T, P> cons...
      function GLM_FUNC_QUALIFIER (line 107) | GLM_FUNC_QUALIFIER detail::tvec4<T, P> fade(detail::tvec4<T, P> cons...

FILE: endless-tunnel/app/src/main/cpp/glm/detail/_swizzle.hpp
  type glm (line 32) | namespace glm {
    type detail (line 33) | namespace detail {
      type _swizzle_base0 (line 36) | struct _swizzle_base0 {
        method GLM_FUNC_QUALIFIER (line 40) | GLM_FUNC_QUALIFIER value_type& elem(size_t i) {
        method GLM_FUNC_QUALIFIER (line 43) | GLM_FUNC_QUALIFIER const value_type& elem(size_t i) const {
      type _swizzle_base1 (line 55) | struct _swizzle_base1 : public _swizzle_base0<T, N> {}
      type _swizzle_base1<T, P, V, E0, E1, -1, -2, 2> (line 58) | struct _swizzle_base1<T, P, V, E0, E1, -1, -2, 2>
        method GLM_FUNC_QUALIFIER (line 60) | GLM_FUNC_QUALIFIER V operator()() const {
      type _swizzle_base1<T, P, V, E0, E1, E2, -1, 3> (line 66) | struct _swizzle_base1<T, P, V, E0, E1, E2, -1, 3>
        method GLM_FUNC_QUALIFIER (line 68) | GLM_FUNC_QUALIFIER V operator()() const {
      type _swizzle_base1<T, P, V, E0, E1, E2, E3, 4> (line 74) | struct _swizzle_base1<T, P, V, E0, E1, E2, E3, 4>
        method GLM_FUNC_QUALIFIER (line 76) | GLM_FUNC_QUALIFIER V operator()() const {
      type _swizzle_base2 (line 97) | struct _swizzle_base2
        method GLM_FUNC_QUALIFIER (line 102) | GLM_FUNC_QUALIFIER _swizzle_base2& operator=(const ValueType& t) {
        method GLM_FUNC_QUALIFIER (line 107) | GLM_FUNC_QUALIFIER _swizzle_base2& operator=(const VecType& that) {
        method GLM_FUNC_QUALIFIER (line 117) | GLM_FUNC_QUALIFIER void operator-=(const VecType& that) {
        method GLM_FUNC_QUALIFIER (line 126) | GLM_FUNC_QUALIFIER void operator+=(const VecType& that) {
        method GLM_FUNC_QUALIFIER (line 135) | GLM_FUNC_QUALIFIER void operator*=(const VecType& that) {
        method GLM_FUNC_QUALIFIER (line 144) | GLM_FUNC_QUALIFIER void operator/=(const VecType& that) {
        method GLM_FUNC_QUALIFIER (line 153) | GLM_FUNC_QUALIFIER value_type& operator[](size_t i) {
        method GLM_FUNC_QUALIFIER (line 170) | GLM_FUNC_QUALIFIER void _apply_op(const VecType& that, T op) {
      type _swizzle_base2<ValueType, P, VecType, N, E0, E1, E2, E3, 1> (line 184) | struct _swizzle_base2<ValueType, P, VecType, N, E0, E1, E2, E3, 1>
        type Stub (line 189) | struct Stub {}
        method GLM_FUNC_QUALIFIER (line 190) | GLM_FUNC_QUALIFIER _swizzle_base2& operator=(Stub const&) { return...
      type _swizzle (line 203) | struct _swizzle
        method GLM_FUNC_QUALIFIER (line 214) | GLM_FUNC_QUALIFIER operator VecType() const { return (*this)(); }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/_vectorize.hpp
  type glm (line 130) | namespace glm {
    type detail (line 131) | namespace detail {
      type If (line 133) | struct If {
        method GLM_FUNC_QUALIFIER (line 135) | static GLM_FUNC_QUALIFIER T apply(F functor, const T& val) {
      type If<false> (line 141) | struct If<false> {
        method GLM_FUNC_QUALIFIER (line 143) | static GLM_FUNC_QUALIFIER T apply(F, const T& val) {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_common.hpp
  type glm (line 46) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_exponential.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_geometric.hpp
  type glm (line 43) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_integer.hpp
  type glm (line 45) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_matrix.hpp
  type glm (line 62) | namespace glm {
    type detail (line 63) | namespace detail {
      type outerProduct_trait<T, P, tvec2, tvec2> (line 65) | struct outerProduct_trait<T, P, tvec2, tvec2> {
      type outerProduct_trait<T, P, tvec2, tvec3> (line 70) | struct outerProduct_trait<T, P, tvec2, tvec3> {
      type outerProduct_trait<T, P, tvec2, tvec4> (line 75) | struct outerProduct_trait<T, P, tvec2, tvec4> {
      type outerProduct_trait<T, P, tvec3, tvec2> (line 80) | struct outerProduct_trait<T, P, tvec3, tvec2> {
      type outerProduct_trait<T, P, tvec3, tvec3> (line 85) | struct outerProduct_trait<T, P, tvec3, tvec3> {
      type outerProduct_trait<T, P, tvec3, tvec4> (line 90) | struct outerProduct_trait<T, P, tvec3, tvec4> {
      type outerProduct_trait<T, P, tvec4, tvec2> (line 95) | struct outerProduct_trait<T, P, tvec4, tvec2> {
      type outerProduct_trait<T, P, tvec4, tvec3> (line 100) | struct outerProduct_trait<T, P, tvec4, tvec3> {
      type outerProduct_trait<T, P, tvec4, tvec4> (line 105) | struct outerProduct_trait<T, P, tvec4, tvec4> {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_noise.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_packing.hpp
  type glm (line 45) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_trigonometric.hpp
  type glm (line 45) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/func_vector_relational.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/glm.cpp
  type glm (line 33) | namespace glm {
    type detail (line 34) | namespace detail {
      type tvec2<uint8, lowp> (line 74) | struct tvec2<uint8, lowp>
      type tvec2<uint16, lowp> (line 75) | struct tvec2<uint16, lowp>
      type tvec2<uint32, lowp> (line 76) | struct tvec2<uint32, lowp>
      type tvec2<uint64, lowp> (line 77) | struct tvec2<uint64, lowp>
      type tvec2<int8, lowp> (line 78) | struct tvec2<int8, lowp>
      type tvec2<int16, lowp> (line 79) | struct tvec2<int16, lowp>
      type tvec2<int32, lowp> (line 80) | struct tvec2<int32, lowp>
      type tvec2<int64, lowp> (line 81) | struct tvec2<int64, lowp>
      type tvec2<float32, lowp> (line 82) | struct tvec2<float32, lowp>
      type tvec2<float64, lowp> (line 83) | struct tvec2<float64, lowp>
      type tvec2<uint8, mediump> (line 85) | struct tvec2<uint8, mediump>
      type tvec2<uint16, mediump> (line 86) | struct tvec2<uint16, mediump>
      type tvec2<uint32, mediump> (line 87) | struct tvec2<uint32, mediump>
      type tvec2<uint64, mediump> (line 88) | struct tvec2<uint64, mediump>
      type tvec2<int8, mediump> (line 89) | struct tvec2<int8, mediump>
      type tvec2<int16, mediump> (line 90) | struct tvec2<int16, mediump>
      type tvec2<int32, mediump> (line 91) | struct tvec2<int32, mediump>
      type tvec2<int64, mediump> (line 92) | struct tvec2<int64, mediump>
      type tvec2<float32, mediump> (line 93) | struct tvec2<float32, mediump>
      type tvec2<float64, mediump> (line 94) | struct tvec2<float64, mediump>
      type tvec2<uint8, highp> (line 96) | struct tvec2<uint8, highp>
      type tvec2<uint16, highp> (line 97) | struct tvec2<uint16, highp>
      type tvec2<uint32, highp> (line 98) | struct tvec2<uint32, highp>
      type tvec2<uint64, highp> (line 99) | struct tvec2<uint64, highp>
      type tvec2<int8, highp> (line 100) | struct tvec2<int8, highp>
      type tvec2<int16, highp> (line 101) | struct tvec2<int16, highp>
      type tvec2<int32, highp> (line 102) | struct tvec2<int32, highp>
      type tvec2<int64, highp> (line 103) | struct tvec2<int64, highp>
      type tvec2<float32, highp> (line 104) | struct tvec2<float32, highp>
      type tvec2<float64, highp> (line 105) | struct tvec2<float64, highp>
      type tvec3<uint8, lowp> (line 108) | struct tvec3<uint8, lowp>
      type tvec3<uint16, lowp> (line 109) | struct tvec3<uint16, lowp>
      type tvec3<uint32, lowp> (line 110) | struct tvec3<uint32, lowp>
      type tvec3<uint64, lowp> (line 111) | struct tvec3<uint64, lowp>
      type tvec3<int8, lowp> (line 112) | struct tvec3<int8, lowp>
      type tvec3<int16, lowp> (line 113) | struct tvec3<int16, lowp>
      type tvec3<int32, lowp> (line 114) | struct tvec3<int32, lowp>
      type tvec3<int64, lowp> (line 115) | struct tvec3<int64, lowp>
      type tvec3<float32, lowp> (line 116) | struct tvec3<float32, lowp>
      type tvec3<float64, lowp> (line 117) | struct tvec3<float64, lowp>
      type tvec3<uint8, mediump> (line 119) | struct tvec3<uint8, mediump>
      type tvec3<uint16, mediump> (line 120) | struct tvec3<uint16, mediump>
      type tvec3<uint32, mediump> (line 121) | struct tvec3<uint32, mediump>
      type tvec3<uint64, mediump> (line 122) | struct tvec3<uint64, mediump>
      type tvec3<int8, mediump> (line 123) | struct tvec3<int8, mediump>
      type tvec3<int16, mediump> (line 124) | struct tvec3<int16, mediump>
      type tvec3<int32, mediump> (line 125) | struct tvec3<int32, mediump>
      type tvec3<int64, mediump> (line 126) | struct tvec3<int64, mediump>
      type tvec3<float32, mediump> (line 127) | struct tvec3<float32, mediump>
      type tvec3<float64, mediump> (line 128) | struct tvec3<float64, mediump>
      type tvec3<uint8, highp> (line 130) | struct tvec3<uint8, highp>
      type tvec3<uint16, highp> (line 131) | struct tvec3<uint16, highp>
      type tvec3<uint32, highp> (line 132) | struct tvec3<uint32, highp>
      type tvec3<uint64, highp> (line 133) | struct tvec3<uint64, highp>
      type tvec3<int8, highp> (line 134) | struct tvec3<int8, highp>
      type tvec3<int16, highp> (line 135) | struct tvec3<int16, highp>
      type tvec3<int32, highp> (line 136) | struct tvec3<int32, highp>
      type tvec3<int64, highp> (line 137) | struct tvec3<int64, highp>
      type tvec3<float32, highp> (line 138) | struct tvec3<float32, highp>
      type tvec3<float64, highp> (line 139) | struct tvec3<float64, highp>
      type tvec4<uint8, lowp> (line 142) | struct tvec4<uint8, lowp>
      type tvec4<uint16, lowp> (line 143) | struct tvec4<uint16, lowp>
      type tvec4<uint32, lowp> (line 144) | struct tvec4<uint32, lowp>
      type tvec4<uint64, lowp> (line 145) | struct tvec4<uint64, lowp>
      type tvec4<int8, lowp> (line 146) | struct tvec4<int8, lowp>
      type tvec4<int16, lowp> (line 147) | struct tvec4<int16, lowp>
      type tvec4<int32, lowp> (line 148) | struct tvec4<int32, lowp>
      type tvec4<int64, lowp> (line 149) | struct tvec4<int64, lowp>
      type tvec4<float32, lowp> (line 150) | struct tvec4<float32, lowp>
      type tvec4<float64, lowp> (line 151) | struct tvec4<float64, lowp>
      type tvec4<uint8, mediump> (line 153) | struct tvec4<uint8, mediump>
      type tvec4<uint16, mediump> (line 154) | struct tvec4<uint16, mediump>
      type tvec4<uint32, mediump> (line 155) | struct tvec4<uint32, mediump>
      type tvec4<uint64, mediump> (line 156) | struct tvec4<uint64, mediump>
      type tvec4<int8, mediump> (line 157) | struct tvec4<int8, mediump>
      type tvec4<int16, mediump> (line 158) | struct tvec4<int16, mediump>
      type tvec4<int32, mediump> (line 159) | struct tvec4<int32, mediump>
      type tvec4<int64, mediump> (line 160) | struct tvec4<int64, mediump>
      type tvec4<float32, mediump> (line 161) | struct tvec4<float32, mediump>
      type tvec4<float64, mediump> (line 162) | struct tvec4<float64, mediump>
      type tvec4<uint8, highp> (line 164) | struct tvec4<uint8, highp>
      type tvec4<uint16, highp> (line 165) | struct tvec4<uint16, highp>
      type tvec4<uint32, highp> (line 166) | struct tvec4<uint32, highp>
      type tvec4<uint64, highp> (line 167) | struct tvec4<uint64, highp>
      type tvec4<int8, highp> (line 168) | struct tvec4<int8, highp>
      type tvec4<int16, highp> (line 169) | struct tvec4<int16, highp>
      type tvec4<int32, highp> (line 170) | struct tvec4<int32, highp>
      type tvec4<int64, highp> (line 171) | struct tvec4<int64, highp>
      type tvec4<float32, highp> (line 172) | struct tvec4<float32, highp>
      type tvec4<float64, highp> (line 173) | struct tvec4<float64, highp>
      type tmat2x2<float32, lowp> (line 176) | struct tmat2x2<float32, lowp>
      type tmat2x2<float64, lowp> (line 177) | struct tmat2x2<float64, lowp>
      type tmat2x2<float32, mediump> (line 179) | struct tmat2x2<float32, mediump>
      type tmat2x2<float64, mediump> (line 180) | struct tmat2x2<float64, mediump>
      type tmat2x2<float32, highp> (line 182) | struct tmat2x2<float32, highp>
      type tmat2x2<float64, highp> (line 183) | struct tmat2x2<float64, highp>
      type tmat2x3<float32, lowp> (line 186) | struct tmat2x3<float32, lowp>
      type tmat2x3<float64, lowp> (line 187) | struct tmat2x3<float64, lowp>
      type tmat2x3<float32, mediump> (line 189) | struct tmat2x3<float32, mediump>
      type tmat2x3<float64, mediump> (line 190) | struct tmat2x3<float64, mediump>
      type tmat2x3<float32, highp> (line 192) | struct tmat2x3<float32, highp>
      type tmat2x3<float64, highp> (line 193) | struct tmat2x3<float64, highp>
      type tmat2x4<float32, lowp> (line 196) | struct tmat2x4<float32, lowp>
      type tmat2x4<float64, lowp> (line 197) | struct tmat2x4<float64, lowp>
      type tmat2x4<float32, mediump> (line 199) | struct tmat2x4<float32, mediump>
      type tmat2x4<float64, mediump> (line 200) | struct tmat2x4<float64, mediump>
      type tmat2x4<float32, highp> (line 202) | struct tmat2x4<float32, highp>
      type tmat2x4<float64, highp> (line 203) | struct tmat2x4<float64, highp>
      type tmat3x2<float32, lowp> (line 206) | struct tmat3x2<float32, lowp>
      type tmat3x2<float64, lowp> (line 207) | struct tmat3x2<float64, lowp>
      type tmat3x2<float32, mediump> (line 209) | struct tmat3x2<float32, mediump>
      type tmat3x2<float64, mediump> (line 210) | struct tmat3x2<float64, mediump>
      type tmat3x2<float32, highp> (line 212) | struct tmat3x2<float32, highp>
      type tmat3x2<float64, highp> (line 213) | struct tmat3x2<float64, highp>
      type tmat3x3<float32, lowp> (line 216) | struct tmat3x3<float32, lowp>
      type tmat3x3<float64, lowp> (line 217) | struct tmat3x3<float64, lowp>
      type tmat3x3<float32, mediump> (line 219) | struct tmat3x3<float32, mediump>
      type tmat3x3<float64, mediump> (line 220) | struct tmat3x3<float64, mediump>
      type tmat3x3<float32, highp> (line 222) | struct tmat3x3<float32, highp>
      type tmat3x3<float64, highp> (line 223) | struct tmat3x3<float64, highp>
      type tmat3x4<float32, lowp> (line 226) | struct tmat3x4<float32, lowp>
      type tmat3x4<float64, lowp> (line 227) | struct tmat3x4<float64, lowp>
      type tmat3x4<float32, mediump> (line 229) | struct tmat3x4<float32, mediump>
      type tmat3x4<float64, mediump> (line 230) | struct tmat3x4<float64, mediump>
      type tmat3x4<float32, highp> (line 232) | struct tmat3x4<float32, highp>
      type tmat3x4<float64, highp> (line 233) | struct tmat3x4<float64, highp>
      type tmat4x2<float32, lowp> (line 236) | struct tmat4x2<float32, lowp>
      type tmat4x2<float64, lowp> (line 237) | struct tmat4x2<float64, lowp>
      type tmat4x2<float32, mediump> (line 239) | struct tmat4x2<float32, mediump>
      type tmat4x2<float64, mediump> (line 240) | struct tmat4x2<float64, mediump>
      type tmat4x2<float32, highp> (line 242) | struct tmat4x2<float32, highp>
      type tmat4x2<float64, highp> (line 243) | struct tmat4x2<float64, highp>
      type tmat4x3<float32, lowp> (line 246) | struct tmat4x3<float32, lowp>
      type tmat4x3<float64, lowp> (line 247) | struct tmat4x3<float64, lowp>
      type tmat4x3<float32, mediump> (line 249) | struct tmat4x3<float32, mediump>
      type tmat4x3<float64, mediump> (line 250) | struct tmat4x3<float64, mediump>
      type tmat4x3<float32, highp> (line 252) | struct tmat4x3<float32, highp>
      type tmat4x3<float64, highp> (line 253) | struct tmat4x3<float64, highp>
      type tmat4x4<float32, lowp> (line 256) | struct tmat4x4<float32, lowp>
      type tmat4x4<float64, lowp> (line 257) | struct tmat4x4<float64, lowp>
      type tmat4x4<float32, mediump> (line 259) | struct tmat4x4<float32, mediump>
      type tmat4x4<float64, mediump> (line 260) | struct tmat4x4<float64, mediump>
      type tmat4x4<float32, highp> (line 262) | struct tmat4x4<float32, highp>
      type tmat4x4<float64, highp> (line 263) | struct tmat4x4<float64, highp>
      type tquat<float32, lowp> (line 266) | struct tquat<float32, lowp>
      type tquat<float64, lowp> (line 267) | struct tquat<float64, lowp>
      type tquat<float32, mediump> (line 269) | struct tquat<float32, mediump>
      type tquat<float64, mediump> (line 270) | struct tquat<float64, mediump>
      type tquat<float32, highp> (line 272) | struct tquat<float32, highp>
      type tquat<float64, highp> (line 273) | struct tquat<float64, highp>
      type tdualquat<float32, lowp> (line 276) | struct tdualquat<float32, lowp>
      type tdualquat<float64, lowp> (line 277) | struct tdualquat<float64, lowp>
      type tdualquat<float32, mediump> (line 279) | struct tdualquat<float32, mediump>
      type tdualquat<float64, mediump> (line 280) | struct tdualquat<float64, mediump>
      type tdualquat<float32, highp> (line 282) | struct tdualquat<float32, highp>
      type tdualquat<float64, highp> (line 283) | struct tdualquat<float64, highp>

FILE: endless-tunnel/app/src/main/cpp/glm/detail/hint.hpp
  type glm (line 32) | namespace glm {
    class dont_care (line 34) | class dont_care {}
    class nicest (line 35) | class nicest {}
    class fastest (line 36) | class fastest {}

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_common.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_exponential.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_geometric.hpp
  type glm (line 40) | namespace glm {
    type detail (line 41) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_integer.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_matrix.hpp
  type glm (line 40) | namespace glm {
    type detail (line 41) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_trigonometric.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {}

FILE: endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_vector_relational.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {}

FILE: endless-tunnel/app/src/main/cpp/glm/detail/precision.hpp
  type glm (line 32) | namespace glm {
    type precision (line 33) | enum precision { highp, mediump, lowp, defaultp = highp }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/setup.hpp
  function _mm_cvtss_f32 (line 636) | inline float _mm_cvtss_f32(__m128 A) { return A.m128_f32[0]; }
  function __m128 (line 637) | inline __m128 _mm_castpd_ps(__m128d PD) {
  function __m128d (line 645) | inline __m128d _mm_castps_pd(__m128 PS) {
  function __m128i (line 653) | inline __m128i _mm_castps_si128(__m128 PS) {
  function __m128 (line 661) | inline __m128 _mm_castsi128_ps(__m128i PI) {
  type glm (line 769) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_float.hpp
  type glm (line 34) | namespace glm {
    type detail (line 35) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_gentype.hpp
  type glm (line 32) | namespace glm {
    type profile (line 33) | enum profile { nice, fast, simd }
    type detail (line 37) | namespace detail {
      type genType (line 39) | struct genType {
        type ctor (line 41) | enum ctor { null }
        method value_const_pointer (line 65) | value_const_pointer value_address() const { return value_pointer(t...
        method value_pointer (line 66) | value_pointer value_address() { return value_pointer(this); }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_half.hpp
  type glm (line 34) | namespace glm {
    type detail (line 35) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_int.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat.hpp
  type glm (line 34) | namespace glm {
    type detail (line 35) | namespace detail {
      type tvec2 (line 37) | struct tvec2
      type tvec3 (line 39) | struct tvec3
      type tvec4 (line 41) | struct tvec4
      type tmat2x2 (line 43) | struct tmat2x2
      type tmat2x3 (line 45) | struct tmat2x3
      type tmat2x4 (line 47) | struct tmat2x4
      type tmat3x2 (line 49) | struct tmat3x2
      type tmat3x3 (line 51) | struct tmat3x3
      type tmat3x4 (line 53) | struct tmat3x4
      type tmat4x2 (line 55) | struct tmat4x2
      type tmat4x3 (line 57) | struct tmat4x3
      type tmat4x4 (line 59) | struct tmat4x4
      type outerProduct_trait (line 63) | struct outerProduct_trait {}
      type compute_inverse (line 66) | struct compute_inverse {}

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x2.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {
      type tmat2x2 (line 41) | struct tmat2x2 {
        type ctor (line 42) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x3.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat2x3 (line 42) | struct tmat2x3 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x4.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat2x4 (line 42) | struct tmat2x4 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x2.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat3x2 (line 42) | struct tmat3x2 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x3.hpp
  type glm (line 38) | namespace glm {
    type detail (line 39) | namespace detail {
      type tmat3x3 (line 41) | struct tmat3x3 {
        type ctor (line 42) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x4.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat3x4 (line 42) | struct tmat3x4 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x2.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat4x2 (line 42) | struct tmat4x2 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x3.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat4x3 (line 42) | struct tmat4x3 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x4.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tmat4x4 (line 42) | struct tmat4x4 {
        type ctor (line 43) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_vec.hpp
  type glm (line 35) | namespace glm {
    type detail (line 36) | namespace detail {
      type tvec1 (line 38) | struct tvec1
      type tvec2 (line 40) | struct tvec2
      type tvec3 (line 42) | struct tvec3
      type tvec4 (line 44) | struct tvec4

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_vec1.hpp
  type glm (line 43) | namespace glm {
    type detail (line 44) | namespace detail {
      type tvec1 (line 46) | struct tvec1 {
        type ctor (line 50) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_vec2.hpp
  type ctor (line 50) | enum ctor { _null }
  function GLM_FUNC_DECL (line 127) | GLM_FUNC_DECL tvec2(

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_vec3.hpp
  type ctor (line 50) | enum ctor { _null }
  function GLM_FUNC_DECL (line 158) | GLM_FUNC_DECL tvec3(
  function GLM_FUNC_DECL (line 164) | GLM_FUNC_DECL tvec3(_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const...
  function GLM_FUNC_DECL (line 170) | GLM_FUNC_DECL tvec3(T const& s,

FILE: endless-tunnel/app/src/main/cpp/glm/detail/type_vec4.hpp
  type ctor (line 51) | enum ctor { _null }
  function GLM_FUNC_DECL (line 174) | GLM_FUNC_DECL tvec4(
  function GLM_FUNC_DECL (line 180) | GLM_FUNC_DECL tvec4(_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const...
  function GLM_FUNC_DECL (line 186) | GLM_FUNC_DECL tvec4(T const& x, T const& y,
  function GLM_FUNC_DECL (line 192) | GLM_FUNC_DECL tvec4(T const& x,
  function GLM_FUNC_DECL (line 199) | GLM_FUNC_DECL tvec4(_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const...
  function GLM_FUNC_DECL (line 205) | GLM_FUNC_DECL tvec4(_swizzle<3, T, P, tvec3<T, P>, E0, E1, E2, -1> const...
  function GLM_FUNC_DECL (line 211) | GLM_FUNC_DECL tvec4(T const& x,

FILE: endless-tunnel/app/src/main/cpp/glm/fwd.hpp
  type glm (line 39) | namespace glm {
    type detail (line 40) | namespace detail {
      type tquat (line 42) | struct tquat
  type glm (line 139) | namespace glm {
    type detail (line 40) | namespace detail {
      type tquat (line 42) | struct tquat

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/constants.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/epsilon.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/matrix_access.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/matrix_integer.hpp
  type glm (line 56) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/matrix_inverse.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/matrix_transform.hpp
  type glm (line 60) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/noise.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/packing.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/quaternion.hpp
  type glm (line 55) | namespace glm {
    type detail (line 56) | namespace detail {
      type tquat (line 58) | struct tquat {
        type ctor (line 59) | enum ctor { null }

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/random.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/reciprocal.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/type_precision.hpp
  type glm (line 66) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/type_ptr.hpp
  type glm (line 85) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtc/ulp.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/associated_min_max.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/bit.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/closest_point.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/color_space.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/color_space_YCoCg.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/compatibility.hpp
  type glm (line 61) | namespace glm {
    function GLM_FUNC_QUALIFIER (line 66) | GLM_FUNC_QUALIFIER T lerp(T x, T y, T a) {
    function GLM_FUNC_QUALIFIER (line 72) | GLM_FUNC_QUALIFIER detail::tvec2<T, P> lerp(const detail::tvec2<T, P>& x,
    function GLM_FUNC_QUALIFIER (line 80) | GLM_FUNC_QUALIFIER detail::tvec3<T, P> lerp(const detail::tvec3<T, P>& x,
    function GLM_FUNC_QUALIFIER (line 87) | GLM_FUNC_QUALIFIER detail::tvec4<T, P> lerp(const detail::tvec4<T, P>& x,
    function GLM_FUNC_QUALIFIER (line 94) | GLM_FUNC_QUALIFIER detail::tvec2<T, P> lerp(const detail::tvec2<T, P>& x,
    function GLM_FUNC_QUALIFIER (line 102) | GLM_FUNC_QUALIFIER detail::tvec3<T, P> lerp(const detail::tvec3<T, P>& x,
    function GLM_FUNC_QUALIFIER (line 110) | GLM_FUNC_QUALIFIER detail::tvec4<T, P> lerp(const detail::tvec4<T, P>& x,
    function GLM_FUNC_QUALIFIER (line 119) | GLM_FUNC_QUALIFIER T slerp(detail::tquat<T, P> const& x,
    function GLM_FUNC_QUALIFIER (line 125) | GLM_FUNC_QUALIFIER T saturate(T x) {
    function GLM_FUNC_QUALIFIER (line 130) | GLM_FUNC_QUALIFIER detail::tvec2<T, P> saturate(const detail::tvec2<T,...
    function GLM_FUNC_QUALIFIER (line 135) | GLM_FUNC_QUALIFIER detail::tvec3<T, P> saturate(const detail::tvec3<T,...
    function GLM_FUNC_QUALIFIER (line 140) | GLM_FUNC_QUALIFIER detail::tvec4<T, P> saturate(const detail::tvec4<T,...
    function GLM_FUNC_QUALIFIER (line 146) | GLM_FUNC_QUALIFIER T atan2(T x, T y) {
    function GLM_FUNC_QUALIFIER (line 153) | GLM_FUNC_QUALIFIER detail::tvec2<T, P> atan2(const detail::tvec2<T, P>...
    function GLM_FUNC_QUALIFIER (line 161) | GLM_FUNC_QUALIFIER detail::tvec3<T, P> atan2(const detail::tvec3<T, P>...
    function GLM_FUNC_QUALIFIER (line 169) | GLM_FUNC_QUALIFIER detail::tvec4<T, P> atan2(const detail::tvec4<T, P>...

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/component_wise.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/dual_quaternion.hpp
  type glm (line 55) | namespace glm {
    type detail (line 56) | namespace detail {
      type tdualquat (line 58) | struct tdualquat {
        type ctor (line 59) | enum ctor { null }

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/euler_angles.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/extend.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/extented_min_max.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/fast_exponential.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/fast_square_root.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/fast_trigonometry.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/gradient_paint.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/handed_coordinate_space.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/inertia.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/int_10_10_10_2.hpp
  type glm (line 36) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/integer.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/intersect.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/io.hpp
  type glm (line 53) | namespace glm {
    type io (line 57) | namespace io {
      class precision_guard (line 59) | class precision_guard {
      class format_guard (line 69) | class format_guard {
        type order_t (line 71) | enum order_t {
    type detail (line 110) | namespace detail {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/log_base.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/matrix_cross_product.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/matrix_interpolation.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/matrix_major_storage.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/matrix_operation.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/matrix_query.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/matrix_transform_2d.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/mixed_product.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/multiple.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/norm.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/normal.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/normalize_dot.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/number_precision.hpp
  type glm (line 52) | namespace glm {
    type gtx (line 53) | namespace gtx {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/optimum_pow.hpp
  type glm (line 48) | namespace glm {
    type gtx (line 49) | namespace gtx {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/orthonormalize.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/perpendicular.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/polar_coordinates.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/projection.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/quaternion.hpp
  type glm (line 52) | namespace glm {
    function GLM_FUNC_DECL (line 138) | GLM_FUNC_DECL detail::tmat3x3<T, P> toMat3(detail::tquat<T, P> const& ...
    function GLM_FUNC_DECL (line 146) | GLM_FUNC_DECL detail::tmat4x4<T, P> toMat4(detail::tquat<T, P> const& ...
    function GLM_FUNC_DECL (line 154) | GLM_FUNC_DECL detail::tquat<T, P> toQuat(detail::tmat3x3<T, P> const& ...
    function GLM_FUNC_DECL (line 162) | GLM_FUNC_DECL detail::tquat<T, P> toQuat(detail::tmat4x4<T, P> const& ...

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/raw_data.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/rotate_normalized_axis.hpp
  type glm (line 53) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/rotate_vector.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/scalar_relational.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/simd_mat4.hpp
  type ctor (line 63) | enum ctor { _null }

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/simd_quat.hpp
  type ctor (line 71) | enum ctor { null }

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/simd_vec4.hpp
  type glm (line 66) | namespace glm {
    type comp (line 67) | enum comp {
  type ctor (line 89) | enum ctor { null }

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/spline.hpp
  type glm (line 49) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/std_based_type.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/string_cast.hpp
  type glm (line 60) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/transform.hpp
  type glm (line 52) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/transform2.hpp
  type glm (line 50) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/vec1.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/vector_angle.hpp
  type glm (line 53) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/vector_query.hpp
  type glm (line 51) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/gtx/wrap.hpp
  type glm (line 48) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat2x2.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat2x3.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat2x4.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat3x2.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat3x3.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat3x4.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat4x2.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat4x3.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/glm/mat4x4.hpp
  type glm (line 34) | namespace glm {

FILE: endless-tunnel/app/src/main/cpp/indexbuf.hpp
  class IndexBuf (line 22) | class IndexBuf {
    method GetCount (line 29) | int GetCount() { return mCount; }

FILE: endless-tunnel/app/src/main/cpp/input_util.cpp
  type DeviceMotionRange (line 25) | struct DeviceMotionRange {
  type DeviceMotionRange (line 31) | struct DeviceMotionRange
  function _init (line 38) | static void _init() {
  function _translate_keycode (line 58) | static int _translate_keycode(int code) {
  function _report_key_state (line 81) | static void _report_key_state(int keyCode, bool state,
  function _report_key_states_from_axes (line 100) | static void _report_key_states_from_axes(float x, float y,
  function _process_keys (line 108) | static bool _process_keys(bool isJoy, AInputEvent* event,
  function _look_up_motion_range (line 141) | static void _look_up_motion_range(int deviceId, int source, float* outMinX,
  function CookEvent_Joy (line 194) | static bool CookEvent_Joy(AInputEvent* event, CookedEventCallback callba...
  function CookEvent_Motion (line 204) | static bool CookEvent_Motion(AInputEvent* event, CookedEventCallback cal...
  function CookEvent (line 261) | bool CookEvent(AInputEvent* event, CookedEventCallback callback) {

FILE: endless-tunnel/app/src/main/cpp/input_util.hpp
  type CookedEvent (line 31) | struct CookedEvent {
  type CookedEvent (line 48) | struct CookedEvent

FILE: endless-tunnel/app/src/main/cpp/jni_util.cpp
  type JniSetup (line 23) | struct JniSetup
  type JniSetup (line 25) | struct JniSetup

FILE: endless-tunnel/app/src/main/cpp/jni_util.hpp
  type JniSetup (line 19) | struct JniSetup {
  type JniSetup (line 26) | struct JniSetup

FILE: endless-tunnel/app/src/main/cpp/native_engine.cpp
  type android_app (line 41) | struct android_app
  type NativeEngineSavedState (line 58) | struct NativeEngineSavedState
  function NativeEngine (line 69) | NativeEngine* NativeEngine::GetInstance() {
  function _handle_cmd_proxy (line 86) | static void _handle_cmd_proxy(struct android_app* app, int32_t cmd) {
  function _handle_input_proxy (line 91) | static int _handle_input_proxy(struct android_app* app, AInputEvent* eve...
  type android_poll_source (line 107) | struct android_poll_source
  function JNIEnv (line 122) | JNIEnv* NativeEngine::GetJniEnv() {
  function _cooked_event_callback (line 228) | static bool _cooked_event_callback(struct CookedEvent* event) {
  function _log_opengl_error (line 485) | static void _log_opengl_error(GLenum err) {
  function android_app (line 568) | android_app* NativeEngine::GetAndroidApp() { return mApp; }

FILE: endless-tunnel/app/src/main/cpp/native_engine.hpp
  type NativeEngineSavedState (line 21) | struct NativeEngineSavedState {
  class NativeEngine (line 25) | class NativeEngine {
    type android_app (line 28) | struct android_app
    type android_app (line 63) | struct android_app
    type NativeEngineSavedState (line 66) | struct NativeEngineSavedState

FILE: endless-tunnel/app/src/main/cpp/obstacle.hpp
  class Obstacle (line 28) | class Obstacle {
    method GetBoxCenter (line 35) | glm::vec3 GetBoxCenter(int gridCol, int gridRow, float posY) {
    method GetBoxSize (line 40) | glm::vec3 GetBoxSize() {
    method GetRowAt (line 44) | int GetRowAt(float z) {
    method GetColAt (line 49) | int GetColAt(float x) {
    method GetMinY (line 54) | float GetMinY(float posY) { return posY - OBS_BOX_SIZE * 0.5f; }
    method GetMaxY (line 55) | float GetMaxY(float posY) { return posY + OBS_BOX_SIZE * 0.5f; }
    method Reset (line 57) | void Reset() {
    method SetBonus (line 63) | void SetBonus(int col, int row) {
    method DeleteBonus (line 70) | void DeleteBonus() { bonusCol = bonusRow = -1; }
    method HasBonus (line 72) | bool HasBonus() {

FILE: endless-tunnel/app/src/main/cpp/obstacle_generator.hpp
  class ObstacleGenerator (line 23) | class ObstacleGenerator {
    method ObstacleGenerator (line 28) | ObstacleGenerator() { mDifficulty = 0; }
    method SetDifficulty (line 30) | void SetDifficulty(int dif) { mDifficulty = dif; }

FILE: endless-tunnel/app/src/main/cpp/our_shader.hpp
  class OurShader (line 23) | class OurShader : public Shader {

FILE: endless-tunnel/app/src/main/cpp/play_scene.cpp
  function GetSectionCenterY (line 408) | static float GetSectionCenterY(int i) {
  function GetSectionEndY (line 412) | static float GetSectionEndY(int i) {
  function _get_obs_color (line 416) | static void _get_obs_color(int style, float* r, float* g, float* b) {
  type PointerCoords (line 557) | struct PointerCoords
  type PointerCoords (line 574) | struct PointerCoords
  type PointerCoords (line 586) | struct PointerCoords

FILE: endless-tunnel/app/src/main/cpp/play_scene.hpp
  class OurShader (line 27) | class OurShader
  class PlayScene (line 32) | class PlayScene : public Scene {
    type PointerCoords (line 38) | struct PointerCoords
    type PointerCoords (line 39) | struct PointerCoords
    type PointerCoords (line 40) | struct PointerCoords
    method GetScore (line 197) | int GetScore() { return (int)(mEncryptedScore ^ 0x600673); }
    method SetScore (line 200) | void SetScore(int s) {
    method AddScore (line 206) | void AddScore(int s) { SetScore(GetScore() + s); }
    method ShowSign (line 232) | void ShowSign(const char *sign, float timeout) {
    method ShowSign (line 238) | void ShowSign(const char *sign) {
    method Obstacle (line 243) | Obstacle *GetObstacleAt(int i) {
    method IsCheckpointLevel (line 267) | bool IsCheckpointLevel() { return 0 == mDifficulty % LEVELS_PER_CHECKP...

FILE: endless-tunnel/app/src/main/cpp/scene.cpp
  type PointerCoords (line 26) | struct PointerCoords
  type PointerCoords (line 27) | struct PointerCoords
  type PointerCoords (line 28) | struct PointerCoords

FILE: endless-tunnel/app/src/main/cpp/scene.hpp
  type PointerCoords (line 19) | struct PointerCoords
  class Scene (line 25) | class Scene {
    type PointerCoords (line 45) | struct PointerCoords
    type PointerCoords (line 48) | struct PointerCoords
    type PointerCoords (line 51) | struct PointerCoords

FILE: endless-tunnel/app/src/main/cpp/scene_manager.cpp
  function Scene (line 68) | Scene* SceneManager::GetScene() { return mCurScene; }
  function SceneManager (line 113) | SceneManager* SceneManager::GetInstance() { return &_sceneManager; }
  type PointerCoords (line 116) | struct PointerCoords
  type PointerCoords (line 123) | struct PointerCoords
  type PointerCoords (line 130) | struct PointerCoords

FILE: endless-tunnel/app/src/main/cpp/scene_manager.hpp
  class Scene (line 21) | class Scene
  type PointerCoords (line 23) | struct PointerCoords {
  class SceneManager (line 37) | class SceneManager {
    method GetScreenWidth (line 52) | int GetScreenWidth() { return mScreenWidth; }
    method GetScreenHeight (line 55) | int GetScreenHeight() { return mScreenHeight; }
    method GetScreenAspect (line 58) | float GetScreenAspect() { return (float)mScreenWidth / mScreenHeight; }
    method HasGraphics (line 61) | bool HasGraphics() { return mHasGraphics; }
    type PointerCoords (line 70) | struct PointerCoords
    type PointerCoords (line 73) | struct PointerCoords
    type PointerCoords (line 76) | struct PointerCoords

FILE: endless-tunnel/app/src/main/cpp/sfxman.cpp
  function SfxMan (line 28) | SfxMan* SfxMan::GetInstance() {
  function _checkError (line 32) | static bool _checkError(SLresult r, const char* what) {
  function _bqPlayerCallback (line 41) | static void _bqPlayerCallback(SLAndroidSimpleBufferQueueItf, void*) {
  function _synth (line 178) | static int _synth(int frequency, float amplitude, short* sample_buf,
  function _taper (line 206) | static void _taper(short* sample_buf, int samples) {

FILE: endless-tunnel/app/src/main/cpp/sfxman.hpp
  class SfxMan (line 31) | class SfxMan {

FILE: endless-tunnel/app/src/main/cpp/shader.cpp
  function _printShaderLog (line 44) | static void _printShaderLog(GLuint shader) {
  function _printProgramLog (line 52) | static void _printProgramLog(GLuint program) {

FILE: endless-tunnel/app/src/main/cpp/shader.hpp
  class VertexBuf (line 22) | class VertexBuf
  class IndexBuf (line 23) | class IndexBuf
  class Shader (line 32) | class Shader {
    method Render (line 60) | void Render(glm::mat4* mvpMat) { Render(NULL, mvpMat); }
    method RenderSimpleGeom (line 70) | void RenderSimpleGeom(glm::mat4* mvpMat, SimpleGeom* sg) {
  class TrivialShader (line 97) | class TrivialShader : public Shader {

FILE: endless-tunnel/app/src/main/cpp/shape_renderer.hpp
  class ShapeRenderer (line 24) | class ShapeRenderer {
    method SetColor (line 34) | void SetColor(float r, float g, float b) {
    method SetColor (line 37) | void SetColor(const float *v) {

FILE: endless-tunnel/app/src/main/cpp/simplegeom.hpp
  class SimpleGeom (line 24) | class SimpleGeom {
    method SimpleGeom (line 29) | SimpleGeom() {
    method SimpleGeom (line 34) | SimpleGeom(VertexBuf *vb, IndexBuf *ib) {
    method SimpleGeom (line 39) | SimpleGeom(VertexBuf *vb) {

FILE: endless-tunnel/app/src/main/cpp/tex_quad.cpp
  function _put_vertex (line 18) | static void _put_vertex(float* v, float x, float y, float tex_u, float t...

FILE: endless-tunnel/app/src/main/cpp/tex_quad.hpp
  class TexQuad (line 24) | class TexQuad {
    method Init (line 34) | void Init(Texture *t, OurShader *shader, float aspect, float umin, flo...
    method TexQuad (line 47) | TexQuad(Texture *t, OurShader *shader, float aspect, float umin, float...
    method TexQuad (line 51) | TexQuad(Texture *t, OurShader *shader, float umin, float vmin, float u...
    method GetCenterX (line 55) | float GetCenterX() { return mCenterX; }
    method GetCenterY (line 56) | float GetCenterY() { return mCenterY; }
    method GetWidth (line 57) | float GetWidth() { return mWidth; }
    method GetHeight (line 58) | float GetHeight() { return mHeight; }
    method GetLeft (line 59) | float GetLeft() { return mCenterX - mWidth * 0.5f; }
    method GetRight (line 60) | float GetRight() { return mCenterX + mWidth * 0.5f; }
    method GetBottom (line 61) | float GetBottom() { return mCenterY - mHeight * 0.5f; }
    method GetTop (line 62) | float GetTop() { return mCenterY + mHeight * 0.5f; }
    method Contains (line 63) | bool Contains(float x, float y) {
    method SetCenter (line 68) | void SetCenter(float x, float y) {
    method SetWidth (line 72) | void SetWidth(float w) {
    method SetHeight (line 76) | void SetHeight(float h) {
    method SetScale (line 85) | void SetScale(float scale) { mScale = scale; }
    method Render (line 86) | void Render() { Render(NULL); }

FILE: endless-tunnel/app/src/main/cpp/text_renderer.cpp
  function TextRenderer (line 53) | TextRenderer* TextRenderer::SetFontScale(float scale) {
  function _count_rows_cols (line 58) | static void _count_rows_cols(const char* p, int* outCols, int* outRows) {
  function TextRenderer (line 76) | TextRenderer* TextRenderer::SetMatrix(glm::mat4 m) {
  function TextRenderer (line 94) | TextRenderer* TextRenderer::RenderText(const char* str, float centerX,

FILE: endless-tunnel/app/src/main/cpp/text_renderer.hpp
  class TextRenderer (line 23) | class TextRenderer {
    method SetColor (line 40) | void SetColor(float r, float g, float b) {
    method SetColor (line 43) | void SetColor(const float *c) {
    method ResetColor (line 46) | void ResetColor() { SetColor(1.0f, 1.0f, 1.0f); }
    method TextRenderer (line 48) | TextRenderer *ResetMatrix() { return SetMatrix(glm::mat4(1.0f)); }
    method MeasureTextWidth (line 53) | static float MeasureTextWidth(const char *str, float fontScale) {
    method MeasureTextHeight (line 59) | static float MeasureTextHeight(const char *str, float fontScale) {

FILE: endless-tunnel/app/src/main/cpp/texture.hpp
  class Texture (line 22) | class Texture {
    method Texture (line 27) | inline Texture() { mTextureH = 0; }

FILE: endless-tunnel/app/src/main/cpp/ui_scene.cpp
  function UiWidget (line 60) | UiWidget* UiScene::NewWidget() {
  function UiWidget (line 107) | UiWidget* UiScene::GetWidgetById(int id) {
  type PointerCoords (line 165) | struct PointerCoords
  type PointerCoords (line 182) | struct PointerCoords
  type PointerCoords (line 192) | struct PointerCoords
  type PointerCoords (line 198) | struct PointerCoords
  function _apply_transition (line 289) | static void _apply_transition(int trans, float f, float* x, float* y, fl...

FILE: endless-tunnel/app/src/main/cpp/ui_scene.hpp
  class UiWidget (line 30) | class UiWidget
    method UiWidget (line 142) | UiWidget(int id) {
    method GetId (line 164) | int GetId() { return mId; }
    method IsButton (line 165) | bool IsButton() { return mIsButton; }
    method GetNav (line 166) | int GetNav(int dir) { return dir >= 0 && dir < 4 ? mNav[dir] : -1; }
    method UiWidget (line 168) | UiWidget* SetNav(int dir, int id) {
    method UiWidget (line 175) | UiWidget* SetTransition(int trans) {
    method UiWidget (line 180) | UiWidget* SetCenter(float x, float y) {
    method UiWidget (line 186) | UiWidget* SetSize(float w, float h) {
    method UiWidget (line 192) | UiWidget* SetText(const char* text) {
    method UiWidget (line 197) | UiWidget* SetTextColor(float r, float g, float b) {
    method UiWidget (line 204) | UiWidget* SetFontScale(float scale) {
    method UiWidget (line 209) | UiWidget* SetIsButton(bool isButton) {
    method StartGraphics (line 215) | void StartGraphics() {
    method KillGraphics (line 221) | void KillGraphics() { CleanUp(&mIconGeom); }
    method PointBelongs (line 223) | bool PointBelongs(float x, float y) {
    method IsClickableButton (line 229) | bool IsClickableButton() { return mIsButton && mVisible && mEnabled; }
  class UiScene (line 33) | class UiScene : public Scene {
    method SetDefaultButton (line 71) | void SetDefaultButton(int id) { mDefaultButton = id; }
    method SetWaitScreen (line 73) | void SetWaitScreen(bool b) {
    type PointerCoords (line 93) | struct PointerCoords
    type PointerCoords (line 94) | struct PointerCoords
    type PointerCoords (line 95) | struct PointerCoords
    type PointerCoords (line 102) | struct PointerCoords
    method DeleteWidgets (line 106) | void DeleteWidgets() { mWidgetCount = 0; }
  class UiWidget (line 111) | class UiWidget {
    method UiWidget (line 142) | UiWidget(int id) {
    method GetId (line 164) | int GetId() { return mId; }
    method IsButton (line 165) | bool IsButton() { return mIsButton; }
    method GetNav (line 166) | int GetNav(int dir) { return dir >= 0 && dir < 4 ? mNav[dir] : -1; }
    method UiWidget (line 168) | UiWidget* SetNav(int dir, int id) {
    method UiWidget (line 175) | UiWidget* SetTransition(int trans) {
    method UiWidget (line 180) | UiWidget* SetCenter(float x, float y) {
    method UiWidget (line 186) | UiWidget* SetSize(float w, float h) {
    method UiWidget (line 192) | UiWidget* SetText(const char* text) {
    method UiWidget (line 197) | UiWidget* SetTextColor(float r, float g, float b) {
    method UiWidget (line 204) | UiWidget* SetFontScale(float scale) {
    method UiWidget (line 209) | UiWidget* SetIsButton(bool isButton) {
    method StartGraphics (line 215) | void StartGraphics() {
    method KillGraphics (line 221) | void KillGraphics() { CleanUp(&mIconGeom); }
    method PointBelongs (line 223) | bool PointBelongs(float x, float y) {
    method IsClickableButton (line 229) | bool IsClickableButton() { return mIsButton && mVisible && mEnabled; }

FILE: endless-tunnel/app/src/main/cpp/util.cpp
  function Random (line 21) | int Random(int uboundExclusive) {
  function Random (line 26) | int Random(int lbound, int uboundExclusive) {
  function Clock (line 32) | float Clock() {
  function SineWave (line 48) | float SineWave(float min, float max, float period, float phase) {
  function BlinkFunc (line 53) | bool BlinkFunc(float period) { return (int)(Clock() / period) & 1; }

FILE: endless-tunnel/app/src/main/cpp/util.hpp
  function CleanUp (line 24) | void CleanUp(T** pptr) {
  function T (line 35) | T Max(T a, T b) {
  function T (line 39) | T Min(T a, T b) {
  function T (line 43) | T Clamp(T v, T min, T max) {
  function T (line 51) | T Interpolate(T x1, T y1, T x2, T y2, T x) {
  function T (line 67) | T Approach(T orig, T target, T amount) {
  function T (line 80) | T Abs(T f) {
  class DeltaClock (line 91) | class DeltaClock {
    method DeltaClock (line 98) | DeltaClock() {
    method DeltaClock (line 102) | DeltaClock(float maxDelta) {
    method ReadDelta (line 107) | float ReadDelta() {
    method SetMaxDelta (line 112) | void SetMaxDelta(float m) { mMaxDelta = m; }
    method Reset (line 113) | void Reset() { mLastTick = Clock(); }

FILE: endless-tunnel/app/src/main/cpp/vertexbuf.hpp
  class VertexBuf (line 22) | class VertexBuf {
    method GetStride (line 38) | int GetStride() { return mStride; }
    method GetCount (line 39) | int GetCount() { return mCount; }
    method GetPositionsOffset (line 40) | int GetPositionsOffset() { return 0; }
    method HasColors (line 42) | bool HasColors() { return mColorsOffset > 0; }
    method GetColorsOffset (line 43) | int GetColorsOffset() { return mColorsOffset; }
    method SetColorsOffset (line 44) | void SetColorsOffset(int offset) { mColorsOffset = offset; }
    method HasTexCoords (line 46) | bool HasTexCoords() { return mTexCoordsOffset > 0; }
    method SetTexCoordsOffset (line 47) | void SetTexCoordsOffset(int offset) { mTexCoordsOffset = offset; }
    method GetTexCoordsOffset (line 48) | int GetTexCoordsOffset() { return mTexCoordsOffset; }
    method GLenum (line 50) | GLenum GetPrimitive() { return mPrimitive; }
    method SetPrimitive (line 51) | void SetPrimitive(GLenum primitive) { mPrimitive = primitive; }

FILE: endless-tunnel/app/src/main/cpp/welcome_scene.hpp
  class WelcomeScene (line 26) | class WelcomeScene : public UiScene {

FILE: exceptions/app/src/main/cpp/exception_helper.cpp
  function jmethodID (line 33) | static jmethodID FindMethod(JNIEnv* env, const char* className,
  function AppendJString (line 41) | static bool AppendJString(JNIEnv* env, jstring text, std::string* dst) {
  function GetExceptionSummary (line 56) | static bool GetExceptionSummary(JNIEnv* env, jthrowable thrown,
  function jstring (line 104) | static jstring CreateExceptionMsg(JNIEnv* env, const char* msg) {
  function DiscardPendingException (line 114) | static void DiscardPendingException(JNIEnv* env, const char* className) {
  function ThrowException (line 128) | static int ThrowException(JNIEnv* env, const char* className,
  function jniThrowException (line 195) | int jniThrowException(JNIEnv* env, const char* className, const char* ms...

FILE: exceptions/app/src/main/cpp/exception_helper.h
  function jniThrowRuntimeException (line 47) | static inline int jniThrowRuntimeException(JNIEnv* env, const char* msg) {

FILE: exceptions/app/src/main/cpp/native-lib.cpp
  function might_throw (line 8) | void might_throw() { throw std::runtime_error("A C++ runtime_error"); }
  function ThrowsException (line 10) | void ThrowsException(JNIEnv* env, jobject /* this */) {
  function JNIEXPORT (line 22) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: gles3jni/app/src/main/cpp/RendererES2.cpp
  class RendererES2 (line 41) | class RendererES2 : public Renderer {
  function Renderer (line 66) | Renderer* createES2Renderer() {

FILE: gles3jni/app/src/main/cpp/RendererES3.cpp
  class RendererES3 (line 51) | class RendererES3 : public Renderer {
  function Renderer (line 72) | Renderer* createES3Renderer() {

FILE: gles3jni/app/src/main/cpp/gles3jni.cpp
  function checkGlError (line 34) | bool checkGlError(const char* funcName) {
  function GLuint (line 43) | GLuint createShader(GLenum shaderType, const char* src) {
  function GLuint (line 73) | GLuint createProgram(const char* vtxSrc, const char* fragSrc) {
  function printGlString (line 117) | static void printGlString(const char* name, GLenum s) {
  function GLboolean (line 232) | static GLboolean gl3stubInit() { return GL_TRUE; }
  function Init (line 235) | void Init(JNIEnv*, jclass) {
  function Resize (line 256) | void Resize(JNIEnv*, jclass, jint width, jint height) {
  function Step (line 262) | void Step(JNIEnv*, jclass) {
  function JNIEXPORT (line 268) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: gles3jni/app/src/main/cpp/gles3jni.h
  type Vertex (line 56) | struct Vertex {
  function class (line 70) | class Renderer {

FILE: gles3jni/app/src/main/java/com/android/gles3jni/GLES3JNIActivity.java
  class GLES3JNIActivity (line 26) | public class GLES3JNIActivity extends Activity {
    method onCreate (line 30) | @Override protected void onCreate(Bundle icicle) {
    method onPause (line 36) | @Override protected void onPause() {
    method onResume (line 41) | @Override protected void onResume() {

FILE: gles3jni/app/src/main/java/com/android/gles3jni/GLES3JNILib.java
  class GLES3JNILib (line 21) | public class GLES3JNILib {
    method init (line 27) | public static native void init();
    method resize (line 28) | public static native void resize(int width, int height);
    method step (line 29) | public static native void step();

FILE: gles3jni/app/src/main/java/com/android/gles3jni/GLES3JNIView.java
  class GLES3JNIView (line 33) | class GLES3JNIView extends GLSurfaceView {
    method GLES3JNIView (line 37) | public GLES3JNIView(Context context) {
    class Renderer (line 46) | private static class Renderer implements GLSurfaceView.Renderer {
      method onDrawFrame (line 47) | public void onDrawFrame(GL10 gl) {
      method onSurfaceChanged (line 51) | public void onSurfaceChanged(GL10 gl, int width, int height) {
      method onSurfaceCreated (line 55) | public void onSurfaceCreated(GL10 gl, EGLConfig config) {

FILE: hello-gl2/app/src/main/cpp/gl_code.cpp
  function printGLString (line 32) | static void printGLString(const char* name, GLenum s) {
  function checkGlError (line 37) | static void checkGlError(const char* op) {
  function GLuint (line 55) | GLuint loadShader(GLenum shaderType, const char* pSource) {
  function GLuint (line 80) | GLuint createProgram(const char* pVertexSource, const char* pFragmentSou...
  function setupGraphics (line 121) | bool setupGraphics(int w, int h) {
  function renderFrame (line 144) | void renderFrame() {
  function Init (line 167) | void Init(JNIEnv*, jclass, jint width, jint height) {
  function Step (line 171) | void Step(JNIEnv*, jclass) { renderFrame(); }
  function JNIEXPORT (line 173) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: hello-gl2/app/src/main/java/com/android/gl2jni/GL2JNIActivity.java
  class GL2JNIActivity (line 27) | public class GL2JNIActivity extends Activity {
    method onCreate (line 31) | @Override protected void onCreate(Bundle icicle) {
    method onPause (line 37) | @Override protected void onPause() {
    method onResume (line 42) | @Override protected void onResume() {

FILE: hello-gl2/app/src/main/java/com/android/gl2jni/GL2JNILib.java
  class GL2JNILib (line 21) | public class GL2JNILib {
    method init (line 31) | public static native void init(int width, int height);
    method step (line 32) | public static native void step();

FILE: hello-gl2/app/src/main/java/com/android/gl2jni/GL2JNIView.java
  class GL2JNIView (line 67) | class GL2JNIView extends GLSurfaceView {
    method GL2JNIView (line 71) | public GL2JNIView(Context context) {
    method GL2JNIView (line 76) | public GL2JNIView(Context context, boolean translucent, int depth, int...
    method init (line 81) | private void init(boolean translucent, int depth, int stencil) {
    class ContextFactory (line 110) | private static class ContextFactory implements GLSurfaceView.EGLContex...
      method createContext (line 112) | public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLCo...
      method destroyContext (line 121) | public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext...
    method checkEglError (line 126) | private static void checkEglError(String prompt, EGL10 egl) {
    class ConfigChooser (line 133) | private static class ConfigChooser implements GLSurfaceView.EGLConfigC...
      method ConfigChooser (line 135) | public ConfigChooser(int r, int g, int b, int a, int depth, int sten...
      method chooseConfig (line 158) | public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
      method chooseConfig (line 184) | public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
      method findConfigAttrib (line 212) | private int findConfigAttrib(EGL10 egl, EGLDisplay display,
      method printConfigs (line 221) | private void printConfigs(EGL10 egl, EGLDisplay display,
      method printConfig (line 231) | private void printConfig(EGL10 egl, EGLDisplay display,
    class Renderer (line 326) | private static class Renderer implements GLSurfaceView.Renderer {
      method onDrawFrame (line 327) | public void onDrawFrame(GL10 gl) {
      method onSurfaceChanged (line 331) | public void onSurfaceChanged(GL10 gl, int width, int height) {
      method onSurfaceCreated (line 335) | public void onSurfaceCreated(GL10 gl, EGLConfig config) {

FILE: hello-jni/app/src/main/cpp/hello-jni.cpp
  function jstring (line 22) | jstring StringFromJni(JNIEnv* env, jobject) {
  function JNIEXPORT (line 27) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm, void* _Nullable) {

FILE: hello-jniCallback/app/src/main/cpp/hello-jnicallback.cpp
  type tick_context (line 35) | struct tick_context {
  function jstring (line 52) | jstring StringFromJni(JNIEnv* env, jobject) {
  function queryRuntimeInfo (line 94) | void queryRuntimeInfo(JNIEnv* env, jobject instance) {
  function sendJavaMsg (line 139) | void sendJavaMsg(JNIEnv* env, jobject instance, jmethodID func,
  type timeval (line 173) | struct timeval
  type timeval (line 174) | struct timeval
  type timespec (line 195) | struct timespec
  function StartTicks (line 216) | void StartTicks(JNIEnv* env, jobject instance) {
  function StopTicks (line 242) | void StopTicks(JNIEnv* env, jobject) {
  function JNIEXPORT (line 276) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {

FILE: hello-jniCallback/app/src/main/java/com/example/hellojnicallback/JniHandler.java
  class JniHandler (line 30) | public class JniHandler {
    method updateStatus (line 34) | @Keep
    method getBuildVersion (line 46) | @Keep
    method getRuntimeMemorySize (line 54) | @Keep

FILE: hello-jniCallback/app/src/main/java/com/example/hellojnicallback/MainActivity.java
  class MainActivity (line 23) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 29) | @Override
    method onResume (line 35) | @Override
    method onPause (line 43) | @Override
    method updateTimer (line 52) | @Keep
    method stringFromJNI (line 76) | public native  String stringFromJNI();
    method startTicks (line 77) | public native void startTicks();
    method StopTicks (line 78) | public native void StopTicks();

FILE: hello-vulkan/app/src/main/cpp/hellovk.h
  type UniformBufferObject (line 56) | struct UniformBufferObject {
  type QueueFamilyIndices (line 60) | struct QueueFamilyIndices {
  type SwapChainSupportDetails (line 68) | struct SwapChainSupportDetails {
  type ANativeWindowDeleter (line 74) | struct ANativeWindowDeleter {
  function VKAPI_CALL (line 128) | VKAPI_CALL
  function populateDebugMessengerCreateInfo (line 140) | static void populateDebugMessengerCreateInfo(
  function VkResult (line 153) | static VkResult CreateDebugUtilsMessengerEXT(
  function DestroyDebugUtilsMessengerEXT (line 166) | static void DestroyDebugUtilsMessengerEXT(
  function class (line 176) | class HelloVK {
  function initVulkan (line 280) | void HelloVK::initVulkan() {
  function createBuffer (line 308) | void HelloVK::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
  function findMemoryType (line 338) | uint32_t HelloVK::findMemoryType(uint32_t typeFilter,
  function createUniformBuffers (line 354) | void HelloVK::createUniformBuffers() {
  function createDescriptorSetLayout (line 368) | void HelloVK::createDescriptorSetLayout() {
  function reset (line 385) | void HelloVK::reset(ANativeWindow* newWindow, AAssetManager* newManager) {
  function recreateSwapChain (line 394) | void HelloVK::recreateSwapChain() {
  function render (line 402) | void HelloVK::render() {
  function getPrerotationMatrix (line 471) | void getPrerotationMatrix(const VkSurfaceTransformFlagBitsKHR& pretransf...
  function createDescriptorPool (line 486) | void HelloVK::createDescriptorPool() {
  function createDescriptorSets (line 500) | void HelloVK::createDescriptorSets() {
  function updateUniformBuffer (line 531) | void HelloVK::updateUniformBuffer(uint32_t currentImage) {
  function onOrientationChange (line 543) | void HelloVK::onOrientationChange() {
  function recordCommandBuffer (line 548) | void HelloVK::recordCommandBuffer(VkCommandBuffer commandBuffer,
  function cleanupSwapChain (line 597) | void HelloVK::cleanupSwapChain() {
  function cleanup (line 609) | void HelloVK::cleanup() {
  function setupDebugMessenger (line 639) | void HelloVK::setupDebugMessenger() {
  function checkValidationLayerSupport (line 651) | bool HelloVK::checkValidationLayerSupport() {
  function VkExtent2D (line 903) | VkExtent2D HelloVK::chooseSwapExtent(
  function establishDisplaySizeIdentity (line 924) | void HelloVK::establishDisplaySizeIdentity() {
  function chooseSwapSurfaceFormat (line 945) | auto chooseSwapSurfaceFormat =
  function createImageViews (line 1014) | void HelloVK::createImageViews() {
  function createRenderPass (line 1036) | void HelloVK::createRenderPass() {
  function createGraphicsPipeline (line 1103) | void HelloVK::createGraphicsPipeline() {

FILE: hello-vulkan/app/src/main/cpp/vk_main.cpp
  type VulkanEngine (line 42) | struct VulkanEngine {
    type android_app (line 43) | struct android_app
  function HandleCmd (line 52) | static void HandleCmd(struct android_app* app, int32_t cmd) {
  function VulkanKeyEventFilter (line 92) | bool VulkanKeyEventFilter(const GameActivityKeyEvent*) {
  function VulkanMotionEventFilter (line 95) | bool VulkanMotionEventFilter(const GameActivityMotionEvent*) {
  function HandleInputEvents (line 105) | static void HandleInputEvents(struct android_app* app) {
  function android_main (line 124) | void android_main(struct android_app* state) {

FILE: native-activity/app/src/main/cpp/main.cpp
  function fatal (line 27) | [[noreturn]] __attribute__((__format__(__printf__, 1, 2))) static void f...
  type Color (line 53) | enum class Color : uint32_t {
  class Engine (line 72) | class Engine {
    method Engine (line 74) | explicit Engine(android_app* app) : app_(app) {}
    method AttachWindow (line 76) | void AttachWindow() {
    method DetachWindow (line 95) | void DetachWindow() {
    method Resume (line 108) | void Resume() {
    method Pause (line 129) | void Pause() {
    method ScheduleNextTick (line 143) | void ScheduleNextTick() {
    method Tick (line 158) | static void Tick(long, void* data) {
    method DoTick (line 164) | void DoTick() {
    method Update (line 176) | void Update() {
    method DrawFrame (line 196) | void DrawFrame() const {
  function engine_handle_cmd (line 236) | static void engine_handle_cmd(android_app* app, int32_t cmd) {
  function android_main (line 279) | void android_main(android_app* state) {

FILE: native-audio/app/src/main/cpp/native-audio-jni.cpp
  function onDlOpen (line 119) | __attribute__((constructor)) static void onDlOpen(void) {
  function releaseResampleBuf (line 126) | void releaseResampleBuf(void) {
  function bqPlayerCallback (line 199) | void bqPlayerCallback([[maybe_unused]] SLAndroidSimpleBufferQueueItf bq,
  function bqRecorderCallback (line 222) | void bqRecorderCallback([[maybe_unused]] SLAndroidSimpleBufferQueueItf bq,
  function CreateEngine (line 238) | void CreateEngine(JNIEnv*, jclass) {
  function CreateBufferQueueAudioPlayer (line 289) | void CreateBufferQueueAudioPlayer(JNIEnv*, jclass, jint sampleRate,
  function jboolean (line 397) | jboolean CreateUriAudioPlayer(JNIEnv* env, jclass, jstring uri) {
  function SetPlayingUriAudioPlayer (line 470) | void SetPlayingUriAudioPlayer(JNIEnv*, jclass, jboolean isPlaying) {
  function SetLoopingUriAudioPlayer (line 485) | void SetLoopingUriAudioPlayer(JNIEnv*, jclass, jboolean isLooping) {
  function SLMuteSoloItf (line 501) | static SLMuteSoloItf getMuteSolo() {
  function SetChannelMuteUriAudioPlayer (line 510) | void SetChannelMuteUriAudioPlayer(JNIEnv*, jclass, jint chan, jboolean m...
  function SetChannelSoloUriAudioPlayer (line 520) | void SetChannelSoloUriAudioPlayer(JNIEnv*, jclass, jint chan, jboolean s...
  function jint (line 530) | jint GetNumChannelsUriAudioPlayer(JNIEnv*, jclass) {
  function SLVolumeItf (line 550) | static SLVolumeItf getVolume() {
  function SetVolumeUriAudioPlayer (line 559) | void SetVolumeUriAudioPlayer(JNIEnv*, jclass, jint millibel) {
  function SetMuteUriAudioPlayer (line 569) | void SetMuteUriAudioPlayer(JNIEnv*, jclass, jboolean mute) {
  function EnableStereoPositionUriAudioPlayer (line 579) | void EnableStereoPositionUriAudioPlayer(JNIEnv*, jclass, jboolean enable) {
  function SetStereoPositionUriAudioPlayer (line 589) | void SetStereoPositionUriAudioPlayer(JNIEnv*, jclass, jint permille) {
  function jboolean (line 600) | jboolean EnableReverb(JNIEnv*, jclass, jboolean enabled) {
  function jboolean (line 628) | jboolean SelectClip(JNIEnv*, jclass, jint which, jint count) {
  function jboolean (line 699) | jboolean CreateAssetAudioPlayer(JNIEnv* env, jclass, jobject assetManager,
  function SetPlayingAssetAudioPlayer (line 787) | void SetPlayingAssetAudioPlayer(JNIEnv*, jclass, jboolean isPlaying) {
  function jboolean (line 804) | jboolean CreateAudioRecorder(JNIEnv*, jclass) {
  function StartRecording (line 864) | void StartRecording(JNIEnv*, jclass) {
  function Shutdown (line 901) | void Shutdown(JNIEnv*, jclass) {
  function JNIEXPORT (line 960) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: native-audio/app/src/main/java/com/example/nativeaudio/NativeAudio.java
  class NativeAudio (line 40) | public class NativeAudio extends Activity
    method onCreate (line 62) | @Override
    method recordAudio (line 316) | private void recordAudio() {
    method onPause (line 326) | @Override
    method onDestroy (line 339) | @Override
    method onRequestPermissionsResult (line 345) | @Override
    method createEngine (line 378) | public static native void createEngine();
    method createBufferQueueAudioPlayer (line 379) | public static native void createBufferQueueAudioPlayer(int sampleRate,...
    method createAssetAudioPlayer (line 380) | public static native boolean createAssetAudioPlayer(AssetManager asset...
    method setPlayingAssetAudioPlayer (line 382) | public static native void setPlayingAssetAudioPlayer(boolean isPlaying);
    method createUriAudioPlayer (line 383) | public static native boolean createUriAudioPlayer(String uri);
    method setPlayingUriAudioPlayer (line 384) | public static native void setPlayingUriAudioPlayer(boolean isPlaying);
    method setLoopingUriAudioPlayer (line 385) | public static native void setLoopingUriAudioPlayer(boolean isLooping);
    method setChannelMuteUriAudioPlayer (line 386) | public static native void setChannelMuteUriAudioPlayer(int chan, boole...
    method setChannelSoloUriAudioPlayer (line 387) | public static native void setChannelSoloUriAudioPlayer(int chan, boole...
    method getNumChannelsUriAudioPlayer (line 388) | public static native int getNumChannelsUriAudioPlayer();
    method setVolumeUriAudioPlayer (line 389) | public static native void setVolumeUriAudioPlayer(int millibel);
    method setMuteUriAudioPlayer (line 390) | public static native void setMuteUriAudioPlayer(boolean mute);
    method enableStereoPositionUriAudioPlayer (line 391) | public static native void enableStereoPositionUriAudioPlayer(boolean e...
    method setStereoPositionUriAudioPlayer (line 392) | public static native void setStereoPositionUriAudioPlayer(int permille);
    method selectClip (line 393) | public static native boolean selectClip(int which, int count);
    method enableReverb (line 394) | public static native boolean enableReverb(boolean enabled);
    method createAudioRecorder (line 395) | public static native boolean createAudioRecorder();
    method startRecording (line 396) | public static native void startRecording();
    method shutdown (line 397) | public static native void shutdown();

FILE: native-codec/app/src/main/cpp/looper.cpp
  type loopermessage (line 37) | struct loopermessage
  type loopermessage (line 38) | struct loopermessage
  type loopermessage (line 40) | struct loopermessage {

FILE: native-codec/app/src/main/cpp/looper.h
  type loopermessage (line 20) | struct loopermessage
  function class (line 22) | class looper {

FILE: native-codec/app/src/main/cpp/native-codec-jni.cpp
  class mylooper (line 77) | class mylooper : public looper {
  function systemnanotime (line 83) | int64_t systemnanotime() {
  function doCodecWork (line 89) | void doCodecWork(workerdata* d) {
  function jboolean (line 200) | jboolean CreateStreamingMediaPlayer(JNIEnv* env, jclass, jobject assetMgr,
  function SetPlayingStreamingMediaPlayer (line 270) | void SetPlayingStreamingMediaPlayer(JNIEnv*, jclass, jboolean isPlaying) {
  function Shutdown (line 282) | void Shutdown(JNIEnv*, jclass) {
  function SetSurface (line 297) | void SetSurface(JNIEnv* env, jclass, jobject surface) {
  function RewindStreamingMediaPlayer (line 308) | void RewindStreamingMediaPlayer(JNIEnv*, jclass) {
  function JNIEXPORT (line 315) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: native-codec/app/src/main/java/com/example/nativecodec/MyGLSurfaceView.java
  class MyGLSurfaceView (line 36) | public class MyGLSurfaceView extends GLSurfaceView {
    method MyGLSurfaceView (line 40) | public MyGLSurfaceView(Context context) {
    method MyGLSurfaceView (line 44) | public MyGLSurfaceView(Context context, AttributeSet attributeSet) {
    method init (line 49) | private void init() {
    method onPause (line 56) | @Override
    method onResume (line 62) | @Override
    method getSurfaceTexture (line 68) | public SurfaceTexture getSurfaceTexture() {
  class MyRenderer (line 73) | class MyRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFra...
    method MyRenderer (line 75) | public MyRenderer() {
    method onPause (line 82) | public void onPause() {
    method onResume (line 85) | public void onResume() {
    method onDrawFrame (line 89) | @Override
    method onSurfaceChanged (line 139) | @Override
    method onSurfaceCreated (line 148) | @Override
    method onFrameAvailable (line 224) | @Override
    method loadShader (line 234) | private int loadShader(int shaderType, String source) {
    method createProgram (line 251) | private int createProgram(String vertexSource, String fragmentSource) {
    method checkGlError (line 280) | private void checkGlError(String op) {
    method getSurfaceTexture (line 346) | public SurfaceTexture getSurfaceTexture() {

FILE: native-codec/app/src/main/java/com/example/nativecodec/NativeCodec.java
  class NativeCodec (line 38) | public class NativeCodec extends Activity {
    method onCreate (line 56) | @Override
    method switchSurface (line 205) | void switchSurface() {
    method onPause (line 222) | @Override
    method onResume (line 231) | @Override
    method onDestroy (line 240) | @Override
    method createEngine (line 255) | public static native void createEngine();
    method createStreamingMediaPlayer (line 256) | public static native boolean createStreamingMediaPlayer(AssetManager a...
    method setPlayingStreamingMediaPlayer (line 257) | public static native void setPlayingStreamingMediaPlayer(boolean isPla...
    method shutdown (line 258) | public static native void shutdown();
    method setSurface (line 259) | public static native void setSurface(Surface surface);
    method rewindStreamingMediaPlayer (line 260) | public static native void rewindStreamingMediaPlayer();
    class VideoSink (line 269) | static abstract class VideoSink {
      method setFixedSize (line 271) | abstract void setFixedSize(int width, int height);
      method useAsSinkForNative (line 272) | abstract void useAsSinkForNative();
    class SurfaceHolderVideoSink (line 276) | static class SurfaceHolderVideoSink extends VideoSink {
      method SurfaceHolderVideoSink (line 280) | SurfaceHolderVideoSink(SurfaceHolder surfaceHolder) {
      method setFixedSize (line 284) | @Override
      method useAsSinkForNative (line 289) | @Override
    class GLViewVideoSink (line 298) | static class GLViewVideoSink extends VideoSink {
      method GLViewVideoSink (line 302) | GLViewVideoSink(MyGLSurfaceView myGLSurfaceView) {
      method setFixedSize (line 306) | @Override
      method useAsSinkForNative (line 310) | @Override

FILE: native-midi/app/src/main/cpp/AppMidiManager.cpp
  function SendTheReceivedData (line 47) | static void SendTheReceivedData(uint8_t* data, int numBytes) {
  function logMidiBuffer (line 70) | static void logMidiBuffer(int64_t timestamp, uint8_t* dataBytes, size_t ...
  function Java_com_example_nativemidi_AppMidiManager_startReadingMidi (line 146) | void Java_com_example_nativemidi_AppMidiManager_startReadingMidi(
  function Java_com_example_nativemidi_AppMidiManager_stopReadingMidi (line 169) | void Java_com_example_nativemidi_AppMidiManager_stopReadingMidi(JNIEnv*,
  function Java_com_example_nativemidi_AppMidiManager_startWritingMidi (line 190) | void Java_com_example_nativemidi_AppMidiManager_startWritingMidi(
  function Java_com_example_nativemidi_AppMidiManager_stopWritingMidi (line 207) | void Java_com_example_nativemidi_AppMidiManager_stopWritingMidi(JNIEnv*,
  function Java_com_example_nativemidi_AppMidiManager_writeMidi (line 226) | void Java_com_example_nativemidi_AppMidiManager_writeMidi(JNIEnv* env, j...

FILE: native-midi/app/src/main/cpp/MainActivity.cpp
  function InitNative (line 29) | void InitNative(JNIEnv* env, jobject instance) {
  function JNIEXPORT (line 40) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: native-midi/app/src/main/java/com/example/nativemidi/AppMidiManager.java
  class AppMidiManager (line 27) | public class AppMidiManager {
    method AppMidiManager (line 40) | public AppMidiManager(MidiManager midiManager) {
    method GetMidiManager (line 44) | public MidiManager GetMidiManager() {
    method ScanMidiDevices (line 53) | public void ScanMidiDevices(ArrayList<MidiDeviceInfo> sendDevices,
    class OpenMidiReceiveDeviceListener (line 79) | public class OpenMidiReceiveDeviceListener implements MidiManager.OnDe...
      method onDeviceOpened (line 80) | @Override
    method openReceiveDevice (line 87) | public void openReceiveDevice(MidiDeviceInfo devInfo) {
    method closeReceiveDevice (line 91) | public void closeReceiveDevice() {
    class OpenMidiSendDeviceListener (line 101) | public class OpenMidiSendDeviceListener implements MidiManager.OnDevic...
      method onDeviceOpened (line 102) | @Override
    method openSendDevice (line 109) | public void openSendDevice(MidiDeviceInfo devInfo) {
    method closeSendDevice (line 113) | public void closeSendDevice() {
    method sendMessages (line 120) | private void sendMessages(byte[] msgBuff) {
    method sendNoteOn (line 127) | public void sendNoteOn(byte chan, byte[] keys, byte[] velocities) {
    method sendNoteOff (line 133) | public void sendNoteOff(byte chan, byte[] keys, byte[] velocities) {
    method sendController (line 139) | public void sendController(byte chan, byte controller, byte value) {
    method sendPitchBend (line 147) | public void sendPitchBend(byte chan, int value) {
    method sendProgramChange (line 155) | public void sendProgramChange(byte chan, byte value) {
    method loadNativeAPI (line 165) | public static void loadNativeAPI() {
    method startReadingMidi (line 169) | public native void startReadingMidi(MidiDevice receiveDevice, int port...
    method stopReadingMidi (line 170) | public native void stopReadingMidi();
    method startWritingMidi (line 172) | public native void startWritingMidi(MidiDevice sendDevice, int portNum...
    method stopWritingMidi (line 173) | public native void stopWritingMidi();
    method writeMidi (line 174) | public native void writeMidi(byte[] data, int length);

FILE: native-midi/app/src/main/java/com/example/nativemidi/MainActivity.java
  class MainActivity (line 46) | public class MainActivity extends Activity
    method onCreate (line 76) | @Override
    class MidiDeviceCallback (line 128) | private class MidiDeviceCallback extends MidiManager.DeviceCallback {
      method onDeviceAdded (line 129) | @Override
      method onDeviceRemoved (line 134) | @Override
    method ScanMidiDevices (line 146) | private void ScanMidiDevices() {
    method showReceivedMessage (line 158) | private void showReceivedMessage(byte[] message) {
    method onClick (line 181) | @Override
    method onProgressChanged (line 215) | @Override
    method onStartTrackingTouch (line 228) | @Override
    method onStopTrackingTouch (line 231) | @Override
    method onItemSelected (line 237) | @Override
    method onNothingSelected (line 254) | @Override
    class MidiDeviceListItem (line 260) | private class MidiDeviceListItem {
      method MidiDeviceListItem (line 263) | public MidiDeviceListItem(MidiDeviceInfo deviceInfo) {
      method getDeviceInfo (line 267) | public MidiDeviceInfo getDeviceInfo() { return mDeviceInfo; }
      method toString (line 269) | @Override
    method fillDeviceList (line 280) | private void fillDeviceList(Spinner spinner, ArrayList<MidiDeviceInfo>...
    method onDeviceListChange (line 301) | private void onDeviceListChange() {
    method initNative (line 309) | private native void initNative();
    method onNativeMessageReceive (line 315) | private void onNativeMessageReceive(final byte[] message) {

FILE: native-midi/app/src/main/java/com/example/nativemidi/MidiDataHelper.java
  class MidiDataHelper (line 21) | class MidiDataHelper {
    method make3ByteMsgBuff (line 38) | static byte[] make3ByteMsgBuff(
    method make2ByteMsgBuff (line 78) | static byte[] make2ByteMsgBuff(

FILE: native-midi/app/src/main/java/com/example/nativemidi/MidiSpec.java
  class MidiSpec (line 20) | public class MidiSpec {
    method makeChanMessageCode (line 43) | public static byte makeChanMessageCode(byte msg, byte chan) {

FILE: orderfile/app/src/main/cpp/orderfile.cpp
  function DumpProfileDataIfNeeded (line 17) | void DumpProfileDataIfNeeded(const char* temp_dir) {
  function RunWorkload (line 51) | void RunWorkload(JNIEnv* env, jobject /* this */, jstring temp_dir) {
  function JNIEXPORT (line 55) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: sanitizers/app/src/main/cpp/native-lib.cpp
  function jstring (line 6) | jstring StringFromJni(JNIEnv* env, jobject /* this */) {
  function JNIEXPORT (line 21) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: sensor-graph/accelerometer/src/main/cpp/sensorgraph.cpp
  function ASensorManager (line 47) | ASensorManager* AcquireASensorManagerInstance(void) {
  class sensorgraph (line 65) | class sensorgraph {
    type AccelerometerData (line 79) | struct AccelerometerData {
    method sensorgraph (line 89) | sensorgraph() : sensorDataIndex(0) {}
    method init (line 91) | void init(AAssetManager* assetManager) {
    method surfaceCreated (line 133) | void surfaceCreated() {
    method surfaceChanged (line 155) | void surfaceChanged(int w, int h) { glViewport(0, 0, w, h); }
    method generateXPos (line 157) | void generateXPos() {
    method GLuint (line 165) | GLuint createProgram(const std::string& pVertexSource,
    method GLuint (line 182) | GLuint loadShader(GLenum shaderType, const std::string& pSource) {
    method update (line 194) | void update() {
    method render (line 212) | void render() {
    method pause (line 242) | void pause() {
    method resume (line 246) | void resume() {
  function Init (line 256) | void Init(JNIEnv* env, jclass, jobject assetManager) {
  function SurfaceCreated (line 261) | void SurfaceCreated(JNIEnv*, jclass) { gSensorGraph.surfaceCreated(); }
  function SurfaceChanged (line 263) | void SurfaceChanged(JNIEnv*, jclass, jint width, jint height) {
  function DrawFrame (line 267) | void DrawFrame(JNIEnv*, jclass) {
  function Pause (line 272) | void Pause(JNIEnv*, jclass) { gSensorGraph.pause(); }
  function Resume (line 274) | void Resume(JNIEnv*, jclass) { gSensorGraph.resume(); }
  function JNIEXPORT (line 276) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: sensor-graph/accelerometer/src/main/java/com/android/accelerometergraph/AccelerometerGraphActivity.java
  class AccelerometerGraphActivity (line 27) | public class AccelerometerGraphActivity extends Activity {
    method onCreate (line 31) | @Override protected void onCreate(Bundle icicle) {
    method onPause (line 60) | @Override protected void onPause() {
    method onResume (line 71) | @Override protected void onResume() {

FILE: sensor-graph/accelerometer/src/main/java/com/android/accelerometergraph/AccelerometerGraphJNI.java
  class AccelerometerGraphJNI (line 23) | public class AccelerometerGraphJNI {
    method init (line 29) | public static native void init(AssetManager assetManager);
    method surfaceCreated (line 30) | public static native void surfaceCreated();
    method surfaceChanged (line 31) | public static native void surfaceChanged(int width, int height);
    method drawFrame (line 32) | public static native void drawFrame();
    method pause (line 33) | public static native void pause();
    method resume (line 34) | public static native void resume();

FILE: teapots/choreographer-30fps/src/main/cpp/ChoreographerNativeActivity.cpp
  type APIMode (line 38) | enum APIMode {
  type AChoreographer (line 52) | struct AChoreographer
  type android_app (line 62) | struct android_app
  class Engine (line 63) | class Engine {
    type android_app (line 116) | struct android_app
  function ChoregrapherCallback (line 307) | void ChoregrapherCallback(JNIEnv*, jobject, jlong frameTimeInNanos) {
  type android_app (line 481) | struct android_app
  function android_main (line 579) | void android_main(android_app* state) {
  function JNIEXPORT (line 615) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: teapots/choreographer-30fps/src/main/cpp/TeapotRenderer.h
  type TEAPOT_VERTEX (line 43) | struct TEAPOT_VERTEX {
  type SHADER_ATTRIBUTES (line 48) | enum SHADER_ATTRIBUTES {
  type SHADER_PARAMS (line 54) | struct SHADER_PARAMS {
  type TEAPOT_MATERIALS (line 65) | struct TEAPOT_MATERIALS {
  function class (line 71) | class TeapotRenderer {

FILE: teapots/choreographer-30fps/src/main/java/com/sample/choreographer/ChoreographerApplication.java
  class ChoreographerApplication (line 33) | public class ChoreographerApplication extends Application {
    method onCreate (line 34) | public void onCreate(){

FILE: teapots/choreographer-30fps/src/main/java/com/sample/choreographer/ChoreographerNativeActivity.java
  class ChoreographerNativeActivity (line 34) | public class ChoreographerNativeActivity extends NativeActivity
    method doFrame (line 45) | @TargetApi(16)
    method startChoreographer (line 52) | @TargetApi(16)
    method stopChoreographer (line 59) | @TargetApi(16)
    method choregrapherCallback (line 64) | protected native void choregrapherCallback(long frameTimeNamos);
    method onCreate (line 66) | @Override
    method onResume (line 84) | @TargetApi(19)
    method onPause (line 104) | protected void onPause()
    method setImmersiveSticky (line 114) | @TargetApi(19)
    method showUI (line 129) | @SuppressLint("InflateParams")
    method updateFPS (line 163) | public void updateFPS(final float fFPS)

FILE: teapots/choreographer-30fps/src/main/java/com/sample/helper/NDKHelper.java
  class NDKHelper (line 48) | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    method NDKHelper (line 51) | public NDKHelper(NativeActivity act) {
    method loadLibrary (line 55) | public void loadLibrary(String soname) {
    method checkSOLoaded (line 62) | public static Boolean checkSOLoaded() {
    method nextPOT (line 84) | private int nextPOT(int i) {
    method scaleBitmap (line 91) | private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth,
    class TextureInformation (line 110) | public class TextureInformation {
    method loadTexture (line 118) | public Object loadTexture(String path) {
    method loadCubemapTexture (line 159) | public Object loadCubemapTexture(String path, int face, int miplevel, ...
    method loadImage (line 208) | public Object loadImage(String path) {
    method openBitmap (line 246) | public Bitmap openBitmap(String path, boolean iScalePOT) {
    method getBitmapWidth (line 269) | public int getBitmapWidth(Bitmap bmp) {
    method getBitmapHeight (line 273) | public int getBitmapHeight(Bitmap bmp) {
    method getBitmapPixels (line 277) | public void getBitmapPixels(Bitmap bmp, int[] pixels) {
    method closeBitmap (line 283) | public void closeBitmap(Bitmap bmp) {
    method getNativeLibraryDirectory (line 287) | public String getNativeLibraryDirectory(Context appContext) {
    method getApplicationName (line 299) | public String getApplicationName() {
    method getStringResource (line 312) | public String getStringResource(String resourceName)
    method getNativeAudioBufferSize (line 322) | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    method getNativeAudioSampleRate (line 336) | public int getNativeAudioSampleRate() {
    method runOnUIThread (line 343) | public void runOnUIThread(final long p) {
    method RunOnUiThreadHandler (line 358) | native public void RunOnUiThreadHandler(long pointer);

FILE: teapots/classic-teapot/src/main/cpp/TeapotNativeActivity.cpp
  type android_app (line 38) | struct android_app
  class Engine (line 39) | class Engine {
    type android_app (line 65) | struct android_app
  type android_app (line 255) | struct android_app
  function android_main (line 389) | void android_main(android_app* state) {

FILE: teapots/classic-teapot/src/main/cpp/TeapotRenderer.h
  type TEAPOT_VERTEX (line 43) | struct TEAPOT_VERTEX {
  type SHADER_ATTRIBUTES (line 48) | enum SHADER_ATTRIBUTES {
  type SHADER_PARAMS (line 54) | struct SHADER_PARAMS {
  type TEAPOT_MATERIALS (line 65) | struct TEAPOT_MATERIALS {
  function class (line 71) | class TeapotRenderer {

FILE: teapots/classic-teapot/src/main/java/com/sample/helper/NDKHelper.java
  class NDKHelper (line 48) | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    method NDKHelper (line 51) | public NDKHelper(NativeActivity act) {
    method loadLibrary (line 55) | public void loadLibrary(String soname) {
    method checkSOLoaded (line 62) | public static Boolean checkSOLoaded() {
    method nextPOT (line 84) | private int nextPOT(int i) {
    method scaleBitmap (line 91) | private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth,
    class TextureInformation (line 110) | public class TextureInformation {
    method loadTexture (line 118) | public Object loadTexture(String path) {
    method loadCubemapTexture (line 159) | public Object loadCubemapTexture(String path, int face, int miplevel, ...
    method loadImage (line 208) | public Object loadImage(String path) {
    method openBitmap (line 246) | public Bitmap openBitmap(String path, boolean iScalePOT) {
    method getBitmapWidth (line 269) | public int getBitmapWidth(Bitmap bmp) {
    method getBitmapHeight (line 273) | public int getBitmapHeight(Bitmap bmp) {
    method getBitmapPixels (line 277) | public void getBitmapPixels(Bitmap bmp, int[] pixels) {
    method closeBitmap (line 283) | public void closeBitmap(Bitmap bmp) {
    method getNativeLibraryDirectory (line 287) | public String getNativeLibraryDirectory(Context appContext) {
    method getApplicationName (line 299) | public String getApplicationName() {
    method getStringResource (line 312) | public String getStringResource(String resourceName)
    method getNativeAudioBufferSize (line 322) | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    method getNativeAudioSampleRate (line 336) | public int getNativeAudioSampleRate() {
    method runOnUIThread (line 343) | public void runOnUIThread(final long p) {
    method RunOnUiThreadHandler (line 358) | native public void RunOnUiThreadHandler(long pointer);

FILE: teapots/classic-teapot/src/main/java/com/sample/teapot/TeapotApplication.java
  class TeapotApplication (line 33) | public class TeapotApplication extends Application {
    method onCreate (line 34) | public void onCreate(){

FILE: teapots/classic-teapot/src/main/java/com/sample/teapot/TeapotNativeActivity.java
  class TeapotNativeActivity (line 32) | public class TeapotNativeActivity extends NativeActivity {
    method onCreate (line 33) | @Override
    method onResume (line 54) | @TargetApi(19)
    method setImmersiveSticky (line 76) | @TargetApi(19)
    method showUI (line 91) | @SuppressLint("InflateParams")
    method onPause (line 125) | protected void onPause()
    method updateFPS (line 130) | public void updateFPS(final float fFPS)

FILE: teapots/common/ndk_helper/GLContext.cpp
  type ndk_helper (line 30) | namespace ndk_helper {
    function EGLint (line 161) | EGLint GLContext::Swap() {
    function EGLint (line 200) | EGLint GLContext::Resume(ANativeWindow* window) {

FILE: teapots/common/ndk_helper/GLContext.h
  function namespace (line 29) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/JNIHelper.cpp
  type ndk_helper (line 26) | namespace ndk_helper {
    function JNIHelper (line 37) | JNIHelper* JNIHelper::GetInstance() {
    function jobject (line 337) | jobject JNIHelper::LoadImage(const char* file_name, int32_t* outWidth,
    function jclass (line 500) | jclass JNIHelper::RetrieveClass(JNIEnv* jni, const char* class_name) {
    function jstring (line 518) | jstring JNIHelper::GetExternalFilesDirJString(JNIEnv* env) {
    function jobject (line 551) | jobject JNIHelper::CallObjectMethod(const char* strMethodName,
    function jobject (line 600) | jobject JNIHelper::CallObjectMethod(jobject object, const char* strMet...
    function jobject (line 730) | jobject JNIHelper::CreateObject(const char* class_name) {
    function JNIEXPORT (line 759) | JNIEXPORT void Java_com_sample_helper_NDKHelper_RunOnUiThreadHandler(

FILE: teapots/common/ndk_helper/JNIHelper.h
  function namespace (line 43) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/gestureDetector.cpp
  type ndk_helper (line 22) | namespace ndk_helper {
    function GESTURE_STATE (line 42) | GESTURE_STATE TapDetector::Detect(const AInputEvent* motion_event) {
    function GESTURE_STATE (line 81) | GESTURE_STATE DoubletapDetector::Detect(const AInputEvent* motion_even...
    function GESTURE_STATE (line 132) | GESTURE_STATE PinchDetector::Detect(const AInputEvent* event) {
    function GESTURE_STATE (line 228) | GESTURE_STATE DragDetector::Detect(const AInputEvent* event) {

FILE: teapots/common/ndk_helper/gestureDetector.h
  function namespace (line 33) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/gl3stub.c
  function GLboolean (line 21) | GLboolean gl3stubInit() {

FILE: teapots/common/ndk_helper/gl3stub.cpp
  function GLboolean (line 21) | GLboolean gl3stubInit() {

FILE: teapots/common/ndk_helper/gl3stub.h
  type GLhalf (line 68) | typedef unsigned short GLhalf;
  type khronos_int64_t (line 70) | typedef khronos_int64_t GLint64;
  type khronos_uint64_t (line 71) | typedef khronos_uint64_t GLuint64;
  type __GLsync (line 72) | struct __GLsync

FILE: teapots/common/ndk_helper/interpolator.cpp
  type ndk_helper (line 23) | namespace ndk_helper {
    function Interpolator (line 37) | Interpolator& Interpolator::Set(const float start, const float dest,
    function Interpolator (line 50) | Interpolator& Interpolator::Add(const float dest, const INTERPOLATOR_T...

FILE: teapots/common/ndk_helper/interpolator.h
  function namespace (line 29) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/perfMonitor.cpp
  type ndk_helper (line 19) | namespace ndk_helper {
    type timeval (line 42) | struct timeval

FILE: teapots/common/ndk_helper/perfMonitor.h
  function namespace (line 26) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/sensorManager.cpp
  type ndk_helper (line 24) | namespace ndk_helper {
    function ASensorManager (line 67) | ASensorManager* AcquireASensorManagerInstance(android_app* app) {

FILE: teapots/common/ndk_helper/sensorManager.h
  function namespace (line 27) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/shader.cpp
  type ndk_helper (line 25) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/shader.h
  function namespace (line 31) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/tapCamera.cpp
  type ndk_helper (line 26) | namespace ndk_helper {
    function Mat4 (line 169) | Mat4& TapCamera::GetRotationMatrix() { return mat_rotation_; }
    function Mat4 (line 171) | Mat4& TapCamera::GetTransformMatrix() { return mat_transform_; }
    function Vec3 (line 310) | Vec3 TapCamera::PointOnSphere(Vec2& point) {

FILE: teapots/common/ndk_helper/tapCamera.h
  function namespace (line 27) | namespace ndk_helper {

FILE: teapots/common/ndk_helper/vecmath.cpp
  type ndk_helper (line 22) | namespace ndk_helper {
    function Vec4 (line 36) | Vec4 Vec4::operator*(const Mat4& rhs) const {
    function Mat4 (line 61) | Mat4 Mat4::operator*(const Mat4& rhs) const {
    function Vec4 (line 102) | Vec4 Mat4::operator*(const Vec4& rhs) const {
    function Mat4 (line 111) | Mat4 Mat4::Inverse() {
    function Mat4 (line 185) | Mat4 Mat4::RotationX(const float fAngle) {
    function Mat4 (line 211) | Mat4 Mat4::RotationY(const float fAngle) {
    function Mat4 (line 237) | Mat4 Mat4::RotationZ(const float fAngle) {
    function Mat4 (line 263) | Mat4 Mat4::Scale(const float scaleX, const float scaleY, const float s...
    function Mat4 (line 275) | Mat4 Mat4::Translation(const float fX, const float fY, const float fZ) {
    function Mat4 (line 296) | Mat4 Mat4::Translation(const Vec3 vec) {
    function Mat4 (line 317) | Mat4 Mat4::Perspective(float width, float height, float nearPlane,
    function Mat4 (line 343) | Mat4 Mat4::Ortho2D(float left, float top, float right, float bottom) {
    function Mat4 (line 373) | Mat4 Mat4::LookAt(const Vec3& vec_eye, const Vec3& vec_at, const Vec3&...

FILE: teapots/common/ndk_helper/vecmath.h
  function namespace (line 24) | namespace ndk_helper {
  function Vec2 (line 75) | Vec2 operator/(const Vec2& rhs) const {
  function Vec2 (line 151) | Vec2 operator/(const float& rhs) const {
  function operator (line 165) | bool operator==(const Vec2& rhs) const {
  function operator (line 170) | bool operator!=(const Vec2& rhs) const {
  function Vec2 (line 178) | Vec2 Normalize() {
  function Dot (line 185) | float Dot(const Vec2& rhs) { return x_ * rhs.x_ + y_ * rhs.y_; }
  function Validate (line 187) | bool Validate() {
  function Value (line 192) | void Value(float& fX, float& fY) {
  function Dump (line 197) | void Dump() { LOGI("Vec2 %f %f", x_, y_); }
  function class (line 204) | class Vec3 {
  function Vec3 (line 244) | Vec3 operator/(const Vec3& rhs) const {
  function Vec3 (line 331) | Vec3 operator/(const float& rhs) const {
  function operator (line 347) | bool operator==(const Vec3& rhs) const {
  function operator (line 352) | bool operator!=(const Vec3& rhs) const {
  function Vec3 (line 360) | Vec3 Normalize() {
  function Dot (line 368) | float Dot(const Vec3& rhs) { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs...
  function Vec3 (line 370) | Vec3 Cross(const Vec3& rhs) {
  function Validate (line 378) | bool Validate() {
  function Value (line 383) | void Value(float& fX, float& fY, float& fZ) {
  function Dump (line 389) | void Dump() { LOGI("Vec3 %f %f %f", x_, y_, z_); }
  function class (line 396) | class Vec4 {
  function fW (line 421) | float fW) {
  function Vec4 (line 445) | Vec4 operator/(const Vec4& rhs) const {
  function Vec4 (line 543) | Vec4 operator/(const float& rhs) const {
  function operator (line 561) | bool operator==(const Vec4& rhs) const {
  function operator (line 567) | bool operator!=(const Vec4& rhs) const {
  function Vec4 (line 577) | Vec4 Normalize() {
  function Dot (line 586) | float Dot(const Vec3& rhs) { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs...
  function Vec3 (line 588) | Vec3 Cross(const Vec3& rhs) {
  function Validate (line 596) | bool Validate() {
  function Value (line 603) | void Value(float& fX, float& fY, float& fZ, float& fW) {
  function class (line 615) | class Mat4 {
  function Mat4 (line 727) | Mat4 Transpose() {
  function Mat4 (line 779) | static Mat4 Identity() {
  function Dump (line 800) | void Dump() {
  function class (line 812) | class Quaternion {
  function Quaternion (line 868) | Quaternion Conjugate() {
  function Quaternion (line 876) | Quaternion Conjugated() {
  function ToMatrix (line 885) | void ToMatrix(Mat4& mat) {
  function ToMatrixPreserveTranslate (line 911) | void ToMatrixPreserveTranslate(Mat4& mat) {
  function Quaternion (line 936) | static Quaternion RotationAxis(const Vec3 axis, const float angle) {
  function Value (line 946) | void Value(float& fX, float& fY, float& fZ, float& fW) {

FILE: teapots/image-decoder/src/main/cpp/ImageDecoderRender.cpp
  function GLint (line 56) | GLint ImageDecoderRender::GetTextureType(void) { return GL_TEXTURE_CUBE_...

FILE: teapots/image-decoder/src/main/cpp/ImageDecoderRender.h
  function class (line 28) | class ImageDecoderRender : public TeapotRenderer {

FILE: teapots/image-decoder/src/main/cpp/TeapotNativeActivity.cpp
  type android_app (line 38) | struct android_app
  class Engine (line 39) | class Engine {
    type android_app (line 65) | struct android_app
  type android_app (line 255) | struct android_app
  function android_main (line 389) | void android_main(android_app* state) {

FILE: teapots/image-decoder/src/main/cpp/TeapotRenderer.h
  type TEAPOT_VERTEX (line 43) | struct TEAPOT_VERTEX {
  type SHADER_ATTRIBUTES (line 48) | enum SHADER_ATTRIBUTES {
  type SHADER_PARAMS (line 54) | struct SHADER_PARAMS {
  type TEAPOT_MATERIALS (line 65) | struct TEAPOT_MATERIALS {
  function class (line 71) | class TeapotRenderer {

FILE: teapots/image-decoder/src/main/cpp/Texture.cpp
  function Load2DTextureFromAsset (line 31) | static bool Load2DTextureFromAsset(std::string& assetFile, AAssetManager...
  class TextureCubemap (line 102) | class TextureCubemap : public Texture {
  class Texture2d (line 118) | class Texture2d : public Texture {
  function Texture (line 152) | Texture* Texture::Create(GLuint type, std::vector<std::string>& texFiles,
  function GLuint (line 205) | GLuint TextureCubemap::GetTexType() { return GL_TEXTURE_CUBE_MAP; }
  function GLuint (line 207) | GLuint TextureCubemap::GetTexId() {
  function GLuint (line 327) | GLuint Texture2d::GetTexType() { return GL_TEXTURE_2D; }
  function GLuint (line 329) | GLuint Texture2d::GetTexId() { return texId_; }

FILE: teapots/image-decoder/src/main/cpp/Texture.h
  function class (line 38) | class Texture {

FILE: teapots/image-decoder/src/main/java/com/sample/helper/NDKHelper.java
  class NDKHelper (line 48) | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    method NDKHelper (line 51) | public NDKHelper(NativeActivity act) {
    method loadLibrary (line 55) | public void loadLibrary(String soname) {
    method checkSOLoaded (line 62) | public static Boolean checkSOLoaded() {
    method nextPOT (line 84) | private int nextPOT(int i) {
    method scaleBitmap (line 91) | private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth,
    class TextureInformation (line 110) | public class TextureInformation {
    method loadTexture (line 118) | public Object loadTexture(String path) {
    method loadCubemapTexture (line 159) | public Object loadCubemapTexture(String path, int face, int miplevel, ...
    method loadImage (line 208) | public Object loadImage(String path) {
    method openBitmap (line 246) | public Bitmap openBitmap(String path, boolean iScalePOT) {
    method getBitmapWidth (line 269) | public int getBitmapWidth(Bitmap bmp) {
    method getBitmapHeight (line 273) | public int getBitmapHeight(Bitmap bmp) {
    method getBitmapPixels (line 277) | public void getBitmapPixels(Bitmap bmp, int[] pixels) {
    method closeBitmap (line 283) | public void closeBitmap(Bitmap bmp) {
    method getNativeLibraryDirectory (line 287) | public String getNativeLibraryDirectory(Context appContext) {
    method getApplicationName (line 299) | public String getApplicationName() {
    method getStringResource (line 312) | public String getStringResource(String resourceName)
    method getNativeAudioBufferSize (line 322) | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    method getNativeAudioSampleRate (line 336) | public int getNativeAudioSampleRate() {
    method runOnUIThread (line 343) | public void runOnUIThread(final long p) {
    method RunOnUiThreadHandler (line 358) | native public void RunOnUiThreadHandler(long pointer);

FILE: teapots/image-decoder/src/main/java/com/sample/imagedecoder/TeapotApplication.java
  class TeapotApplication (line 33) | public class TeapotApplication extends Application {
    method onCreate (line 34) | public void onCreate(){

FILE: teapots/image-decoder/src/main/java/com/sample/imagedecoder/TeapotNativeActivity.java
  class TeapotNativeActivity (line 32) | public class TeapotNativeActivity extends NativeActivity {
    method onCreate (line 33) | @Override
    method onResume (line 54) | @TargetApi(19)
    method setImmersiveSticky (line 76) | @TargetApi(19)
    method showUI (line 91) | @SuppressLint("InflateParams")
    method onPause (line 125) | protected void onPause()
    method updateFPS (line 130) | public void updateFPS(final float fFPS)

FILE: teapots/more-teapots/src/main/cpp/MoreTeapotsNativeActivity.cpp
  type android_app (line 48) | struct android_app
  class Engine (line 49) | class Engine {
    type android_app (line 75) | struct android_app
  type android_app (line 266) | struct android_app
  function android_main (line 400) | void android_main(android_app* state) {

FILE: teapots/more-teapots/src/main/cpp/MoreTeapotsRenderer.h
  type TEAPOT_VERTEX (line 44) | struct TEAPOT_VERTEX {
  type SHADER_ATTRIBUTES (line 49) | enum SHADER_ATTRIBUTES {
  type SHADER_PARAMS (line 56) | struct SHADER_PARAMS {
  type TEAPOT_MATERIALS (line 67) | struct TEAPOT_MATERIALS {
  function class (line 72) | class MoreTeapotsRenderer {

FILE: teapots/more-teapots/src/main/java/com/sample/helper/NDKHelper.java
  class NDKHelper (line 48) | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    method NDKHelper (line 51) | public NDKHelper(NativeActivity act) {
    method loadLibrary (line 55) | public void loadLibrary(String soname) {
    method checkSOLoaded (line 62) | public static Boolean checkSOLoaded() {
    method nextPOT (line 84) | private int nextPOT(int i) {
    method scaleBitmap (line 91) | private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth,
    class TextureInformation (line 110) | public class TextureInformation {
    method loadTexture (line 118) | public Object loadTexture(String path) {
    method loadCubemapTexture (line 159) | public Object loadCubemapTexture(String path, int face, int miplevel, ...
    method loadImage (line 208) | public Object loadImage(String path) {
    method openBitmap (line 246) | public Bitmap openBitmap(String path, boolean iScalePOT) {
    method getBitmapWidth (line 269) | public int getBitmapWidth(Bitmap bmp) {
    method getBitmapHeight (line 273) | public int getBitmapHeight(Bitmap bmp) {
    method getBitmapPixels (line 277) | public void getBitmapPixels(Bitmap bmp, int[] pixels) {
    method closeBitmap (line 283) | public void closeBitmap(Bitmap bmp) {
    method getNativeLibraryDirectory (line 287) | public String getNativeLibraryDirectory(Context appContext) {
    method getApplicationName (line 299) | public String getApplicationName() {
    method getStringResource (line 312) | public String getStringResource(String resourceName)
    method getNativeAudioBufferSize (line 322) | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    method getNativeAudioSampleRate (line 336) | public int getNativeAudioSampleRate() {
    method runOnUIThread (line 343) | public void runOnUIThread(final long p) {
    method RunOnUiThreadHandler (line 358) | native public void RunOnUiThreadHandler(long pointer);

FILE: teapots/more-teapots/src/main/java/com/sample/moreteapots/MoreTeapotsApplication.java
  class MoreTeapotsApplication (line 35) | public class MoreTeapotsApplication extends Application {
    method onCreate (line 37) | public void onCreate(){

FILE: teapots/more-teapots/src/main/java/com/sample/moreteapots/MoreTeapotsNativeActivity.java
  class MoreTeapotsNativeActivity (line 34) | public class MoreTeapotsNativeActivity extends NativeActivity {
    method onCreate (line 35) | @Override
    method onResume (line 56) | @TargetApi(19)
    method onPause (line 76) | protected void onPause()
    method setImmersiveSticky (line 82) | @TargetApi(19)
    method showUI (line 97) | @SuppressLint("InflateParams")
    method updateFPS (line 131) | public void updateFPS(final float fFPS)

FILE: teapots/textured-teapot/src/main/cpp/AssetUtil.cpp
  function StringToUpper (line 26) | void StringToUpper(std::string& str) {
  function AssetEnumerateFileType (line 31) | bool AssetEnumerateFileType(AAssetManager* assetManager, const char* type,
  function AssetReadFile (line 61) | bool AssetReadFile(AAssetManager* assetManager, std::string& assetName,

FILE: teapots/textured-teapot/src/main/cpp/TeapotNativeActivity.cpp
  type android_app (line 38) | struct android_app
  class Engine (line 39) | class Engine {
    type android_app (line 65) | struct android_app
  type android_app (line 255) | struct android_app
  function android_main (line 389) | void android_main(android_app* state) {

FILE: teapots/textured-teapot/src/main/cpp/TeapotRenderer.h
  type TEAPOT_VERTEX (line 43) | struct TEAPOT_VERTEX {
  type SHADER_ATTRIBUTES (line 48) | enum SHADER_ATTRIBUTES {
  type SHADER_PARAMS (line 54) | struct SHADER_PARAMS {
  type TEAPOT_MATERIALS (line 65) | struct TEAPOT_MATERIALS {
  function class (line 71) | class TeapotRenderer {

FILE: teapots/textured-teapot/src/main/cpp/Texture.h
  function class (line 37) | class Texture {

FILE: teapots/textured-teapot/src/main/cpp/TexturedTeapotRender.h
  function class (line 28) | class TexturedTeapotRender : public TeapotRenderer {

FILE: teapots/textured-teapot/src/main/java/com/sample/helper/NDKHelper.java
  class NDKHelper (line 48) | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    method NDKHelper (line 51) | public NDKHelper(NativeActivity act) {
    method loadLibrary (line 55) | public void loadLibrary(String soname) {
    method checkSOLoaded (line 62) | public static Boolean checkSOLoaded() {
    method nextPOT (line 84) | private int nextPOT(int i) {
    method scaleBitmap (line 91) | private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth,
    class TextureInformation (line 110) | public class TextureInformation {
    method loadTexture (line 118) | public Object loadTexture(String path) {
    method loadCubemapTexture (line 159) | public Object loadCubemapTexture(String path, int face, int miplevel, ...
    method loadImage (line 208) | public Object loadImage(String path) {
    method openBitmap (line 246) | public Bitmap openBitmap(String path, boolean iScalePOT) {
    method getBitmapWidth (line 269) | public int getBitmapWidth(Bitmap bmp) {
    method getBitmapHeight (line 273) | public int getBitmapHeight(Bitmap bmp) {
    method getBitmapPixels (line 277) | public void getBitmapPixels(Bitmap bmp, int[] pixels) {
    method closeBitmap (line 283) | public void closeBitmap(Bitmap bmp) {
    method getNativeLibraryDirectory (line 287) | public String getNativeLibraryDirectory(Context appContext) {
    method getApplicationName (line 299) | public String getApplicationName() {
    method getStringResource (line 312) | public String getStringResource(String resourceName)
    method getNativeAudioBufferSize (line 322) | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    method getNativeAudioSampleRate (line 336) | public int getNativeAudioSampleRate() {
    method runOnUIThread (line 343) | public void runOnUIThread(final long p) {
    method RunOnUiThreadHandler (line 358) | native public void RunOnUiThreadHandler(long pointer);

FILE: teapots/textured-teapot/src/main/java/com/sample/texturedteapot/TeapotApplication.java
  class TeapotApplication (line 33) | public class TeapotApplication extends Application {
    method onCreate (line 34) | public void onCreate(){

FILE: teapots/textured-teapot/src/main/java/com/sample/texturedteapot/TeapotNativeActivity.java
  class TeapotNativeActivity (line 32) | public class TeapotNativeActivity extends NativeActivity {
    method onCreate (line 33) | @Override
    method onResume (line 54) | @TargetApi(19)
    method setImmersiveSticky (line 76) | @TargetApi(19)
    method showUI (line 91) | @SuppressLint("InflateParams")
    method onPause (line 125) | protected void onPause()
    method updateFPS (line 130) | public void updateFPS(final float fFPS)

FILE: unit-test/app/src/main/cpp/adder.cpp
  function add (line 3) | int add(int a, int b) { return a + b; }

FILE: unit-test/app/src/main/cpp/adder_test.cpp
  function TEST (line 5) | TEST(adder, adder) { EXPECT_EQ(3, add(1, 2)); }

FILE: unit-test/app/src/main/cpp/native-lib.cpp
  function jint (line 6) | jint Add(JNIEnv*, jobject, jint a, jint b) { return add((int)a, (int)b); }
  function JNIEXPORT (line 8) | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: vectorization/src/main/cpp/auto_vectorization.h
  function namespace (line 23) | namespace samples::vectorization {

FILE: vectorization/src/main/cpp/benchmark.cpp
  type samples::vectorization (line 32) | namespace samples::vectorization {
    function Benchmark (line 50) | [[nodiscard, clang::noinline]] std::chrono::nanoseconds Benchmark(
    function BenchmarkMatrixMultiplication (line 72) | [[nodiscard]] std::expected<std::chrono::nanoseconds, BenchmarkError>

FILE: vectorization/src/main/cpp/benchmark.h
  type class (line 28) | enum class
  function BenchmarkError (line 46) | enum class BenchmarkError : int8_t {

FILE: vectorization/src/main/cpp/clang_vector.h
  function namespace (line 23) | namespace samples::vectorization {

FILE: vectorization/src/main/cpp/jni.cpp
  function jlong (line 28) | static jlong BenchmarkMatrixMultiplyJni(JNIEnv* _Nonnull /* env */,
  function JNIEXPORT (line 38) | JNIEXPORT jint JNI_OnLoad(JavaVM* _Nonnull vm,

FILE: vectorization/src/main/cpp/matrix.h
  function namespace (line 27) | namespace samples::vectorization {

FILE: vectorization/src/main/cpp/omp_simd.h
  function namespace (line 23) | namespace samples::vectorization {
Condensed preview — 797 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,532K chars).
[
  {
    "path": ".clang-format",
    "chars": 51,
    "preview": "BasedOnStyle: Google\nDerivePointerAlignment: false\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 469,
    "preview": "name: build\n\non:\n  workflow_dispatch:\n  push:\n  pull_request:\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n  "
  },
  {
    "path": ".gitignore",
    "chars": 136,
    "preview": ".gradle\n.idea\n**/*.iml\nlocal.properties\nbuild\n*~\n.externalNativeBuild\nlibwebp\n.DS_Store\n**/ndkHelperBin\n**/.cxx\ndisplay-"
  },
  {
    "path": ".google/packaging.yaml",
    "chars": 171,
    "preview": "status: PUBLISHED\ntechnologies:\n  - Android\n  - NDK\n  - Platform\ncategories:\n  - NDK\nlanguages:\n  - C++\nsolutions:\n  - M"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 136,
    "preview": "repos:\n-   repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v4.4.0\n    hooks:\n    -   id: check-xml\n    -  "
  },
  {
    "path": "ARCHITECTURE.md",
    "chars": 3786,
    "preview": "# Architecture\n\nThis document describes the layout of the samples repository.\n\nThe top level directory is a Gradle proje"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1437,
    "preview": "# How to become a contributor and submit your own code\n\n## Contributor License Agreements\n\nWe'd love to accept your samp"
  },
  {
    "path": "LICENSE",
    "chars": 10272,
    "preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
  },
  {
    "path": "README.md",
    "chars": 6780,
    "preview": "# Android NDK Samples\n\nThis repository contains sample apps that use the [Android NDK].\n\nFor an explanation of the layou"
  },
  {
    "path": "REFERENCE.md",
    "chars": 394,
    "preview": "Android Studio/Gradle DSL References\n\n| Name           | Function            | Type | Options      | Default |\n| -------"
  },
  {
    "path": "audio-echo/README.md",
    "chars": 208,
    "preview": "# Sample removed\n\nThis sample has been removed because the API it demonstrated (OpenSLES) is\ndeprecated. New apps should"
  },
  {
    "path": "base/.gitignore",
    "chars": 6,
    "preview": "/build"
  },
  {
    "path": "base/build.gradle.kts",
    "chars": 600,
    "preview": "plugins {\n    id(\"ndksamples.android.library\")\n}\n\nandroid {\n    namespace = \"com.android.ndk.samples.base\"\n\n    external"
  },
  {
    "path": "base/src/main/cpp/CMakeLists.txt",
    "chars": 336,
    "preview": "cmake_minimum_required(VERSION 3.22.1)\nproject(Base LANGUAGES CXX)\n\ninclude(AppLibrary)\n\nadd_app_library(base\n    STATIC"
  },
  {
    "path": "base/src/main/cpp/include/base/errno_restorer.h",
    "chars": 1097,
    "preview": "/*\n * Copyright (C) 2020 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "base/src/main/cpp/include/base/logging.h",
    "chars": 18904,
    "preview": "/*\n * Copyright (C) 2015 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "base/src/main/cpp/include/base/macros.h",
    "chars": 3828,
    "preview": "/*\n * Copyright (C) 2015 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "base/src/main/cpp/logging.cpp",
    "chars": 7920,
    "preview": "/*\n * Copyright (C) 2015 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "base/src/main/cpp/logging_splitters.h",
    "chars": 5462,
    "preview": "/*\n * Copyright (C) 2020 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "bitmap-plasma/README.md",
    "chars": 244,
    "preview": "# Bitmap Plasma\n\nBitmap Plasma is an Android sample that uses JNI to render a plasma effect in an\nAndroid\n[Bitmap](http:"
  },
  {
    "path": "bitmap-plasma/app/build.gradle",
    "chars": 375,
    "preview": "plugins {\n    id \"ndksamples.android.application\"\n}\n\nandroid {\n    namespace 'com.example.plasma'\n    defaultConfig {\n  "
  },
  {
    "path": "bitmap-plasma/app/src/main/AndroidManifest.xml",
    "chars": 680,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:"
  },
  {
    "path": "bitmap-plasma/app/src/main/cpp/CMakeLists.txt",
    "chars": 271,
    "preview": "cmake_minimum_required(VERSION 3.22.1)\nproject(BitmapPlasma LANGUAGES CXX)\n\ninclude(AppLibrary)\nfind_package(base CONFIG"
  },
  {
    "path": "bitmap-plasma/app/src/main/cpp/jni.cpp",
    "chars": 730,
    "preview": "// Copyright (C) 2025 The Android Open Source Project\n// SPDX-License-Identifier: Apache-2.0\n\n#include <base/macros.h>\n#"
  },
  {
    "path": "bitmap-plasma/app/src/main/cpp/libplasma.map.txt",
    "chars": 57,
    "preview": "LIBPLASMA {\n  global:\n    JNI_OnLoad;\n  local:\n    *;\n};\n"
  },
  {
    "path": "bitmap-plasma/app/src/main/cpp/plasma.cpp",
    "chars": 9961,
    "preview": "/*\n * Copyright (C) 2010 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "bitmap-plasma/app/src/main/cpp/plasma.h",
    "chars": 197,
    "preview": "// Copyright (C) 2025 The Android Open Source Project\n// SPDX-License-Identifier: Apache-2.0\n\n#pragma once\n\n#include <jn"
  },
  {
    "path": "bitmap-plasma/app/src/main/java/com/example/plasma/Plasma.java",
    "chars": 2539,
    "preview": "/*\n * Copyright (C) 2010 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "bitmap-plasma/app/src/main/res/values/strings.xml",
    "chars": 108,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Plasma</string>\n</resources>\n"
  },
  {
    "path": "build-logic/.gitignore",
    "chars": 5,
    "preview": "/bin\n"
  },
  {
    "path": "build-logic/README.md",
    "chars": 646,
    "preview": "# Convention plugins\n\nThis directory contains [convention plugins] used by the NDK samples. These are\nused to remove Gra"
  },
  {
    "path": "build-logic/build.gradle.kts",
    "chars": 1126,
    "preview": "import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n    id(\"java-gradle-plugin\")\n    `kotlin-dsl`\n    alia"
  },
  {
    "path": "build-logic/settings.gradle.kts",
    "chars": 253,
    "preview": "dependencyResolutionManagement {\n    repositories {\n        google()\n        mavenCentral()\n    }\n    versionCatalogs {\n"
  },
  {
    "path": "build-logic/src/main/java/com/android/ndk/samples/buildlogic/AndroidApplicationConventionPlugin.kt",
    "chars": 2598,
    "preview": "package com.android.ndk.samples.buildlogic\n\nimport com.android.build.api.dsl.ApplicationExtension\n\nimport org.gradle.api"
  },
  {
    "path": "build-logic/src/main/java/com/android/ndk/samples/buildlogic/AndroidLibraryConventionPlugin.kt",
    "chars": 2744,
    "preview": "package com.android.ndk.samples.buildlogic\n\nimport com.android.build.api.dsl.LibraryExtension\nimport org.gradle.api.Plug"
  },
  {
    "path": "build-logic/src/main/java/com/android/ndk/samples/buildlogic/KotlinConventionPlugin.kt",
    "chars": 798,
    "preview": "package com.android.ndk.samples.buildlogic\n\nimport com.android.build.api.dsl.ApplicationExtension\n\nimport org.gradle.api"
  },
  {
    "path": "build-logic/src/main/java/com/android/ndk/samples/buildlogic/Versions.kt",
    "chars": 299,
    "preview": "package com.android.ndk.samples.buildlogic\n\nimport org.gradle.api.JavaVersion\n\nobject Versions {\n    const val COMPILE_S"
  },
  {
    "path": "build.gradle",
    "chars": 279,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nplugins {\n    alias("
  },
  {
    "path": "camera/README.md",
    "chars": 821,
    "preview": "# NdkCamera Sample\n\nTwo API samples:\n\n- texture-view: Preview NDK camera image with\n  [Android TextureView](https://deve"
  },
  {
    "path": "camera/basic/build.gradle",
    "chars": 622,
    "preview": "plugins {\n    id \"ndksamples.android.application\"\n}\n\nandroid {\n    namespace 'com.sample.camera.basic'\n    defaultConfig"
  },
  {
    "path": "camera/basic/src/main/AndroidManifest.xml",
    "chars": 1079,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:"
  },
  {
    "path": "camera/basic/src/main/cpp/CMakeLists.txt",
    "chars": 1386,
    "preview": "#\n# Copyright (C)  2017 The Android Open Source Project\n#\n# Licensed under the Apache License, Version 2.0 (the \"License"
  },
  {
    "path": "camera/basic/src/main/cpp/android_main.cpp",
    "chars": 4455,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/cpp/camera_engine.cpp",
    "chars": 5233,
    "preview": "/**\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "camera/basic/src/main/cpp/camera_engine.h",
    "chars": 2143,
    "preview": "\n/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "camera/basic/src/main/cpp/camera_listeners.cpp",
    "chars": 8454,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/cpp/camera_manager.cpp",
    "chars": 16554,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/cpp/camera_manager.h",
    "chars": 4331,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/cpp/camera_ui.cpp",
    "chars": 5456,
    "preview": "\n/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "camera/basic/src/main/cpp/image_reader.cpp",
    "chars": 14597,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/cpp/image_reader.h",
    "chars": 3559,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/cpp/libndk_camera.map.txt",
    "chars": 91,
    "preview": "LIBNDK_CAMERA {\n  global:\n    ANativeActivity_onCreate;\n    JNI_OnLoad;\n  local:\n    *;\n};\n"
  },
  {
    "path": "camera/basic/src/main/java/com/sample/camera/basic/CameraActivity.java",
    "chars": 14529,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/basic/src/main/res/layout/widgets.xml",
    "chars": 2900,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    an"
  },
  {
    "path": "camera/basic/src/main/res/values/strings.xml",
    "chars": 111,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">NDKCamera</string>\n</resources>\n"
  },
  {
    "path": "camera/camera-utils/build.gradle.kts",
    "chars": 445,
    "preview": "plugins {\n    id(\"ndksamples.android.library\")\n}\n\nandroid {\n    namespace = \"com.android.ndk.samples.camera.utils\"\n\n    "
  },
  {
    "path": "camera/camera-utils/src/main/cpp/CMakeLists.txt",
    "chars": 264,
    "preview": "cmake_minimum_required(VERSION 3.22.1)\nproject(CameraCommon LANGUAGES CXX)\n\ninclude(AppLibrary)\n\nadd_app_library(camera-"
  },
  {
    "path": "camera/camera-utils/src/main/cpp/camera_utils.cpp",
    "chars": 17881,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/camera-utils/src/main/cpp/include/ndksamples/camera/camera_utils.h",
    "chars": 2251,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/camera-utils/src/main/cpp/include/ndksamples/camera/native_debug.h",
    "chars": 489,
    "preview": "#include <android/log.h>\n\n#define LOG_TAG \"CAMERA-SAMPLE\"\n#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TA"
  },
  {
    "path": "camera/texture-view/build.gradle",
    "chars": 625,
    "preview": "plugins {\n    id \"ndksamples.android.application\"\n}\n\nandroid {\n    namespace 'com.sample.textureview'\n    defaultConfig "
  },
  {
    "path": "camera/texture-view/src/main/AndroidManifest.xml",
    "chars": 1040,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:"
  },
  {
    "path": "camera/texture-view/src/main/cpp/CMakeLists.txt",
    "chars": 1071,
    "preview": "#\n# Copyright (C)  2017 The Android Open Source Project\n#\n# Licensed under the Apache License, Version 2.0 (the \"License"
  },
  {
    "path": "camera/texture-view/src/main/cpp/android_main.cpp",
    "chars": 6211,
    "preview": "/**\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "camera/texture-view/src/main/cpp/camera_engine.cpp",
    "chars": 2630,
    "preview": "/**\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "camera/texture-view/src/main/cpp/camera_engine.h",
    "chars": 1451,
    "preview": "\n/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "camera/texture-view/src/main/cpp/camera_listeners.cpp",
    "chars": 8454,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/texture-view/src/main/cpp/camera_manager.cpp",
    "chars": 16943,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/texture-view/src/main/cpp/camera_manager.h",
    "chars": 4797,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/texture-view/src/main/cpp/libcamera_textureview.map.txt",
    "chars": 69,
    "preview": "LIBCAMERA_TEXTUREVIEW {\n  global:\n    JNI_OnLoad;\n  local:\n    *;\n};\n"
  },
  {
    "path": "camera/texture-view/src/main/java/com/sample/textureview/ViewActivity.java",
    "chars": 10177,
    "preview": "/*\n * Copyright (C) 2017 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "camera/texture-view/src/main/res/layout/activity_main.xml",
    "chars": 518,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n         "
  },
  {
    "path": "camera/texture-view/src/main/res/values/strings.xml",
    "chars": 122,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\r\n    <string name=\"app_name\">texture-view</string>\r\n\r\n</resources>"
  },
  {
    "path": "cmake/AppLibrary.cmake",
    "chars": 731,
    "preview": "include_guard()\n\n# Wrapper for add_library which enables common options we want for all\n# libraries.\nfunction(add_app_li"
  },
  {
    "path": "endless-tunnel/README.md",
    "chars": 6273,
    "preview": "# Endless Tunnel\n\nEndless Tunnel is a sample game that shows how to:\n\n- use the Android Studio C++ support\n- implement a"
  },
  {
    "path": "endless-tunnel/app/build.gradle",
    "chars": 1070,
    "preview": "/*\n * Copyright (C) 2015 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "endless-tunnel/app/src/main/AndroidManifest.xml",
    "chars": 1645,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) 2013 Google Inc.\n\n   Licensed under the Apache License, Ver"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/CMakeLists.txt",
    "chars": 2158,
    "preview": "#\n# Copyright (C) The Android Open Source Project\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/android_main.cpp",
    "chars": 823,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/anim.cpp",
    "chars": 1513,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/anim.hpp",
    "chars": 865,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/ascii_to_geom.cpp",
    "chars": 7456,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/ascii_to_geom.hpp",
    "chars": 1153,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/common.hpp",
    "chars": 1910,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/alphabet.inl",
    "chars": 12857,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/ascii_art.inl",
    "chars": 892,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/blurb.inl",
    "chars": 1251,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/cube_geom.inl",
    "chars": 2970,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/our_shader.inl",
    "chars": 4019,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/strings.inl",
    "chars": 1122,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/data/tunnel_geom.inl",
    "chars": 3445,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/dialog_scene.cpp",
    "chars": 5463,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/dialog_scene.hpp",
    "chars": 2138,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/engine.hpp",
    "chars": 1086,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/game_consts.hpp",
    "chars": 5132,
    "preview": "/*\n * Copyright (C) Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/CMakeLists.txt",
    "chars": 719,
    "preview": "#\n# Copyright (C) The Android Open Source Project\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/common.hpp",
    "chars": 1595,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_features.hpp",
    "chars": 12877,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_fixes.hpp",
    "chars": 1856,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_literals.hpp",
    "chars": 1976,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_noise.hpp",
    "chars": 4414,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_swizzle.hpp",
    "chars": 102110,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_swizzle_func.hpp",
    "chars": 103830,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/_vectorize.hpp",
    "chars": 6848,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_common.hpp",
    "chars": 22710,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_common.inl",
    "chars": 27487,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_exponential.hpp",
    "chars": 6595,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_exponential.inl",
    "chars": 7304,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_geometric.hpp",
    "chars": 6685,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_geometric.inl",
    "chars": 9785,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_integer.hpp",
    "chars": 9886,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_integer.inl",
    "chars": 16900,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_matrix.hpp",
    "chars": 6926,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_matrix.inl",
    "chars": 15722,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_noise.hpp",
    "chars": 4183,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_noise.inl",
    "chars": 15448,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_packing.hpp",
    "chars": 12347,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_packing.inl",
    "chars": 3634,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_trigonometric.hpp",
    "chars": 9949,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_trigonometric.inl",
    "chars": 6068,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_vector_relational.hpp",
    "chars": 7701,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/func_vector_relational.inl",
    "chars": 5629,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/glm.cpp",
    "chars": 9669,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/hint.hpp",
    "chars": 1703,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_common.hpp",
    "chars": 2634,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_common.inl",
    "chars": 13784,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_exponential.hpp",
    "chars": 3047,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_exponential.inl",
    "chars": 1491,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_geometric.hpp",
    "chars": 2357,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_geometric.inl",
    "chars": 4630,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_integer.hpp",
    "chars": 1955,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_integer.inl",
    "chars": 5175,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_matrix.hpp",
    "chars": 2474,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_matrix.inl",
    "chars": 43299,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_trigonometric.hpp",
    "chars": 1880,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_trigonometric.inl",
    "chars": 1493,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_vector_relational.hpp",
    "chars": 1900,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/intrinsic_vector_relational.inl",
    "chars": 10517,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/precision.hpp",
    "chars": 1688,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/precision.inl",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/setup.hpp",
    "chars": 27927,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_float.hpp",
    "chars": 4282,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_gentype.hpp",
    "chars": 6677,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_gentype.inl",
    "chars": 10461,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_half.hpp",
    "chars": 1887,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_half.inl",
    "chars": 6158,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_int.hpp",
    "chars": 8549,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat.hpp",
    "chars": 43090,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat.inl",
    "chars": 1478,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x2.hpp",
    "chars": 7881,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x2.inl",
    "chars": 14732,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x3.hpp",
    "chars": 6703,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x3.inl",
    "chars": 13853,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x4.hpp",
    "chars": 6784,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat2x4.inl",
    "chars": 14906,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x2.hpp",
    "chars": 6771,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x2.inl",
    "chars": 14592,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x3.hpp",
    "chars": 8183,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x3.inl",
    "chars": 20171,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x4.hpp",
    "chars": 7075,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat3x4.inl",
    "chars": 17365,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x2.hpp",
    "chars": 6914,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x2.inl",
    "chars": 17225,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x3.hpp",
    "chars": 7162,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x3.inl",
    "chars": 19704,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x4.hpp",
    "chars": 8617,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_mat4x4.inl",
    "chars": 29840,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec.hpp",
    "chars": 27830,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec.inl",
    "chars": 1478,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec1.hpp",
    "chars": 10122,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec1.inl",
    "chars": 14372,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec2.hpp",
    "chars": 11087,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec2.inl",
    "chars": 15435,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec3.hpp",
    "chars": 11847,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec3.inl",
    "chars": 16608,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec4.hpp",
    "chars": 13897,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/detail/type_vec4.inl",
    "chars": 19536,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/exponential.hpp",
    "chars": 1620,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/ext.hpp",
    "chars": 5287,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/fwd.hpp",
    "chars": 81086,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/geometric.hpp",
    "chars": 1610,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/glm.hpp",
    "chars": 4477,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/constants.hpp",
    "chars": 4954,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/constants.inl",
    "chars": 4572,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/epsilon.hpp",
    "chars": 3496,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/epsilon.inl",
    "chars": 4421,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_access.hpp",
    "chars": 3060,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_access.inl",
    "chars": 2733,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_integer.hpp",
    "chars": 15484,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_inverse.hpp",
    "chars": 2907,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_inverse.inl",
    "chars": 6747,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_transform.hpp",
    "chars": 12286,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/matrix_transform.inl",
    "chars": 13319,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/noise.hpp",
    "chars": 2872,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/noise.inl",
    "chars": 41141,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/packing.hpp",
    "chars": 26457,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/packing.inl",
    "chars": 14486,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/quaternion.hpp",
    "chars": 13413,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/quaternion.inl",
    "chars": 23999,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  },
  {
    "path": "endless-tunnel/app/src/main/cpp/glm/gtc/random.hpp",
    "chars": 3793,
    "preview": "///////////////////////////////////////////////////////////////////////////////////\n/// OpenGL Mathematics (glm.g-truc.n"
  }
]

// ... and 597 more files (download for full content)

About this extraction

This page contains the full source code of the android/ndk-samples GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 797 files (6.0 MB), approximately 1.6M tokens, and a symbol index with 1555 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!