Project import
diff --git a/libhardware/Android.bp b/libhardware/Android.bp new file mode 100644 index 0000000..f093c56 --- /dev/null +++ b/libhardware/Android.bp
@@ -0,0 +1,18 @@ +// Copyright 2006 The Android Open Source Project + +cc_library_shared { + name: "libhardware", + + srcs: ["hardware.c"], + shared_libs: [ + "libcutils", + "liblog", + "libdl", + ], + cflags: ["-DQEMU_HARDWARE"], +} + +subdirs = [ + "modules/*", + "tests/*", +]
diff --git a/libhardware/Android.mk b/libhardware/Android.mk new file mode 100644 index 0000000..8744f46 --- /dev/null +++ b/libhardware/Android.mk
@@ -0,0 +1,3 @@ +# Copyright 2006 The Android Open Source Project + +include $(call all-named-subdir-makefiles,modules tests)
diff --git a/libhardware/CleanSpec.mk b/libhardware/CleanSpec.mk new file mode 100644 index 0000000..b84e1b6 --- /dev/null +++ b/libhardware/CleanSpec.mk
@@ -0,0 +1,49 @@ +# Copyright (C) 2007 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. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************
diff --git a/libhardware/MODULE_LICENSE_APACHE2 b/libhardware/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libhardware/MODULE_LICENSE_APACHE2
diff --git a/libhardware/NOTICE b/libhardware/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/libhardware/NOTICE
@@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +
diff --git a/libhardware/hardware.c b/libhardware/hardware.c new file mode 100644 index 0000000..79d0a2f --- /dev/null +++ b/libhardware/hardware.c
@@ -0,0 +1,201 @@ +/* + * Copyright (C) 2008 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 <hardware/hardware.h> + +#include <cutils/properties.h> + +#include <dlfcn.h> +#include <string.h> +#include <pthread.h> +#include <errno.h> +#include <limits.h> + +#define LOG_TAG "HAL" +#include <utils/Log.h> + +/** Base path of the hal modules */ +#if defined(__LP64__) +#define HAL_LIBRARY_PATH1 "/system/lib64/hw" +#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw" +#else +#define HAL_LIBRARY_PATH1 "/system/lib/hw" +#define HAL_LIBRARY_PATH2 "/vendor/lib/hw" +#endif + +/** + * There are a set of variant filename for modules. The form of the filename + * is "<MODULE_ID>.variant.so" so for the led module the Dream variants + * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be: + * + * led.trout.so + * led.msm7k.so + * led.ARMV6.so + * led.default.so + */ + +static const char *variant_keys[] = { + "ro.hardware", /* This goes first so that it can pick up a different + file on the emulator. */ + "ro.product.board", + "ro.board.platform", + "ro.arch" +}; + +static const int HAL_VARIANT_KEYS_COUNT = + (sizeof(variant_keys)/sizeof(variant_keys[0])); + +/** + * Load the file defined by the variant and if successful + * return the dlopen handle and the hmi. + * @return 0 = success, !0 = failure. + */ +static int load(const char *id, + const char *path, + const struct hw_module_t **pHmi) +{ + int status = -EINVAL; + void *handle = NULL; + struct hw_module_t *hmi = NULL; + + /* + * load the symbols resolving undefined symbols before + * dlopen returns. Since RTLD_GLOBAL is not or'd in with + * RTLD_NOW the external symbols will not be global + */ + handle = dlopen(path, RTLD_NOW); + if (handle == NULL) { + char const *err_str = dlerror(); + ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown"); + status = -EINVAL; + goto done; + } + + /* Get the address of the struct hal_module_info. */ + const char *sym = HAL_MODULE_INFO_SYM_AS_STR; + hmi = (struct hw_module_t *)dlsym(handle, sym); + if (hmi == NULL) { + ALOGE("load: couldn't find symbol %s", sym); + status = -EINVAL; + goto done; + } + + /* Check that the id matches */ + if (strcmp(id, hmi->id) != 0) { + ALOGE("load: id=%s != hmi->id=%s", id, hmi->id); + status = -EINVAL; + goto done; + } + + hmi->dso = handle; + + /* success */ + status = 0; + + done: + if (status != 0) { + hmi = NULL; + if (handle != NULL) { + dlclose(handle); + handle = NULL; + } + } else { + ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", + id, path, *pHmi, handle); + } + + *pHmi = hmi; + + return status; +} + +/* + * Check if a HAL with given name and subname exists, if so return 0, otherwise + * otherwise return negative. On success path will contain the path to the HAL. + */ +static int hw_module_exists(char *path, size_t path_len, const char *name, + const char *subname) +{ + snprintf(path, path_len, "%s/%s.%s.so", + HAL_LIBRARY_PATH2, name, subname); + if (access(path, R_OK) == 0) + return 0; + + snprintf(path, path_len, "%s/%s.%s.so", + HAL_LIBRARY_PATH1, name, subname); + if (access(path, R_OK) == 0) + return 0; + + return -ENOENT; +} + +int hw_get_module_by_class(const char *class_id, const char *inst, + const struct hw_module_t **module) +{ + int i = 0; + char prop[PATH_MAX] = {0}; + char path[PATH_MAX] = {0}; + char name[PATH_MAX] = {0}; + char prop_name[PATH_MAX] = {0}; + + + if (inst) + snprintf(name, PATH_MAX, "%s.%s", class_id, inst); + else + strlcpy(name, class_id, PATH_MAX); + + /* + * Here we rely on the fact that calling dlopen multiple times on + * the same .so will simply increment a refcount (and not load + * a new copy of the library). + * We also assume that dlopen() is thread-safe. + */ + + /* First try a property specific to the class and possibly instance */ + snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name); + if (property_get(prop_name, prop, NULL) > 0) { + if (hw_module_exists(path, sizeof(path), name, prop) == 0) { + goto found; + } + } + + /* Loop through the configuration variants looking for a module */ + for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) { + if (property_get(variant_keys[i], prop, NULL) == 0) { + continue; + } + if (hw_module_exists(path, sizeof(path), name, prop) == 0) { + goto found; + } + } + + /* Nothing found, try the default */ + if (hw_module_exists(path, sizeof(path), name, "default") == 0) { + goto found; + } + + return -ENOENT; + +found: + /* load the module, if this fails, we're doomed, and we should not try + * to load a different variant. */ + return load(class_id, path, module); +} + +int hw_get_module(const char *id, const struct hw_module_t **module) +{ + return hw_get_module_by_class(id, NULL, module); +}
diff --git a/libhardware/include/hardware/activity_recognition.h b/libhardware/include/hardware/activity_recognition.h new file mode 100644 index 0000000..8f99459 --- /dev/null +++ b/libhardware/include/hardware/activity_recognition.h
@@ -0,0 +1,223 @@ +/* + * Copyright (C) 2014 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. + */ + +/* + * Activity Recognition HAL. The goal is to provide low power, low latency, always-on activity + * recognition implemented in hardware (i.e. these activity recognition algorithms/classifers + * should NOT be run on the AP). By low power we mean that this may be activated 24/7 without + * impacting the battery drain speed (goal in order of 1mW including the power for sensors). + * This HAL does not specify the input sources that are used towards detecting these activities. + * It has one monitor interface which can be used to batch activities for always-on + * activity_recognition and if the latency is zero, the same interface can be used for low latency + * detection. + */ + +#ifndef ANDROID_ACTIVITY_RECOGNITION_INTERFACE_H +#define ANDROID_ACTIVITY_RECOGNITION_INTERFACE_H + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define ACTIVITY_RECOGNITION_HEADER_VERSION 1 +#define ACTIVITY_RECOGNITION_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION_2(0, 1, ACTIVITY_RECOGNITION_HEADER_VERSION) + +#define ACTIVITY_RECOGNITION_HARDWARE_MODULE_ID "activity_recognition" +#define ACTIVITY_RECOGNITION_HARDWARE_INTERFACE "activity_recognition_hw_if" + +/* + * Define types for various activities. Multiple activities may be active at the same time and + * sometimes none of these activities may be active. + * + * Each activity has a corresponding type. Only activities that are defined here should use + * android.activity_recognition.* prefix. OEM defined activities should not use this prefix. + * Activity type of OEM-defined activities should start with the reverse domain name of the entity + * defining the activity. + * + * When android introduces a new activity type that can potentially replace an OEM-defined activity + * type, the OEM must use the official activity type on versions of the HAL that support this new + * official activity type. + * + * Example (made up): Suppose Google's Glass team wants to detect nodding activity. + * - Such an activity is not officially supported in android L + * - Glass devices launching on L can implement a custom activity with + * type = "com.google.glass.nodding" + * - In M android release, if android decides to define ACITIVITY_TYPE_NODDING, those types + * should replace the Glass-team-specific types in all future launches. + * - When launching glass on the M release, Google should now use the official activity type + * - This way, other applications can use this activity. + */ + +#define ACTIVITY_TYPE_IN_VEHICLE "android.activity_recognition.in_vehicle" + +#define ACTIVITY_TYPE_ON_BICYCLE "android.activity_recognition.on_bicycle" + +#define ACTIVITY_TYPE_WALKING "android.activity_recognition.walking" + +#define ACTIVITY_TYPE_RUNNING "android.activity_recognition.running" + +#define ACTIVITY_TYPE_STILL "android.activity_recognition.still" + +#define ACTIVITY_TYPE_TILTING "android.activity_recognition.tilting" + +/* Values for activity_event.event_types. */ +enum { + /* + * A flush_complete event which indicates that a flush() has been successfully completed. This + * does not correspond to any activity/event. An event of this type should be added to the end + * of a batch FIFO and it indicates that all the events in the batch FIFO have been successfully + * reported to the framework. An event of this type should be generated only if flush() has been + * explicitly called and if the FIFO is empty at the time flush() is called it should trivially + * return a flush_complete_event to indicate that the FIFO is empty. + * + * A flush complete event should have the following parameters set. + * activity_event_t.event_type = ACTIVITY_EVENT_FLUSH_COMPLETE + * activity_event_t.activity = 0 + * activity_event_t.timestamp = 0 + * activity_event_t.reserved = 0 + * See (*flush)() for more details. + */ + ACTIVITY_EVENT_FLUSH_COMPLETE = 0, + + /* Signifies entering an activity. */ + ACTIVITY_EVENT_ENTER = 1, + + /* Signifies exiting an activity. */ + ACTIVITY_EVENT_EXIT = 2 +}; + +/* + * Each event is a separate activity with event_type indicating whether this activity has started + * or ended. Eg event: (event_type="enter", activity="ON_FOOT", timestamp) + */ +typedef struct activity_event { + /* One of the ACTIVITY_EVENT_* constants defined above. */ + uint32_t event_type; + + /* + * Index of the activity in the list returned by get_supported_activities_list. If this event + * is a flush complete event, this should be set to zero. + */ + uint32_t activity; + + /* Time at which the transition/event has occurred in nanoseconds using elapsedRealTimeNano. */ + int64_t timestamp; + + /* Set to zero. */ + int32_t reserved[4]; +} activity_event_t; + +typedef struct activity_recognition_module { + /** + * Common methods of the activity recognition module. This *must* be the first member of + * activity_recognition_module as users of this structure will cast a hw_module_t to + * activity_recognition_module pointer in contexts where it's known the hw_module_t + * references an activity_recognition_module. + */ + hw_module_t common; + + /* + * List of all activities supported by this module including OEM defined activities. Each + * activity is represented using a string defined above. Each string should be null terminated. + * The index of the activity in this array is used as a "handle" for enabling/disabling and + * event delivery. + * Return value is the size of this list. + */ + int (*get_supported_activities_list)(struct activity_recognition_module* module, + char const* const* *activity_list); +} activity_recognition_module_t; + +struct activity_recognition_device; + +typedef struct activity_recognition_callback_procs { + // Callback for activity_data. This is guaranteed to not invoke any HAL methods. + // Memory allocated for the events can be reused after this method returns. + // events - Array of activity_event_t s that are reported. + // count - size of the array. + void (*activity_callback)(const struct activity_recognition_callback_procs* procs, + const activity_event_t* events, int count); +} activity_recognition_callback_procs_t; + +typedef struct activity_recognition_device { + /** + * Common methods of the activity recognition device. This *must* be the first member of + * activity_recognition_device as users of this structure will cast a hw_device_t to + * activity_recognition_device pointer in contexts where it's known the hw_device_t + * references an activity_recognition_device. + */ + hw_device_t common; + + /* + * Sets the callback to invoke when there are events to report. This call overwrites the + * previously registered callback (if any). + */ + void (*register_activity_callback)(const struct activity_recognition_device* dev, + const activity_recognition_callback_procs_t* callback); + + /* + * Activates monitoring of activity transitions. Activities need not be reported as soon as they + * are detected. The detected activities are stored in a FIFO and reported in batches when the + * "max_batch_report_latency" expires or when the batch FIFO is full. The implementation should + * allow the AP to go into suspend mode while the activities are detected and stored in the + * batch FIFO. Whenever events need to be reported (like when the FIFO is full or when the + * max_batch_report_latency has expired for an activity, event pair), it should wake_up the AP + * so that no events are lost. Activities are stored as transitions and they are allowed to + * overlap with each other. Each (activity, event_type) pair can be activated or deactivated + * independently of the other. The HAL implementation needs to keep track of which pairs are + * currently active and needs to detect only those pairs. + * + * activity_handle - Index of the specific activity that needs to be detected in the list + * returned by get_supported_activities_list. + * event_type - Specific transition of the activity that needs to be detected. + * max_batch_report_latency_ns - a transition can be delayed by at most + * “max_batch_report_latency” nanoseconds. + * Return 0 on success, negative errno code otherwise. + */ + int (*enable_activity_event)(const struct activity_recognition_device* dev, + uint32_t activity_handle, uint32_t event_type, int64_t max_batch_report_latency_ns); + + /* + * Disables detection of a specific (activity, event_type) pair. + */ + int (*disable_activity_event)(const struct activity_recognition_device* dev, + uint32_t activity_handle, uint32_t event_type); + + /* + * Flush all the batch FIFOs. Report all the activities that were stored in the FIFO so far as + * if max_batch_report_latency had expired. This shouldn't change the latency in any way. Add + * a flush_complete_event to indicate the end of the FIFO after all events are delivered. + * See ACTIVITY_EVENT_FLUSH_COMPLETE for more details. + * Return 0 on success, negative errno code otherwise. + */ + int (*flush)(const struct activity_recognition_device* dev); + + // Must be set to NULL. + void (*reserved_procs[16 - 4])(void); +} activity_recognition_device_t; + +static inline int activity_recognition_open(const hw_module_t* module, + activity_recognition_device_t** device) { + return module->methods->open(module, + ACTIVITY_RECOGNITION_HARDWARE_INTERFACE, (hw_device_t**)device); +} + +static inline int activity_recognition_close(activity_recognition_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_ACTIVITY_RECOGNITION_INTERFACE_H
diff --git a/libhardware/include/hardware/audio.h b/libhardware/include/hardware/audio.h new file mode 100644 index 0000000..2389c09 --- /dev/null +++ b/libhardware/include/hardware/audio.h
@@ -0,0 +1,672 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_AUDIO_HAL_INTERFACE_H +#define ANDROID_AUDIO_HAL_INTERFACE_H + +#include <stdint.h> +#include <strings.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <cutils/bitops.h> + +#include <hardware/hardware.h> +#include <system/audio.h> +#include <hardware/audio_effect.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define AUDIO_HARDWARE_MODULE_ID "audio" + +/** + * Name of the audio devices to open + */ +#define AUDIO_HARDWARE_INTERFACE "audio_hw_if" + + +/* Use version 0.1 to be compatible with first generation of audio hw module with version_major + * hardcoded to 1. No audio module API change. + */ +#define AUDIO_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define AUDIO_MODULE_API_VERSION_CURRENT AUDIO_MODULE_API_VERSION_0_1 + +/* First generation of audio devices had version hardcoded to 0. all devices with versions < 1.0 + * will be considered of first generation API. + */ +#define AUDIO_DEVICE_API_VERSION_0_0 HARDWARE_DEVICE_API_VERSION(0, 0) +#define AUDIO_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define AUDIO_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) +#define AUDIO_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0) +#define AUDIO_DEVICE_API_VERSION_CURRENT AUDIO_DEVICE_API_VERSION_3_0 +/* Minimal audio HAL version supported by the audio framework */ +#define AUDIO_DEVICE_API_VERSION_MIN AUDIO_DEVICE_API_VERSION_2_0 + +/** + * List of known audio HAL modules. This is the base name of the audio HAL + * library composed of the "audio." prefix, one of the base names below and + * a suffix specific to the device. + * e.g: audio.primary.goldfish.so or audio.a2dp.default.so + */ + +#define AUDIO_HARDWARE_MODULE_ID_PRIMARY "primary" +#define AUDIO_HARDWARE_MODULE_ID_A2DP "a2dp" +#define AUDIO_HARDWARE_MODULE_ID_USB "usb" +#define AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX "r_submix" +#define AUDIO_HARDWARE_MODULE_ID_CODEC_OFFLOAD "codec_offload" + +/**************************************/ + +/** + * standard audio parameters that the HAL may need to handle + */ + +/** + * audio device parameters + */ + +/* BT SCO Noise Reduction + Echo Cancellation parameters */ +#define AUDIO_PARAMETER_KEY_BT_NREC "bt_headset_nrec" +#define AUDIO_PARAMETER_VALUE_ON "on" +#define AUDIO_PARAMETER_VALUE_OFF "off" + +/* TTY mode selection */ +#define AUDIO_PARAMETER_KEY_TTY_MODE "tty_mode" +#define AUDIO_PARAMETER_VALUE_TTY_OFF "tty_off" +#define AUDIO_PARAMETER_VALUE_TTY_VCO "tty_vco" +#define AUDIO_PARAMETER_VALUE_TTY_HCO "tty_hco" +#define AUDIO_PARAMETER_VALUE_TTY_FULL "tty_full" + +/* Hearing Aid Compatibility - Telecoil (HAC-T) mode on/off + Strings must be in sync with CallFeaturesSetting.java */ +#define AUDIO_PARAMETER_KEY_HAC "HACSetting" +#define AUDIO_PARAMETER_VALUE_HAC_ON "ON" +#define AUDIO_PARAMETER_VALUE_HAC_OFF "OFF" + +/* A2DP sink address set by framework */ +#define AUDIO_PARAMETER_A2DP_SINK_ADDRESS "a2dp_sink_address" + +/* A2DP source address set by framework */ +#define AUDIO_PARAMETER_A2DP_SOURCE_ADDRESS "a2dp_source_address" + +/* Screen state */ +#define AUDIO_PARAMETER_KEY_SCREEN_STATE "screen_state" + +/* Bluetooth SCO wideband */ +#define AUDIO_PARAMETER_KEY_BT_SCO_WB "bt_wbs" + +/* Get a new HW synchronization source identifier. + * Return a valid source (positive integer) or AUDIO_HW_SYNC_INVALID if an error occurs + * or no HW sync is available. */ +#define AUDIO_PARAMETER_HW_AV_SYNC "hw_av_sync" + +/** + * audio stream parameters + */ + +#define AUDIO_PARAMETER_STREAM_ROUTING "routing" /* audio_devices_t */ +#define AUDIO_PARAMETER_STREAM_FORMAT "format" /* audio_format_t */ +#define AUDIO_PARAMETER_STREAM_CHANNELS "channels" /* audio_channel_mask_t */ +#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count" /* size_t */ +#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" /* audio_source_t */ +#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */ + +#define AUDIO_PARAMETER_DEVICE_CONNECT "connect" /* audio_devices_t */ +#define AUDIO_PARAMETER_DEVICE_DISCONNECT "disconnect" /* audio_devices_t */ + +/* Query supported formats. The response is a '|' separated list of strings from + * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */ +#define AUDIO_PARAMETER_STREAM_SUP_FORMATS "sup_formats" +/* Query supported channel masks. The response is a '|' separated list of strings from + * audio_channel_mask_t enum e.g: "sup_channels=AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_MONO" */ +#define AUDIO_PARAMETER_STREAM_SUP_CHANNELS "sup_channels" +/* Query supported sampling rates. The response is a '|' separated list of integer values e.g: + * "sup_sampling_rates=44100|48000" */ +#define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates" + +/* Set the HW synchronization source for an output stream. */ +#define AUDIO_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync" + +/** + * audio codec parameters + */ + +#define AUDIO_OFFLOAD_CODEC_PARAMS "music_offload_codec_param" +#define AUDIO_OFFLOAD_CODEC_BIT_PER_SAMPLE "music_offload_bit_per_sample" +#define AUDIO_OFFLOAD_CODEC_BIT_RATE "music_offload_bit_rate" +#define AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE "music_offload_avg_bit_rate" +#define AUDIO_OFFLOAD_CODEC_ID "music_offload_codec_id" +#define AUDIO_OFFLOAD_CODEC_BLOCK_ALIGN "music_offload_block_align" +#define AUDIO_OFFLOAD_CODEC_SAMPLE_RATE "music_offload_sample_rate" +#define AUDIO_OFFLOAD_CODEC_ENCODE_OPTION "music_offload_encode_option" +#define AUDIO_OFFLOAD_CODEC_NUM_CHANNEL "music_offload_num_channels" +#define AUDIO_OFFLOAD_CODEC_DOWN_SAMPLING "music_offload_down_sampling" +#define AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES "delay_samples" +#define AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES "padding_samples" + +/**************************************/ + +/* common audio stream parameters and operations */ +struct audio_stream { + + /** + * Return the sampling rate in Hz - eg. 44100. + */ + uint32_t (*get_sample_rate)(const struct audio_stream *stream); + + /* currently unused - use set_parameters with key + * AUDIO_PARAMETER_STREAM_SAMPLING_RATE + */ + int (*set_sample_rate)(struct audio_stream *stream, uint32_t rate); + + /** + * Return size of input/output buffer in bytes for this stream - eg. 4800. + * It should be a multiple of the frame size. See also get_input_buffer_size. + */ + size_t (*get_buffer_size)(const struct audio_stream *stream); + + /** + * Return the channel mask - + * e.g. AUDIO_CHANNEL_OUT_STEREO or AUDIO_CHANNEL_IN_STEREO + */ + audio_channel_mask_t (*get_channels)(const struct audio_stream *stream); + + /** + * Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT + */ + audio_format_t (*get_format)(const struct audio_stream *stream); + + /* currently unused - use set_parameters with key + * AUDIO_PARAMETER_STREAM_FORMAT + */ + int (*set_format)(struct audio_stream *stream, audio_format_t format); + + /** + * Put the audio hardware input/output into standby mode. + * Driver should exit from standby mode at the next I/O operation. + * Returns 0 on success and <0 on failure. + */ + int (*standby)(struct audio_stream *stream); + + /** dump the state of the audio input/output device */ + int (*dump)(const struct audio_stream *stream, int fd); + + /** Return the set of device(s) which this stream is connected to */ + audio_devices_t (*get_device)(const struct audio_stream *stream); + + /** + * Currently unused - set_device() corresponds to set_parameters() with key + * AUDIO_PARAMETER_STREAM_ROUTING for both input and output. + * AUDIO_PARAMETER_STREAM_INPUT_SOURCE is an additional information used by + * input streams only. + */ + int (*set_device)(struct audio_stream *stream, audio_devices_t device); + + /** + * set/get audio stream parameters. The function accepts a list of + * parameter key value pairs in the form: key1=value1;key2=value2;... + * + * Some keys are reserved for standard parameters (See AudioParameter class) + * + * If the implementation does not accept a parameter change while + * the output is active but the parameter is acceptable otherwise, it must + * return -ENOSYS. + * + * The audio flinger will put the stream in standby and then change the + * parameter value. + */ + int (*set_parameters)(struct audio_stream *stream, const char *kv_pairs); + + /* + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + char * (*get_parameters)(const struct audio_stream *stream, + const char *keys); + int (*add_audio_effect)(const struct audio_stream *stream, + effect_handle_t effect); + int (*remove_audio_effect)(const struct audio_stream *stream, + effect_handle_t effect); +}; +typedef struct audio_stream audio_stream_t; + +/* type of asynchronous write callback events. Mutually exclusive */ +typedef enum { + STREAM_CBK_EVENT_WRITE_READY, /* non blocking write completed */ + STREAM_CBK_EVENT_DRAIN_READY /* drain completed */ +} stream_callback_event_t; + +typedef int (*stream_callback_t)(stream_callback_event_t event, void *param, void *cookie); + +/* type of drain requested to audio_stream_out->drain(). Mutually exclusive */ +typedef enum { + AUDIO_DRAIN_ALL, /* drain() returns when all data has been played */ + AUDIO_DRAIN_EARLY_NOTIFY /* drain() returns a short time before all data + from the current track has been played to + give time for gapless track switch */ +} audio_drain_type_t; + +/** + * audio_stream_out is the abstraction interface for the audio output hardware. + * + * It provides information about various properties of the audio output + * hardware driver. + */ + +struct audio_stream_out { + /** + * Common methods of the audio stream out. This *must* be the first member of audio_stream_out + * as users of this structure will cast a audio_stream to audio_stream_out pointer in contexts + * where it's known the audio_stream references an audio_stream_out. + */ + struct audio_stream common; + + /** + * Return the audio hardware driver estimated latency in milliseconds. + */ + uint32_t (*get_latency)(const struct audio_stream_out *stream); + + /** + * Use this method in situations where audio mixing is done in the + * hardware. This method serves as a direct interface with hardware, + * allowing you to directly set the volume as apposed to via the framework. + * This method might produce multiple PCM outputs or hardware accelerated + * codecs, such as MP3 or AAC. + */ + int (*set_volume)(struct audio_stream_out *stream, float left, float right); + + /** + * Write audio buffer to driver. Returns number of bytes written, or a + * negative status_t. If at least one frame was written successfully prior to the error, + * it is suggested that the driver return that successful (short) byte count + * and then return an error in the subsequent call. + * + * If set_callback() has previously been called to enable non-blocking mode + * the write() is not allowed to block. It must write only the number of + * bytes that currently fit in the driver/hardware buffer and then return + * this byte count. If this is less than the requested write size the + * callback function must be called when more space is available in the + * driver/hardware buffer. + */ + ssize_t (*write)(struct audio_stream_out *stream, const void* buffer, + size_t bytes); + + /* return the number of audio frames written by the audio dsp to DAC since + * the output has exited standby + */ + int (*get_render_position)(const struct audio_stream_out *stream, + uint32_t *dsp_frames); + + /** + * get the local time at which the next write to the audio driver will be presented. + * The units are microseconds, where the epoch is decided by the local audio HAL. + */ + int (*get_next_write_timestamp)(const struct audio_stream_out *stream, + int64_t *timestamp); + + /** + * set the callback function for notifying completion of non-blocking + * write and drain. + * Calling this function implies that all future write() and drain() + * must be non-blocking and use the callback to signal completion. + */ + int (*set_callback)(struct audio_stream_out *stream, + stream_callback_t callback, void *cookie); + + /** + * Notifies to the audio driver to stop playback however the queued buffers are + * retained by the hardware. Useful for implementing pause/resume. Empty implementation + * if not supported however should be implemented for hardware with non-trivial + * latency. In the pause state audio hardware could still be using power. User may + * consider calling suspend after a timeout. + * + * Implementation of this function is mandatory for offloaded playback. + */ + int (*pause)(struct audio_stream_out* stream); + + /** + * Notifies to the audio driver to resume playback following a pause. + * Returns error if called without matching pause. + * + * Implementation of this function is mandatory for offloaded playback. + */ + int (*resume)(struct audio_stream_out* stream); + + /** + * Requests notification when data buffered by the driver/hardware has + * been played. If set_callback() has previously been called to enable + * non-blocking mode, the drain() must not block, instead it should return + * quickly and completion of the drain is notified through the callback. + * If set_callback() has not been called, the drain() must block until + * completion. + * If type==AUDIO_DRAIN_ALL, the drain completes when all previously written + * data has been played. + * If type==AUDIO_DRAIN_EARLY_NOTIFY, the drain completes shortly before all + * data for the current track has played to allow time for the framework + * to perform a gapless track switch. + * + * Drain must return immediately on stop() and flush() call + * + * Implementation of this function is mandatory for offloaded playback. + */ + int (*drain)(struct audio_stream_out* stream, audio_drain_type_t type ); + + /** + * Notifies to the audio driver to flush the queued data. Stream must already + * be paused before calling flush(). + * + * Implementation of this function is mandatory for offloaded playback. + */ + int (*flush)(struct audio_stream_out* stream); + + /** + * Return a recent count of the number of audio frames presented to an external observer. + * This excludes frames which have been written but are still in the pipeline. + * The count is not reset to zero when output enters standby. + * Also returns the value of CLOCK_MONOTONIC as of this presentation count. + * The returned count is expected to be 'recent', + * but does not need to be the most recent possible value. + * However, the associated time should correspond to whatever count is returned. + * Example: assume that N+M frames have been presented, where M is a 'small' number. + * Then it is permissible to return N instead of N+M, + * and the timestamp should correspond to N rather than N+M. + * The terms 'recent' and 'small' are not defined. + * They reflect the quality of the implementation. + * + * 3.0 and higher only. + */ + int (*get_presentation_position)(const struct audio_stream_out *stream, + uint64_t *frames, struct timespec *timestamp); + +}; +typedef struct audio_stream_out audio_stream_out_t; + +struct audio_stream_in { + /** + * Common methods of the audio stream in. This *must* be the first member of audio_stream_in + * as users of this structure will cast a audio_stream to audio_stream_in pointer in contexts + * where it's known the audio_stream references an audio_stream_in. + */ + struct audio_stream common; + + /** set the input gain for the audio driver. This method is for + * for future use */ + int (*set_gain)(struct audio_stream_in *stream, float gain); + + /** Read audio buffer in from audio driver. Returns number of bytes read, or a + * negative status_t. If at least one frame was read prior to the error, + * read should return that byte count and then return an error in the subsequent call. + */ + ssize_t (*read)(struct audio_stream_in *stream, void* buffer, + size_t bytes); + + /** + * Return the amount of input frames lost in the audio driver since the + * last call of this function. + * Audio driver is expected to reset the value to 0 and restart counting + * upon returning the current value by this function call. + * Such loss typically occurs when the user space process is blocked + * longer than the capacity of audio driver buffers. + * + * Unit: the number of input audio frames + */ + uint32_t (*get_input_frames_lost)(struct audio_stream_in *stream); +}; +typedef struct audio_stream_in audio_stream_in_t; + +/** + * return the frame size (number of bytes per sample). + * + * Deprecated: use audio_stream_out_frame_size() or audio_stream_in_frame_size() instead. + */ +__attribute__((__deprecated__)) +static inline size_t audio_stream_frame_size(const struct audio_stream *s) +{ + size_t chan_samp_sz; + audio_format_t format = s->get_format(s); + + if (audio_is_linear_pcm(format)) { + chan_samp_sz = audio_bytes_per_sample(format); + return popcount(s->get_channels(s)) * chan_samp_sz; + } + + return sizeof(int8_t); +} + +/** + * return the frame size (number of bytes per sample) of an output stream. + */ +static inline size_t audio_stream_out_frame_size(const struct audio_stream_out *s) +{ + size_t chan_samp_sz; + audio_format_t format = s->common.get_format(&s->common); + + if (audio_is_linear_pcm(format)) { + chan_samp_sz = audio_bytes_per_sample(format); + return audio_channel_count_from_out_mask(s->common.get_channels(&s->common)) * chan_samp_sz; + } + + return sizeof(int8_t); +} + +/** + * return the frame size (number of bytes per sample) of an input stream. + */ +static inline size_t audio_stream_in_frame_size(const struct audio_stream_in *s) +{ + size_t chan_samp_sz; + audio_format_t format = s->common.get_format(&s->common); + + if (audio_is_linear_pcm(format)) { + chan_samp_sz = audio_bytes_per_sample(format); + return audio_channel_count_from_in_mask(s->common.get_channels(&s->common)) * chan_samp_sz; + } + + return sizeof(int8_t); +} + +/**********************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct audio_module { + struct hw_module_t common; +}; + +struct audio_hw_device { + /** + * Common methods of the audio device. This *must* be the first member of audio_hw_device + * as users of this structure will cast a hw_device_t to audio_hw_device pointer in contexts + * where it's known the hw_device_t references an audio_hw_device. + */ + struct hw_device_t common; + + /** + * used by audio flinger to enumerate what devices are supported by + * each audio_hw_device implementation. + * + * Return value is a bitmask of 1 or more values of audio_devices_t + * + * NOTE: audio HAL implementations starting with + * AUDIO_DEVICE_API_VERSION_2_0 do not implement this function. + * All supported devices should be listed in audio_policy.conf + * file and the audio policy manager must choose the appropriate + * audio module based on information in this file. + */ + uint32_t (*get_supported_devices)(const struct audio_hw_device *dev); + + /** + * check to see if the audio hardware interface has been initialized. + * returns 0 on success, -ENODEV on failure. + */ + int (*init_check)(const struct audio_hw_device *dev); + + /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */ + int (*set_voice_volume)(struct audio_hw_device *dev, float volume); + + /** + * set the audio volume for all audio activities other than voice call. + * Range between 0.0 and 1.0. If any value other than 0 is returned, + * the software mixer will emulate this capability. + */ + int (*set_master_volume)(struct audio_hw_device *dev, float volume); + + /** + * Get the current master volume value for the HAL, if the HAL supports + * master volume control. AudioFlinger will query this value from the + * primary audio HAL when the service starts and use the value for setting + * the initial master volume across all HALs. HALs which do not support + * this method may leave it set to NULL. + */ + int (*get_master_volume)(struct audio_hw_device *dev, float *volume); + + /** + * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode + * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is + * playing, and AUDIO_MODE_IN_CALL when a call is in progress. + */ + int (*set_mode)(struct audio_hw_device *dev, audio_mode_t mode); + + /* mic mute */ + int (*set_mic_mute)(struct audio_hw_device *dev, bool state); + int (*get_mic_mute)(const struct audio_hw_device *dev, bool *state); + + /* set/get global audio parameters */ + int (*set_parameters)(struct audio_hw_device *dev, const char *kv_pairs); + + /* + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + char * (*get_parameters)(const struct audio_hw_device *dev, + const char *keys); + + /* Returns audio input buffer size according to parameters passed or + * 0 if one of the parameters is not supported. + * See also get_buffer_size which is for a particular stream. + */ + size_t (*get_input_buffer_size)(const struct audio_hw_device *dev, + const struct audio_config *config); + + /** This method creates and opens the audio hardware output stream. + * The "address" parameter qualifies the "devices" audio device type if needed. + * The format format depends on the device type: + * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC" + * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y" + * - Other devices may use a number or any other string. + */ + + int (*open_output_stream)(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out, + const char *address); + + void (*close_output_stream)(struct audio_hw_device *dev, + struct audio_stream_out* stream_out); + + /** This method creates and opens the audio hardware input stream */ + int (*open_input_stream)(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in, + audio_input_flags_t flags, + const char *address, + audio_source_t source); + + void (*close_input_stream)(struct audio_hw_device *dev, + struct audio_stream_in *stream_in); + + /** This method dumps the state of the audio hardware */ + int (*dump)(const struct audio_hw_device *dev, int fd); + + /** + * set the audio mute status for all audio activities. If any value other + * than 0 is returned, the software mixer will emulate this capability. + */ + int (*set_master_mute)(struct audio_hw_device *dev, bool mute); + + /** + * Get the current master mute status for the HAL, if the HAL supports + * master mute control. AudioFlinger will query this value from the primary + * audio HAL when the service starts and use the value for setting the + * initial master mute across all HALs. HALs which do not support this + * method may leave it set to NULL. + */ + int (*get_master_mute)(struct audio_hw_device *dev, bool *mute); + + /** + * Routing control + */ + + /* Creates an audio patch between several source and sink ports. + * The handle is allocated by the HAL and should be unique for this + * audio HAL module. */ + int (*create_audio_patch)(struct audio_hw_device *dev, + unsigned int num_sources, + const struct audio_port_config *sources, + unsigned int num_sinks, + const struct audio_port_config *sinks, + audio_patch_handle_t *handle); + + /* Release an audio patch */ + int (*release_audio_patch)(struct audio_hw_device *dev, + audio_patch_handle_t handle); + + /* Fills the list of supported attributes for a given audio port. + * As input, "port" contains the information (type, role, address etc...) + * needed by the HAL to identify the port. + * As output, "port" contains possible attributes (sampling rates, formats, + * channel masks, gain controllers...) for this port. + */ + int (*get_audio_port)(struct audio_hw_device *dev, + struct audio_port *port); + + /* Set audio port configuration */ + int (*set_audio_port_config)(struct audio_hw_device *dev, + const struct audio_port_config *config); + +}; +typedef struct audio_hw_device audio_hw_device_t; + +/** convenience API for opening and closing a supported device */ + +static inline int audio_hw_device_open(const struct hw_module_t* module, + struct audio_hw_device** device) +{ + return module->methods->open(module, AUDIO_HARDWARE_INTERFACE, + (struct hw_device_t**)device); +} + +static inline int audio_hw_device_close(struct audio_hw_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_AUDIO_INTERFACE_H
diff --git a/libhardware/include/hardware/audio_alsaops.h b/libhardware/include/hardware/audio_alsaops.h new file mode 100644 index 0000000..0d266ff --- /dev/null +++ b/libhardware/include/hardware/audio_alsaops.h
@@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file contains shared utility functions to handle the tinyalsa + * implementation for Android internal audio, generally in the hardware layer. + * Some routines may log a fatal error on failure, as noted. + */ + +#ifndef ANDROID_AUDIO_ALSAOPS_H +#define ANDROID_AUDIO_ALSAOPS_H + +#include <cutils/log.h> +#include <system/audio.h> +#include <tinyalsa/asoundlib.h> + +__BEGIN_DECLS + +/* Converts audio_format to pcm_format. + * Parameters: + * format the audio_format_t to convert + * + * Logs a fatal error if format is not a valid convertible audio_format_t. + */ +static inline enum pcm_format pcm_format_from_audio_format(audio_format_t format) +{ + switch (format) { +#ifdef HAVE_BIG_ENDIAN + case AUDIO_FORMAT_PCM_16_BIT: + return PCM_FORMAT_S16_BE; + case AUDIO_FORMAT_PCM_24_BIT_PACKED: + return PCM_FORMAT_S24_3BE; + case AUDIO_FORMAT_PCM_32_BIT: + return PCM_FORMAT_S32_BE; + case AUDIO_FORMAT_PCM_8_24_BIT: + return PCM_FORMAT_S24_BE; +#else + case AUDIO_FORMAT_PCM_16_BIT: + return PCM_FORMAT_S16_LE; + case AUDIO_FORMAT_PCM_24_BIT_PACKED: + return PCM_FORMAT_S24_3LE; + case AUDIO_FORMAT_PCM_32_BIT: + return PCM_FORMAT_S32_LE; + case AUDIO_FORMAT_PCM_8_24_BIT: + return PCM_FORMAT_S24_LE; +#endif + case AUDIO_FORMAT_PCM_FLOAT: /* there is no equivalent for float */ + default: + LOG_ALWAYS_FATAL("pcm_format_from_audio_format: invalid audio format %#x", format); + return 0; + } +} + +/* Converts pcm_format to audio_format. + * Parameters: + * format the pcm_format to convert + * + * Logs a fatal error if format is not a valid convertible pcm_format. + */ +static inline audio_format_t audio_format_from_pcm_format(enum pcm_format format) +{ + switch (format) { +#ifdef HAVE_BIG_ENDIAN + case PCM_FORMAT_S16_BE: + return AUDIO_FORMAT_PCM_16_BIT; + case PCM_FORMAT_S24_3BE: + return AUDIO_FORMAT_PCM_24_BIT_PACKED; + case PCM_FORMAT_S24_BE: + return AUDIO_FORMAT_PCM_8_24_BIT; + case PCM_FORMAT_S32_BE: + return AUDIO_FORMAT_PCM_32_BIT; +#else + case PCM_FORMAT_S16_LE: + return AUDIO_FORMAT_PCM_16_BIT; + case PCM_FORMAT_S24_3LE: + return AUDIO_FORMAT_PCM_24_BIT_PACKED; + case PCM_FORMAT_S24_LE: + return AUDIO_FORMAT_PCM_8_24_BIT; + case PCM_FORMAT_S32_LE: + return AUDIO_FORMAT_PCM_32_BIT; +#endif + default: + LOG_ALWAYS_FATAL("audio_format_from_pcm_format: invalid pcm format %#x", format); + return 0; + } +} + +__END_DECLS + +#endif /* ANDROID_AUDIO_ALSAOPS_H */
diff --git a/libhardware/include/hardware/audio_effect.h b/libhardware/include/hardware/audio_effect.h new file mode 100644 index 0000000..41cd2e6 --- /dev/null +++ b/libhardware/include/hardware/audio_effect.h
@@ -0,0 +1,1014 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_AUDIO_EFFECT_H +#define ANDROID_AUDIO_EFFECT_H + +#include <errno.h> +#include <stdint.h> +#include <strings.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <cutils/bitops.h> + +#include <system/audio.h> + + +__BEGIN_DECLS + + +///////////////////////////////////////////////// +// Common Definitions +///////////////////////////////////////////////// + +// +//--- Effect descriptor structure effect_descriptor_t +// + +// Unique effect ID (can be generated from the following site: +// http://www.itu.int/ITU-T/asn1/uuid.html) +// This format is used for both "type" and "uuid" fields of the effect descriptor structure. +// - When used for effect type and the engine is implementing and effect corresponding to a standard +// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface. +// - When used as uuid, it should be a unique UUID for this particular implementation. +typedef struct effect_uuid_s { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} effect_uuid_t; + +// Maximum length of character strings in structures defines by this API. +#define EFFECT_STRING_LEN_MAX 64 + +// NULL UUID definition (matches SL_IID_NULL_) +#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \ + { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } } +static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER; +static const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_; +static const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210"; + + +// The effect descriptor contains necessary information to facilitate the enumeration of the effect +// engines present in a library. +typedef struct effect_descriptor_s { + effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect + effect_uuid_t uuid; // UUID for this particular implementation + uint32_t apiVersion; // Version of the effect control API implemented + uint32_t flags; // effect engine capabilities/requirements flags (see below) + uint16_t cpuLoad; // CPU load indication (see below) + uint16_t memoryUsage; // Data Memory usage (see below) + char name[EFFECT_STRING_LEN_MAX]; // human readable effect name + char implementor[EFFECT_STRING_LEN_MAX]; // human readable effect implementor name +} effect_descriptor_t; + +// CPU load and memory usage indication: each effect implementation must provide an indication of +// its CPU and memory usage for the audio effect framework to limit the number of effects +// instantiated at a given time on a given platform. +// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS. +// The memory usage is expressed in KB and includes only dynamically allocated memory + +// Definitions for flags field of effect descriptor. +// +---------------------------+-----------+----------------------------------- +// | description | bits | values +// +---------------------------+-----------+----------------------------------- +// | connection mode | 0..2 | 0 insert: after track process +// | | | 1 auxiliary: connect to track auxiliary +// | | | output and use send level +// | | | 2 replace: replaces track process function; +// | | | must implement SRC, volume and mono to stereo. +// | | | 3 pre processing: applied below audio HAL on input +// | | | 4 post processing: applied below audio HAL on output +// | | | 5 - 7 reserved +// +---------------------------+-----------+----------------------------------- +// | insertion preference | 3..5 | 0 none +// | | | 1 first of the chain +// | | | 2 last of the chain +// | | | 3 exclusive (only effect in the insert chain) +// | | | 4..7 reserved +// +---------------------------+-----------+----------------------------------- +// | Volume management | 6..8 | 0 none +// | | | 1 implements volume control +// | | | 2 requires volume indication +// | | | 4 reserved +// +---------------------------+-----------+----------------------------------- +// | Device indication | 9..11 | 0 none +// | | | 1 requires device updates +// | | | 2, 4 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample input mode | 12..13 | 1 direct: process() function or EFFECT_CMD_SET_CONFIG +// | | | command must specify a buffer descriptor +// | | | 2 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_SET_CONFIG command to request input. +// | | | buffers. +// | | | 3 both: both input modes are supported +// +---------------------------+-----------+----------------------------------- +// | Sample output mode | 14..15 | 1 direct: process() function or EFFECT_CMD_SET_CONFIG +// | | | command must specify a buffer descriptor +// | | | 2 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_SET_CONFIG command to request output +// | | | buffers. +// | | | 3 both: both output modes are supported +// +---------------------------+-----------+----------------------------------- +// | Hardware acceleration | 16..17 | 0 No hardware acceleration +// | | | 1 non tunneled hw acceleration: the process() function +// | | | reads the samples, send them to HW accelerated +// | | | effect processor, reads back the processed samples +// | | | and returns them to the output buffer. +// | | | 2 tunneled hw acceleration: the process() function is +// | | | transparent. The effect interface is only used to +// | | | control the effect engine. This mode is relevant for +// | | | global effects actually applied by the audio +// | | | hardware on the output stream. +// +---------------------------+-----------+----------------------------------- +// | Audio Mode indication | 18..19 | 0 none +// | | | 1 requires audio mode updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Audio source indication | 20..21 | 0 none +// | | | 1 requires audio source updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Effect offload supported | 22 | 0 The effect cannot be offloaded to an audio DSP +// | | | 1 The effect can be offloaded to an audio DSP +// +---------------------------+-----------+----------------------------------- + +// Insert mode +#define EFFECT_FLAG_TYPE_SHIFT 0 +#define EFFECT_FLAG_TYPE_SIZE 3 +#define EFFECT_FLAG_TYPE_MASK (((1 << EFFECT_FLAG_TYPE_SIZE) -1) \ + << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_INSERT (0 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_AUXILIARY (1 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_REPLACE (2 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_PRE_PROC (3 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_POST_PROC (4 << EFFECT_FLAG_TYPE_SHIFT) + +// Insert preference +#define EFFECT_FLAG_INSERT_SHIFT (EFFECT_FLAG_TYPE_SHIFT + EFFECT_FLAG_TYPE_SIZE) +#define EFFECT_FLAG_INSERT_SIZE 3 +#define EFFECT_FLAG_INSERT_MASK (((1 << EFFECT_FLAG_INSERT_SIZE) -1) \ + << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_ANY (0 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_FIRST (1 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_LAST (2 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_EXCLUSIVE (3 << EFFECT_FLAG_INSERT_SHIFT) + + +// Volume control +#define EFFECT_FLAG_VOLUME_SHIFT (EFFECT_FLAG_INSERT_SHIFT + EFFECT_FLAG_INSERT_SIZE) +#define EFFECT_FLAG_VOLUME_SIZE 3 +#define EFFECT_FLAG_VOLUME_MASK (((1 << EFFECT_FLAG_VOLUME_SIZE) -1) \ + << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_CTRL (1 << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_IND (2 << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_NONE (0 << EFFECT_FLAG_VOLUME_SHIFT) + +// Device indication +#define EFFECT_FLAG_DEVICE_SHIFT (EFFECT_FLAG_VOLUME_SHIFT + EFFECT_FLAG_VOLUME_SIZE) +#define EFFECT_FLAG_DEVICE_SIZE 3 +#define EFFECT_FLAG_DEVICE_MASK (((1 << EFFECT_FLAG_DEVICE_SIZE) -1) \ + << EFFECT_FLAG_DEVICE_SHIFT) +#define EFFECT_FLAG_DEVICE_IND (1 << EFFECT_FLAG_DEVICE_SHIFT) +#define EFFECT_FLAG_DEVICE_NONE (0 << EFFECT_FLAG_DEVICE_SHIFT) + +// Sample input modes +#define EFFECT_FLAG_INPUT_SHIFT (EFFECT_FLAG_DEVICE_SHIFT + EFFECT_FLAG_DEVICE_SIZE) +#define EFFECT_FLAG_INPUT_SIZE 2 +#define EFFECT_FLAG_INPUT_MASK (((1 << EFFECT_FLAG_INPUT_SIZE) -1) \ + << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_DIRECT (1 << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_PROVIDER (2 << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_BOTH (3 << EFFECT_FLAG_INPUT_SHIFT) + +// Sample output modes +#define EFFECT_FLAG_OUTPUT_SHIFT (EFFECT_FLAG_INPUT_SHIFT + EFFECT_FLAG_INPUT_SIZE) +#define EFFECT_FLAG_OUTPUT_SIZE 2 +#define EFFECT_FLAG_OUTPUT_MASK (((1 << EFFECT_FLAG_OUTPUT_SIZE) -1) \ + << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_DIRECT (1 << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_PROVIDER (2 << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_BOTH (3 << EFFECT_FLAG_OUTPUT_SHIFT) + +// Hardware acceleration mode +#define EFFECT_FLAG_HW_ACC_SHIFT (EFFECT_FLAG_OUTPUT_SHIFT + EFFECT_FLAG_OUTPUT_SIZE) +#define EFFECT_FLAG_HW_ACC_SIZE 2 +#define EFFECT_FLAG_HW_ACC_MASK (((1 << EFFECT_FLAG_HW_ACC_SIZE) -1) \ + << EFFECT_FLAG_HW_ACC_SHIFT) +#define EFFECT_FLAG_HW_ACC_SIMPLE (1 << EFFECT_FLAG_HW_ACC_SHIFT) +#define EFFECT_FLAG_HW_ACC_TUNNEL (2 << EFFECT_FLAG_HW_ACC_SHIFT) + +// Audio mode indication +#define EFFECT_FLAG_AUDIO_MODE_SHIFT (EFFECT_FLAG_HW_ACC_SHIFT + EFFECT_FLAG_HW_ACC_SIZE) +#define EFFECT_FLAG_AUDIO_MODE_SIZE 2 +#define EFFECT_FLAG_AUDIO_MODE_MASK (((1 << EFFECT_FLAG_AUDIO_MODE_SIZE) -1) \ + << EFFECT_FLAG_AUDIO_MODE_SHIFT) +#define EFFECT_FLAG_AUDIO_MODE_IND (1 << EFFECT_FLAG_AUDIO_MODE_SHIFT) +#define EFFECT_FLAG_AUDIO_MODE_NONE (0 << EFFECT_FLAG_AUDIO_MODE_SHIFT) + +// Audio source indication +#define EFFECT_FLAG_AUDIO_SOURCE_SHIFT (EFFECT_FLAG_AUDIO_MODE_SHIFT + EFFECT_FLAG_AUDIO_MODE_SIZE) +#define EFFECT_FLAG_AUDIO_SOURCE_SIZE 2 +#define EFFECT_FLAG_AUDIO_SOURCE_MASK (((1 << EFFECT_FLAG_AUDIO_SOURCE_SIZE) -1) \ + << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) +#define EFFECT_FLAG_AUDIO_SOURCE_IND (1 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) +#define EFFECT_FLAG_AUDIO_SOURCE_NONE (0 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) + +// Effect offload indication +#define EFFECT_FLAG_OFFLOAD_SHIFT (EFFECT_FLAG_AUDIO_SOURCE_SHIFT + \ + EFFECT_FLAG_AUDIO_SOURCE_SIZE) +#define EFFECT_FLAG_OFFLOAD_SIZE 1 +#define EFFECT_FLAG_OFFLOAD_MASK (((1 << EFFECT_FLAG_OFFLOAD_SIZE) -1) \ + << EFFECT_FLAG_OFFLOAD_SHIFT) +#define EFFECT_FLAG_OFFLOAD_SUPPORTED (1 << EFFECT_FLAG_OFFLOAD_SHIFT) + +#define EFFECT_MAKE_API_VERSION(M, m) (((M)<<16) | ((m) & 0xFFFF)) +#define EFFECT_API_VERSION_MAJOR(v) ((v)>>16) +#define EFFECT_API_VERSION_MINOR(v) ((m) & 0xFFFF) + + + +///////////////////////////////////////////////// +// Effect control interface +///////////////////////////////////////////////// + +// Effect control interface version 2.0 +#define EFFECT_CONTROL_API_VERSION EFFECT_MAKE_API_VERSION(2,0) + +// Effect control interface structure: effect_interface_s +// The effect control interface is exposed by each effect engine implementation. It consists of +// a set of functions controlling the configuration, activation and process of the engine. +// The functions are grouped in a structure of type effect_interface_s. +// +// Effect control interface handle: effect_handle_t +// The effect_handle_t serves two purposes regarding the implementation of the effect engine: +// - 1 it is the address of a pointer to an effect_interface_s structure where the functions +// of the effect control API for a particular effect are located. +// - 2 it is the address of the context of a particular effect instance. +// A typical implementation in the effect library would define a structure as follows: +// struct effect_module_s { +// const struct effect_interface_s *itfe; +// effect_config_t config; +// effect_context_t context; +// } +// The implementation of EffectCreate() function would then allocate a structure of this +// type and return its address as effect_handle_t +typedef struct effect_interface_s **effect_handle_t; + + +// Forward definition of type audio_buffer_t +typedef struct audio_buffer_s audio_buffer_t; + + + + + + +// Effect control interface definition +struct effect_interface_s { + //////////////////////////////////////////////////////////////////////////////// + // + // Function: process + // + // Description: Effect process function. Takes input samples as specified + // (count and location) in input buffer descriptor and output processed + // samples as specified in output buffer descriptor. If the buffer descriptor + // is not specified the function must use either the buffer or the + // buffer provider function installed by the EFFECT_CMD_SET_CONFIG command. + // The effect framework will call the process() function after the EFFECT_CMD_ENABLE + // command is received and until the EFFECT_CMD_DISABLE is received. When the engine + // receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully + // and when done indicate that it is OK to stop calling the process() function by + // returning the -ENODATA status. + // + // NOTE: the process() function implementation should be "real-time safe" that is + // it should not perform blocking calls: malloc/free, sleep, read/write/open/close, + // pthread_cond_wait/pthread_mutex_lock... + // + // Input: + // self: handle to the effect interface this function + // is called on. + // inBuffer: buffer descriptor indicating where to read samples to process. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG command. + // + // outBuffer: buffer descriptor indicating where to write processed samples. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG command. + // + // Output: + // returned value: 0 successful operation + // -ENODATA the engine has finished the disable phase and the framework + // can stop calling process() + // -EINVAL invalid interface handle or + // invalid input/output buffer description + //////////////////////////////////////////////////////////////////////////////// + int32_t (*process)(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: command + // + // Description: Send a command and receive a response to/from effect engine. + // + // Input: + // self: handle to the effect interface this function + // is called on. + // cmdCode: command code: the command can be a standardized command defined in + // effect_command_e (see below) or a proprietary command. + // cmdSize: size of command in bytes + // pCmdData: pointer to command data + // pReplyData: pointer to reply data + // + // Input/Output: + // replySize: maximum size of reply data as input + // actual size of reply data as output + // + // Output: + // returned value: 0 successful operation + // -EINVAL invalid interface handle or + // invalid command/reply size or format according to + // command code + // The return code should be restricted to indicate problems related to this API + // specification. Status related to the execution of a particular command should be + // indicated as part of the reply field. + // + // *pReplyData updated with command response + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*command)(effect_handle_t self, + uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: get_descriptor + // + // Description: Returns the effect descriptor + // + // Input: + // self: handle to the effect interface this function + // is called on. + // + // Input/Output: + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -EINVAL invalid interface handle or invalid pDescriptor + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*get_descriptor)(effect_handle_t self, + effect_descriptor_t *pDescriptor); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: process_reverse + // + // Description: Process reverse stream function. This function is used to pass + // a reference stream to the effect engine. If the engine does not need a reference + // stream, this function pointer can be set to NULL. + // This function would typically implemented by an Echo Canceler. + // + // Input: + // self: handle to the effect interface this function + // is called on. + // inBuffer: buffer descriptor indicating where to read samples to process. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG_REVERSE command. + // + // outBuffer: buffer descriptor indicating where to write processed samples. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG_REVERSE command. + // If the buffer and buffer provider in the configuration received by + // EFFECT_CMD_SET_CONFIG_REVERSE are also NULL, do not return modified reverse + // stream data + // + // Output: + // returned value: 0 successful operation + // -ENODATA the engine has finished the disable phase and the framework + // can stop calling process_reverse() + // -EINVAL invalid interface handle or + // invalid input/output buffer description + //////////////////////////////////////////////////////////////////////////////// + int32_t (*process_reverse)(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); +}; + + +// +//--- Standardized command codes for command() function +// +enum effect_command_e { + EFFECT_CMD_INIT, // initialize effect engine + EFFECT_CMD_SET_CONFIG, // configure effect engine (see effect_config_t) + EFFECT_CMD_RESET, // reset effect engine + EFFECT_CMD_ENABLE, // enable effect process + EFFECT_CMD_DISABLE, // disable effect process + EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t) + EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred + EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred + EFFECT_CMD_GET_PARAM, // get parameter + EFFECT_CMD_SET_DEVICE, // set audio device (see audio.h, audio_devices_t) + EFFECT_CMD_SET_VOLUME, // set volume + EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...) + EFFECT_CMD_SET_CONFIG_REVERSE, // configure effect engine reverse stream(see effect_config_t) + EFFECT_CMD_SET_INPUT_DEVICE, // set capture device (see audio.h, audio_devices_t) + EFFECT_CMD_GET_CONFIG, // read effect engine configuration + EFFECT_CMD_GET_CONFIG_REVERSE, // read configure effect engine reverse stream configuration + EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature. + EFFECT_CMD_GET_FEATURE_CONFIG, // get current feature configuration + EFFECT_CMD_SET_FEATURE_CONFIG, // set current feature configuration + EFFECT_CMD_SET_AUDIO_SOURCE, // set the audio source (see audio.h, audio_source_t) + EFFECT_CMD_OFFLOAD, // set if effect thread is an offload one, + // send the ioHandle of the effect thread + EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code +}; + +//================================================================================================== +// command: EFFECT_CMD_INIT +//-------------------------------------------------------------------------------------------------- +// description: +// Initialize effect engine: All configurations return to default +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_RESET +//-------------------------------------------------------------------------------------------------- +// description: +// Reset the effect engine. Keep configuration but resets state and buffer content +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_ENABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Enable the process. Called by the framework before the first call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_DISABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Disable the process. Called by the framework after the last call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter and apply it immediately +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_DEFERRED +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_COMMIT +//-------------------------------------------------------------------------------------------------- +// description: +// Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_GET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Get a parameter value +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param +// data: effect_param_t + param +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//================================================================================================== +// command: EFFECT_CMD_SET_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the rendering device the audio output path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_VOLUME +//-------------------------------------------------------------------------------------------------- +// description: +// Set and get volume. Used by audio framework to delegate volume control to effect engine. +// The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in +// its descriptor to receive this command before every call to process() function +// If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return +// the volume that should be applied before the effect is processed. The overall volume (the volume +// actually applied by the effect engine multiplied by the returned value) should match the value +// indicated in the command. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: n * sizeof(uint32_t) +// data: volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: n * sizeof(uint32_t) / 0 +// data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor: +// volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +// - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor: +// N/A +// It is legal to receive a null pointer as pReplyData in which case the effect framework has +// delegated volume control to another effect +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_MODE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its +// descriptor to receive this command when the audio mode changes. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: audio_mode_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers of reverse stream. +// An example of reverse stream is the echo reference supplied to an Acoustic Echo Canceler. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_INPUT_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the capture device the audio input path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_GET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: EFFECT_CMD_GET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers of reverse stream +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS +//-------------------------------------------------------------------------------------------------- +// description: +// Queries for supported configurations for a particular feature (e.g. get the supported +// combinations of main and auxiliary channels for a noise suppressor). +// The command parameter is the feature identifier (See effect_feature_e for a list of defined +// features) followed by the maximum number of configuration descriptor to return. +// The reply is composed of: +// - status (uint32_t): +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -ENOMEM if the feature is supported but the total number of supported configurations +// exceeds the maximum number indicated by the caller. +// - total number of supported configurations (uint32_t) +// - an array of configuration descriptors. +// The actual number of descriptors returned must not exceed the maximum number indicated by +// the caller. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 2 x sizeof(uint32_t) +// data: effect_feature_e + maximum number of configurations to return +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 2 x sizeof(uint32_t) + n x sizeof (<config descriptor>) +// data: status + total number of configurations supported + array of n config descriptors +//================================================================================================== +// command: EFFECT_CMD_GET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Retrieves current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: effect_feature_e +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) + sizeof (<config descriptor>) +// data: status + config descriptor +//================================================================================================== +// command: EFFECT_CMD_SET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Sets current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -EINVAL if the configuration is invalid +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) + sizeof (<config descriptor>) +// data: effect_feature_e + config descriptor +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_SOURCE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio source the capture path is configured for (Camcorder, voice recognition...). +// See audio.h, audio_source_t for values. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_OFFLOAD +//-------------------------------------------------------------------------------------------------- +// description: +// 1.indicate if the playback thread the effect is attached to is offloaded or not +// 2.update the io handle of the playback thread the effect is attached to +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_offload_param_t) +// data: effect_offload_param_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// command: EFFECT_CMD_FIRST_PROPRIETARY +//-------------------------------------------------------------------------------------------------- +// description: +// All proprietary effect commands must use command codes above this value. The size and format of +// command and response fields is free in this case +//================================================================================================== + + +// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t +// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with +// regard to the channel mask definition in audio.h, audio_channel_mask_t e.g : +// Stereo: left, right +// 5 point 1: front left, front right, front center, low frequency, back left, back right +// The buffer size is expressed in frame count, a frame being composed of samples for all +// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by +// definition +struct audio_buffer_s { + size_t frameCount; // number of frames in buffer + union { + void* raw; // raw pointer to start of buffer + int32_t* s32; // pointer to signed 32 bit data at start of buffer + int16_t* s16; // pointer to signed 16 bit data at start of buffer + uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer + }; +}; + +// The buffer_provider_s structure contains functions that can be used +// by the effect engine process() function to query and release input +// or output audio buffer. +// The getBuffer() function is called to retrieve a buffer where data +// should read from or written to by process() function. +// The releaseBuffer() function MUST be called when the buffer retrieved +// with getBuffer() is not needed anymore. +// The process function should use the buffer provider mechanism to retrieve +// input or output buffer if the inBuffer or outBuffer passed as argument is NULL +// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_SET_CONFIG +// command did not specify an audio buffer. + +typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer); + +typedef struct buffer_provider_s { + buffer_function_t getBuffer; // retrieve next buffer + buffer_function_t releaseBuffer; // release used buffer + void *cookie; // for use by client of buffer provider functions +} buffer_provider_t; + + +// The buffer_config_s structure specifies the input or output audio format +// to be used by the effect engine. It is part of the effect_config_t +// structure that defines both input and output buffer configurations and is +// passed by the EFFECT_CMD_SET_CONFIG or EFFECT_CMD_SET_CONFIG_REVERSE command. +typedef struct buffer_config_s { + audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly + uint32_t samplingRate; // sampling rate + uint32_t channels; // channel mask (see audio_channel_mask_t in audio.h) + buffer_provider_t bufferProvider; // buffer provider + uint8_t format; // Audio format (see audio_format_t in audio.h) + uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e) + uint16_t mask; // indicates which of the above fields is valid +} buffer_config_t; + +// Values for "accessMode" field of buffer_config_t: +// overwrite, read only, accumulate (read/modify/write) +enum effect_buffer_access_e { + EFFECT_BUFFER_ACCESS_WRITE, + EFFECT_BUFFER_ACCESS_READ, + EFFECT_BUFFER_ACCESS_ACCUMULATE + +}; + +// feature identifiers for EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS command +enum effect_feature_e { + EFFECT_FEATURE_AUX_CHANNELS, // supports auxiliary channels (e.g. dual mic noise suppressor) + EFFECT_FEATURE_CNT +}; + +// EFFECT_FEATURE_AUX_CHANNELS feature configuration descriptor. Describe a combination +// of main and auxiliary channels supported +typedef struct channel_config_s { + audio_channel_mask_t main_channels; // channel mask for main channels + audio_channel_mask_t aux_channels; // channel mask for auxiliary channels +} channel_config_t; + + +// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field +// in buffer_config_t must be taken into account when executing the EFFECT_CMD_SET_CONFIG command +#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account +#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account +#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account +#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account +#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account +#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account +#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \ + EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \ + EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER) + + +// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_CONFIG +// command to configure audio parameters and buffers for effect engine input and output. +typedef struct effect_config_s { + buffer_config_t inputCfg; + buffer_config_t outputCfg; +} effect_config_t; + + +// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM +// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command. +// psize and vsize represent the actual size of parameter and value. +// +// NOTE: the start of value field inside the data field is always on a 32 bit boundary: +// +// +-----------+ +// | status | sizeof(int) +// +-----------+ +// | psize | sizeof(int) +// +-----------+ +// | vsize | sizeof(int) +// +-----------+ +// | | | | +// ~ parameter ~ > psize | +// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int) +// +-----------+ | +// | padding | | +// +-----------+ +// | | | +// ~ value ~ > vsize +// | | | +// +-----------+ + +typedef struct effect_param_s { + int32_t status; // Transaction status (unused for command, used for reply) + uint32_t psize; // Parameter size + uint32_t vsize; // Value size + char data[]; // Start of Parameter + Value data +} effect_param_t; + +// structure used by EFFECT_CMD_OFFLOAD command +typedef struct effect_offload_param_s { + bool isOffload; // true if the playback thread the effect is attached to is offloaded + int ioHandle; // io handle of the playback thread the effect is attached to +} effect_offload_param_t; + + +///////////////////////////////////////////////// +// Effect library interface +///////////////////////////////////////////////// + +// Effect library interface version 3.0 +// Note that EffectsFactory.c only checks the major version component, so changes to the minor +// number can only be used for fully backwards compatible changes +#define EFFECT_LIBRARY_API_VERSION EFFECT_MAKE_API_VERSION(3,0) + +#define AUDIO_EFFECT_LIBRARY_TAG ((('A') << 24) | (('E') << 16) | (('L') << 8) | ('T')) + +// Every effect library must have a data structure named AUDIO_EFFECT_LIBRARY_INFO_SYM +// and the fields of this data structure must begin with audio_effect_library_t + +typedef struct audio_effect_library_s { + // tag must be initialized to AUDIO_EFFECT_LIBRARY_TAG + uint32_t tag; + // Version of the effect library API : 0xMMMMmmmm MMMM: Major, mmmm: minor + uint32_t version; + // Name of this library + const char *name; + // Author/owner/implementor of the library + const char *implementor; + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: create_effect + // + // Description: Creates an effect engine of the specified implementation uuid and + // returns an effect control interface on this engine. The function will allocate the + // resources for an instance of the requested effect engine and return + // a handle on the effect control interface. + // + // Input: + // uuid: pointer to the effect uuid. + // sessionId: audio session to which this effect instance will be attached. + // All effects created with the same session ID are connected in series and process + // the same signal stream. Knowing that two effects are part of the same effect + // chain can help the library implement some kind of optimizations. + // ioId: identifies the output or input stream this effect is directed to in + // audio HAL. + // For future use especially with tunneled HW accelerated effects + // + // Input/Output: + // pHandle: address where to return the effect interface handle. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pEffectUuid or pHandle + // -ENOENT no effect with this uuid found + // *pHandle: updated with the effect interface handle. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*create_effect)(const effect_uuid_t *uuid, + int32_t sessionId, + int32_t ioId, + effect_handle_t *pHandle); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: release_effect + // + // Description: Releases the effect engine whose handle is given as argument. + // All resources allocated to this particular instance of the effect are + // released. + // + // Input: + // handle: handle on the effect interface to be released. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid interface handle + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*release_effect)(effect_handle_t handle); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: get_descriptor + // + // Description: Returns the descriptor of the effect engine which implementation UUID is + // given as argument. + // + // Input/Output: + // uuid: pointer to the effect uuid. + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pDescriptor or uuid + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*get_descriptor)(const effect_uuid_t *uuid, + effect_descriptor_t *pDescriptor); +} audio_effect_library_t; + +// Name of the hal_module_info +#define AUDIO_EFFECT_LIBRARY_INFO_SYM AELI + +// Name of the hal_module_info as a string +#define AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR "AELI" + +__END_DECLS + +#endif // ANDROID_AUDIO_EFFECT_H
diff --git a/libhardware/include/hardware/audio_policy.h b/libhardware/include/hardware/audio_policy.h new file mode 100644 index 0000000..99cb044 --- /dev/null +++ b/libhardware/include/hardware/audio_policy.h
@@ -0,0 +1,457 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_AUDIO_POLICY_INTERFACE_H +#define ANDROID_AUDIO_POLICY_INTERFACE_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +#include <system/audio.h> +#include <system/audio_policy.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy" + +/** + * Name of the audio devices to open + */ +#define AUDIO_POLICY_INTERFACE "policy" + +/* ---------------------------------------------------------------------------- */ + +/* + * The audio_policy and audio_policy_service_ops structs define the + * communication interfaces between the platform specific audio policy manager + * and Android generic audio policy manager. + * The platform specific audio policy manager must implement methods of the + * audio_policy struct. + * This implementation makes use of the audio_policy_service_ops to control + * the activity and configuration of audio input and output streams. + * + * The platform specific audio policy manager is in charge of the audio + * routing and volume control policies for a given platform. + * The main roles of this module are: + * - keep track of current system state (removable device connections, phone + * state, user requests...). + * System state changes and user actions are notified to audio policy + * manager with methods of the audio_policy. + * + * - process get_output() queries received when AudioTrack objects are + * created: Those queries return a handler on an output that has been + * selected, configured and opened by the audio policy manager and that + * must be used by the AudioTrack when registering to the AudioFlinger + * with the createTrack() method. + * When the AudioTrack object is released, a release_output() query + * is received and the audio policy manager can decide to close or + * reconfigure the output depending on other streams using this output and + * current system state. + * + * - similarly process get_input() and release_input() queries received from + * AudioRecord objects and configure audio inputs. + * - process volume control requests: the stream volume is converted from + * an index value (received from UI) to a float value applicable to each + * output as a function of platform specific settings and current output + * route (destination device). It also make sure that streams are not + * muted if not allowed (e.g. camera shutter sound in some countries). + */ + +/* XXX: this should be defined OUTSIDE of frameworks/base */ +struct effect_descriptor_s; + +struct audio_policy { + /* + * configuration functions + */ + + /* indicate a change in device connection status */ + int (*set_device_connection_state)(struct audio_policy *pol, + audio_devices_t device, + audio_policy_dev_state_t state, + const char *device_address); + + /* retrieve a device connection status */ + audio_policy_dev_state_t (*get_device_connection_state)( + const struct audio_policy *pol, + audio_devices_t device, + const char *device_address); + + /* indicate a change in phone state. Valid phones states are defined + * by audio_mode_t */ + void (*set_phone_state)(struct audio_policy *pol, audio_mode_t state); + + /* deprecated, never called (was "indicate a change in ringer mode") */ + void (*set_ringer_mode)(struct audio_policy *pol, uint32_t mode, + uint32_t mask); + + /* force using a specific device category for the specified usage */ + void (*set_force_use)(struct audio_policy *pol, + audio_policy_force_use_t usage, + audio_policy_forced_cfg_t config); + + /* retrieve current device category forced for a given usage */ + audio_policy_forced_cfg_t (*get_force_use)(const struct audio_policy *pol, + audio_policy_force_use_t usage); + + /* if can_mute is true, then audio streams that are marked ENFORCED_AUDIBLE + * can still be muted. */ + void (*set_can_mute_enforced_audible)(struct audio_policy *pol, + bool can_mute); + + /* check proper initialization */ + int (*init_check)(const struct audio_policy *pol); + + /* + * Audio routing query functions + */ + + /* request an output appropriate for playback of the supplied stream type and + * parameters */ + audio_io_handle_t (*get_output)(struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo); + + /* indicates to the audio policy manager that the output starts being used + * by corresponding stream. */ + int (*start_output)(struct audio_policy *pol, + audio_io_handle_t output, + audio_stream_type_t stream, + int session); + + /* indicates to the audio policy manager that the output stops being used + * by corresponding stream. */ + int (*stop_output)(struct audio_policy *pol, + audio_io_handle_t output, + audio_stream_type_t stream, + int session); + + /* releases the output. */ + void (*release_output)(struct audio_policy *pol, audio_io_handle_t output); + + /* request an input appropriate for record from the supplied device with + * supplied parameters. */ + audio_io_handle_t (*get_input)(struct audio_policy *pol, audio_source_t inputSource, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_in_acoustics_t acoustics); + + /* indicates to the audio policy manager that the input starts being used */ + int (*start_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* indicates to the audio policy manager that the input stops being used. */ + int (*stop_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* releases the input. */ + void (*release_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* + * volume control functions + */ + + /* initialises stream volume conversion parameters by specifying volume + * index range. The index range for each stream is defined by AudioService. */ + void (*init_stream_volume)(struct audio_policy *pol, + audio_stream_type_t stream, + int index_min, + int index_max); + + /* sets the new stream volume at a level corresponding to the supplied + * index. The index is within the range specified by init_stream_volume() */ + int (*set_stream_volume_index)(struct audio_policy *pol, + audio_stream_type_t stream, + int index); + + /* retrieve current volume index for the specified stream */ + int (*get_stream_volume_index)(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index); + + /* sets the new stream volume at a level corresponding to the supplied + * index for the specified device. + * The index is within the range specified by init_stream_volume() */ + int (*set_stream_volume_index_for_device)(struct audio_policy *pol, + audio_stream_type_t stream, + int index, + audio_devices_t device); + + /* retrieve current volume index for the specified stream for the specified device */ + int (*get_stream_volume_index_for_device)(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index, + audio_devices_t device); + + /* return the strategy corresponding to a given stream type */ + uint32_t (*get_strategy_for_stream)(const struct audio_policy *pol, + audio_stream_type_t stream); + + /* return the enabled output devices for the given stream type */ + audio_devices_t (*get_devices_for_stream)(const struct audio_policy *pol, + audio_stream_type_t stream); + + /* Audio effect management */ + audio_io_handle_t (*get_output_for_effect)(struct audio_policy *pol, + const struct effect_descriptor_s *desc); + + int (*register_effect)(struct audio_policy *pol, + const struct effect_descriptor_s *desc, + audio_io_handle_t output, + uint32_t strategy, + int session, + int id); + + int (*unregister_effect)(struct audio_policy *pol, int id); + + int (*set_effect_enabled)(struct audio_policy *pol, int id, bool enabled); + + bool (*is_stream_active)(const struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t in_past_ms); + + bool (*is_stream_active_remotely)(const struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t in_past_ms); + + bool (*is_source_active)(const struct audio_policy *pol, + audio_source_t source); + + /* dump state */ + int (*dump)(const struct audio_policy *pol, int fd); + + /* check if offload is possible for given sample rate, bitrate, duration, ... */ + bool (*is_offload_supported)(const struct audio_policy *pol, + const audio_offload_info_t *info); +}; + + +struct audio_policy_service_ops { + /* + * Audio output Control functions + */ + + /* Opens an audio output with the requested parameters. + * + * The parameter values can indicate to use the default values in case the + * audio policy manager has no specific requirements for the output being + * opened. + * + * When the function returns, the parameter values reflect the actual + * values used by the audio hardware output stream. + * + * The audio policy manager can check if the proposed parameters are + * suitable or not and act accordingly. + */ + audio_io_handle_t (*open_output)(void *service, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_output_flags_t flags); + + /* creates a special output that is duplicated to the two outputs passed as + * arguments. The duplication is performed by + * a special mixer thread in the AudioFlinger. + */ + audio_io_handle_t (*open_duplicate_output)(void *service, + audio_io_handle_t output1, + audio_io_handle_t output2); + + /* closes the output stream */ + int (*close_output)(void *service, audio_io_handle_t output); + + /* suspends the output. + * + * When an output is suspended, the corresponding audio hardware output + * stream is placed in standby and the AudioTracks attached to the mixer + * thread are still processed but the output mix is discarded. + */ + int (*suspend_output)(void *service, audio_io_handle_t output); + + /* restores a suspended output. */ + int (*restore_output)(void *service, audio_io_handle_t output); + + /* */ + /* Audio input Control functions */ + /* */ + + /* opens an audio input + * deprecated - new implementations should use open_input_on_module, + * and the acoustics parameter is ignored + */ + audio_io_handle_t (*open_input)(void *service, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + audio_in_acoustics_t acoustics); + + /* closes an audio input */ + int (*close_input)(void *service, audio_io_handle_t input); + + /* */ + /* misc control functions */ + /* */ + + /* set a stream volume for a particular output. + * + * For the same user setting, a given stream type can have different + * volumes for each output (destination device) it is attached to. + */ + int (*set_stream_volume)(void *service, + audio_stream_type_t stream, + float volume, + audio_io_handle_t output, + int delay_ms); + + /* invalidate a stream type, causing a reroute to an unspecified new output */ + int (*invalidate_stream)(void *service, + audio_stream_type_t stream); + + /* function enabling to send proprietary informations directly from audio + * policy manager to audio hardware interface. */ + void (*set_parameters)(void *service, + audio_io_handle_t io_handle, + const char *kv_pairs, + int delay_ms); + + /* function enabling to receive proprietary informations directly from + * audio hardware interface to audio policy manager. + * + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + + char * (*get_parameters)(void *service, audio_io_handle_t io_handle, + const char *keys); + + /* request the playback of a tone on the specified stream. + * used for instance to replace notification sounds when playing over a + * telephony device during a phone call. + */ + int (*start_tone)(void *service, + audio_policy_tone_t tone, + audio_stream_type_t stream); + + int (*stop_tone)(void *service); + + /* set down link audio volume. */ + int (*set_voice_volume)(void *service, + float volume, + int delay_ms); + + /* move effect to the specified output */ + int (*move_effects)(void *service, + int session, + audio_io_handle_t src_output, + audio_io_handle_t dst_output); + + /* loads an audio hw module. + * + * The module name passed is the base name of the HW module library, e.g "primary" or "a2dp". + * The function returns a handle on the module that will be used to specify a particular + * module when calling open_output_on_module() or open_input_on_module() + */ + audio_module_handle_t (*load_hw_module)(void *service, + const char *name); + + /* Opens an audio output on a particular HW module. + * + * Same as open_output() but specifying a specific HW module on which the output must be opened. + */ + audio_io_handle_t (*open_output_on_module)(void *service, + audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo); + + /* Opens an audio input on a particular HW module. + * + * Same as open_input() but specifying a specific HW module on which the input must be opened. + * Also removed deprecated acoustics parameter + */ + audio_io_handle_t (*open_input_on_module)(void *service, + audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask); + +}; + +/**********************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct audio_policy_module { + struct hw_module_t common; +} audio_policy_module_t; + +struct audio_policy_device { + /** + * Common methods of the audio policy device. This *must* be the first member of + * audio_policy_device as users of this structure will cast a hw_device_t to + * audio_policy_device pointer in contexts where it's known the hw_device_t references an + * audio_policy_device. + */ + struct hw_device_t common; + + int (*create_audio_policy)(const struct audio_policy_device *device, + struct audio_policy_service_ops *aps_ops, + void *service, + struct audio_policy **ap); + + int (*destroy_audio_policy)(const struct audio_policy_device *device, + struct audio_policy *ap); +}; + +/** convenience API for opening and closing a supported device */ + +static inline int audio_policy_dev_open(const hw_module_t* module, + struct audio_policy_device** device) +{ + return module->methods->open(module, AUDIO_POLICY_INTERFACE, + (hw_device_t**)device); +} + +static inline int audio_policy_dev_close(struct audio_policy_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_AUDIO_POLICY_INTERFACE_H
diff --git a/libhardware/include/hardware/ble_advertiser.h b/libhardware/include/hardware/ble_advertiser.h new file mode 100644 index 0000000..f486ed8 --- /dev/null +++ b/libhardware/include/hardware/ble_advertiser.h
@@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BLE_ADVERTISER_H +#define ANDROID_INCLUDE_BLE_ADVERTISER_H + +#include <base/callback_forward.h> +#include <stdint.h> +#include <vector> +#include "bt_common_types.h" +#include "bt_gatt_types.h" + +using std::vector; + +/** Callback invoked when multi-adv operation has completed */ +using BleAdvertiserCb = base::Callback<void(uint8_t /* status */)>; + +class BleAdvertiserInterface { + public: + virtual ~BleAdvertiserInterface() = default; + + /** Registers an advertiser with the stack */ + virtual void RegisterAdvertiser( + base::Callback<void(uint8_t /* advertiser_id */, uint8_t /* status */)>) = 0; + + /* This function disable a Multi-ADV instance */ + virtual void Unregister(uint8_t advertiser_id) = 0; + + /** Set the advertising data or scan response data */ + virtual void SetData(bool set_scan_rsp, vector<uint8_t> data) = 0; + + /** Start or stop advertising */ + virtual void Enable(bool start, BleAdvertiserCb cb) = 0; + + /* Set the parameters as per spec, user manual specified values */ + virtual void MultiAdvSetParameters(int advertiser_id, int min_interval, + int max_interval, int adv_type, + int chnl_map, int tx_power, + BleAdvertiserCb cb) = 0; + + /* Setup the data for the specified instance */ + virtual void MultiAdvSetInstData(int advertiser_id, bool set_scan_rsp, + vector<uint8_t> data, + BleAdvertiserCb cb) = 0; + + /* Enable the advertising instance as per spec */ + virtual void MultiAdvEnable(uint8_t advertiser_id, bool enable, + BleAdvertiserCb cb, int timeout_s, + BleAdvertiserCb timeout_cb) = 0; +}; + +#endif /* ANDROID_INCLUDE_BLE_ADVERTISER_H */
diff --git a/libhardware/include/hardware/ble_scanner.h b/libhardware/include/hardware/ble_scanner.h new file mode 100644 index 0000000..dca7e43 --- /dev/null +++ b/libhardware/include/hardware/ble_scanner.h
@@ -0,0 +1,125 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BLE_SCANNER_H +#define ANDROID_INCLUDE_BLE_SCANNER_H + +#include <stdint.h> +#include <vector> +#include "bt_gatt_types.h" +#include "bt_common_types.h" +#include "bt_gatt_client.h" + +/** Callback invoked in response to register_scanner */ +typedef void (*register_scanner_callback)(int status, int scanner_id, + bt_uuid_t *app_uuid); + +/** Callback invoked when batchscan storage config operation has completed */ +typedef void (*batchscan_cfg_storage_callback)(int client_if, int status); + +/** Callback invoked when batchscan enable / disable operation has completed */ +typedef void (*batchscan_enable_disable_callback)(int action, int client_if, int status); + +/** Callback invoked when batchscan reports are obtained */ +typedef void (*batchscan_reports_callback)(int client_if, int status, int report_format, + int num_records, std::vector<uint8_t> data); + +/** Callback invoked when batchscan storage threshold limit is crossed */ +typedef void (*batchscan_threshold_callback)(int client_if); + +/** Track ADV VSE callback invoked when tracked device is found or lost */ +typedef void (*track_adv_event_callback)(btgatt_track_adv_info_t *p_track_adv_info); + +/** Callback invoked when scan parameter setup has completed */ +typedef void (*scan_parameter_setup_completed_callback)(int client_if, + btgattc_error_t status); + +/** Callback for scan results */ +typedef void (*scan_result_callback)(bt_bdaddr_t* bda, int rssi, std::vector<uint8_t> adv_data); + +/** Callback invoked when a scan filter configuration command has completed */ +typedef void (*scan_filter_cfg_callback)(int action, int client_if, int status, int filt_type, + int avbl_space); + +/** Callback invoked when scan param has been added, cleared, or deleted */ +typedef void (*scan_filter_param_callback)(int action, int client_if, int status, + int avbl_space); + +/** Callback invoked when a scan filter configuration command has completed */ +typedef void (*scan_filter_status_callback)(int enable, int client_if, int status); + +typedef struct { + register_scanner_callback register_scanner_cb; + scan_result_callback scan_result_cb; + batchscan_cfg_storage_callback batchscan_cfg_storage_cb; + batchscan_enable_disable_callback batchscan_enb_disable_cb; + batchscan_reports_callback batchscan_reports_cb; + batchscan_threshold_callback batchscan_threshold_cb; + track_adv_event_callback track_adv_event_cb; + scan_parameter_setup_completed_callback scan_parameter_setup_completed_cb; + scan_filter_cfg_callback scan_filter_cfg_cb; + scan_filter_param_callback scan_filter_param_cb; + scan_filter_status_callback scan_filter_status_cb; +} btgatt_scanner_callbacks_t; + +typedef struct { + /** Registers a scanner with the stack */ + bt_status_t (*register_scanner)( bt_uuid_t *uuid ); + + /** Unregister a scanner from the stack */ + bt_status_t (*unregister_scanner)(int scanner_id ); + + /** Start or stop LE device scanning */ + bt_status_t (*scan)( bool start ); + + /** Setup scan filter params */ + bt_status_t (*scan_filter_param_setup)(btgatt_filt_param_setup_t filt_param); + + + /** Configure a scan filter condition */ + bt_status_t (*scan_filter_add_remove)(int client_if, int action, int filt_type, + int filt_index, int company_id, + int company_id_mask, const bt_uuid_t *p_uuid, + const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr, + char addr_type, std::vector<uint8_t> data, + std::vector<uint8_t> p_mask); + + /** Clear all scan filter conditions for specific filter index*/ + bt_status_t (*scan_filter_clear)(int client_if, int filt_index); + + /** Enable / disable scan filter feature*/ + bt_status_t (*scan_filter_enable)(int client_if, bool enable); + + /** Sets the LE scan interval and window in units of N*0.625 msec */ + bt_status_t (*set_scan_parameters)(int client_if, int scan_interval, int scan_window); + + /* Configure the batchscan storage */ + bt_status_t (*batchscan_cfg_storage)(int client_if, int batch_scan_full_max, + int batch_scan_trunc_max, int batch_scan_notify_threshold); + + /* Enable batchscan */ + bt_status_t (*batchscan_enb_batch_scan)(int client_if, int scan_mode, + int scan_interval, int scan_window, int addr_type, int discard_rule); + + /* Disable batchscan */ + bt_status_t (*batchscan_dis_batch_scan)(int client_if); + + /* Read out batchscan reports */ + bt_status_t (*batchscan_read_reports)(int client_if, int scan_mode); + +} btgatt_scanner_interface_t; + +#endif /* ANDROID_INCLUDE_BLE_SCANNER_H */ \ No newline at end of file
diff --git a/libhardware/include/hardware/bluetooth.h b/libhardware/include/hardware/bluetooth.h new file mode 100644 index 0000000..125a95b --- /dev/null +++ b/libhardware/include/hardware/bluetooth.h
@@ -0,0 +1,610 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BLUETOOTH_H +#define ANDROID_INCLUDE_BLUETOOTH_H + +#include <stdbool.h> +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +/** + * The Bluetooth Hardware Module ID + */ + +#define BT_HARDWARE_MODULE_ID "bluetooth" +#define BT_STACK_MODULE_ID "bluetooth" +#define BT_STACK_TEST_MODULE_ID "bluetooth_test" + + +/* Bluetooth profile interface IDs */ + +#define BT_PROFILE_HANDSFREE_ID "handsfree" +#define BT_PROFILE_HANDSFREE_CLIENT_ID "handsfree_client" +#define BT_PROFILE_ADVANCED_AUDIO_ID "a2dp" +#define BT_PROFILE_ADVANCED_AUDIO_SINK_ID "a2dp_sink" +#define BT_PROFILE_HEALTH_ID "health" +#define BT_PROFILE_SOCKETS_ID "socket" +#define BT_PROFILE_HIDHOST_ID "hidhost" +#define BT_PROFILE_PAN_ID "pan" +#define BT_PROFILE_MAP_CLIENT_ID "map_client" +#define BT_PROFILE_SDP_CLIENT_ID "sdp" +#define BT_PROFILE_GATT_ID "gatt" +#define BT_PROFILE_AV_RC_ID "avrcp" +#define BT_PROFILE_AV_RC_CTRL_ID "avrcp_ctrl" + +/** Bluetooth Address */ +typedef struct { + uint8_t address[6]; +} __attribute__((packed))bt_bdaddr_t; + +/** Bluetooth Device Name */ +typedef struct { + uint8_t name[249]; +} __attribute__((packed))bt_bdname_t; + +/** Bluetooth Adapter Visibility Modes*/ +typedef enum { + BT_SCAN_MODE_NONE, + BT_SCAN_MODE_CONNECTABLE, + BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE +} bt_scan_mode_t; + +/** Bluetooth Adapter State */ +typedef enum { + BT_STATE_OFF, + BT_STATE_ON +} bt_state_t; + +/** Bluetooth Error Status */ +/** We need to build on this */ + +typedef enum { + BT_STATUS_SUCCESS, + BT_STATUS_FAIL, + BT_STATUS_NOT_READY, + BT_STATUS_NOMEM, + BT_STATUS_BUSY, + BT_STATUS_DONE, /* request already completed */ + BT_STATUS_UNSUPPORTED, + BT_STATUS_PARM_INVALID, + BT_STATUS_UNHANDLED, + BT_STATUS_AUTH_FAILURE, + BT_STATUS_RMT_DEV_DOWN, + BT_STATUS_AUTH_REJECTED, + BT_STATUS_JNI_ENVIRONMENT_ERROR, + BT_STATUS_JNI_THREAD_ATTACH_ERROR, + BT_STATUS_WAKELOCK_ERROR +} bt_status_t; + +/** Bluetooth PinKey Code */ +typedef struct { + uint8_t pin[16]; +} __attribute__((packed))bt_pin_code_t; + +typedef struct { + uint8_t status; + uint8_t ctrl_state; /* stack reported state */ + uint64_t tx_time; /* in ms */ + uint64_t rx_time; /* in ms */ + uint64_t idle_time; /* in ms */ + uint64_t energy_used; /* a product of mA, V and ms */ +} __attribute__((packed))bt_activity_energy_info; + +typedef struct { + int32_t app_uid; + uint64_t tx_bytes; + uint64_t rx_bytes; +} __attribute__((packed))bt_uid_traffic_t; + +/** Bluetooth Adapter Discovery state */ +typedef enum { + BT_DISCOVERY_STOPPED, + BT_DISCOVERY_STARTED +} bt_discovery_state_t; + +/** Bluetooth ACL connection state */ +typedef enum { + BT_ACL_STATE_CONNECTED, + BT_ACL_STATE_DISCONNECTED +} bt_acl_state_t; + +/** Bluetooth 128-bit UUID */ +typedef struct { + uint8_t uu[16]; +} bt_uuid_t; + +/** Bluetooth SDP service record */ +typedef struct +{ + bt_uuid_t uuid; + uint16_t channel; + char name[256]; // what's the maximum length +} bt_service_record_t; + + +/** Bluetooth Remote Version info */ +typedef struct +{ + int version; + int sub_ver; + int manufacturer; +} bt_remote_version_t; + +typedef struct +{ + uint16_t version_supported; + uint8_t local_privacy_enabled; + uint8_t max_adv_instance; + uint8_t rpa_offload_supported; + uint8_t max_irk_list_size; + uint8_t max_adv_filter_supported; + uint8_t activity_energy_info_supported; + uint16_t scan_result_storage_size; + uint16_t total_trackable_advertisers; + bool extended_scan_support; + bool debug_logging_supported; +}bt_local_le_features_t; + +/* Bluetooth Adapter and Remote Device property types */ +typedef enum { + /* Properties common to both adapter and remote device */ + /** + * Description - Bluetooth Device Name + * Access mode - Adapter name can be GET/SET. Remote device can be GET + * Data type - bt_bdname_t + */ + BT_PROPERTY_BDNAME = 0x1, + /** + * Description - Bluetooth Device Address + * Access mode - Only GET. + * Data type - bt_bdaddr_t + */ + BT_PROPERTY_BDADDR, + /** + * Description - Bluetooth Service 128-bit UUIDs + * Access mode - Only GET. + * Data type - Array of bt_uuid_t (Array size inferred from property length). + */ + BT_PROPERTY_UUIDS, + /** + * Description - Bluetooth Class of Device as found in Assigned Numbers + * Access mode - Only GET. + * Data type - uint32_t. + */ + BT_PROPERTY_CLASS_OF_DEVICE, + /** + * Description - Device Type - BREDR, BLE or DUAL Mode + * Access mode - Only GET. + * Data type - bt_device_type_t + */ + BT_PROPERTY_TYPE_OF_DEVICE, + /** + * Description - Bluetooth Service Record + * Access mode - Only GET. + * Data type - bt_service_record_t + */ + BT_PROPERTY_SERVICE_RECORD, + + /* Properties unique to adapter */ + /** + * Description - Bluetooth Adapter scan mode + * Access mode - GET and SET + * Data type - bt_scan_mode_t. + */ + BT_PROPERTY_ADAPTER_SCAN_MODE, + /** + * Description - List of bonded devices + * Access mode - Only GET. + * Data type - Array of bt_bdaddr_t of the bonded remote devices + * (Array size inferred from property length). + */ + BT_PROPERTY_ADAPTER_BONDED_DEVICES, + /** + * Description - Bluetooth Adapter Discovery timeout (in seconds) + * Access mode - GET and SET + * Data type - uint32_t + */ + BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + + /* Properties unique to remote device */ + /** + * Description - User defined friendly name of the remote device + * Access mode - GET and SET + * Data type - bt_bdname_t. + */ + BT_PROPERTY_REMOTE_FRIENDLY_NAME, + /** + * Description - RSSI value of the inquired remote device + * Access mode - Only GET. + * Data type - int32_t. + */ + BT_PROPERTY_REMOTE_RSSI, + /** + * Description - Remote version info + * Access mode - SET/GET. + * Data type - bt_remote_version_t. + */ + + BT_PROPERTY_REMOTE_VERSION_INFO, + + /** + * Description - Local LE features + * Access mode - GET. + * Data type - bt_local_le_features_t. + */ + BT_PROPERTY_LOCAL_LE_FEATURES, + + BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF, +} bt_property_type_t; + +/** Bluetooth Adapter Property data structure */ +typedef struct +{ + bt_property_type_t type; + int len; + void *val; +} bt_property_t; + +/** Bluetooth Out Of Band data for bonding */ +typedef struct +{ + uint8_t le_bt_dev_addr[7]; /* LE Bluetooth Device Address */ + uint8_t c192[16]; /* Simple Pairing Hash C-192 */ + uint8_t r192[16]; /* Simple Pairing Randomizer R-192 */ + uint8_t c256[16]; /* Simple Pairing Hash C-256 */ + uint8_t r256[16]; /* Simple Pairing Randomizer R-256 */ + uint8_t sm_tk[16]; /* Security Manager TK Value */ + uint8_t le_sc_c[16]; /* LE Secure Connections Confirmation Value */ + uint8_t le_sc_r[16]; /* LE Secure Connections Random Value */ +} bt_out_of_band_data_t; + + + +/** Bluetooth Device Type */ +typedef enum { + BT_DEVICE_DEVTYPE_BREDR = 0x1, + BT_DEVICE_DEVTYPE_BLE, + BT_DEVICE_DEVTYPE_DUAL +} bt_device_type_t; +/** Bluetooth Bond state */ +typedef enum { + BT_BOND_STATE_NONE, + BT_BOND_STATE_BONDING, + BT_BOND_STATE_BONDED +} bt_bond_state_t; + +/** Bluetooth SSP Bonding Variant */ +typedef enum { + BT_SSP_VARIANT_PASSKEY_CONFIRMATION, + BT_SSP_VARIANT_PASSKEY_ENTRY, + BT_SSP_VARIANT_CONSENT, + BT_SSP_VARIANT_PASSKEY_NOTIFICATION +} bt_ssp_variant_t; + +#define BT_MAX_NUM_UUIDS 32 + +/** Bluetooth Interface callbacks */ + +/** Bluetooth Enable/Disable Callback. */ +typedef void (*adapter_state_changed_callback)(bt_state_t state); + +/** GET/SET Adapter Properties callback */ +/* TODO: For the GET/SET property APIs/callbacks, we may need a session + * identifier to associate the call with the callback. This would be needed + * whenever more than one simultaneous instance of the same adapter_type + * is get/set. + * + * If this is going to be handled in the Java framework, then we do not need + * to manage sessions here. + */ +typedef void (*adapter_properties_callback)(bt_status_t status, + int num_properties, + bt_property_t *properties); + +/** GET/SET Remote Device Properties callback */ +/** TODO: For remote device properties, do not see a need to get/set + * multiple properties - num_properties shall be 1 + */ +typedef void (*remote_device_properties_callback)(bt_status_t status, + bt_bdaddr_t *bd_addr, + int num_properties, + bt_property_t *properties); + +/** New device discovered callback */ +/** If EIR data is not present, then BD_NAME and RSSI shall be NULL and -1 + * respectively */ +typedef void (*device_found_callback)(int num_properties, + bt_property_t *properties); + +/** Discovery state changed callback */ +typedef void (*discovery_state_changed_callback)(bt_discovery_state_t state); + +/** Bluetooth Legacy PinKey Request callback */ +typedef void (*pin_request_callback)(bt_bdaddr_t *remote_bd_addr, + bt_bdname_t *bd_name, uint32_t cod, bool min_16_digit); + +/** Bluetooth SSP Request callback - Just Works & Numeric Comparison*/ +/** pass_key - Shall be 0 for BT_SSP_PAIRING_VARIANT_CONSENT & + * BT_SSP_PAIRING_PASSKEY_ENTRY */ +/* TODO: Passkey request callback shall not be needed for devices with display + * capability. We still need support this in the stack for completeness */ +typedef void (*ssp_request_callback)(bt_bdaddr_t *remote_bd_addr, + bt_bdname_t *bd_name, + uint32_t cod, + bt_ssp_variant_t pairing_variant, + uint32_t pass_key); + +/** Bluetooth Bond state changed callback */ +/* Invoked in response to create_bond, cancel_bond or remove_bond */ +typedef void (*bond_state_changed_callback)(bt_status_t status, + bt_bdaddr_t *remote_bd_addr, + bt_bond_state_t state); + +/** Bluetooth ACL connection state changed callback */ +typedef void (*acl_state_changed_callback)(bt_status_t status, bt_bdaddr_t *remote_bd_addr, + bt_acl_state_t state); + +typedef enum { + ASSOCIATE_JVM, + DISASSOCIATE_JVM +} bt_cb_thread_evt; + +/** Thread Associate/Disassociate JVM Callback */ +/* Callback that is invoked by the callback thread to allow upper layer to attach/detach to/from + * the JVM */ +typedef void (*callback_thread_event)(bt_cb_thread_evt evt); + +/** Bluetooth Test Mode Callback */ +/* Receive any HCI event from controller. Must be in DUT Mode for this callback to be received */ +typedef void (*dut_mode_recv_callback)(uint16_t opcode, uint8_t *buf, uint8_t len); + +/* LE Test mode callbacks +* This callback shall be invoked whenever the le_tx_test, le_rx_test or le_test_end is invoked +* The num_packets is valid only for le_test_end command */ +typedef void (*le_test_mode_callback)(bt_status_t status, uint16_t num_packets); + +/** Callback invoked when energy details are obtained */ +/* Ctrl_state-Current controller state-Active-1,scan-2,or idle-3 state as defined by HCI spec. + * If the ctrl_state value is 0, it means the API call failed + * Time values-In milliseconds as returned by the controller + * Energy used-Value as returned by the controller + * Status-Provides the status of the read_energy_info API call + * uid_data provides an array of bt_uid_traffic_t, where the array is terminated by an element with + * app_uid set to -1. + */ +typedef void (*energy_info_callback)(bt_activity_energy_info *energy_info, + bt_uid_traffic_t *uid_data); + +/** TODO: Add callbacks for Link Up/Down and other generic + * notifications/callbacks */ + +/** Bluetooth DM callback structure. */ +typedef struct { + /** set to sizeof(bt_callbacks_t) */ + size_t size; + adapter_state_changed_callback adapter_state_changed_cb; + adapter_properties_callback adapter_properties_cb; + remote_device_properties_callback remote_device_properties_cb; + device_found_callback device_found_cb; + discovery_state_changed_callback discovery_state_changed_cb; + pin_request_callback pin_request_cb; + ssp_request_callback ssp_request_cb; + bond_state_changed_callback bond_state_changed_cb; + acl_state_changed_callback acl_state_changed_cb; + callback_thread_event thread_evt_cb; + dut_mode_recv_callback dut_mode_recv_cb; + le_test_mode_callback le_test_mode_cb; + energy_info_callback energy_info_cb; +} bt_callbacks_t; + +typedef void (*alarm_cb)(void *data); +typedef bool (*set_wake_alarm_callout)(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data); +typedef int (*acquire_wake_lock_callout)(const char *lock_name); +typedef int (*release_wake_lock_callout)(const char *lock_name); + +/** The set of functions required by bluedroid to set wake alarms and + * grab wake locks. This struct is passed into the stack through the + * |set_os_callouts| function on |bt_interface_t|. + */ +typedef struct { + /* set to sizeof(bt_os_callouts_t) */ + size_t size; + + set_wake_alarm_callout set_wake_alarm; + acquire_wake_lock_callout acquire_wake_lock; + release_wake_lock_callout release_wake_lock; +} bt_os_callouts_t; + +/** NOTE: By default, no profiles are initialized at the time of init/enable. + * Whenever the application invokes the 'init' API of a profile, then one of + * the following shall occur: + * + * 1.) If Bluetooth is not enabled, then the Bluetooth core shall mark the + * profile as enabled. Subsequently, when the application invokes the + * Bluetooth 'enable', as part of the enable sequence the profile that were + * marked shall be enabled by calling appropriate stack APIs. The + * 'adapter_properties_cb' shall return the list of UUIDs of the + * enabled profiles. + * + * 2.) If Bluetooth is enabled, then the Bluetooth core shall invoke the stack + * profile API to initialize the profile and trigger a + * 'adapter_properties_cb' with the current list of UUIDs including the + * newly added profile's UUID. + * + * The reverse shall occur whenever the profile 'cleanup' APIs are invoked + */ + +/** Represents the standard Bluetooth DM interface. */ +typedef struct { + /** set to sizeof(bt_interface_t) */ + size_t size; + /** + * Opens the interface and provides the callback routines + * to the implemenation of this interface. + */ + int (*init)(bt_callbacks_t* callbacks ); + + /** Enable Bluetooth. */ + int (*enable)(bool guest_mode); + + /** Disable Bluetooth. */ + int (*disable)(void); + + /** Closes the interface. */ + void (*cleanup)(void); + + /** Get all Bluetooth Adapter properties at init */ + int (*get_adapter_properties)(void); + + /** Get Bluetooth Adapter property of 'type' */ + int (*get_adapter_property)(bt_property_type_t type); + + /** Set Bluetooth Adapter property of 'type' */ + /* Based on the type, val shall be one of + * bt_bdaddr_t or bt_bdname_t or bt_scanmode_t etc + */ + int (*set_adapter_property)(const bt_property_t *property); + + /** Get all Remote Device properties */ + int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr); + + /** Get Remote Device property of 'type' */ + int (*get_remote_device_property)(bt_bdaddr_t *remote_addr, + bt_property_type_t type); + + /** Set Remote Device property of 'type' */ + int (*set_remote_device_property)(bt_bdaddr_t *remote_addr, + const bt_property_t *property); + + /** Get Remote Device's service record for the given UUID */ + int (*get_remote_service_record)(bt_bdaddr_t *remote_addr, + bt_uuid_t *uuid); + + /** Start SDP to get remote services */ + int (*get_remote_services)(bt_bdaddr_t *remote_addr); + + /** Start Discovery */ + int (*start_discovery)(void); + + /** Cancel Discovery */ + int (*cancel_discovery)(void); + + /** Create Bluetooth Bonding */ + int (*create_bond)(const bt_bdaddr_t *bd_addr, int transport); + + /** Create Bluetooth Bond using out of band data */ + int (*create_bond_out_of_band)(const bt_bdaddr_t *bd_addr, int transport, + const bt_out_of_band_data_t *oob_data); + + /** Remove Bond */ + int (*remove_bond)(const bt_bdaddr_t *bd_addr); + + /** Cancel Bond */ + int (*cancel_bond)(const bt_bdaddr_t *bd_addr); + + /** + * Get the connection status for a given remote device. + * return value of 0 means the device is not connected, + * non-zero return status indicates an active connection. + */ + int (*get_connection_state)(const bt_bdaddr_t *bd_addr); + + /** BT Legacy PinKey Reply */ + /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */ + int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept, + uint8_t pin_len, bt_pin_code_t *pin_code); + + /** BT SSP Reply - Just Works, Numeric Comparison and Passkey + * passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON & + * BT_SSP_VARIANT_CONSENT + * For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey + * shall be zero */ + int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant, + uint8_t accept, uint32_t passkey); + + /** Get Bluetooth profile interface */ + const void* (*get_profile_interface) (const char *profile_id); + + /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */ + /* Configure DUT Mode - Use this mode to enter/exit DUT mode */ + int (*dut_mode_configure)(uint8_t enable); + + /* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */ + int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len); + /** BLE Test Mode APIs */ + /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End */ + int (*le_test_mode)(uint16_t opcode, uint8_t *buf, uint8_t len); + + /* enable or disable bluetooth HCI snoop log */ + int (*config_hci_snoop_log)(uint8_t enable); + + /** Sets the OS call-out functions that bluedroid needs for alarms and wake locks. + * This should be called immediately after a successful |init|. + */ + int (*set_os_callouts)(bt_os_callouts_t *callouts); + + /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or BT_STATUS_NOT_READY + * Success indicates that the VSC command was sent to controller + */ + int (*read_energy_info)(); + + /** + * Native support for dumpsys function + * Function is synchronous and |fd| is owned by caller. + * |arguments| are arguments which may affect the output, encoded as + * UTF-8 strings. + */ + void (*dump)(int fd, const char **arguments); + + /** + * Clear /data/misc/bt_config.conf and erase all stored connections + */ + int (*config_clear)(void); + + /** + * Clear (reset) the dynamic portion of the device interoperability database. + */ + void (*interop_database_clear)(void); + + /** + * Add a new device interoperability workaround for a remote device whose + * first |len| bytes of the its device address match |addr|. + * NOTE: |feature| has to match an item defined in interop_feature_t (interop.h). + */ + void (*interop_database_add)(uint16_t feature, const bt_bdaddr_t *addr, size_t len); +} bt_interface_t; + +/** TODO: Need to add APIs for Service Discovery, Service authorization and + * connection management. Also need to add APIs for configuring + * properties of remote bonded devices such as name, UUID etc. */ + +typedef struct { + struct hw_device_t common; + const bt_interface_t* (*get_bluetooth_interface)(); +} bluetooth_device_t; + +typedef bluetooth_device_t bluetooth_module_t; + + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BLUETOOTH_H */
diff --git a/libhardware/include/hardware/boot_control.h b/libhardware/include/hardware/boot_control.h new file mode 100644 index 0000000..36a867d --- /dev/null +++ b/libhardware/include/hardware/boot_control.h
@@ -0,0 +1,134 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_BOOT_CONTROL_H +#define ANDROID_INCLUDE_HARDWARE_BOOT_CONTROL_H + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define BOOT_CONTROL_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +/** + * The id of this module + */ +#define BOOT_CONTROL_HARDWARE_MODULE_ID "bootctrl" + +/* + * The Boot Control HAL is designed to allow for managing sets of redundant + * partitions, called slots, that can be booted from independantly. Slots + * are sets of partitions whose names differ only by a given suffix. + * They are identified here by a 0 indexed number, and associated with their + * suffix, which can be appended to the base name for any particular partition + * to find the one associated with that slot. The bootloader must pass the suffix + * of the currently active slot either through a kernel command line property at + * androidboot.slot_suffix, or the device tree at /firmware/android/slot_suffix. + * The primary use of this set up is to allow for background updates while the + * device is running, and to provide a fallback in the event that the update fails. + */ + + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct boot_control_module { + struct hw_module_t common; + + /* + * (*init)() perform any initialization tasks needed for the HAL. + * This is called only once. + */ + void (*init)(struct boot_control_module *module); + + /* + * (*getNumberSlots)() returns the number of available slots. + * For instance, a system with a single set of partitions would return + * 1, a system with A/B would return 2, A/B/C -> 3... + */ + unsigned (*getNumberSlots)(struct boot_control_module *module); + + /* + * (*getCurrentSlot)() returns the value letting the system know + * whether the current slot is A or B. The meaning of A and B is + * left up to the implementer. It is assumed that if the current slot + * is A, then the block devices underlying B can be accessed directly + * without any risk of corruption. + * The returned value is always guaranteed to be strictly less than the + * value returned by getNumberSlots. Slots start at 0 and + * finish at getNumberSlots() - 1 + */ + unsigned (*getCurrentSlot)(struct boot_control_module *module); + + /* + * (*markBootSuccessful)() marks the current slot + * as having booted successfully + * + * Returns 0 on success, -errno on error. + */ + int (*markBootSuccessful)(struct boot_control_module *module); + + /* + * (*setActiveBootSlot)() marks the slot passed in parameter as + * the active boot slot (see getCurrentSlot for an explanation + * of the "slot" parameter). This overrides any previous call to + * setSlotAsUnbootable. + * Returns 0 on success, -errno on error. + */ + int (*setActiveBootSlot)(struct boot_control_module *module, unsigned slot); + + /* + * (*setSlotAsUnbootable)() marks the slot passed in parameter as + * an unbootable. This can be used while updating the contents of the slot's + * partitions, so that the system will not attempt to boot a known bad set up. + * Returns 0 on success, -errno on error. + */ + int (*setSlotAsUnbootable)(struct boot_control_module *module, unsigned slot); + + /* + * (*isSlotBootable)() returns if the slot passed in parameter is + * bootable. Note that slots can be made unbootable by both the + * bootloader and by the OS using setSlotAsUnbootable. + * Returns 1 if the slot is bootable, 0 if it's not, and -errno on + * error. + */ + int (*isSlotBootable)(struct boot_control_module *module, unsigned slot); + + /* + * (*getSuffix)() returns the string suffix used by partitions that + * correspond to the slot number passed in parameter. The returned string + * is expected to be statically allocated and not need to be freed. + * Returns NULL if slot does not match an existing slot. + */ + const char* (*getSuffix)(struct boot_control_module *module, unsigned slot); + + /* + * (*isSlotMarkedSucessful)() returns if the slot passed in parameter has + * been marked as successful using markBootSuccessful. + * Returns 1 if the slot has been marked as successful, 0 if it's + * not the case, and -errno on error. + */ + int (*isSlotMarkedSuccessful)(struct boot_control_module *module, unsigned slot); + + void* reserved[31]; +} boot_control_module_t; + + +__END_DECLS + +#endif // ANDROID_INCLUDE_HARDWARE_BOOT_CONTROL_H
diff --git a/libhardware/include/hardware/bt_av.h b/libhardware/include/hardware/bt_av.h new file mode 100644 index 0000000..9b32216 --- /dev/null +++ b/libhardware/include/hardware/bt_av.h
@@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_AV_H +#define ANDROID_INCLUDE_BT_AV_H + +__BEGIN_DECLS + +/* Bluetooth AV connection states */ +typedef enum { + BTAV_CONNECTION_STATE_DISCONNECTED = 0, + BTAV_CONNECTION_STATE_CONNECTING, + BTAV_CONNECTION_STATE_CONNECTED, + BTAV_CONNECTION_STATE_DISCONNECTING +} btav_connection_state_t; + +/* Bluetooth AV datapath states */ +typedef enum { + BTAV_AUDIO_STATE_REMOTE_SUSPEND = 0, + BTAV_AUDIO_STATE_STOPPED, + BTAV_AUDIO_STATE_STARTED, +} btav_audio_state_t; + + +/** Callback for connection state change. + * state will have one of the values from btav_connection_state_t + */ +typedef void (* btav_connection_state_callback)(btav_connection_state_t state, + bt_bdaddr_t *bd_addr); + +/** Callback for audiopath state change. + * state will have one of the values from btav_audio_state_t + */ +typedef void (* btav_audio_state_callback)(btav_audio_state_t state, + bt_bdaddr_t *bd_addr); + +/** Callback for audio configuration change. + * Used only for the A2DP sink interface. + * state will have one of the values from btav_audio_state_t + * sample_rate: sample rate in Hz + * channel_count: number of channels (1 for mono, 2 for stereo) + */ +typedef void (* btav_audio_config_callback)(bt_bdaddr_t *bd_addr, + uint32_t sample_rate, + uint8_t channel_count); + +/** BT-AV callback structure. */ +typedef struct { + /** set to sizeof(btav_callbacks_t) */ + size_t size; + btav_connection_state_callback connection_state_cb; + btav_audio_state_callback audio_state_cb; + btav_audio_config_callback audio_config_cb; +} btav_callbacks_t; + +/** + * NOTE: + * + * 1. AVRCP 1.0 shall be supported initially. AVRCP passthrough commands + * shall be handled internally via uinput + * + * 2. A2DP data path shall be handled via a socket pipe between the AudioFlinger + * android_audio_hw library and the Bluetooth stack. + * + */ +/** Represents the standard BT-AV interface. + * Used for both the A2DP source and sink interfaces. + */ +typedef struct { + + /** set to sizeof(btav_interface_t) */ + size_t size; + /** + * Register the BtAv callbacks + */ + bt_status_t (*init)( btav_callbacks_t* callbacks ); + + /** connect to headset */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); + + /** dis-connect from headset */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** Closes the interface. */ + void (*cleanup)( void ); + + /** Sends Audio Focus State. */ + void (*set_audio_focus_state)( int focus_state ); + + /** Sets the audio track gain. */ + void (*set_audio_track_gain)( float gain ); +} btav_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_AV_H */
diff --git a/libhardware/include/hardware/bt_common_types.h b/libhardware/include/hardware/bt_common_types.h new file mode 100644 index 0000000..1e6be6b --- /dev/null +++ b/libhardware/include/hardware/bt_common_types.h
@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** + * + * This file contains constants and definitions that can be used commonly between JNI and stack layer + * + ******************************************************************************/ +#ifndef ANDROID_INCLUDE_BT_COMMON_TYPES_H +#define ANDROID_INCLUDE_BT_COMMON_TYPES_H + +#include "bluetooth.h" + +typedef struct +{ + uint8_t client_if; + uint8_t filt_index; + uint8_t advertiser_state; + uint8_t advertiser_info_present; + uint8_t addr_type; + uint8_t tx_power; + int8_t rssi_value; + uint16_t time_stamp; + bt_bdaddr_t bd_addr; + uint8_t adv_pkt_len; + uint8_t *p_adv_pkt_data; + uint8_t scan_rsp_len; + uint8_t *p_scan_rsp_data; +} btgatt_track_adv_info_t; + +typedef enum +{ + BTGATT_DB_PRIMARY_SERVICE, + BTGATT_DB_SECONDARY_SERVICE, + BTGATT_DB_INCLUDED_SERVICE, + BTGATT_DB_CHARACTERISTIC, + BTGATT_DB_DESCRIPTOR, +} bt_gatt_db_attribute_type_t; + +typedef struct +{ + uint16_t id; + bt_uuid_t uuid; + bt_gatt_db_attribute_type_t type; + uint16_t attribute_handle; + + /* + * If |type| is |BTGATT_DB_PRIMARY_SERVICE|, or + * |BTGATT_DB_SECONDARY_SERVICE|, this contains the start and end attribute + * handles. + */ + uint16_t start_handle; + uint16_t end_handle; + + /* + * If |type| is |BTGATT_DB_CHARACTERISTIC|, this contains the properties of + * the characteristic. + */ + uint8_t properties; + uint16_t permissions; +} btgatt_db_element_t; + +#endif /* ANDROID_INCLUDE_BT_COMMON_TYPES_H */
diff --git a/libhardware/include/hardware/bt_gatt.h b/libhardware/include/hardware/bt_gatt.h new file mode 100644 index 0000000..414d3e4 --- /dev/null +++ b/libhardware/include/hardware/bt_gatt.h
@@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_INCLUDE_BT_GATT_H +#define ANDROID_INCLUDE_BT_GATT_H + +#include <stdint.h> +#include "ble_advertiser.h" +#include "ble_scanner.h" +#include "bt_gatt_client.h" +#include "bt_gatt_server.h" + +__BEGIN_DECLS + +/** BT-GATT callbacks */ +typedef struct { + /** Set to sizeof(btgatt_callbacks_t) */ + size_t size; + + /** GATT Client callbacks */ + const btgatt_client_callbacks_t* client; + + /** GATT Server callbacks */ + const btgatt_server_callbacks_t* server; + + /** LE scanner callbacks */ + const btgatt_scanner_callbacks_t* scanner; +} btgatt_callbacks_t; + +/** Represents the standard Bluetooth GATT interface. */ +typedef struct { + /** Set to sizeof(btgatt_interface_t) */ + size_t size; + + /** + * Initializes the interface and provides callback routines + */ + bt_status_t (*init)( const btgatt_callbacks_t* callbacks ); + + /** Closes the interface */ + void (*cleanup)( void ); + + /** Pointer to the GATT client interface methods.*/ + const btgatt_client_interface_t* client; + + /** Pointer to the GATT server interface methods.*/ + const btgatt_server_interface_t* server; + + /** Pointer to the LE scanner interface methods.*/ + const btgatt_scanner_interface_t* scanner; + + /** Pointer to the advertiser interface methods.*/ + BleAdvertiserInterface* advertiser; +} btgatt_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_GATT_H */
diff --git a/libhardware/include/hardware/bt_gatt_client.h b/libhardware/include/hardware/bt_gatt_client.h new file mode 100644 index 0000000..6c5a85e --- /dev/null +++ b/libhardware/include/hardware/bt_gatt_client.h
@@ -0,0 +1,287 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_INCLUDE_BT_GATT_CLIENT_H +#define ANDROID_INCLUDE_BT_GATT_CLIENT_H + +#include <stdint.h> +#include <vector> +#include "bt_gatt_types.h" +#include "bt_common_types.h" + +using std::vector; + +__BEGIN_DECLS + +/** + * Buffer sizes for maximum attribute length and maximum read/write + * operation buffer size. + */ +#define BTGATT_MAX_ATTR_LEN 600 + +/** Buffer type for unformatted reads/writes */ +typedef struct +{ + uint8_t value[BTGATT_MAX_ATTR_LEN]; + uint16_t len; +} btgatt_unformatted_value_t; + +/** Parameters for GATT read operations */ +typedef struct +{ + uint16_t handle; + btgatt_unformatted_value_t value; + uint16_t value_type; + uint8_t status; +} btgatt_read_params_t; + +/** Parameters for GATT write operations */ +typedef struct +{ + btgatt_srvc_id_t srvc_id; + btgatt_gatt_id_t char_id; + btgatt_gatt_id_t descr_id; + uint8_t status; +} btgatt_write_params_t; + +/** Attribute change notification parameters */ +typedef struct +{ + uint8_t value[BTGATT_MAX_ATTR_LEN]; + bt_bdaddr_t bda; + uint16_t handle; + uint16_t len; + uint8_t is_notify; +} btgatt_notify_params_t; + +typedef struct +{ + uint8_t client_if; + uint8_t action; + uint8_t filt_index; + uint16_t feat_seln; + uint16_t list_logic_type; + uint8_t filt_logic_type; + uint8_t rssi_high_thres; + uint8_t rssi_low_thres; + uint8_t dely_mode; + uint16_t found_timeout; + uint16_t lost_timeout; + uint8_t found_timeout_cnt; + uint16_t num_of_tracking_entries; +} btgatt_filt_param_setup_t; + +typedef struct +{ + bt_bdaddr_t *bda1; + bt_uuid_t *uuid1; + uint16_t u1; + uint16_t u2; + uint16_t u3; + uint16_t u4; + uint16_t u5; +} btgatt_test_params_t; + +/* BT GATT client error codes */ +typedef enum +{ + BT_GATTC_COMMAND_SUCCESS = 0, /* 0 Command succeeded */ + BT_GATTC_COMMAND_STARTED, /* 1 Command started OK. */ + BT_GATTC_COMMAND_BUSY, /* 2 Device busy with another command */ + BT_GATTC_COMMAND_STORED, /* 3 request is stored in control block */ + BT_GATTC_NO_RESOURCES, /* 4 No resources to issue command */ + BT_GATTC_MODE_UNSUPPORTED, /* 5 Request for 1 or more unsupported modes */ + BT_GATTC_ILLEGAL_VALUE, /* 6 Illegal command /parameter value */ + BT_GATTC_INCORRECT_STATE, /* 7 Device in wrong state for request */ + BT_GATTC_UNKNOWN_ADDR, /* 8 Unknown remote BD address */ + BT_GATTC_DEVICE_TIMEOUT, /* 9 Device timeout */ + BT_GATTC_INVALID_CONTROLLER_OUTPUT,/* 10 An incorrect value was received from HCI */ + BT_GATTC_SECURITY_ERROR, /* 11 Authorization or security failure or not authorized */ + BT_GATTC_DELAYED_ENCRYPTION_CHECK, /*12 Delayed encryption check */ + BT_GATTC_ERR_PROCESSING /* 12 Generic error */ +} btgattc_error_t; + +/** BT-GATT Client callback structure. */ + +/** Callback invoked in response to register_client */ +typedef void (*register_client_callback)(int status, int client_if, + bt_uuid_t *app_uuid); + +/** GATT open callback invoked in response to open */ +typedef void (*connect_callback)(int conn_id, int status, int client_if, bt_bdaddr_t* bda); + +/** Callback invoked in response to close */ +typedef void (*disconnect_callback)(int conn_id, int status, + int client_if, bt_bdaddr_t* bda); + +/** + * Invoked in response to search_service when the GATT service search + * has been completed. + */ +typedef void (*search_complete_callback)(int conn_id, int status); + +/** Callback invoked in response to [de]register_for_notification */ +typedef void (*register_for_notification_callback)(int conn_id, + int registered, int status, uint16_t handle); + +/** + * Remote device notification callback, invoked when a remote device sends + * a notification or indication that a client has registered for. + */ +typedef void (*notify_callback)(int conn_id, btgatt_notify_params_t *p_data); + +/** Reports result of a GATT read operation */ +typedef void (*read_characteristic_callback)(int conn_id, int status, + btgatt_read_params_t *p_data); + +/** GATT write characteristic operation callback */ +typedef void (*write_characteristic_callback)(int conn_id, int status, uint16_t handle); + +/** GATT execute prepared write callback */ +typedef void (*execute_write_callback)(int conn_id, int status); + +/** Callback invoked in response to read_descriptor */ +typedef void (*read_descriptor_callback)(int conn_id, int status, + btgatt_read_params_t *p_data); + +/** Callback invoked in response to write_descriptor */ +typedef void (*write_descriptor_callback)(int conn_id, int status, uint16_t handle); + +/** Callback triggered in response to read_remote_rssi */ +typedef void (*read_remote_rssi_callback)(int client_if, bt_bdaddr_t* bda, + int rssi, int status); + +/** Callback invoked when the MTU for a given connection changes */ +typedef void (*configure_mtu_callback)(int conn_id, int status, int mtu); + + +/** + * Callback notifying an application that a remote device connection is currently congested + * and cannot receive any more data. An application should avoid sending more data until + * a further callback is received indicating the congestion status has been cleared. + */ +typedef void (*congestion_callback)(int conn_id, bool congested); + +/** GATT get database callback */ +typedef void (*get_gatt_db_callback)(int conn_id, btgatt_db_element_t *db, int count); + +/** GATT services between start_handle and end_handle were removed */ +typedef void (*services_removed_callback)(int conn_id, uint16_t start_handle, uint16_t end_handle); + +/** GATT services were added */ +typedef void (*services_added_callback)(int conn_id, btgatt_db_element_t *added, int added_count); + +typedef struct { + register_client_callback register_client_cb; + connect_callback open_cb; + disconnect_callback close_cb; + search_complete_callback search_complete_cb; + register_for_notification_callback register_for_notification_cb; + notify_callback notify_cb; + read_characteristic_callback read_characteristic_cb; + write_characteristic_callback write_characteristic_cb; + read_descriptor_callback read_descriptor_cb; + write_descriptor_callback write_descriptor_cb; + execute_write_callback execute_write_cb; + read_remote_rssi_callback read_remote_rssi_cb; + configure_mtu_callback configure_mtu_cb; + congestion_callback congestion_cb; + get_gatt_db_callback get_gatt_db_cb; + services_removed_callback services_removed_cb; + services_added_callback services_added_cb; +} btgatt_client_callbacks_t; + +/** Represents the standard BT-GATT client interface. */ + +typedef struct { + /** Registers a GATT client application with the stack */ + bt_status_t (*register_client)( bt_uuid_t *uuid ); + + /** Unregister a client application from the stack */ + bt_status_t (*unregister_client)(int client_if ); + + /** Create a connection to a remote LE or dual-mode device */ + bt_status_t (*connect)( int client_if, const bt_bdaddr_t *bd_addr, + bool is_direct, int transport ); + + /** Disconnect a remote device or cancel a pending connection */ + bt_status_t (*disconnect)( int client_if, const bt_bdaddr_t *bd_addr, + int conn_id); + + /** Clear the attribute cache for a given device */ + bt_status_t (*refresh)( int client_if, const bt_bdaddr_t *bd_addr ); + + /** + * Enumerate all GATT services on a connected device. + * Optionally, the results can be filtered for a given UUID. + */ + bt_status_t (*search_service)(int conn_id, bt_uuid_t *filter_uuid ); + + /** Read a characteristic on a remote device */ + bt_status_t (*read_characteristic)( int conn_id, uint16_t handle, + int auth_req ); + + /** Write a remote characteristic */ + bt_status_t (*write_characteristic)(int conn_id, uint16_t handle, + int write_type, int auth_req, + vector<uint8_t> value); + + /** Read the descriptor for a given characteristic */ + bt_status_t (*read_descriptor)(int conn_id, uint16_t handle, int auth_req); + + /** Write a remote descriptor for a given characteristic */ + bt_status_t (*write_descriptor)( int conn_id, uint16_t handle, + int auth_req, vector<uint8_t> value); + + /** Execute a prepared write operation */ + bt_status_t (*execute_write)(int conn_id, int execute); + + /** + * Register to receive notifications or indications for a given + * characteristic + */ + bt_status_t (*register_for_notification)( int client_if, + const bt_bdaddr_t *bd_addr, uint16_t handle); + + /** Deregister a previous request for notifications/indications */ + bt_status_t (*deregister_for_notification)( int client_if, + const bt_bdaddr_t *bd_addr, uint16_t handle); + + /** Request RSSI for a given remote device */ + bt_status_t (*read_remote_rssi)( int client_if, const bt_bdaddr_t *bd_addr); + + /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */ + int (*get_device_type)( const bt_bdaddr_t *bd_addr ); + + /** Configure the MTU for a given connection */ + bt_status_t (*configure_mtu)(int conn_id, int mtu); + + /** Request a connection parameter update */ + bt_status_t (*conn_parameter_update)(const bt_bdaddr_t *bd_addr, int min_interval, + int max_interval, int latency, int timeout); + + /** Test mode interface */ + bt_status_t (*test_command)( int command, btgatt_test_params_t* params); + + /** Get gatt db content */ + bt_status_t (*get_gatt_db)( int conn_id); + +} btgatt_client_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_GATT_CLIENT_H */
diff --git a/libhardware/include/hardware/bt_gatt_server.h b/libhardware/include/hardware/bt_gatt_server.h new file mode 100644 index 0000000..92af285 --- /dev/null +++ b/libhardware/include/hardware/bt_gatt_server.h
@@ -0,0 +1,165 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_INCLUDE_BT_GATT_SERVER_H +#define ANDROID_INCLUDE_BT_GATT_SERVER_H + +#include <stdint.h> +#include <vector> + +#include "bt_gatt_types.h" + +using std::vector; + +__BEGIN_DECLS + +/** GATT value type used in response to remote read requests */ +typedef struct +{ + uint8_t value[BTGATT_MAX_ATTR_LEN]; + uint16_t handle; + uint16_t offset; + uint16_t len; + uint8_t auth_req; +} btgatt_value_t; + +/** GATT remote read request response type */ +typedef union +{ + btgatt_value_t attr_value; + uint16_t handle; +} btgatt_response_t; + +/** BT-GATT Server callback structure. */ + +/** Callback invoked in response to register_server */ +typedef void (*register_server_callback)(int status, int server_if, + bt_uuid_t *app_uuid); + +/** Callback indicating that a remote device has connected or been disconnected */ +typedef void (*connection_callback)(int conn_id, int server_if, int connected, + bt_bdaddr_t *bda); + +/** Callback invoked in response to create_service */ +typedef void (*service_added_callback)(int status, int server_if, + vector<btgatt_db_element_t> service); + +/** Callback invoked in response to stop_service */ +typedef void (*service_stopped_callback)(int status, int server_if, + int srvc_handle); + +/** Callback triggered when a service has been deleted */ +typedef void (*service_deleted_callback)(int status, int server_if, + int srvc_handle); + +/** + * Callback invoked when a remote device has requested to read a characteristic + * or descriptor. The application must respond by calling send_response + */ +typedef void (*request_read_callback)(int conn_id, int trans_id, bt_bdaddr_t *bda, + int attr_handle, int offset, bool is_long); + +/** + * Callback invoked when a remote device has requested to write to a + * characteristic or descriptor. + */ +typedef void (*request_write_callback)(int conn_id, int trans_id, bt_bdaddr_t *bda, + int attr_handle, int offset, bool need_rsp, + bool is_prep, vector<uint8_t> value); + +/** Callback invoked when a previously prepared write is to be executed */ +typedef void (*request_exec_write_callback)(int conn_id, int trans_id, + bt_bdaddr_t *bda, int exec_write); + +/** + * Callback triggered in response to send_response if the remote device + * sends a confirmation. + */ +typedef void (*response_confirmation_callback)(int status, int handle); + +/** + * Callback confirming that a notification or indication has been sent + * to a remote device. + */ +typedef void (*indication_sent_callback)(int conn_id, int status); + +/** + * Callback notifying an application that a remote device connection is currently congested + * and cannot receive any more data. An application should avoid sending more data until + * a further callback is received indicating the congestion status has been cleared. + */ +typedef void (*congestion_callback)(int conn_id, bool congested); + +/** Callback invoked when the MTU for a given connection changes */ +typedef void (*mtu_changed_callback)(int conn_id, int mtu); + +typedef struct { + register_server_callback register_server_cb; + connection_callback connection_cb; + service_added_callback service_added_cb; + service_stopped_callback service_stopped_cb; + service_deleted_callback service_deleted_cb; + request_read_callback request_read_characteristic_cb; + request_read_callback request_read_descriptor_cb; + request_write_callback request_write_characteristic_cb; + request_write_callback request_write_descriptor_cb; + request_exec_write_callback request_exec_write_cb; + response_confirmation_callback response_confirmation_cb; + indication_sent_callback indication_sent_cb; + congestion_callback congestion_cb; + mtu_changed_callback mtu_changed_cb; +} btgatt_server_callbacks_t; + +/** Represents the standard BT-GATT server interface. */ +typedef struct { + /** Registers a GATT server application with the stack */ + bt_status_t (*register_server)( bt_uuid_t *uuid ); + + /** Unregister a server application from the stack */ + bt_status_t (*unregister_server)(int server_if ); + + /** Create a connection to a remote peripheral */ + bt_status_t (*connect)(int server_if, const bt_bdaddr_t *bd_addr, + bool is_direct, int transport); + + /** Disconnect an established connection or cancel a pending one */ + bt_status_t (*disconnect)(int server_if, const bt_bdaddr_t *bd_addr, + int conn_id ); + + /** Create a new service */ + bt_status_t (*add_service)(int server_if, vector<btgatt_db_element_t> service); + + /** Stops a local service */ + bt_status_t (*stop_service)(int server_if, int service_handle); + + /** Delete a local service */ + bt_status_t (*delete_service)(int server_if, int service_handle); + + /** Send value indication to a remote device */ + bt_status_t (*send_indication)(int server_if, int attribute_handle, + int conn_id, int confirm, + vector<uint8_t> value); + + /** Send a response to a read/write operation */ + bt_status_t (*send_response)(int conn_id, int trans_id, + int status, btgatt_response_t *response); + +} btgatt_server_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_GATT_CLIENT_H */
diff --git a/libhardware/include/hardware/bt_gatt_types.h b/libhardware/include/hardware/bt_gatt_types.h new file mode 100644 index 0000000..e037ddc --- /dev/null +++ b/libhardware/include/hardware/bt_gatt_types.h
@@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_INCLUDE_BT_GATT_TYPES_H +#define ANDROID_INCLUDE_BT_GATT_TYPES_H + +#include <stdint.h> +#include <stdbool.h> + +__BEGIN_DECLS + +/** + * GATT Service types + */ +#define BTGATT_SERVICE_TYPE_PRIMARY 0 +#define BTGATT_SERVICE_TYPE_SECONDARY 1 + +/** GATT ID adding instance id tracking to the UUID */ +typedef struct +{ + bt_uuid_t uuid; + uint8_t inst_id; +} btgatt_gatt_id_t; + +/** GATT Service ID also identifies the service type (primary/secondary) */ +typedef struct +{ + btgatt_gatt_id_t id; + uint8_t is_primary; +} btgatt_srvc_id_t; + +/** Preferred physical Transport for GATT connection */ +typedef enum +{ + GATT_TRANSPORT_AUTO, + GATT_TRANSPORT_BREDR, + GATT_TRANSPORT_LE +} btgatt_transport_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_GATT_TYPES_H */
diff --git a/libhardware/include/hardware/bt_hf.h b/libhardware/include/hardware/bt_hf.h new file mode 100644 index 0000000..0a77675 --- /dev/null +++ b/libhardware/include/hardware/bt_hf.h
@@ -0,0 +1,330 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_HF_H +#define ANDROID_INCLUDE_BT_HF_H + +__BEGIN_DECLS + +/* AT response code - OK/Error */ +typedef enum { + BTHF_AT_RESPONSE_ERROR = 0, + BTHF_AT_RESPONSE_OK +} bthf_at_response_t; + +typedef enum { + BTHF_CONNECTION_STATE_DISCONNECTED = 0, + BTHF_CONNECTION_STATE_CONNECTING, + BTHF_CONNECTION_STATE_CONNECTED, + BTHF_CONNECTION_STATE_SLC_CONNECTED, + BTHF_CONNECTION_STATE_DISCONNECTING +} bthf_connection_state_t; + +typedef enum { + BTHF_AUDIO_STATE_DISCONNECTED = 0, + BTHF_AUDIO_STATE_CONNECTING, + BTHF_AUDIO_STATE_CONNECTED, + BTHF_AUDIO_STATE_DISCONNECTING +} bthf_audio_state_t; + +typedef enum { + BTHF_VR_STATE_STOPPED = 0, + BTHF_VR_STATE_STARTED +} bthf_vr_state_t; + +typedef enum { + BTHF_VOLUME_TYPE_SPK = 0, + BTHF_VOLUME_TYPE_MIC +} bthf_volume_type_t; + +/* Noise Reduction and Echo Cancellation */ +typedef enum +{ + BTHF_NREC_STOP, + BTHF_NREC_START +} bthf_nrec_t; + +/* WBS codec setting */ +typedef enum +{ + BTHF_WBS_NONE, + BTHF_WBS_NO, + BTHF_WBS_YES +}bthf_wbs_config_t; + +/* CHLD - Call held handling */ +typedef enum +{ + BTHF_CHLD_TYPE_RELEASEHELD, // Terminate all held or set UDUB("busy") to a waiting call + BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD, // Terminate all active calls and accepts a waiting/held call + BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD, // Hold all active calls and accepts a waiting/held call + BTHF_CHLD_TYPE_ADDHELDTOCONF, // Add all held calls to a conference +} bthf_chld_type_t; + + +/* HF Indicators HFP 1.7 */ +typedef enum +{ + BTHF_HF_IND_ENHANCED_DRIVER_SAFETY = 1, + BTHF_HF_IND_BATTERY_LEVEL_STATUS = 2, +} bthf_hf_ind_type_t; + +typedef enum +{ + BTHF_HF_IND_DISABLED = 0, + BTHF_HF_IND_ENABLED, +} bthf_hf_ind_status_t; + +/** Callback for connection state change. + * state will have one of the values from BtHfConnectionState + */ +typedef void (* bthf_connection_state_callback)(bthf_connection_state_t state, bt_bdaddr_t *bd_addr); + +/** Callback for audio connection state change. + * state will have one of the values from BtHfAudioState + */ +typedef void (* bthf_audio_state_callback)(bthf_audio_state_t state, bt_bdaddr_t *bd_addr); + +/** Callback for VR connection state change. + * state will have one of the values from BtHfVRState + */ +typedef void (* bthf_vr_cmd_callback)(bthf_vr_state_t state, bt_bdaddr_t *bd_addr); + +/** Callback for answer incoming call (ATA) + */ +typedef void (* bthf_answer_call_cmd_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for disconnect call (AT+CHUP) + */ +typedef void (* bthf_hangup_call_cmd_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for disconnect call (AT+CHUP) + * type will denote Speaker/Mic gain (BtHfVolumeControl). + */ +typedef void (* bthf_volume_cmd_callback)(bthf_volume_type_t type, int volume, bt_bdaddr_t *bd_addr); + +/** Callback for dialing an outgoing call + * If number is NULL, redial + */ +typedef void (* bthf_dial_call_cmd_callback)(char *number, bt_bdaddr_t *bd_addr); + +/** Callback for sending DTMF tones + * tone contains the dtmf character to be sent + */ +typedef void (* bthf_dtmf_cmd_callback)(char tone, bt_bdaddr_t *bd_addr); + +/** Callback for enabling/disabling noise reduction/echo cancellation + * value will be 1 to enable, 0 to disable + */ +typedef void (* bthf_nrec_cmd_callback)(bthf_nrec_t nrec, bt_bdaddr_t *bd_addr); + +/** Callback for AT+BCS and event from BAC + * WBS enable, WBS disable + */ +typedef void (* bthf_wbs_callback)(bthf_wbs_config_t wbs, bt_bdaddr_t *bd_addr); + +/** Callback for call hold handling (AT+CHLD) + * value will contain the call hold command (0, 1, 2, 3) + */ +typedef void (* bthf_chld_cmd_callback)(bthf_chld_type_t chld, bt_bdaddr_t *bd_addr); + +/** Callback for CNUM (subscriber number) + */ +typedef void (* bthf_cnum_cmd_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for indicators (CIND) + */ +typedef void (* bthf_cind_cmd_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for operator selection (COPS) + */ +typedef void (* bthf_cops_cmd_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for call list (AT+CLCC) + */ +typedef void (* bthf_clcc_cmd_callback) (bt_bdaddr_t *bd_addr); + +/** Callback for unknown AT command recd from HF + * at_string will contain the unparsed AT string + */ +typedef void (* bthf_unknown_at_cmd_callback)(char *at_string, bt_bdaddr_t *bd_addr); + +/** Callback for keypressed (HSP) event. + */ +typedef void (* bthf_key_pressed_cmd_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for BIND. Pass the remote HF Indicators supported. + */ +typedef void (* bthf_bind_cmd_callback)(char *at_string, bt_bdaddr_t *bd_addr); + +/** Callback for BIEV. Pass the change in the Remote HF indicator values + */ +typedef void (* bthf_biev_cmd_callback)(bthf_hf_ind_type_t ind_id, int ind_value, + bt_bdaddr_t *bd_addr); + +/** BT-HF callback structure. */ +typedef struct { + /** set to sizeof(BtHfCallbacks) */ + size_t size; + bthf_connection_state_callback connection_state_cb; + bthf_audio_state_callback audio_state_cb; + bthf_vr_cmd_callback vr_cmd_cb; + bthf_answer_call_cmd_callback answer_call_cmd_cb; + bthf_hangup_call_cmd_callback hangup_call_cmd_cb; + bthf_volume_cmd_callback volume_cmd_cb; + bthf_dial_call_cmd_callback dial_call_cmd_cb; + bthf_dtmf_cmd_callback dtmf_cmd_cb; + bthf_nrec_cmd_callback nrec_cmd_cb; + bthf_wbs_callback wbs_cb; + bthf_chld_cmd_callback chld_cmd_cb; + bthf_cnum_cmd_callback cnum_cmd_cb; + bthf_cind_cmd_callback cind_cmd_cb; + bthf_cops_cmd_callback cops_cmd_cb; + bthf_clcc_cmd_callback clcc_cmd_cb; + bthf_unknown_at_cmd_callback unknown_at_cmd_cb; + bthf_bind_cmd_callback bind_cb; + bthf_biev_cmd_callback biev_cb; + bthf_key_pressed_cmd_callback key_pressed_cmd_cb; +} bthf_callbacks_t; + +/** Network Status */ +typedef enum +{ + BTHF_NETWORK_STATE_NOT_AVAILABLE = 0, + BTHF_NETWORK_STATE_AVAILABLE +} bthf_network_state_t; + +/** Service type */ +typedef enum +{ + BTHF_SERVICE_TYPE_HOME = 0, + BTHF_SERVICE_TYPE_ROAMING +} bthf_service_type_t; + +typedef enum { + BTHF_CALL_STATE_ACTIVE = 0, + BTHF_CALL_STATE_HELD, + BTHF_CALL_STATE_DIALING, + BTHF_CALL_STATE_ALERTING, + BTHF_CALL_STATE_INCOMING, + BTHF_CALL_STATE_WAITING, + BTHF_CALL_STATE_IDLE +} bthf_call_state_t; + +typedef enum { + BTHF_CALL_DIRECTION_OUTGOING = 0, + BTHF_CALL_DIRECTION_INCOMING +} bthf_call_direction_t; + +typedef enum { + BTHF_CALL_TYPE_VOICE = 0, + BTHF_CALL_TYPE_DATA, + BTHF_CALL_TYPE_FAX +} bthf_call_mode_t; + +typedef enum { + BTHF_CALL_MPTY_TYPE_SINGLE = 0, + BTHF_CALL_MPTY_TYPE_MULTI +} bthf_call_mpty_type_t; + +typedef enum { + BTHF_CALL_ADDRTYPE_UNKNOWN = 0x81, + BTHF_CALL_ADDRTYPE_INTERNATIONAL = 0x91 +} bthf_call_addrtype_t; +/** Represents the standard BT-HF interface. */ +typedef struct { + + /** set to sizeof(BtHfInterface) */ + size_t size; + /** + * Register the BtHf callbacks + */ + bt_status_t (*init)( bthf_callbacks_t* callbacks, int max_hf_clients); + + /** connect to headset */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); + + /** dis-connect from headset */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** create an audio connection */ + bt_status_t (*connect_audio)( bt_bdaddr_t *bd_addr ); + + /** close the audio connection */ + bt_status_t (*disconnect_audio)( bt_bdaddr_t *bd_addr ); + + /** start voice recognition */ + bt_status_t (*start_voice_recognition)( bt_bdaddr_t *bd_addr ); + + /** stop voice recognition */ + bt_status_t (*stop_voice_recognition)( bt_bdaddr_t *bd_addr ); + + /** volume control */ + bt_status_t (*volume_control) (bthf_volume_type_t type, int volume, bt_bdaddr_t *bd_addr ); + + /** Combined device status change notification */ + bt_status_t (*device_status_notification)(bthf_network_state_t ntk_state, bthf_service_type_t svc_type, int signal, + int batt_chg); + + /** Response for COPS command */ + bt_status_t (*cops_response)(const char *cops, bt_bdaddr_t *bd_addr ); + + /** Response for CIND command */ + bt_status_t (*cind_response)(int svc, int num_active, int num_held, bthf_call_state_t call_setup_state, + int signal, int roam, int batt_chg, bt_bdaddr_t *bd_addr ); + + /** Pre-formatted AT response, typically in response to unknown AT cmd */ + bt_status_t (*formatted_at_response)(const char *rsp, bt_bdaddr_t *bd_addr ); + + /** ok/error response + * ERROR (0) + * OK (1) + */ + bt_status_t (*at_response) (bthf_at_response_t response_code, int error_code, bt_bdaddr_t *bd_addr ); + + /** response for CLCC command + * Can be iteratively called for each call index + * Call index of 0 will be treated as NULL termination (Completes response) + */ + bt_status_t (*clcc_response) (int index, bthf_call_direction_t dir, + bthf_call_state_t state, bthf_call_mode_t mode, + bthf_call_mpty_type_t mpty, const char *number, + bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr ); + + /** notify of a call state change + * Each update notifies + * 1. Number of active/held/ringing calls + * 2. call_state: This denotes the state change that triggered this msg + * This will take one of the values from BtHfCallState + * 3. number & type: valid only for incoming & waiting call + */ + bt_status_t (*phone_state_change) (int num_active, int num_held, bthf_call_state_t call_setup_state, + const char *number, bthf_call_addrtype_t type); + + /** Closes the interface. */ + void (*cleanup)( void ); + + /** configureation for the SCO codec */ + bt_status_t (*configure_wbs)( bt_bdaddr_t *bd_addr ,bthf_wbs_config_t config ); + + /** Response for HF Indicator change (+BIND) */ + bt_status_t (*bind_response)(bthf_hf_ind_type_t ind_id, bthf_hf_ind_status_t ind_status, + bt_bdaddr_t *bd_addr); +} bthf_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HF_H */
diff --git a/libhardware/include/hardware/bt_hf_client.h b/libhardware/include/hardware/bt_hf_client.h new file mode 100644 index 0000000..8acf1b2 --- /dev/null +++ b/libhardware/include/hardware/bt_hf_client.h
@@ -0,0 +1,363 @@ +/* + * Copyright (C) 2012-2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_HF_CLIENT_H +#define ANDROID_INCLUDE_BT_HF_CLIENT_H + +__BEGIN_DECLS + +typedef enum { + BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED = 0, + BTHF_CLIENT_CONNECTION_STATE_CONNECTING, + BTHF_CLIENT_CONNECTION_STATE_CONNECTED, + BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED, + BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING +} bthf_client_connection_state_t; + +typedef enum { + BTHF_CLIENT_AUDIO_STATE_DISCONNECTED = 0, + BTHF_CLIENT_AUDIO_STATE_CONNECTING, + BTHF_CLIENT_AUDIO_STATE_CONNECTED, + BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC, +} bthf_client_audio_state_t; + +typedef enum { + BTHF_CLIENT_VR_STATE_STOPPED = 0, + BTHF_CLIENT_VR_STATE_STARTED +} bthf_client_vr_state_t; + +typedef enum { + BTHF_CLIENT_VOLUME_TYPE_SPK = 0, + BTHF_CLIENT_VOLUME_TYPE_MIC +} bthf_client_volume_type_t; + +typedef enum +{ + BTHF_CLIENT_NETWORK_STATE_NOT_AVAILABLE = 0, + BTHF_CLIENT_NETWORK_STATE_AVAILABLE +} bthf_client_network_state_t; + +typedef enum +{ + BTHF_CLIENT_SERVICE_TYPE_HOME = 0, + BTHF_CLIENT_SERVICE_TYPE_ROAMING +} bthf_client_service_type_t; + +typedef enum { + BTHF_CLIENT_CALL_STATE_ACTIVE = 0, + BTHF_CLIENT_CALL_STATE_HELD, + BTHF_CLIENT_CALL_STATE_DIALING, + BTHF_CLIENT_CALL_STATE_ALERTING, + BTHF_CLIENT_CALL_STATE_INCOMING, + BTHF_CLIENT_CALL_STATE_WAITING, + BTHF_CLIENT_CALL_STATE_HELD_BY_RESP_HOLD, +} bthf_client_call_state_t; + +typedef enum { + BTHF_CLIENT_CALL_NO_CALLS_IN_PROGRESS = 0, + BTHF_CLIENT_CALL_CALLS_IN_PROGRESS +} bthf_client_call_t; + +typedef enum { + BTHF_CLIENT_CALLSETUP_NONE = 0, + BTHF_CLIENT_CALLSETUP_INCOMING, + BTHF_CLIENT_CALLSETUP_OUTGOING, + BTHF_CLIENT_CALLSETUP_ALERTING + +} bthf_client_callsetup_t; + +typedef enum { + BTHF_CLIENT_CALLHELD_NONE = 0, + BTHF_CLIENT_CALLHELD_HOLD_AND_ACTIVE, + BTHF_CLIENT_CALLHELD_HOLD, +} bthf_client_callheld_t; + +typedef enum { + BTHF_CLIENT_RESP_AND_HOLD_HELD = 0, + BTRH_CLIENT_RESP_AND_HOLD_ACCEPT, + BTRH_CLIENT_RESP_AND_HOLD_REJECT, +} bthf_client_resp_and_hold_t; + +typedef enum { + BTHF_CLIENT_CALL_DIRECTION_OUTGOING = 0, + BTHF_CLIENT_CALL_DIRECTION_INCOMING +} bthf_client_call_direction_t; + +typedef enum { + BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE = 0, + BTHF_CLIENT_CALL_MPTY_TYPE_MULTI +} bthf_client_call_mpty_type_t; + +typedef enum { + BTHF_CLIENT_CMD_COMPLETE_OK = 0, + BTHF_CLIENT_CMD_COMPLETE_ERROR, + BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_CARRIER, + BTHF_CLIENT_CMD_COMPLETE_ERROR_BUSY, + BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_ANSWER, + BTHF_CLIENT_CMD_COMPLETE_ERROR_DELAYED, + BTHF_CLIENT_CMD_COMPLETE_ERROR_BLACKLISTED, + BTHF_CLIENT_CMD_COMPLETE_ERROR_CME +} bthf_client_cmd_complete_t; + +typedef enum { + BTHF_CLIENT_CALL_ACTION_CHLD_0 = 0, + BTHF_CLIENT_CALL_ACTION_CHLD_1, + BTHF_CLIENT_CALL_ACTION_CHLD_2, + BTHF_CLIENT_CALL_ACTION_CHLD_3, + BTHF_CLIENT_CALL_ACTION_CHLD_4, + BTHF_CLIENT_CALL_ACTION_CHLD_1x, + BTHF_CLIENT_CALL_ACTION_CHLD_2x, + BTHF_CLIENT_CALL_ACTION_ATA, + BTHF_CLIENT_CALL_ACTION_CHUP, + BTHF_CLIENT_CALL_ACTION_BTRH_0, + BTHF_CLIENT_CALL_ACTION_BTRH_1, + BTHF_CLIENT_CALL_ACTION_BTRH_2, +} bthf_client_call_action_t; + +typedef enum { + BTHF_CLIENT_SERVICE_UNKNOWN = 0, + BTHF_CLIENT_SERVICE_VOICE, + BTHF_CLIENT_SERVICE_FAX +} bthf_client_subscriber_service_type_t; + +typedef enum { + BTHF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED = 0, + BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED, +} bthf_client_in_band_ring_state_t; + +/* Peer features masks */ +#define BTHF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */ +#define BTHF_CLIENT_PEER_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */ +#define BTHF_CLIENT_PEER_FEAT_VREC 0x00000004 /* Voice recognition */ +#define BTHF_CLIENT_PEER_FEAT_INBAND 0x00000008 /* In-band ring tone */ +#define BTHF_CLIENT_PEER_FEAT_VTAG 0x00000010 /* Attach a phone number to a voice tag */ +#define BTHF_CLIENT_PEER_FEAT_REJECT 0x00000020 /* Ability to reject incoming call */ +#define BTHF_CLIENT_PEER_FEAT_ECS 0x00000040 /* Enhanced Call Status */ +#define BTHF_CLIENT_PEER_FEAT_ECC 0x00000080 /* Enhanced Call Control */ +#define BTHF_CLIENT_PEER_FEAT_EXTERR 0x00000100 /* Extended error codes */ +#define BTHF_CLIENT_PEER_FEAT_CODEC 0x00000200 /* Codec Negotiation */ + +/* Peer call handling features masks */ +#define BTHF_CLIENT_CHLD_FEAT_REL 0x00000001 /* 0 Release waiting call or held calls */ +#define BTHF_CLIENT_CHLD_FEAT_REL_ACC 0x00000002 /* 1 Release active calls and accept other + (waiting or held) cal */ +#define BTHF_CLIENT_CHLD_FEAT_REL_X 0x00000004 /* 1x Release specified active call only */ +#define BTHF_CLIENT_CHLD_FEAT_HOLD_ACC 0x00000008 /* 2 Active calls on hold and accept other + (waiting or held) call */ +#define BTHF_CLIENT_CHLD_FEAT_PRIV_X 0x00000010 /* 2x Request private mode with specified + call (put the rest on hold) */ +#define BTHF_CLIENT_CHLD_FEAT_MERGE 0x00000020 /* 3 Add held call to multiparty */ +#define BTHF_CLIENT_CHLD_FEAT_MERGE_DETACH 0x00000040 /* 4 Connect two calls and leave + (disconnect from) multiparty */ + +/** Callback for connection state change. + * state will have one of the values from BtHfConnectionState + * peer/chld_features are valid only for BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED state + */ +typedef void (* bthf_client_connection_state_callback)(bthf_client_connection_state_t state, + unsigned int peer_feat, + unsigned int chld_feat, + bt_bdaddr_t *bd_addr); + +/** Callback for audio connection state change. + * state will have one of the values from BtHfAudioState + */ +typedef void (* bthf_client_audio_state_callback)(bthf_client_audio_state_t state, + bt_bdaddr_t *bd_addr); + +/** Callback for VR connection state change. + * state will have one of the values from BtHfVRState + */ +typedef void (* bthf_client_vr_cmd_callback)(bthf_client_vr_state_t state); + +/** Callback for network state change + */ +typedef void (* bthf_client_network_state_callback) (bthf_client_network_state_t state); + +/** Callback for network roaming status change + */ +typedef void (* bthf_client_network_roaming_callback) (bthf_client_service_type_t type); + +/** Callback for signal strength indication + */ +typedef void (* bthf_client_network_signal_callback) (int signal_strength); + +/** Callback for battery level indication + */ +typedef void (* bthf_client_battery_level_callback) (int battery_level); + +/** Callback for current operator name + */ +typedef void (* bthf_client_current_operator_callback) (const char *name); + +/** Callback for call indicator + */ +typedef void (* bthf_client_call_callback) (bthf_client_call_t call); + +/** Callback for callsetup indicator + */ +typedef void (* bthf_client_callsetup_callback) (bthf_client_callsetup_t callsetup); + +/** Callback for callheld indicator + */ +typedef void (* bthf_client_callheld_callback) (bthf_client_callheld_t callheld); + +/** Callback for response and hold + */ +typedef void (* bthf_client_resp_and_hold_callback) (bthf_client_resp_and_hold_t resp_and_hold); + +/** Callback for Calling Line Identification notification + * Will be called only when there is an incoming call and number is provided. + */ +typedef void (* bthf_client_clip_callback) (const char *number); + +/** + * Callback for Call Waiting notification + */ +typedef void (* bthf_client_call_waiting_callback) (const char *number); + +/** + * Callback for listing current calls. Can be called multiple time. + * If number is unknown NULL is passed. + */ +typedef void (*bthf_client_current_calls) (int index, bthf_client_call_direction_t dir, + bthf_client_call_state_t state, + bthf_client_call_mpty_type_t mpty, + const char *number); + +/** Callback for audio volume change + */ +typedef void (*bthf_client_volume_change_callback) (bthf_client_volume_type_t type, int volume); + +/** Callback for command complete event + * cme is valid only for BTHF_CLIENT_CMD_COMPLETE_ERROR_CME type + */ +typedef void (*bthf_client_cmd_complete_callback) (bthf_client_cmd_complete_t type, int cme); + +/** Callback for subscriber information + */ +typedef void (* bthf_client_subscriber_info_callback) (const char *name, + bthf_client_subscriber_service_type_t type); + +/** Callback for in-band ring tone settings + */ +typedef void (* bthf_client_in_band_ring_tone_callback) (bthf_client_in_band_ring_state_t state); + +/** + * Callback for requested number from AG + */ +typedef void (* bthf_client_last_voice_tag_number_callback) (const char *number); + +/** + * Callback for sending ring indication to app + */ +typedef void (* bthf_client_ring_indication_callback) (void); + +/** BT-HF callback structure. */ +typedef struct { + /** set to sizeof(BtHfClientCallbacks) */ + size_t size; + bthf_client_connection_state_callback connection_state_cb; + bthf_client_audio_state_callback audio_state_cb; + bthf_client_vr_cmd_callback vr_cmd_cb; + bthf_client_network_state_callback network_state_cb; + bthf_client_network_roaming_callback network_roaming_cb; + bthf_client_network_signal_callback network_signal_cb; + bthf_client_battery_level_callback battery_level_cb; + bthf_client_current_operator_callback current_operator_cb; + bthf_client_call_callback call_cb; + bthf_client_callsetup_callback callsetup_cb; + bthf_client_callheld_callback callheld_cb; + bthf_client_resp_and_hold_callback resp_and_hold_cb; + bthf_client_clip_callback clip_cb; + bthf_client_call_waiting_callback call_waiting_cb; + bthf_client_current_calls current_calls_cb; + bthf_client_volume_change_callback volume_change_cb; + bthf_client_cmd_complete_callback cmd_complete_cb; + bthf_client_subscriber_info_callback subscriber_info_cb; + bthf_client_in_band_ring_tone_callback in_band_ring_tone_cb; + bthf_client_last_voice_tag_number_callback last_voice_tag_number_callback; + bthf_client_ring_indication_callback ring_indication_cb; +} bthf_client_callbacks_t; + +/** Represents the standard BT-HF interface. */ +typedef struct { + + /** set to sizeof(BtHfClientInterface) */ + size_t size; + /** + * Register the BtHf callbacks + */ + bt_status_t (*init)(bthf_client_callbacks_t* callbacks); + + /** connect to audio gateway */ + bt_status_t (*connect)(bt_bdaddr_t *bd_addr); + + /** disconnect from audio gateway */ + bt_status_t (*disconnect)(bt_bdaddr_t *bd_addr); + + /** create an audio connection */ + bt_status_t (*connect_audio)(bt_bdaddr_t *bd_addr); + + /** close the audio connection */ + bt_status_t (*disconnect_audio)(bt_bdaddr_t *bd_addr); + + /** start voice recognition */ + bt_status_t (*start_voice_recognition)(void); + + /** stop voice recognition */ + bt_status_t (*stop_voice_recognition)(void); + + /** volume control */ + bt_status_t (*volume_control) (bthf_client_volume_type_t type, int volume); + + /** place a call with number a number + * if number is NULL last called number is called (aka re-dial)*/ + bt_status_t (*dial) (const char *number); + + /** place a call with number specified by location (speed dial) */ + bt_status_t (*dial_memory) (int location); + + /** perform specified call related action + * idx is limited only for enhanced call control related action + */ + bt_status_t (*handle_call_action) (bthf_client_call_action_t action, int idx); + + /** query list of current calls */ + bt_status_t (*query_current_calls) (void); + + /** query name of current selected operator */ + bt_status_t (*query_current_operator_name) (void); + + /** Retrieve subscriber information */ + bt_status_t (*retrieve_subscriber_info) (void); + + /** Send DTMF code*/ + bt_status_t (*send_dtmf) (char code); + + /** Request a phone number from AG corresponding to last voice tag recorded */ + bt_status_t (*request_last_voice_tag_number) (void); + + /** Closes the interface. */ + void (*cleanup)(void); + + /** Send AT Command. */ + bt_status_t (*send_at_cmd) (int cmd, int val1, int val2, const char *arg); +} bthf_client_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HF_CLIENT_H */
diff --git a/libhardware/include/hardware/bt_hh.h b/libhardware/include/hardware/bt_hh.h new file mode 100644 index 0000000..dad9586 --- /dev/null +++ b/libhardware/include/hardware/bt_hh.h
@@ -0,0 +1,185 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_HH_H +#define ANDROID_INCLUDE_BT_HH_H + +#include <stdint.h> + +__BEGIN_DECLS + +#define BTHH_MAX_DSC_LEN 884 + +/* HH connection states */ +typedef enum +{ + BTHH_CONN_STATE_CONNECTED = 0, + BTHH_CONN_STATE_CONNECTING, + BTHH_CONN_STATE_DISCONNECTED, + BTHH_CONN_STATE_DISCONNECTING, + BTHH_CONN_STATE_FAILED_MOUSE_FROM_HOST, + BTHH_CONN_STATE_FAILED_KBD_FROM_HOST, + BTHH_CONN_STATE_FAILED_TOO_MANY_DEVICES, + BTHH_CONN_STATE_FAILED_NO_BTHID_DRIVER, + BTHH_CONN_STATE_FAILED_GENERIC, + BTHH_CONN_STATE_UNKNOWN +} bthh_connection_state_t; + +typedef enum +{ + BTHH_OK = 0, + BTHH_HS_HID_NOT_READY, /* handshake error : device not ready */ + BTHH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */ + BTHH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */ + BTHH_HS_INVALID_PARAM, /* handshake error : invalid paremter */ + BTHH_HS_ERROR, /* handshake error : unspecified HS error */ + BTHH_ERR, /* general BTA HH error */ + BTHH_ERR_SDP, /* SDP error */ + BTHH_ERR_PROTO, /* SET_Protocol error, + only used in BTA_HH_OPEN_EVT callback */ + BTHH_ERR_DB_FULL, /* device database full error, used */ + BTHH_ERR_TOD_UNSPT, /* type of device not supported */ + BTHH_ERR_NO_RES, /* out of system resources */ + BTHH_ERR_AUTH_FAILED, /* authentication fail */ + BTHH_ERR_HDL +}bthh_status_t; + +/* Protocol modes */ +typedef enum { + BTHH_REPORT_MODE = 0x00, + BTHH_BOOT_MODE = 0x01, + BTHH_UNSUPPORTED_MODE = 0xff +}bthh_protocol_mode_t; + +/* Report types */ +typedef enum { + BTHH_INPUT_REPORT = 1, + BTHH_OUTPUT_REPORT, + BTHH_FEATURE_REPORT +}bthh_report_type_t; + +typedef struct +{ + int attr_mask; + uint8_t sub_class; + uint8_t app_id; + int vendor_id; + int product_id; + int version; + uint8_t ctry_code; + int dl_len; + uint8_t dsc_list[BTHH_MAX_DSC_LEN]; +} bthh_hid_info_t; + +/** Callback for connection state change. + * state will have one of the values from bthh_connection_state_t + */ +typedef void (* bthh_connection_state_callback)(bt_bdaddr_t *bd_addr, bthh_connection_state_t state); + +/** Callback for vitual unplug api. + * the status of the vitual unplug + */ +typedef void (* bthh_virtual_unplug_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status); + +/** Callback for get hid info + * hid_info will contain attr_mask, sub_class, app_id, vendor_id, product_id, version, ctry_code, len + */ +typedef void (* bthh_hid_info_callback)(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info); + +/** Callback for get protocol api. + * the protocol mode is one of the value from bthh_protocol_mode_t + */ +typedef void (* bthh_protocol_mode_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status, bthh_protocol_mode_t mode); + +/** Callback for get/set_idle_time api. + */ +typedef void (* bthh_idle_time_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status, int idle_rate); + + +/** Callback for get report api. + * if staus is ok rpt_data contains the report data + */ +typedef void (* bthh_get_report_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status, uint8_t* rpt_data, int rpt_size); + +/** Callback for set_report/set_protocol api and if error + * occurs for get_report/get_protocol api. + */ +typedef void (* bthh_handshake_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status); + + +/** BT-HH callback structure. */ +typedef struct { + /** set to sizeof(BtHfCallbacks) */ + size_t size; + bthh_connection_state_callback connection_state_cb; + bthh_hid_info_callback hid_info_cb; + bthh_protocol_mode_callback protocol_mode_cb; + bthh_idle_time_callback idle_time_cb; + bthh_get_report_callback get_report_cb; + bthh_virtual_unplug_callback virtual_unplug_cb; + bthh_handshake_callback handshake_cb; + +} bthh_callbacks_t; + + + +/** Represents the standard BT-HH interface. */ +typedef struct { + + /** set to sizeof(BtHhInterface) */ + size_t size; + + /** + * Register the BtHh callbacks + */ + bt_status_t (*init)( bthh_callbacks_t* callbacks ); + + /** connect to hid device */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr); + + /** dis-connect from hid device */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** Virtual UnPlug (VUP) the specified HID device */ + bt_status_t (*virtual_unplug)(bt_bdaddr_t *bd_addr); + + /** Set the HID device descriptor for the specified HID device. */ + bt_status_t (*set_info)(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info ); + + /** Get the HID proto mode. */ + bt_status_t (*get_protocol) (bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode); + + /** Set the HID proto mode. */ + bt_status_t (*set_protocol)(bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode); + + /** Send a GET_REPORT to HID device. */ + bt_status_t (*get_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, uint8_t reportId, int bufferSize); + + /** Send a SET_REPORT to HID device. */ + bt_status_t (*set_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, char* report); + + /** Send data to HID device. */ + bt_status_t (*send_data)(bt_bdaddr_t *bd_addr, char* data); + + /** Closes the interface. */ + void (*cleanup)( void ); + +} bthh_interface_t; +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HH_H */ + +
diff --git a/libhardware/include/hardware/bt_hl.h b/libhardware/include/hardware/bt_hl.h new file mode 100644 index 0000000..bd29e3a --- /dev/null +++ b/libhardware/include/hardware/bt_hl.h
@@ -0,0 +1,123 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_HL_H +#define ANDROID_INCLUDE_BT_HL_H + +__BEGIN_DECLS + +/* HL connection states */ + +typedef enum +{ + BTHL_MDEP_ROLE_SOURCE, + BTHL_MDEP_ROLE_SINK +} bthl_mdep_role_t; + +typedef enum { + BTHL_APP_REG_STATE_REG_SUCCESS, + BTHL_APP_REG_STATE_REG_FAILED, + BTHL_APP_REG_STATE_DEREG_SUCCESS, + BTHL_APP_REG_STATE_DEREG_FAILED +} bthl_app_reg_state_t; + +typedef enum +{ + BTHL_CHANNEL_TYPE_RELIABLE, + BTHL_CHANNEL_TYPE_STREAMING, + BTHL_CHANNEL_TYPE_ANY +} bthl_channel_type_t; + + +/* HL connection states */ +typedef enum { + BTHL_CONN_STATE_CONNECTING, + BTHL_CONN_STATE_CONNECTED, + BTHL_CONN_STATE_DISCONNECTING, + BTHL_CONN_STATE_DISCONNECTED, + BTHL_CONN_STATE_DESTROYED +} bthl_channel_state_t; + +typedef struct +{ + bthl_mdep_role_t mdep_role; + int data_type; + bthl_channel_type_t channel_type; + const char *mdep_description; /* MDEP description to be used in the SDP (optional); null terminated */ +} bthl_mdep_cfg_t; + +typedef struct +{ + const char *application_name; + const char *provider_name; /* provider name to be used in the SDP (optional); null terminated */ + const char *srv_name; /* service name to be used in the SDP (optional); null terminated*/ + const char *srv_desp; /* service description to be used in the SDP (optional); null terminated */ + int number_of_mdeps; + bthl_mdep_cfg_t *mdep_cfg; /* Dynamic array */ +} bthl_reg_param_t; + +/** Callback for application registration status. + * state will have one of the values from bthl_app_reg_state_t + */ +typedef void (* bthl_app_reg_state_callback)(int app_id, bthl_app_reg_state_t state); + +/** Callback for channel connection state change. + * state will have one of the values from + * bthl_connection_state_t and fd (file descriptor) + */ +typedef void (* bthl_channel_state_callback)(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd); + +/** BT-HL callback structure. */ +typedef struct { + /** set to sizeof(bthl_callbacks_t) */ + size_t size; + bthl_app_reg_state_callback app_reg_state_cb; + bthl_channel_state_callback channel_state_cb; +} bthl_callbacks_t; + + +/** Represents the standard BT-HL interface. */ +typedef struct { + + /** set to sizeof(bthl_interface_t) */ + size_t size; + + /** + * Register the Bthl callbacks + */ + bt_status_t (*init)( bthl_callbacks_t* callbacks ); + + /** Register HL application */ + bt_status_t (*register_application) ( bthl_reg_param_t *p_reg_param, int *app_id); + + /** Unregister HL application */ + bt_status_t (*unregister_application) (int app_id); + + /** connect channel */ + bt_status_t (*connect_channel)(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int *channel_id); + + /** destroy channel */ + bt_status_t (*destroy_channel)(int channel_id); + + /** Close the Bthl callback **/ + void (*cleanup)(void); + +} bthl_interface_t; +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HL_H */ + +
diff --git a/libhardware/include/hardware/bt_mce.h b/libhardware/include/hardware/bt_mce.h new file mode 100644 index 0000000..5d159b3 --- /dev/null +++ b/libhardware/include/hardware/bt_mce.h
@@ -0,0 +1,54 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_MCE_H +#define ANDROID_INCLUDE_BT_MCE_H + +__BEGIN_DECLS + +/** MAS instance description */ +typedef struct +{ + int id; + int scn; + int msg_types; + char *p_name; +} btmce_mas_instance_t; + +/** callback for get_remote_mas_instances */ +typedef void (*btmce_remote_mas_instances_callback)(bt_status_t status, bt_bdaddr_t *bd_addr, + int num_instances, btmce_mas_instance_t *instances); + +typedef struct { + /** set to sizeof(btmce_callbacks_t) */ + size_t size; + btmce_remote_mas_instances_callback remote_mas_instances_cb; +} btmce_callbacks_t; + +typedef struct { + /** set to size of this struct */ + size_t size; + + /** register BT MCE callbacks */ + bt_status_t (*init)(btmce_callbacks_t *callbacks); + + /** search for MAS instances on remote device */ + bt_status_t (*get_remote_mas_instances)(bt_bdaddr_t *bd_addr); +} btmce_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_MCE_H */
diff --git a/libhardware/include/hardware/bt_pan.h b/libhardware/include/hardware/bt_pan.h new file mode 100644 index 0000000..83e7949 --- /dev/null +++ b/libhardware/include/hardware/bt_pan.h
@@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_PAN_H +#define ANDROID_INCLUDE_BT_PAN_H + +__BEGIN_DECLS + +#define BTPAN_ROLE_NONE 0 +#define BTPAN_ROLE_PANNAP 1 +#define BTPAN_ROLE_PANU 2 + +typedef enum { + BTPAN_STATE_CONNECTED = 0, + BTPAN_STATE_CONNECTING = 1, + BTPAN_STATE_DISCONNECTED = 2, + BTPAN_STATE_DISCONNECTING = 3 +} btpan_connection_state_t; + +typedef enum { + BTPAN_STATE_ENABLED = 0, + BTPAN_STATE_DISABLED = 1 +} btpan_control_state_t; + +/** +* Callback for pan connection state +*/ +typedef void (*btpan_connection_state_callback)(btpan_connection_state_t state, bt_status_t error, + const bt_bdaddr_t *bd_addr, int local_role, int remote_role); +typedef void (*btpan_control_state_callback)(btpan_control_state_t state, int local_role, + bt_status_t error, const char* ifname); + +typedef struct { + size_t size; + btpan_control_state_callback control_state_cb; + btpan_connection_state_callback connection_state_cb; +} btpan_callbacks_t; +typedef struct { + /** set to size of this struct*/ + size_t size; + /** + * Initialize the pan interface and register the btpan callbacks + */ + bt_status_t (*init)(const btpan_callbacks_t* callbacks); + /* + * enable the pan service by specified role. The result state of + * enabl will be returned by btpan_control_state_callback. when pan-nap is enabled, + * the state of connecting panu device will be notified by btpan_connection_state_callback + */ + bt_status_t (*enable)(int local_role); + /* + * get current pan local role + */ + int (*get_local_role)(void); + /** + * start bluetooth pan connection to the remote device by specified pan role. The result state will be + * returned by btpan_connection_state_callback + */ + bt_status_t (*connect)(const bt_bdaddr_t *bd_addr, int local_role, int remote_role); + /** + * stop bluetooth pan connection. The result state will be returned by btpan_connection_state_callback + */ + bt_status_t (*disconnect)(const bt_bdaddr_t *bd_addr); + + /** + * Cleanup the pan interface + */ + void (*cleanup)(void); + +} btpan_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_PAN_H */
diff --git a/libhardware/include/hardware/bt_rc.h b/libhardware/include/hardware/bt_rc.h new file mode 100644 index 0000000..71a8901 --- /dev/null +++ b/libhardware/include/hardware/bt_rc.h
@@ -0,0 +1,723 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_BT_RC_H +#define ANDROID_INCLUDE_BT_RC_H + +__BEGIN_DECLS + +/* Change this macro to use multiple RC */ +#define BT_RC_NUM_APP 1 + +/* Macros */ +#define BTRC_MAX_ATTR_STR_LEN (1 << 16) +#define BTRC_UID_SIZE 8 +#define BTRC_MAX_APP_SETTINGS 8 +#define BTRC_MAX_FOLDER_DEPTH 4 +#define BTRC_MAX_APP_ATTR_SIZE 16 +#define BTRC_MAX_ELEM_ATTR_SIZE 8 +#define BTRC_FEATURE_BIT_MASK_SIZE 16 + +/* Macros for valid scopes in get_folder_items */ +#define BTRC_SCOPE_PLAYER_LIST 0x00 /* Media Player List */ +#define BTRC_SCOPE_FILE_SYSTEM 0x01 /* Virtual File System */ +#define BTRC_SCOPE_SEARCH 0x02 /* Search */ +#define BTRC_SCOPE_NOW_PLAYING 0x03 /* Now Playing */ + +/* Macros for supported character encoding */ +#define BTRC_CHARSET_ID_UTF8 0x006A + +/* Macros for item types */ +#define BTRC_ITEM_PLAYER 0x01 /* Media Player */ +#define BTRC_ITEM_FOLDER 0x02 /* Folder */ +#define BTRC_ITEM_MEDIA 0x03 /* Media File */ + +/* Macros for media attribute IDs */ +#define BTRC_MEDIA_ATTR_ID_INVALID -1 +#define BTRC_MEDIA_ATTR_ID_TITLE 0x00000001 +#define BTRC_MEDIA_ATTR_ID_ARTIST 0x00000002 +#define BTRC_MEDIA_ATTR_ID_ALBUM 0x00000003 +#define BTRC_MEDIA_ATTR_ID_TRACK_NUM 0x00000004 +#define BTRC_MEDIA_ATTR_ID_NUM_TRACKS 0x00000005 +#define BTRC_MEDIA_ATTR_ID_GENRE 0x00000006 +#define BTRC_MEDIA_ATTR_ID_PLAYING_TIME 0x00000007 /* in miliseconds */ + +/* Macros for folder types */ +#define BTRC_FOLDER_TYPE_MIXED 0x00 +#define BTRC_FOLDER_TYPE_TITLES 0x01 +#define BTRC_FOLDER_TYPE_ALBUMS 0x02 +#define BTRC_FOLDER_TYPE_ARTISTS 0x03 +#define BTRC_FOLDER_TYPE_GENRES 0x04 +#define BTRC_FOLDER_TYPE_PLAYLISTS 0x05 +#define BTRC_FOLDER_TYPE_YEARS 0x06 + +/* Macros for media types */ +#define BTRC_MEDIA_TYPE_AUDIO 0x00 /* audio */ +#define BTRC_MEDIA_TYPE_VIDEO 0x01 /* video */ + +/* Macros for num attributes */ +#define BTRC_NUM_ATTR_NONE 0xFF /* No attributes required */ +#define BTRC_NUM_ATTR_ALL 0X00 /* All attributes required */ + +#define BTRC_HANDLE_NONE 0xFF + +typedef uint8_t btrc_uid_t[BTRC_UID_SIZE]; + +typedef enum { + BTRC_CONNECTION_STATE_DISCONNECTED = 0, + BTRC_CONNECTION_STATE_CONNECTED +} btrc_connection_state_t; + +typedef enum { + BTRC_FEAT_NONE = 0x00, /* AVRCP 1.0 */ + BTRC_FEAT_METADATA = 0x01, /* AVRCP 1.3 */ + BTRC_FEAT_ABSOLUTE_VOLUME = 0x02, /* Supports TG role and volume sync */ + BTRC_FEAT_BROWSE = 0x04, /* AVRCP 1.4 and up, with Browsing support */ +} btrc_remote_features_t; + +typedef enum { + BTRC_PLAYSTATE_STOPPED = 0x00, /* Stopped */ + BTRC_PLAYSTATE_PLAYING = 0x01, /* Playing */ + BTRC_PLAYSTATE_PAUSED = 0x02, /* Paused */ + BTRC_PLAYSTATE_FWD_SEEK = 0x03, /* Fwd Seek*/ + BTRC_PLAYSTATE_REV_SEEK = 0x04, /* Rev Seek*/ + BTRC_PLAYSTATE_ERROR = 0xFF, /* Error */ +} btrc_play_status_t; + +typedef enum { + BTRC_EVT_PLAY_STATUS_CHANGED = 0x01, + BTRC_EVT_TRACK_CHANGE = 0x02, + BTRC_EVT_TRACK_REACHED_END = 0x03, + BTRC_EVT_TRACK_REACHED_START = 0x04, + BTRC_EVT_PLAY_POS_CHANGED = 0x05, + BTRC_EVT_APP_SETTINGS_CHANGED = 0x08, + BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED = 0x09, + BTRC_EVT_AVAL_PLAYER_CHANGE = 0x0a, + BTRC_EVT_ADDR_PLAYER_CHANGE = 0x0b, + BTRC_EVT_UIDS_CHANGED = 0x0c, + BTRC_EVT_VOL_CHANGED = 0x0d, +} btrc_event_id_t; + +typedef enum { + BTRC_NOTIFICATION_TYPE_INTERIM = 0, + BTRC_NOTIFICATION_TYPE_CHANGED = 1, +} btrc_notification_type_t; + +typedef enum { + BTRC_PLAYER_ATTR_EQUALIZER = 0x01, + BTRC_PLAYER_ATTR_REPEAT = 0x02, + BTRC_PLAYER_ATTR_SHUFFLE = 0x03, + BTRC_PLAYER_ATTR_SCAN = 0x04, +} btrc_player_attr_t; + +typedef enum { + BTRC_MEDIA_ATTR_TITLE = 0x01, + BTRC_MEDIA_ATTR_ARTIST = 0x02, + BTRC_MEDIA_ATTR_ALBUM = 0x03, + BTRC_MEDIA_ATTR_TRACK_NUM = 0x04, + BTRC_MEDIA_ATTR_NUM_TRACKS = 0x05, + BTRC_MEDIA_ATTR_GENRE = 0x06, + BTRC_MEDIA_ATTR_PLAYING_TIME = 0x07, +} btrc_media_attr_t; + +typedef enum { + BTRC_PLAYER_VAL_OFF_REPEAT = 0x01, + BTRC_PLAYER_VAL_SINGLE_REPEAT = 0x02, + BTRC_PLAYER_VAL_ALL_REPEAT = 0x03, + BTRC_PLAYER_VAL_GROUP_REPEAT = 0x04 +} btrc_player_repeat_val_t; + +typedef enum { + BTRC_PLAYER_VAL_OFF_SHUFFLE = 0x01, + BTRC_PLAYER_VAL_ALL_SHUFFLE = 0x02, + BTRC_PLAYER_VAL_GROUP_SHUFFLE = 0x03 +} btrc_player_shuffle_val_t; + +typedef enum { + BTRC_STS_BAD_CMD = 0x00, /* Invalid command */ + BTRC_STS_BAD_PARAM = 0x01, /* Invalid parameter */ + BTRC_STS_NOT_FOUND = 0x02, /* Specified parameter is wrong or not found */ + BTRC_STS_INTERNAL_ERR = 0x03, /* Internal Error */ + BTRC_STS_NO_ERROR = 0x04, /* Operation Success */ + BTRC_STS_UID_CHANGED = 0x05, /* UIDs changed */ + BTRC_STS_RESERVED = 0x06, /* Reserved */ + BTRC_STS_INV_DIRN = 0x07, /* Invalid direction */ + BTRC_STS_INV_DIRECTORY = 0x08, /* Invalid directory */ + BTRC_STS_INV_ITEM = 0x09, /* Invalid Item */ + BTRC_STS_INV_SCOPE = 0x0a, /* Invalid scope */ + BTRC_STS_INV_RANGE = 0x0b, /* Invalid range */ + BTRC_STS_DIRECTORY = 0x0c, /* UID is a directory */ + BTRC_STS_MEDIA_IN_USE = 0x0d, /* Media in use */ + BTRC_STS_PLAY_LIST_FULL = 0x0e, /* Playing list full */ + BTRC_STS_SRCH_NOT_SPRTD = 0x0f, /* Search not supported */ + BTRC_STS_SRCH_IN_PROG = 0x10, /* Search in progress */ + BTRC_STS_INV_PLAYER = 0x11, /* Invalid player */ + BTRC_STS_PLAY_NOT_BROW = 0x12, /* Player not browsable */ + BTRC_STS_PLAY_NOT_ADDR = 0x13, /* Player not addressed */ + BTRC_STS_INV_RESULTS = 0x14, /* Invalid results */ + BTRC_STS_NO_AVBL_PLAY = 0x15, /* No available players */ + BTRC_STS_ADDR_PLAY_CHGD = 0x16, /* Addressed player changed */ +} btrc_status_t; + +typedef struct { + uint16_t player_id; + uint16_t uid_counter; +} btrc_addr_player_changed_t; + +typedef struct { + uint8_t num_attr; + uint8_t attr_ids[BTRC_MAX_APP_SETTINGS]; + uint8_t attr_values[BTRC_MAX_APP_SETTINGS]; +} btrc_player_settings_t; + +typedef struct { + uint8_t val; + uint16_t charset_id; + uint16_t str_len; + uint8_t *p_str; +} btrc_player_app_ext_attr_val_t; + +typedef struct { + uint8_t attr_id; + uint16_t charset_id; + uint16_t str_len; + uint8_t *p_str; + uint8_t num_val; + btrc_player_app_ext_attr_val_t ext_attr_val[BTRC_MAX_APP_ATTR_SIZE]; +} btrc_player_app_ext_attr_t; + +typedef struct { + uint8_t attr_id; + uint8_t num_val; + uint8_t attr_val[BTRC_MAX_APP_ATTR_SIZE]; +} btrc_player_app_attr_t; + +typedef struct { + uint32_t start_item; + uint32_t end_item; + uint32_t size; + uint32_t attrs[BTRC_MAX_ELEM_ATTR_SIZE]; + uint8_t attr_count; +} btrc_getfolderitem_t; + +typedef struct { + uint16_t type; + uint16_t uid_counter; +} btrc_uids_changed_t; + +typedef struct { + uint16_t type; +} btrc_now_playing_changed_t; + +typedef union +{ + btrc_play_status_t play_status; + btrc_uid_t track; /* queue position in NowPlaying */ + uint32_t song_pos; + uint16_t uid_counter; + btrc_player_settings_t player_setting; + btrc_addr_player_changed_t addr_player_changed; + btrc_uids_changed_t uids_changed; + btrc_now_playing_changed_t now_playing_changed; +} btrc_register_notification_t; + +typedef struct { + uint8_t id; /* can be attr_id or value_id */ + uint8_t text[BTRC_MAX_ATTR_STR_LEN]; +} btrc_player_setting_text_t; + +typedef struct { + uint32_t attr_id; + uint8_t text[BTRC_MAX_ATTR_STR_LEN]; +} btrc_element_attr_val_t; + +typedef struct { + uint16_t player_id; + uint8_t major_type; + uint32_t sub_type; + uint8_t play_status; + uint8_t features[BTRC_FEATURE_BIT_MASK_SIZE]; + uint16_t charset_id; + uint8_t name[BTRC_MAX_ATTR_STR_LEN]; +} btrc_item_player_t; + +typedef struct { + uint8_t uid[BTRC_UID_SIZE]; + uint8_t type; + uint8_t playable; + uint16_t charset_id; + uint8_t name[BTRC_MAX_ATTR_STR_LEN]; +} btrc_item_folder_t; + +typedef struct { + uint8_t uid[BTRC_UID_SIZE]; + uint8_t type; + uint16_t charset_id; + uint8_t name[BTRC_MAX_ATTR_STR_LEN]; + int num_attrs; + btrc_element_attr_val_t* p_attrs; +} btrc_item_media_t; + +typedef struct { + uint8_t item_type; + union + { + btrc_item_player_t player; + btrc_item_folder_t folder; + btrc_item_media_t media; + }; +} btrc_folder_items_t; + +typedef struct { + uint16_t str_len; + uint8_t p_str[BTRC_MAX_ATTR_STR_LEN]; +} btrc_br_folder_name_t; + +/** Callback for the controller's supported feautres */ +typedef void (* btrc_remote_features_callback)(bt_bdaddr_t *bd_addr, + btrc_remote_features_t features); + +/** Callback for play status request */ +typedef void (* btrc_get_play_status_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for list player application attributes (Shuffle, Repeat,...) */ +typedef void (* btrc_list_player_app_attr_callback)(bt_bdaddr_t *bd_addr); + +/** Callback for list player application attributes (Shuffle, Repeat,...) */ +typedef void (* btrc_list_player_app_values_callback)(btrc_player_attr_t attr_id, + bt_bdaddr_t *bd_addr); + +/** Callback for getting the current player application settings value +** num_attr: specifies the number of attribute ids contained in p_attrs +*/ +typedef void (* btrc_get_player_app_value_callback) (uint8_t num_attr, + btrc_player_attr_t *p_attrs, bt_bdaddr_t *bd_addr); + +/** Callback for getting the player application settings attributes' text +** num_attr: specifies the number of attribute ids contained in p_attrs +*/ +typedef void (* btrc_get_player_app_attrs_text_callback) (uint8_t num_attr, + btrc_player_attr_t *p_attrs, bt_bdaddr_t *bd_addr); + +/** Callback for getting the player application settings values' text +** num_attr: specifies the number of value ids contained in p_vals +*/ +typedef void (* btrc_get_player_app_values_text_callback) (uint8_t attr_id, uint8_t num_val, + uint8_t *p_vals, bt_bdaddr_t *bd_addr); + +/** Callback for setting the player application settings values */ +typedef void (* btrc_set_player_app_value_callback) (btrc_player_settings_t *p_vals, + bt_bdaddr_t *bd_addr); + +/** Callback to fetch the get element attributes of the current song +** num_attr: specifies the number of attributes requested in p_attrs +*/ +typedef void (* btrc_get_element_attr_callback) (uint8_t num_attr, btrc_media_attr_t *p_attrs, + bt_bdaddr_t *bd_addr); + +/** Callback for register notification (Play state change/track change/...) +** param: Is only valid if event_id is BTRC_EVT_PLAY_POS_CHANGED +*/ +typedef void (* btrc_register_notification_callback) (btrc_event_id_t event_id, uint32_t param, + bt_bdaddr_t *bd_addr); + +/* AVRCP 1.4 Enhancements */ +/** Callback for volume change on CT +** volume: Current volume setting on the CT (0-127) +*/ +typedef void (* btrc_volume_change_callback) (uint8_t volume, uint8_t ctype, bt_bdaddr_t *bd_addr); + +/** Callback for passthrough commands */ +typedef void (* btrc_passthrough_cmd_callback) (int id, int key_state, bt_bdaddr_t *bd_addr); + +/** Callback for set addressed player response on TG **/ +typedef void (* btrc_set_addressed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr); + +/** Callback for set browsed player response on TG **/ +typedef void (* btrc_set_browsed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr); + +/** Callback for get folder items on TG +** num_attr: specifies the number of attributes requested in p_attr_ids +*/ +typedef void (* btrc_get_folder_items_callback) (uint8_t scope, uint32_t start_item, + uint32_t end_item, uint8_t num_attr, uint32_t *p_attr_ids, bt_bdaddr_t *bd_addr); + +/** Callback for changing browsed path on TG **/ +typedef void (* btrc_change_path_callback) (uint8_t direction, + uint8_t* folder_uid, bt_bdaddr_t *bd_addr); + +/** Callback to fetch the get item attributes of the media item +** num_attr: specifies the number of attributes requested in p_attrs +*/ +typedef void (* btrc_get_item_attr_callback) (uint8_t scope, uint8_t* uid, uint16_t uid_counter, + uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr); + +/** Callback for play request for the media item indicated by an identifier */ +typedef void (* btrc_play_item_callback) (uint8_t scope, + uint16_t uid_counter, uint8_t* uid, bt_bdaddr_t *bd_addr); + +/** Callback to fetch total number of items from a folder **/ +typedef void (* btrc_get_total_num_of_items_callback) (uint8_t scope, bt_bdaddr_t *bd_addr); + +/** Callback for conducting recursive search on a current browsed path for a specified string */ +typedef void (* btrc_search_callback) (uint16_t charset_id, + uint16_t str_len, uint8_t* p_str, bt_bdaddr_t *bd_addr); + +/** Callback to add a specified media item indicated by an identifier to now playing queue. */ +typedef void (* btrc_add_to_now_playing_callback) (uint8_t scope, + uint8_t* uid, uint16_t uid_counter, bt_bdaddr_t *bd_addr); + +/** Callback for set addressed player response on TG **/ +typedef void (* btrc_set_addressed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr); + +/** Callback for set browsed player response on TG **/ +typedef void (* btrc_set_browsed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr); + +/** Callback for get folder items on TG +** num_attr: specifies the number of attributes requested in p_attr_ids +*/ +typedef void (* btrc_get_folder_items_callback) (uint8_t scope, uint32_t start_item, + uint32_t end_item, uint8_t num_attr, uint32_t *p_attr_ids, bt_bdaddr_t *bd_addr); + +/** Callback for changing browsed path on TG **/ +typedef void (* btrc_change_path_callback) (uint8_t direction, + uint8_t* folder_uid, bt_bdaddr_t *bd_addr); + +/** Callback to fetch the get item attributes of the media item +** num_attr: specifies the number of attributes requested in p_attrs +*/ +typedef void (* btrc_get_item_attr_callback) (uint8_t scope, uint8_t* uid, uint16_t uid_counter, + uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr); + +/** Callback for play request for the media item indicated by an identifier */ +typedef void (* btrc_play_item_callback) (uint8_t scope, + uint16_t uid_counter, uint8_t* uid, bt_bdaddr_t *bd_addr); + +/** Callback to fetch total number of items from a folder **/ +typedef void (* btrc_get_total_num_of_items_callback) (uint8_t scope, bt_bdaddr_t *bd_addr); + +/** Callback for conducting recursive search on a current browsed path for a specified string */ +typedef void (* btrc_search_callback) (uint16_t charset_id, + uint16_t str_len, uint8_t* p_str, bt_bdaddr_t *bd_addr); + +/** Callback to add a specified media item indicated by an identifier to now playing queue. */ +typedef void (* btrc_add_to_now_playing_callback) (uint8_t scope, + uint8_t* uid, uint16_t uid_counter, bt_bdaddr_t *bd_addr); + +/** Callback for set addressed player response on TG **/ +typedef void (* btrc_set_addressed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr); + +/** Callback for set browsed player response on TG **/ +typedef void (* btrc_set_browsed_player_callback) (uint16_t player_id, bt_bdaddr_t *bd_addr); + +/** Callback for get folder items on TG +** num_attr: specifies the number of attributes requested in p_attr_ids +*/ +typedef void (* btrc_get_folder_items_callback) (uint8_t scope, uint32_t start_item, + uint32_t end_item, uint8_t num_attr, uint32_t *p_attr_ids, bt_bdaddr_t *bd_addr); + +/** Callback for changing browsed path on TG **/ +typedef void (* btrc_change_path_callback) (uint8_t direction, + uint8_t* folder_uid, bt_bdaddr_t *bd_addr); + +/** Callback to fetch the get item attributes of the media item +** num_attr: specifies the number of attributes requested in p_attrs +*/ +typedef void (* btrc_get_item_attr_callback) (uint8_t scope, uint8_t* uid, uint16_t uid_counter, + uint8_t num_attr, btrc_media_attr_t *p_attrs, bt_bdaddr_t *bd_addr); + +/** Callback for play request for the media item indicated by an identifier */ +typedef void (* btrc_play_item_callback) (uint8_t scope, + uint16_t uid_counter, uint8_t* uid, bt_bdaddr_t *bd_addr); + +/** Callback to fetch total number of items from a folder **/ +typedef void (* btrc_get_total_num_of_items_callback) (uint8_t scope, bt_bdaddr_t *bd_addr); + +/** Callback for conducting recursive search on a current browsed path for a specified string */ +typedef void (* btrc_search_callback) (uint16_t charset_id, + uint16_t str_len, uint8_t* p_str, bt_bdaddr_t *bd_addr); + +/** Callback to add a specified media item indicated by an identifier to now playing queue. */ +typedef void (* btrc_add_to_now_playing_callback) (uint8_t scope, + uint8_t* uid, uint16_t uid_counter, bt_bdaddr_t *bd_addr); + +/** BT-RC Target callback structure. */ +typedef struct { + /** set to sizeof(BtRcCallbacks) */ + size_t size; + btrc_remote_features_callback remote_features_cb; + btrc_get_play_status_callback get_play_status_cb; + btrc_list_player_app_attr_callback list_player_app_attr_cb; + btrc_list_player_app_values_callback list_player_app_values_cb; + btrc_get_player_app_value_callback get_player_app_value_cb; + btrc_get_player_app_attrs_text_callback get_player_app_attrs_text_cb; + btrc_get_player_app_values_text_callback get_player_app_values_text_cb; + btrc_set_player_app_value_callback set_player_app_value_cb; + btrc_get_element_attr_callback get_element_attr_cb; + btrc_register_notification_callback register_notification_cb; + btrc_volume_change_callback volume_change_cb; + btrc_passthrough_cmd_callback passthrough_cmd_cb; + btrc_set_addressed_player_callback set_addressed_player_cb; + btrc_set_browsed_player_callback set_browsed_player_cb; + btrc_get_folder_items_callback get_folder_items_cb; + btrc_change_path_callback change_path_cb; + btrc_get_item_attr_callback get_item_attr_cb; + btrc_play_item_callback play_item_cb; + btrc_get_total_num_of_items_callback get_total_num_of_items_cb; + btrc_search_callback search_cb; + btrc_add_to_now_playing_callback add_to_now_playing_cb; +} btrc_callbacks_t; + +/** Represents the standard BT-RC AVRCP Target interface. */ +typedef struct { + + /** set to sizeof(BtRcInterface) */ + size_t size; + /** + * Register the BtRc callbacks + */ + bt_status_t (*init)( btrc_callbacks_t* callbacks ); + + /** Respose to GetPlayStatus request. Contains the current + ** 1. Play status + ** 2. Song duration/length + ** 3. Song position + */ + bt_status_t (*get_play_status_rsp)( bt_bdaddr_t *bd_addr, btrc_play_status_t play_status, + uint32_t song_len, uint32_t song_pos); + + /** Lists the support player application attributes (Shuffle/Repeat/...) + ** num_attr: Specifies the number of attributes contained in the pointer p_attrs + */ + bt_status_t (*list_player_app_attr_rsp)( bt_bdaddr_t *bd_addr, int num_attr, + btrc_player_attr_t *p_attrs); + + /** Lists the support player application attributes (Shuffle Off/On/Group) + ** num_val: Specifies the number of values contained in the pointer p_vals + */ + bt_status_t (*list_player_app_value_rsp)( bt_bdaddr_t *bd_addr, int num_val, uint8_t *p_vals); + + /** Returns the current application attribute values for each of the specified attr_id */ + bt_status_t (*get_player_app_value_rsp)( bt_bdaddr_t *bd_addr, btrc_player_settings_t *p_vals); + + /** Returns the application attributes text ("Shuffle"/"Repeat"/...) + ** num_attr: Specifies the number of attributes' text contained in the pointer p_attrs + */ + bt_status_t (*get_player_app_attr_text_rsp)( bt_bdaddr_t *bd_addr, int num_attr, + btrc_player_setting_text_t *p_attrs); + + /** Returns the application attributes text ("Shuffle"/"Repeat"/...) + ** num_attr: Specifies the number of attribute values' text contained in the pointer p_vals + */ + bt_status_t (*get_player_app_value_text_rsp)( bt_bdaddr_t *bd_addr, int num_val, + btrc_player_setting_text_t *p_vals); + + /** Returns the current songs' element attributes text ("Title"/"Album"/"Artist") + ** num_attr: Specifies the number of attributes' text contained in the pointer p_attrs + */ + bt_status_t (*get_element_attr_rsp)( bt_bdaddr_t *bd_addr, uint8_t num_attr, + btrc_element_attr_val_t *p_attrs); + + /** Response to set player attribute request ("Shuffle"/"Repeat") + ** rsp_status: Status of setting the player attributes for the current media player + */ + bt_status_t (*set_player_app_value_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status); + + /* Response to the register notification request (Play state change/track change/...). + ** event_id: Refers to the event_id this notification change corresponds too + ** type: Response type - interim/changed + ** p_params: Based on the event_id, this parameter should be populated + */ + bt_status_t (*register_notification_rsp)(btrc_event_id_t event_id, + btrc_notification_type_t type, + btrc_register_notification_t *p_param); + + /* AVRCP 1.4 enhancements */ + + /**Send current volume setting to remote side. Support limited to SetAbsoluteVolume + ** This can be enhanced to support Relative Volume (AVRCP 1.0). + ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN opposed to absolute volume level + ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set + */ + bt_status_t (*set_volume)(uint8_t volume); + + /* Set addressed player response from TG to CT */ + bt_status_t (*set_addressed_player_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status); + + /* Set browsed player response from TG to CT */ + bt_status_t (*set_browsed_player_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, + uint32_t num_items, uint16_t charset_id, uint8_t folder_depth, + btrc_br_folder_name_t *p_folders); + + /* Get folder item list response from TG to CT */ + bt_status_t (*get_folder_items_list_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, + uint16_t uid_counter, uint8_t num_items, btrc_folder_items_t *p_items); + + /* Change path response from TG to CT */ + bt_status_t (*change_path_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, + uint32_t num_items); + + /** Returns the element's attributes num_attr: Specifies the number of attributes' text + * contained in the pointer p_attrs + */ + bt_status_t (*get_item_attr_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, + uint8_t num_attr, btrc_element_attr_val_t *p_attrs); + + /* play media item response from TG to CT */ + bt_status_t (*play_item_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status); + + /* get total number of items response from TG to CT*/ + bt_status_t (*get_total_num_of_items_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, + uint32_t uid_counter, uint32_t num_items); + + /* Search VFS response from TG to CT */ + bt_status_t (*search_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status, uint32_t uid_counter, + uint32_t num_items); + + /* add_to_now playing list response from TG to CT */ + bt_status_t (*add_to_now_playing_rsp)(bt_bdaddr_t *bd_addr, btrc_status_t rsp_status); + + /** Closes the interface. */ + void (*cleanup)( void ); +} btrc_interface_t; + +typedef void (* btrc_passthrough_rsp_callback) (bt_bdaddr_t *bd_addr, int id, int key_state); + +typedef void (* btrc_groupnavigation_rsp_callback) (int id, int key_state); + +typedef void (* btrc_connection_state_callback) ( + bool rc_connect, bool bt_connect, bt_bdaddr_t *bd_addr); + +typedef void (* btrc_ctrl_getrcfeatures_callback) (bt_bdaddr_t *bd_addr, int features); + +typedef void (* btrc_ctrl_setabsvol_cmd_callback) (bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label); + +typedef void (* btrc_ctrl_registernotification_abs_vol_callback) (bt_bdaddr_t *bd_addr, uint8_t label); + +typedef void (* btrc_ctrl_setplayerapplicationsetting_rsp_callback) (bt_bdaddr_t *bd_addr, + uint8_t accepted); + +typedef void (* btrc_ctrl_playerapplicationsetting_callback)(bt_bdaddr_t *bd_addr, + uint8_t num_attr, + btrc_player_app_attr_t *app_attrs, + uint8_t num_ext_attr, + btrc_player_app_ext_attr_t *ext_attrs); + +typedef void (* btrc_ctrl_playerapplicationsetting_changed_callback)(bt_bdaddr_t *bd_addr, + btrc_player_settings_t *p_vals); + +typedef void (* btrc_ctrl_track_changed_callback)(bt_bdaddr_t *bd_addr, uint8_t num_attr, + btrc_element_attr_val_t *p_attrs); + +typedef void (* btrc_ctrl_play_position_changed_callback)(bt_bdaddr_t *bd_addr, + uint32_t song_len, uint32_t song_pos); + +typedef void (* btrc_ctrl_play_status_changed_callback)(bt_bdaddr_t *bd_addr, + btrc_play_status_t play_status); + +typedef void (* btrc_ctrl_get_folder_items_callback )(bt_bdaddr_t *bd_addr, + btrc_status_t status, + const btrc_folder_items_t *folder_items, + uint8_t count); + +typedef void (* btrc_ctrl_change_path_callback)(bt_bdaddr_t *bd_addr, uint8_t count); + +typedef void (* btrc_ctrl_set_browsed_player_callback )( + bt_bdaddr_t *bd_addr, uint8_t num_items, uint8_t depth); +typedef void (* btrc_ctrl_set_addressed_player_callback)(bt_bdaddr_t *bd_addr, uint8_t status); +/** BT-RC Controller callback structure. */ +typedef struct { + /** set to sizeof(BtRcCallbacks) */ + size_t size; + btrc_passthrough_rsp_callback passthrough_rsp_cb; + btrc_groupnavigation_rsp_callback groupnavigation_rsp_cb; + btrc_connection_state_callback connection_state_cb; + btrc_ctrl_getrcfeatures_callback getrcfeatures_cb; + btrc_ctrl_setplayerapplicationsetting_rsp_callback setplayerappsetting_rsp_cb; + btrc_ctrl_playerapplicationsetting_callback playerapplicationsetting_cb; + btrc_ctrl_playerapplicationsetting_changed_callback playerapplicationsetting_changed_cb; + btrc_ctrl_setabsvol_cmd_callback setabsvol_cmd_cb; + btrc_ctrl_registernotification_abs_vol_callback registernotification_absvol_cb; + btrc_ctrl_track_changed_callback track_changed_cb; + btrc_ctrl_play_position_changed_callback play_position_changed_cb; + btrc_ctrl_play_status_changed_callback play_status_changed_cb; + btrc_ctrl_get_folder_items_callback get_folder_items_cb; + btrc_ctrl_change_path_callback change_folder_path_cb; + btrc_ctrl_set_browsed_player_callback set_browsed_player_cb; + btrc_ctrl_set_addressed_player_callback set_addressed_player_cb; +} btrc_ctrl_callbacks_t; + +/** Represents the standard BT-RC AVRCP Controller interface. */ +typedef struct { + + /** set to sizeof(BtRcInterface) */ + size_t size; + /** + * Register the BtRc callbacks + */ + bt_status_t (*init)( btrc_ctrl_callbacks_t* callbacks ); + + /** send pass through command to target */ + bt_status_t (*send_pass_through_cmd) (bt_bdaddr_t *bd_addr, uint8_t key_code, + uint8_t key_state ); + + /** send group navigation command to target */ + bt_status_t (*send_group_navigation_cmd) (bt_bdaddr_t *bd_addr, uint8_t key_code, + uint8_t key_state ); + + /** send command to set player applicaiton setting attributes to target */ + bt_status_t (*set_player_app_setting_cmd) (bt_bdaddr_t *bd_addr, uint8_t num_attrib, + uint8_t* attrib_ids, uint8_t* attrib_vals); + + /** send command to play a particular item */ + bt_status_t (*play_item_cmd) ( + bt_bdaddr_t *bd_addr, uint8_t scope, uint8_t *uid, uint16_t uid_counter); + + /** get the playback state */ + bt_status_t (*get_playback_state_cmd) (bt_bdaddr_t *bd_addr); + + /** get the now playing list */ + bt_status_t (*get_now_playing_list_cmd) (bt_bdaddr_t *bd_addr, uint8_t start, uint8_t items); + + /** get the folder list */ + bt_status_t (*get_folder_list_cmd) (bt_bdaddr_t *bd_addr, uint8_t start, uint8_t items); + + /** get the folder list */ + bt_status_t (*get_player_list_cmd) (bt_bdaddr_t *bd_addr, uint8_t start, uint8_t items); + + /** get the folder list */ + bt_status_t (*change_folder_path_cmd) (bt_bdaddr_t *bd_addr, uint8_t direction, uint8_t * uid); + + /** set browsed player */ + bt_status_t (*set_browsed_player_cmd) (bt_bdaddr_t *bd_addr, uint16_t player_id); + + /** set addressed player */ + bt_status_t (*set_addressed_player_cmd) (bt_bdaddr_t *bd_addr, uint16_t player_id); + + /** send rsp to set_abs_vol received from target */ + bt_status_t (*set_volume_rsp) (bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label); + + /** send notificaiton rsp for abs vol to target */ + bt_status_t (*register_abs_vol_rsp) (bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type, + uint8_t abs_vol, uint8_t label); + + /** Closes the interface. */ + void (*cleanup)( void ); +} btrc_ctrl_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_RC_H */
diff --git a/libhardware/include/hardware/bt_sdp.h b/libhardware/include/hardware/bt_sdp.h new file mode 100644 index 0000000..8f39bc5 --- /dev/null +++ b/libhardware/include/hardware/bt_sdp.h
@@ -0,0 +1,150 @@ +/* + * 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 "bluetooth.h" + +#define SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH 15 + +__BEGIN_DECLS + +/** + * These events are handled by the state machine + */ +typedef enum { + SDP_TYPE_RAW, // Used to carry raw SDP search data for unknown UUIDs + SDP_TYPE_MAP_MAS, // Message Access Profile - Server + SDP_TYPE_MAP_MNS, // Message Access Profile - Client (Notification Server) + SDP_TYPE_PBAP_PSE, // Phone Book Profile - Server + SDP_TYPE_PBAP_PCE, // Phone Book Profile - Client + SDP_TYPE_OPP_SERVER, // Object Push Profile + SDP_TYPE_SAP_SERVER // SIM Access Profile +} bluetooth_sdp_types; + +typedef struct _bluetooth_sdp_hdr { + bluetooth_sdp_types type; + bt_uuid_t uuid; + uint32_t service_name_length; + char *service_name; + int32_t rfcomm_channel_number; + int32_t l2cap_psm; + int32_t profile_version; +} bluetooth_sdp_hdr; + +/** + * Some signals need additional pointers, hence we introduce a + * generic way to handle these pointers. + */ +typedef struct _bluetooth_sdp_hdr_overlay { + bluetooth_sdp_types type; + bt_uuid_t uuid; + uint32_t service_name_length; + char *service_name; + int32_t rfcomm_channel_number; + int32_t l2cap_psm; + int32_t profile_version; + + // User pointers, only used for some signals - see bluetooth_sdp_ops_record + int user1_ptr_len; + uint8_t *user1_ptr; + int user2_ptr_len; + uint8_t *user2_ptr; +} bluetooth_sdp_hdr_overlay; + +typedef struct _bluetooth_sdp_mas_record { + bluetooth_sdp_hdr_overlay hdr; + uint32_t mas_instance_id; + uint32_t supported_features; + uint32_t supported_message_types; +} bluetooth_sdp_mas_record; + +typedef struct _bluetooth_sdp_mns_record { + bluetooth_sdp_hdr_overlay hdr; + uint32_t supported_features; +} bluetooth_sdp_mns_record; + +typedef struct _bluetooth_sdp_pse_record { + bluetooth_sdp_hdr_overlay hdr; + uint32_t supported_features; + uint32_t supported_repositories; +} bluetooth_sdp_pse_record; + +typedef struct _bluetooth_sdp_pce_record { + bluetooth_sdp_hdr_overlay hdr; +} bluetooth_sdp_pce_record; + +typedef struct _bluetooth_sdp_ops_record { + bluetooth_sdp_hdr_overlay hdr; + int supported_formats_list_len; + uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH]; +} bluetooth_sdp_ops_record; + +typedef struct _bluetooth_sdp_sap_record { + bluetooth_sdp_hdr_overlay hdr; +} bluetooth_sdp_sap_record; + +typedef union { + bluetooth_sdp_hdr_overlay hdr; + bluetooth_sdp_mas_record mas; + bluetooth_sdp_mns_record mns; + bluetooth_sdp_pse_record pse; + bluetooth_sdp_pce_record pce; + bluetooth_sdp_ops_record ops; + bluetooth_sdp_sap_record sap; +} bluetooth_sdp_record; + + +/** Callback for SDP search */ +typedef void (*btsdp_search_callback)(bt_status_t status, bt_bdaddr_t *bd_addr, uint8_t* uuid, int num_records, bluetooth_sdp_record *records); + +typedef struct { + /** Set to sizeof(btsdp_callbacks_t) */ + size_t size; + btsdp_search_callback sdp_search_cb; +} btsdp_callbacks_t; + +typedef struct { + /** Set to size of this struct */ + size_t size; + + /** Register BT SDP search callbacks */ + bt_status_t (*init)(btsdp_callbacks_t *callbacks); + + /** Unregister BT SDP */ + bt_status_t (*deinit)(); + + /** Search for SDP records with specific uuid on remote device */ + bt_status_t (*sdp_search)(bt_bdaddr_t *bd_addr, const uint8_t* uuid); + + /** + * Use listen in the socket interface to create rfcomm and/or l2cap PSM channels, + * (without UUID and service_name and set the BTSOCK_FLAG_NO_SDP flag in flags). + * Then use createSdpRecord to create the SDP record associated with the rfcomm/l2cap channels. + * + * Returns a handle to the SDP record, which can be parsed to remove_sdp_record. + * + * record (in) The SDP record to create + * record_handle (out)The corresponding record handle will be written to this pointer. + */ + bt_status_t (*create_sdp_record)(bluetooth_sdp_record *record, int* record_handle); + + /** Remove a SDP record created by createSdpRecord */ + bt_status_t (*remove_sdp_record)(int sdp_handle); +} btsdp_interface_t; + +__END_DECLS +
diff --git a/libhardware/include/hardware/bt_sock.h b/libhardware/include/hardware/bt_sock.h new file mode 100644 index 0000000..8d1a9e0 --- /dev/null +++ b/libhardware/include/hardware/bt_sock.h
@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 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 + +__BEGIN_DECLS + +#define BTSOCK_FLAG_ENCRYPT 1 +#define BTSOCK_FLAG_AUTH (1 << 1) +#define BTSOCK_FLAG_NO_SDP (1 << 2) +#define BTSOCK_FLAG_AUTH_MITM (1 << 3) +#define BTSOCK_FLAG_AUTH_16_DIGIT (1 << 4) + +typedef enum { + BTSOCK_RFCOMM = 1, + BTSOCK_SCO = 2, + BTSOCK_L2CAP = 3 +} btsock_type_t; + +/** Represents the standard BT SOCKET interface. */ +typedef struct { + short size; + bt_bdaddr_t bd_addr; + int channel; + int status; + + // The writer must make writes using a buffer of this maximum size + // to avoid loosing data. (L2CAP only) + unsigned short max_tx_packet_size; + + // The reader must read using a buffer of at least this size to avoid + // loosing data. (L2CAP only) + unsigned short max_rx_packet_size; +} __attribute__((packed)) sock_connect_signal_t; + +typedef struct { + /** set to size of this struct*/ + size_t size; + + /** + * Listen to a RFCOMM UUID or channel. It returns the socket fd from which + * btsock_connect_signal can be read out when a remote device connected. + * If neither a UUID nor a channel is provided, a channel will be allocated + * and a service record can be created providing the channel number to + * create_sdp_record(...) in bt_sdp. + * The callingUid is the UID of the application which is requesting the socket. This is + * used for traffic accounting purposes. + */ + bt_status_t (*listen)(btsock_type_t type, const char* service_name, + const uint8_t* service_uuid, int channel, int* sock_fd, int flags, int callingUid); + + /** + * Connect to a RFCOMM UUID channel of remote device, It returns the socket fd from which + * the btsock_connect_signal and a new socket fd to be accepted can be read out when connected. + * The callingUid is the UID of the application which is requesting the socket. This is + * used for traffic accounting purposes. + */ + bt_status_t (*connect)(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t* uuid, + int channel, int* sock_fd, int flags, int callingUid); +} btsock_interface_t; + +__END_DECLS +
diff --git a/libhardware/include/hardware/camera.h b/libhardware/include/hardware/camera.h new file mode 100644 index 0000000..b1f18ff --- /dev/null +++ b/libhardware/include/hardware/camera.h
@@ -0,0 +1,298 @@ +/* + * Copyright (C) 2010-2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_CAMERA_H +#define ANDROID_INCLUDE_CAMERA_H + +#include "camera_common.h" + +/** + * Camera device HAL, initial version [ CAMERA_DEVICE_API_VERSION_1_0 ] + * + * DEPRECATED. New devices should use Camera HAL v3.2 or newer. + * + * Supports the android.hardware.Camera API, and the android.hardware.camera2 + * API in legacy mode only. + * + * Camera devices that support this version of the HAL must return a value in + * the range HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF) in + * camera_device_t.common.version. CAMERA_DEVICE_API_VERSION_1_0 is the + * recommended value. + * + * Camera modules that implement version 2.0 or higher of camera_module_t must + * also return the value of camera_device_t.common.version in + * camera_info_t.device_version. + * + * See camera_common.h for more details. + */ + +__BEGIN_DECLS + +struct camera_memory; +typedef void (*camera_release_memory)(struct camera_memory *mem); + +typedef struct camera_memory { + void *data; + size_t size; + void *handle; + camera_release_memory release; +} camera_memory_t; + +typedef camera_memory_t* (*camera_request_memory)(int fd, size_t buf_size, unsigned int num_bufs, + void *user); + +typedef void (*camera_notify_callback)(int32_t msg_type, + int32_t ext1, + int32_t ext2, + void *user); + +typedef void (*camera_data_callback)(int32_t msg_type, + const camera_memory_t *data, unsigned int index, + camera_frame_metadata_t *metadata, void *user); + +typedef void (*camera_data_timestamp_callback)(int64_t timestamp, + int32_t msg_type, + const camera_memory_t *data, unsigned int index, + void *user); + +#define HAL_CAMERA_PREVIEW_WINDOW_TAG 0xcafed00d + +typedef struct preview_stream_ops { + int (*dequeue_buffer)(struct preview_stream_ops* w, + buffer_handle_t** buffer, int *stride); + int (*enqueue_buffer)(struct preview_stream_ops* w, + buffer_handle_t* buffer); + int (*cancel_buffer)(struct preview_stream_ops* w, + buffer_handle_t* buffer); + int (*set_buffer_count)(struct preview_stream_ops* w, int count); + int (*set_buffers_geometry)(struct preview_stream_ops* pw, + int w, int h, int format); + int (*set_crop)(struct preview_stream_ops *w, + int left, int top, int right, int bottom); + int (*set_usage)(struct preview_stream_ops* w, int usage); + int (*set_swap_interval)(struct preview_stream_ops *w, int interval); + int (*get_min_undequeued_buffer_count)(const struct preview_stream_ops *w, + int *count); + int (*lock_buffer)(struct preview_stream_ops* w, + buffer_handle_t* buffer); + // Timestamps are measured in nanoseconds, and must be comparable + // and monotonically increasing between two frames in the same + // preview stream. They do not need to be comparable between + // consecutive or parallel preview streams, cameras, or app runs. + int (*set_timestamp)(struct preview_stream_ops *w, int64_t timestamp); +} preview_stream_ops_t; + +struct camera_device; +typedef struct camera_device_ops { + /** Set the ANativeWindow to which preview frames are sent */ + int (*set_preview_window)(struct camera_device *, + struct preview_stream_ops *window); + + /** Set the notification and data callbacks */ + void (*set_callbacks)(struct camera_device *, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user); + + /** + * The following three functions all take a msg_type, which is a bitmask of + * the messages defined in include/ui/Camera.h + */ + + /** + * Enable a message, or set of messages. + */ + void (*enable_msg_type)(struct camera_device *, int32_t msg_type); + + /** + * Disable a message, or a set of messages. + * + * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera + * HAL should not rely on its client to call releaseRecordingFrame() to + * release video recording frames sent out by the cameral HAL before and + * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL + * clients must not modify/access any video recording frame after calling + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). + */ + void (*disable_msg_type)(struct camera_device *, int32_t msg_type); + + /** + * Query whether a message, or a set of messages, is enabled. Note that + * this is operates as an AND, if any of the messages queried are off, this + * will return false. + */ + int (*msg_type_enabled)(struct camera_device *, int32_t msg_type); + + /** + * Start preview mode. + */ + int (*start_preview)(struct camera_device *); + + /** + * Stop a previously started preview. + */ + void (*stop_preview)(struct camera_device *); + + /** + * Returns true if preview is enabled. + */ + int (*preview_enabled)(struct camera_device *); + + /** + * Request the camera HAL to store meta data or real YUV data in the video + * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If + * it is not called, the default camera HAL behavior is to store real YUV + * data in the video buffers. + * + * This method should be called before startRecording() in order to be + * effective. + * + * If meta data is stored in the video buffers, it is up to the receiver of + * the video buffers to interpret the contents and to find the actual frame + * data with the help of the meta data in the buffer. How this is done is + * outside of the scope of this method. + * + * Some camera HALs may not support storing meta data in the video buffers, + * but all camera HALs should support storing real YUV data in the video + * buffers. If the camera HAL does not support storing the meta data in the + * video buffers when it is requested to do do, INVALID_OPERATION must be + * returned. It is very useful for the camera HAL to pass meta data rather + * than the actual frame data directly to the video encoder, since the + * amount of the uncompressed frame data can be very large if video size is + * large. + * + * @param enable if true to instruct the camera HAL to store + * meta data in the video buffers; false to instruct + * the camera HAL to store real YUV data in the video + * buffers. + * + * @return OK on success. + */ + int (*store_meta_data_in_buffers)(struct camera_device *, int enable); + + /** + * Start record mode. When a record image is available, a + * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding + * frame. Every record frame must be released by a camera HAL client via + * releaseRecordingFrame() before the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames, + * and the client must not modify/access any video recording frames. + */ + int (*start_recording)(struct camera_device *); + + /** + * Stop a previously started recording. + */ + void (*stop_recording)(struct camera_device *); + + /** + * Returns true if recording is enabled. + */ + int (*recording_enabled)(struct camera_device *); + + /** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + * + * It is camera HAL client's responsibility to release video recording + * frames sent out by the camera HAL before the camera HAL receives a call + * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames. + */ + void (*release_recording_frame)(struct camera_device *, + const void *opaque); + + /** + * Start auto focus, the notification callback routine is called with + * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be + * called again if another auto focus is needed. + */ + int (*auto_focus)(struct camera_device *); + + /** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress or + * not, this function will return the focus position to the default. If + * the camera does not support auto-focus, this is a no-op. + */ + int (*cancel_auto_focus)(struct camera_device *); + + /** + * Take a picture. + */ + int (*take_picture)(struct camera_device *); + + /** + * Cancel a picture that was started with takePicture. Calling this method + * when no picture is being taken is a no-op. + */ + int (*cancel_picture)(struct camera_device *); + + /** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. + */ + int (*set_parameters)(struct camera_device *, const char *parms); + + /** Retrieve the camera parameters. The buffer returned by the camera HAL + must be returned back to it with put_parameters, if put_parameters + is not NULL. + */ + char *(*get_parameters)(struct camera_device *); + + /** The camera HAL uses its own memory to pass us the parameters when we + call get_parameters. Use this function to return the memory back to + the camera HAL, if put_parameters is not NULL. If put_parameters + is NULL, then you have to use free() to release the memory. + */ + void (*put_parameters)(struct camera_device *, char *); + + /** + * Send command to camera driver. + */ + int (*send_command)(struct camera_device *, + int32_t cmd, int32_t arg1, int32_t arg2); + + /** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ + void (*release)(struct camera_device *); + + /** + * Dump state of the camera hardware + */ + int (*dump)(struct camera_device *, int fd); +} camera_device_ops_t; + +typedef struct camera_device { + /** + * camera_device.common.version must be in the range + * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is + * recommended. + */ + hw_device_t common; + camera_device_ops_t *ops; + void *priv; +} camera_device_t; + +__END_DECLS + +#endif /* #ifdef ANDROID_INCLUDE_CAMERA_H */
diff --git a/libhardware/include/hardware/camera2.h b/libhardware/include/hardware/camera2.h new file mode 100644 index 0000000..d920d4b --- /dev/null +++ b/libhardware/include/hardware/camera2.h
@@ -0,0 +1,839 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_CAMERA2_H +#define ANDROID_INCLUDE_CAMERA2_H + +#include "camera_common.h" +#include "system/camera_metadata.h" + +/** + * Camera device HAL 2.1 [ CAMERA_DEVICE_API_VERSION_2_0, CAMERA_DEVICE_API_VERSION_2_1 ] + * + * DEPRECATED. New devices should use Camera HAL v3.2 or newer. + * + * Supports the android.hardware.Camera API, and the android.hardware.camera2 + * API in legacy mode only. + * + * Camera devices that support this version of the HAL must return + * CAMERA_DEVICE_API_VERSION_2_1 in camera_device_t.common.version and in + * camera_info_t.device_version (from camera_module_t.get_camera_info). + * + * Camera modules that may contain version 2.x devices must implement at least + * version 2.0 of the camera module interface (as defined by + * camera_module_t.common.module_api_version). + * + * See camera_common.h for more versioning details. + * + * Version history: + * + * 2.0: CAMERA_DEVICE_API_VERSION_2_0. Initial release (Android 4.2): + * - Sufficient for implementing existing android.hardware.Camera API. + * - Allows for ZSL queue in camera service layer + * - Not tested for any new features such manual capture control, + * Bayer RAW capture, reprocessing of RAW data. + * + * 2.1: CAMERA_DEVICE_API_VERSION_2_1. Support per-device static metadata: + * - Add get_instance_metadata() method to retrieve metadata that is fixed + * after device open, but may be variable between open() calls. + */ + +__BEGIN_DECLS + +struct camera2_device; + +/********************************************************************** + * + * Input/output stream buffer queue interface definitions + * + */ + +/** + * Output image stream queue interface. A set of these methods is provided to + * the HAL device in allocate_stream(), and are used to interact with the + * gralloc buffer queue for that stream. They may not be called until after + * allocate_stream returns. + */ +typedef struct camera2_stream_ops { + /** + * Get a buffer to fill from the queue. The size and format of the buffer + * are fixed for a given stream (defined in allocate_stream), and the stride + * should be queried from the platform gralloc module. The gralloc buffer + * will have been allocated based on the usage flags provided by + * allocate_stream, and will be locked for use. + */ + int (*dequeue_buffer)(const struct camera2_stream_ops* w, + buffer_handle_t** buffer); + + /** + * Push a filled buffer to the stream to be used by the consumer. + * + * The timestamp represents the time at start of exposure of the first row + * of the image; it must be from a monotonic clock, and is measured in + * nanoseconds. The timestamps do not need to be comparable between + * different cameras, or consecutive instances of the same camera. However, + * they must be comparable between streams from the same camera. If one + * capture produces buffers for multiple streams, each stream must have the + * same timestamp for that buffer, and that timestamp must match the + * timestamp in the output frame metadata. + */ + int (*enqueue_buffer)(const struct camera2_stream_ops* w, + int64_t timestamp, + buffer_handle_t* buffer); + /** + * Return a buffer to the queue without marking it as filled. + */ + int (*cancel_buffer)(const struct camera2_stream_ops* w, + buffer_handle_t* buffer); + /** + * Set the crop window for subsequently enqueued buffers. The parameters are + * measured in pixels relative to the buffer width and height. + */ + int (*set_crop)(const struct camera2_stream_ops *w, + int left, int top, int right, int bottom); + +} camera2_stream_ops_t; + +/** + * Temporary definition during transition. + * + * These formats will be removed and replaced with + * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. To maximize forward compatibility, + * HAL implementations are strongly recommended to treat FORMAT_OPAQUE and + * FORMAT_ZSL as equivalent to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, and + * return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED in the format_actual output + * parameter of allocate_stream, allowing the gralloc module to select the + * specific format based on the usage flags from the camera and the stream + * consumer. + */ +enum { + CAMERA2_HAL_PIXEL_FORMAT_OPAQUE = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + CAMERA2_HAL_PIXEL_FORMAT_ZSL = -1 +}; + +/** + * Transport header for compressed JPEG buffers in output streams. + * + * To capture JPEG images, a stream is created using the pixel format + * HAL_PIXEL_FORMAT_BLOB, and the static metadata field android.jpeg.maxSize is + * used as the buffer size. Since compressed JPEG images are of variable size, + * the HAL needs to include the final size of the compressed image using this + * structure inside the output stream buffer. The JPEG blob ID field must be set + * to CAMERA2_JPEG_BLOB_ID. + * + * Transport header should be at the end of the JPEG output stream buffer. That + * means the jpeg_blob_id must start at byte[android.jpeg.maxSize - + * sizeof(camera2_jpeg_blob)]. Any HAL using this transport header must + * account for it in android.jpeg.maxSize. The JPEG data itself starts at + * byte[0] and should be jpeg_size bytes long. + */ +typedef struct camera2_jpeg_blob { + uint16_t jpeg_blob_id; + uint32_t jpeg_size; +}; + +enum { + CAMERA2_JPEG_BLOB_ID = 0x00FF +}; + +/** + * Input reprocess stream queue management. A set of these methods is provided + * to the HAL device in allocate_reprocess_stream(); they are used to interact + * with the reprocess stream's input gralloc buffer queue. + */ +typedef struct camera2_stream_in_ops { + /** + * Get the next buffer of image data to reprocess. The width, height, and + * format of the buffer is fixed in allocate_reprocess_stream(), and the + * stride and other details should be queried from the platform gralloc + * module as needed. The buffer will already be locked for use. + */ + int (*acquire_buffer)(const struct camera2_stream_in_ops *w, + buffer_handle_t** buffer); + /** + * Return a used buffer to the buffer queue for reuse. + */ + int (*release_buffer)(const struct camera2_stream_in_ops *w, + buffer_handle_t* buffer); + +} camera2_stream_in_ops_t; + +/********************************************************************** + * + * Metadata queue management, used for requests sent to HAL module, and for + * frames produced by the HAL. + * + */ + +enum { + CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS = -1 +}; + +/** + * Request input queue protocol: + * + * The framework holds the queue and its contents. At start, the queue is empty. + * + * 1. When the first metadata buffer is placed into the queue, the framework + * signals the device by calling notify_request_queue_not_empty(). + * + * 2. After receiving notify_request_queue_not_empty, the device must call + * dequeue() once it's ready to handle the next buffer. + * + * 3. Once the device has processed a buffer, and is ready for the next buffer, + * it must call dequeue() again instead of waiting for a notification. If + * there are no more buffers available, dequeue() will return NULL. After + * this point, when a buffer becomes available, the framework must call + * notify_request_queue_not_empty() again. If the device receives a NULL + * return from dequeue, it does not need to query the queue again until a + * notify_request_queue_not_empty() call is received from the source. + * + * 4. If the device calls buffer_count() and receives 0, this does not mean that + * the framework will provide a notify_request_queue_not_empty() call. The + * framework will only provide such a notification after the device has + * received a NULL from dequeue, or on initial startup. + * + * 5. The dequeue() call in response to notify_request_queue_not_empty() may be + * on the same thread as the notify_request_queue_not_empty() call, and may + * be performed from within the notify call. + * + * 6. All dequeued request buffers must be returned to the framework by calling + * free_request, including when errors occur, a device flush is requested, or + * when the device is shutting down. + */ +typedef struct camera2_request_queue_src_ops { + /** + * Get the count of request buffers pending in the queue. May return + * CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS if a repeating request (stream + * request) is currently configured. Calling this method has no effect on + * whether the notify_request_queue_not_empty() method will be called by the + * framework. + */ + int (*request_count)(const struct camera2_request_queue_src_ops *q); + + /** + * Get a metadata buffer from the framework. Returns OK if there is no + * error. If the queue is empty, returns NULL in buffer. In that case, the + * device must wait for a notify_request_queue_not_empty() message before + * attempting to dequeue again. Buffers obtained in this way must be + * returned to the framework with free_request(). + */ + int (*dequeue_request)(const struct camera2_request_queue_src_ops *q, + camera_metadata_t **buffer); + /** + * Return a metadata buffer to the framework once it has been used, or if + * an error or shutdown occurs. + */ + int (*free_request)(const struct camera2_request_queue_src_ops *q, + camera_metadata_t *old_buffer); + +} camera2_request_queue_src_ops_t; + +/** + * Frame output queue protocol: + * + * The framework holds the queue and its contents. At start, the queue is empty. + * + * 1. When the device is ready to fill an output metadata frame, it must dequeue + * a metadata buffer of the required size. + * + * 2. It should then fill the metadata buffer, and place it on the frame queue + * using enqueue_frame. The framework takes ownership of the frame. + * + * 3. In case of an error, a request to flush the pipeline, or shutdown, the + * device must return any affected dequeued frames to the framework by + * calling cancel_frame. + */ +typedef struct camera2_frame_queue_dst_ops { + /** + * Get an empty metadata buffer to fill from the framework. The new metadata + * buffer will have room for entries number of metadata entries, plus + * data_bytes worth of extra storage. Frames dequeued here must be returned + * to the framework with either cancel_frame or enqueue_frame. + */ + int (*dequeue_frame)(const struct camera2_frame_queue_dst_ops *q, + size_t entries, size_t data_bytes, + camera_metadata_t **buffer); + + /** + * Return a dequeued metadata buffer to the framework for reuse; do not mark it as + * filled. Use when encountering errors, or flushing the internal request queue. + */ + int (*cancel_frame)(const struct camera2_frame_queue_dst_ops *q, + camera_metadata_t *buffer); + + /** + * Place a completed metadata frame on the frame output queue. + */ + int (*enqueue_frame)(const struct camera2_frame_queue_dst_ops *q, + camera_metadata_t *buffer); + +} camera2_frame_queue_dst_ops_t; + +/********************************************************************** + * + * Notification callback and message definition, and trigger definitions + * + */ + +/** + * Asynchronous notification callback from the HAL, fired for various + * reasons. Only for information independent of frame capture, or that require + * specific timing. The user pointer must be the same one that was passed to the + * device in set_notify_callback(). + */ +typedef void (*camera2_notify_callback)(int32_t msg_type, + int32_t ext1, + int32_t ext2, + int32_t ext3, + void *user); + +/** + * Possible message types for camera2_notify_callback + */ +enum { + /** + * An error has occurred. Argument ext1 contains the error code, and + * ext2 and ext3 contain any error-specific information. + */ + CAMERA2_MSG_ERROR = 0x0001, + /** + * The exposure of a given request has begun. Argument ext1 contains the + * frame number, and ext2 and ext3 contain the low-order and high-order + * bytes of the timestamp for when exposure began. + * (timestamp = (ext3 << 32 | ext2)) + */ + CAMERA2_MSG_SHUTTER = 0x0010, + /** + * The autofocus routine has changed state. Argument ext1 contains the new + * state; the values are the same as those for the metadata field + * android.control.afState. Ext2 contains the latest trigger ID passed to + * trigger_action(CAMERA2_TRIGGER_AUTOFOCUS) or + * trigger_action(CAMERA2_TRIGGER_CANCEL_AUTOFOCUS), or 0 if trigger has not + * been called with either of those actions. + */ + CAMERA2_MSG_AUTOFOCUS = 0x0020, + /** + * The autoexposure routine has changed state. Argument ext1 contains the + * new state; the values are the same as those for the metadata field + * android.control.aeState. Ext2 contains the latest trigger ID value passed to + * trigger_action(CAMERA2_TRIGGER_PRECAPTURE_METERING), or 0 if that method + * has not been called. + */ + CAMERA2_MSG_AUTOEXPOSURE = 0x0021, + /** + * The auto-whitebalance routine has changed state. Argument ext1 contains + * the new state; the values are the same as those for the metadata field + * android.control.awbState. Ext2 contains the latest trigger ID passed to + * trigger_action(CAMERA2_TRIGGER_PRECAPTURE_METERING), or 0 if that method + * has not been called. + */ + CAMERA2_MSG_AUTOWB = 0x0022 +}; + +/** + * Error codes for CAMERA_MSG_ERROR + */ +enum { + /** + * A serious failure occured. Camera device may not work without reboot, and + * no further frames or buffer streams will be produced by the + * device. Device should be treated as closed. + */ + CAMERA2_MSG_ERROR_HARDWARE = 0x0001, + /** + * A serious failure occured. No further frames or buffer streams will be + * produced by the device. Device should be treated as closed. The client + * must reopen the device to use it again. + */ + CAMERA2_MSG_ERROR_DEVICE, + /** + * An error has occurred in processing a request. No output (metadata or + * buffers) will be produced for this request. ext2 contains the frame + * number of the request. Subsequent requests are unaffected, and the device + * remains operational. + */ + CAMERA2_MSG_ERROR_REQUEST, + /** + * An error has occurred in producing an output frame metadata buffer for a + * request, but image buffers for it will still be available. Subsequent + * requests are unaffected, and the device remains operational. ext2 + * contains the frame number of the request. + */ + CAMERA2_MSG_ERROR_FRAME, + /** + * An error has occurred in placing an output buffer into a stream for a + * request. The frame metadata and other buffers may still be + * available. Subsequent requests are unaffected, and the device remains + * operational. ext2 contains the frame number of the request, and ext3 + * contains the stream id. + */ + CAMERA2_MSG_ERROR_STREAM, + /** + * Number of error types + */ + CAMERA2_MSG_NUM_ERRORS +}; + +/** + * Possible trigger ids for trigger_action() + */ +enum { + /** + * Trigger an autofocus cycle. The effect of the trigger depends on the + * autofocus mode in effect when the trigger is received, which is the mode + * listed in the latest capture request to be dequeued by the HAL. If the + * mode is OFF, EDOF, or FIXED, the trigger has no effect. In AUTO, MACRO, + * or CONTINUOUS_* modes, see below for the expected behavior. The state of + * the autofocus cycle can be tracked in android.control.afMode and the + * corresponding notifications. + * + ** + * In AUTO or MACRO mode, the AF state transitions (and notifications) + * when calling with trigger ID = N with the previous ID being K are: + * + * Initial state Transitions + * INACTIVE (K) -> ACTIVE_SCAN (N) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_FOCUSED (K) -> ACTIVE_SCAN (N) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_NOT_FOCUSED (K) -> ACTIVE_SCAN (N) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * ACTIVE_SCAN (K) -> AF_FOCUSED(N) or AF_NOT_FOCUSED(N) + * PASSIVE_SCAN (K) Not used in AUTO/MACRO mode + * PASSIVE_FOCUSED (K) Not used in AUTO/MACRO mode + * + ** + * In CONTINUOUS_PICTURE mode, triggering AF must lock the AF to the current + * lens position and transition the AF state to either AF_FOCUSED or + * NOT_FOCUSED. If a passive scan is underway, that scan must complete and + * then lock the lens position and change AF state. TRIGGER_CANCEL_AUTOFOCUS + * will allow the AF to restart its operation. + * + * Initial state Transitions + * INACTIVE (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_FOCUSED (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_SCAN (K) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_FOCUSED (K) no effect except to change next notification ID to N + * AF_NOT_FOCUSED (K) no effect except to change next notification ID to N + * + ** + * In CONTINUOUS_VIDEO mode, triggering AF must lock the AF to the current + * lens position and transition the AF state to either AF_FOCUSED or + * NOT_FOCUSED. If a passive scan is underway, it must immediately halt, in + * contrast with CONTINUOUS_PICTURE mode. TRIGGER_CANCEL_AUTOFOCUS will + * allow the AF to restart its operation. + * + * Initial state Transitions + * INACTIVE (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_FOCUSED (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_SCAN (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_FOCUSED (K) no effect except to change next notification ID to N + * AF_NOT_FOCUSED (K) no effect except to change next notification ID to N + * + * Ext1 is an ID that must be returned in subsequent auto-focus state change + * notifications through camera2_notify_callback() and stored in + * android.control.afTriggerId. + */ + CAMERA2_TRIGGER_AUTOFOCUS = 0x0001, + /** + * Send a cancel message to the autofocus algorithm. The effect of the + * cancellation depends on the autofocus mode in effect when the trigger is + * received, which is the mode listed in the latest capture request to be + * dequeued by the HAL. If the AF mode is OFF or EDOF, the cancel has no + * effect. For other modes, the lens should return to its default position, + * any current autofocus scan must be canceled, and the AF state should be + * set to INACTIVE. + * + * The state of the autofocus cycle can be tracked in android.control.afMode + * and the corresponding notification. Continuous autofocus modes may resume + * focusing operations thereafter exactly as if the camera had just been set + * to a continuous AF mode. + * + * Ext1 is an ID that must be returned in subsequent auto-focus state change + * notifications through camera2_notify_callback() and stored in + * android.control.afTriggerId. + */ + CAMERA2_TRIGGER_CANCEL_AUTOFOCUS, + /** + * Trigger a pre-capture metering cycle, which may include firing the flash + * to determine proper capture parameters. Typically, this trigger would be + * fired for a half-depress of a camera shutter key, or before a snapshot + * capture in general. The state of the metering cycle can be tracked in + * android.control.aeMode and the corresponding notification. If the + * auto-exposure mode is OFF, the trigger does nothing. + * + * Ext1 is an ID that must be returned in subsequent + * auto-exposure/auto-white balance state change notifications through + * camera2_notify_callback() and stored in android.control.aePrecaptureId. + */ + CAMERA2_TRIGGER_PRECAPTURE_METERING +}; + +/** + * Possible template types for construct_default_request() + */ +enum { + /** + * Standard camera preview operation with 3A on auto. + */ + CAMERA2_TEMPLATE_PREVIEW = 1, + /** + * Standard camera high-quality still capture with 3A and flash on auto. + */ + CAMERA2_TEMPLATE_STILL_CAPTURE, + /** + * Standard video recording plus preview with 3A on auto, torch off. + */ + CAMERA2_TEMPLATE_VIDEO_RECORD, + /** + * High-quality still capture while recording video. Application will + * include preview, video record, and full-resolution YUV or JPEG streams in + * request. Must not cause stuttering on video stream. 3A on auto. + */ + CAMERA2_TEMPLATE_VIDEO_SNAPSHOT, + /** + * Zero-shutter-lag mode. Application will request preview and + * full-resolution data for each frame, and reprocess it to JPEG when a + * still image is requested by user. Settings should provide highest-quality + * full-resolution images without compromising preview frame rate. 3A on + * auto. + */ + CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG, + + /* Total number of templates */ + CAMERA2_TEMPLATE_COUNT +}; + + +/********************************************************************** + * + * Camera device operations + * + */ +typedef struct camera2_device_ops { + + /********************************************************************** + * Request and frame queue setup and management methods + */ + + /** + * Pass in input request queue interface methods. + */ + int (*set_request_queue_src_ops)(const struct camera2_device *, + const camera2_request_queue_src_ops_t *request_src_ops); + + /** + * Notify device that the request queue is no longer empty. Must only be + * called when the first buffer is added a new queue, or after the source + * has returned NULL in response to a dequeue call. + */ + int (*notify_request_queue_not_empty)(const struct camera2_device *); + + /** + * Pass in output frame queue interface methods + */ + int (*set_frame_queue_dst_ops)(const struct camera2_device *, + const camera2_frame_queue_dst_ops_t *frame_dst_ops); + + /** + * Number of camera requests being processed by the device at the moment + * (captures/reprocesses that have had their request dequeued, but have not + * yet been enqueued onto output pipeline(s) ). No streams may be released + * by the framework until the in-progress count is 0. + */ + int (*get_in_progress_count)(const struct camera2_device *); + + /** + * Flush all in-progress captures. This includes all dequeued requests + * (regular or reprocessing) that have not yet placed any outputs into a + * stream or the frame queue. Partially completed captures must be completed + * normally. No new requests may be dequeued from the request queue until + * the flush completes. + */ + int (*flush_captures_in_progress)(const struct camera2_device *); + + /** + * Create a filled-in default request for standard camera use cases. + * + * The device must return a complete request that is configured to meet the + * requested use case, which must be one of the CAMERA2_TEMPLATE_* + * enums. All request control fields must be included, except for + * android.request.outputStreams. + * + * The metadata buffer returned must be allocated with + * allocate_camera_metadata. The framework takes ownership of the buffer. + */ + int (*construct_default_request)(const struct camera2_device *, + int request_template, + camera_metadata_t **request); + + /********************************************************************** + * Stream management + */ + + /** + * allocate_stream: + * + * Allocate a new output stream for use, defined by the output buffer width, + * height, target, and possibly the pixel format. Returns the new stream's + * ID, gralloc usage flags, minimum queue buffer count, and possibly the + * pixel format, on success. Error conditions: + * + * - Requesting a width/height/format combination not listed as + * supported by the sensor's static characteristics + * + * - Asking for too many streams of a given format type (2 bayer raw + * streams, for example). + * + * Input parameters: + * + * - width, height, format: Specification for the buffers to be sent through + * this stream. Format is a value from the HAL_PIXEL_FORMAT_* list. If + * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform + * gralloc module will select a format based on the usage flags provided + * by the camera HAL and the consumer of the stream. The camera HAL should + * inspect the buffers handed to it in the register_stream_buffers call to + * obtain the implementation-specific format if necessary. + * + * - stream_ops: A structure of function pointers for obtaining and queuing + * up buffers for this stream. The underlying stream will be configured + * based on the usage and max_buffers outputs. The methods in this + * structure may not be called until after allocate_stream returns. + * + * Output parameters: + * + * - stream_id: An unsigned integer identifying this stream. This value is + * used in incoming requests to identify the stream, and in releasing the + * stream. + * + * - usage: The gralloc usage mask needed by the HAL device for producing + * the requested type of data. This is used in allocating new gralloc + * buffers for the stream buffer queue. + * + * - max_buffers: The maximum number of buffers the HAL device may need to + * have dequeued at the same time. The device may not dequeue more buffers + * than this value at the same time. + * + */ + int (*allocate_stream)( + const struct camera2_device *, + // inputs + uint32_t width, + uint32_t height, + int format, + const camera2_stream_ops_t *stream_ops, + // outputs + uint32_t *stream_id, + uint32_t *format_actual, // IGNORED, will be removed + uint32_t *usage, + uint32_t *max_buffers); + + /** + * Register buffers for a given stream. This is called after a successful + * allocate_stream call, and before the first request referencing the stream + * is enqueued. This method is intended to allow the HAL device to map or + * otherwise prepare the buffers for later use. num_buffers is guaranteed to + * be at least max_buffers (from allocate_stream), but may be larger. The + * buffers will already be locked for use. At the end of the call, all the + * buffers must be ready to be returned to the queue. If the stream format + * was set to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, the camera HAL should + * inspect the passed-in buffers here to determine any platform-private + * pixel format information. + */ + int (*register_stream_buffers)( + const struct camera2_device *, + uint32_t stream_id, + int num_buffers, + buffer_handle_t *buffers); + + /** + * Release a stream. Returns an error if called when get_in_progress_count + * is non-zero, or if the stream id is invalid. + */ + int (*release_stream)( + const struct camera2_device *, + uint32_t stream_id); + + /** + * allocate_reprocess_stream: + * + * Allocate a new input stream for use, defined by the output buffer width, + * height, and the pixel format. Returns the new stream's ID, gralloc usage + * flags, and required simultaneously acquirable buffer count, on + * success. Error conditions: + * + * - Requesting a width/height/format combination not listed as + * supported by the sensor's static characteristics + * + * - Asking for too many reprocessing streams to be configured at once. + * + * Input parameters: + * + * - width, height, format: Specification for the buffers to be sent through + * this stream. Format must be a value from the HAL_PIXEL_FORMAT_* list. + * + * - reprocess_stream_ops: A structure of function pointers for acquiring + * and releasing buffers for this stream. The underlying stream will be + * configured based on the usage and max_buffers outputs. + * + * Output parameters: + * + * - stream_id: An unsigned integer identifying this stream. This value is + * used in incoming requests to identify the stream, and in releasing the + * stream. These ids are numbered separately from the input stream ids. + * + * - consumer_usage: The gralloc usage mask needed by the HAL device for + * consuming the requested type of data. This is used in allocating new + * gralloc buffers for the stream buffer queue. + * + * - max_buffers: The maximum number of buffers the HAL device may need to + * have acquired at the same time. The device may not have more buffers + * acquired at the same time than this value. + * + */ + int (*allocate_reprocess_stream)(const struct camera2_device *, + uint32_t width, + uint32_t height, + uint32_t format, + const camera2_stream_in_ops_t *reprocess_stream_ops, + // outputs + uint32_t *stream_id, + uint32_t *consumer_usage, + uint32_t *max_buffers); + + /** + * allocate_reprocess_stream_from_stream: + * + * Allocate a new input stream for use, which will use the buffers allocated + * for an existing output stream. That is, after the HAL enqueues a buffer + * onto the output stream, it may see that same buffer handed to it from + * this input reprocessing stream. After the HAL releases the buffer back to + * the reprocessing stream, it will be returned to the output queue for + * reuse. + * + * Error conditions: + * + * - Using an output stream of unsuitable size/format for the basis of the + * reprocessing stream. + * + * - Attempting to allocatee too many reprocessing streams at once. + * + * Input parameters: + * + * - output_stream_id: The ID of an existing output stream which has + * a size and format suitable for reprocessing. + * + * - reprocess_stream_ops: A structure of function pointers for acquiring + * and releasing buffers for this stream. The underlying stream will use + * the same graphics buffer handles as the output stream uses. + * + * Output parameters: + * + * - stream_id: An unsigned integer identifying this stream. This value is + * used in incoming requests to identify the stream, and in releasing the + * stream. These ids are numbered separately from the input stream ids. + * + * The HAL client must always release the reprocessing stream before it + * releases the output stream it is based on. + * + */ + int (*allocate_reprocess_stream_from_stream)(const struct camera2_device *, + uint32_t output_stream_id, + const camera2_stream_in_ops_t *reprocess_stream_ops, + // outputs + uint32_t *stream_id); + + /** + * Release a reprocessing stream. Returns an error if called when + * get_in_progress_count is non-zero, or if the stream id is not + * valid. + */ + int (*release_reprocess_stream)( + const struct camera2_device *, + uint32_t stream_id); + + /********************************************************************** + * Miscellaneous methods + */ + + /** + * Trigger asynchronous activity. This is used for triggering special + * behaviors of the camera 3A routines when they are in use. See the + * documentation for CAMERA2_TRIGGER_* above for details of the trigger ids + * and their arguments. + */ + int (*trigger_action)(const struct camera2_device *, + uint32_t trigger_id, + int32_t ext1, + int32_t ext2); + + /** + * Notification callback setup + */ + int (*set_notify_callback)(const struct camera2_device *, + camera2_notify_callback notify_cb, + void *user); + + /** + * Get methods to query for vendor extension metadata tag infomation. May + * set ops to NULL if no vendor extension tags are defined. + */ + int (*get_metadata_vendor_tag_ops)(const struct camera2_device*, + vendor_tag_query_ops_t **ops); + + /** + * Dump state of the camera hardware + */ + int (*dump)(const struct camera2_device *, int fd); + + /** + * Get device-instance-specific metadata. This metadata must be constant for + * a single instance of the camera device, but may be different between + * open() calls. The returned camera_metadata pointer must be valid until + * the device close() method is called. + * + * Version information: + * + * CAMERA_DEVICE_API_VERSION_2_0: + * + * Not available. Framework may not access this function pointer. + * + * CAMERA_DEVICE_API_VERSION_2_1: + * + * Valid. Can be called by the framework. + * + */ + int (*get_instance_metadata)(const struct camera2_device *, + camera_metadata **instance_metadata); + +} camera2_device_ops_t; + +/********************************************************************** + * + * Camera device definition + * + */ +typedef struct camera2_device { + /** + * common.version must equal CAMERA_DEVICE_API_VERSION_2_0 to identify + * this device as implementing version 2.0 of the camera device HAL. + */ + hw_device_t common; + camera2_device_ops_t *ops; + void *priv; +} camera2_device_t; + +__END_DECLS + +#endif /* #ifdef ANDROID_INCLUDE_CAMERA2_H */
diff --git a/libhardware/include/hardware/camera3.h b/libhardware/include/hardware/camera3.h new file mode 100644 index 0000000..3ef6d6f --- /dev/null +++ b/libhardware/include/hardware/camera3.h
@@ -0,0 +1,3077 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_CAMERA3_H +#define ANDROID_INCLUDE_CAMERA3_H + +#include <system/camera_metadata.h> +#include "camera_common.h" + +/** + * Camera device HAL 3.3 [ CAMERA_DEVICE_API_VERSION_3_3 ] + * + * This is the current recommended version of the camera device HAL. + * + * Supports the android.hardware.Camera API, and as of v3.2, the + * android.hardware.camera2 API in LIMITED or FULL modes. + * + * Camera devices that support this version of the HAL must return + * CAMERA_DEVICE_API_VERSION_3_3 in camera_device_t.common.version and in + * camera_info_t.device_version (from camera_module_t.get_camera_info). + * + * CAMERA_DEVICE_API_VERSION_3_3: + * Camera modules that may contain version 3.3 devices must implement at + * least version 2.2 of the camera module interface (as defined by + * camera_module_t.common.module_api_version). + * + * CAMERA_DEVICE_API_VERSION_3_2: + * Camera modules that may contain version 3.2 devices must implement at + * least version 2.2 of the camera module interface (as defined by + * camera_module_t.common.module_api_version). + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * Camera modules that may contain version 3.1 (or 3.0) devices must + * implement at least version 2.0 of the camera module interface + * (as defined by camera_module_t.common.module_api_version). + * + * See camera_common.h for more versioning details. + * + * Documentation index: + * S1. Version history + * S2. Startup and operation sequencing + * S3. Operational modes + * S4. 3A modes and state machines + * S5. Cropping + * S6. Error management + * S7. Key Performance Indicator (KPI) glossary + * S8. Sample Use Cases + * S9. Notes on Controls and Metadata + * S10. Reprocessing flow and controls + */ + +/** + * S1. Version history: + * + * 1.0: Initial Android camera HAL (Android 4.0) [camera.h]: + * + * - Converted from C++ CameraHardwareInterface abstraction layer. + * + * - Supports android.hardware.Camera API. + * + * 2.0: Initial release of expanded-capability HAL (Android 4.2) [camera2.h]: + * + * - Sufficient for implementing existing android.hardware.Camera API. + * + * - Allows for ZSL queue in camera service layer + * + * - Not tested for any new features such manual capture control, Bayer RAW + * capture, reprocessing of RAW data. + * + * 3.0: First revision of expanded-capability HAL: + * + * - Major version change since the ABI is completely different. No change to + * the required hardware capabilities or operational model from 2.0. + * + * - Reworked input request and stream queue interfaces: Framework calls into + * HAL with next request and stream buffers already dequeued. Sync framework + * support is included, necessary for efficient implementations. + * + * - Moved triggers into requests, most notifications into results. + * + * - Consolidated all callbacks into framework into one structure, and all + * setup methods into a single initialize() call. + * + * - Made stream configuration into a single call to simplify stream + * management. Bidirectional streams replace STREAM_FROM_STREAM construct. + * + * - Limited mode semantics for older/limited hardware devices. + * + * 3.1: Minor revision of expanded-capability HAL: + * + * - configure_streams passes consumer usage flags to the HAL. + * + * - flush call to drop all in-flight requests/buffers as fast as possible. + * + * 3.2: Minor revision of expanded-capability HAL: + * + * - Deprecates get_metadata_vendor_tag_ops. Please use get_vendor_tag_ops + * in camera_common.h instead. + * + * - register_stream_buffers deprecated. All gralloc buffers provided + * by framework to HAL in process_capture_request may be new at any time. + * + * - add partial result support. process_capture_result may be called + * multiple times with a subset of the available result before the full + * result is available. + * + * - add manual template to camera3_request_template. The applications may + * use this template to control the capture settings directly. + * + * - Rework the bidirectional and input stream specifications. + * + * - change the input buffer return path. The buffer is returned in + * process_capture_result instead of process_capture_request. + * + * 3.3: Minor revision of expanded-capability HAL: + * + * - OPAQUE and YUV reprocessing API updates. + * + * - Basic support for depth output buffers. + * + * - Addition of data_space field to camera3_stream_t. + * + * - Addition of rotation field to camera3_stream_t. + * + * - Addition of camera3 stream configuration operation mode to camera3_stream_configuration_t + * + */ + +/** + * S2. Startup and general expected operation sequence: + * + * 1. Framework calls camera_module_t->common.open(), which returns a + * hardware_device_t structure. + * + * 2. Framework inspects the hardware_device_t->version field, and instantiates + * the appropriate handler for that version of the camera hardware device. In + * case the version is CAMERA_DEVICE_API_VERSION_3_0, the device is cast to + * a camera3_device_t. + * + * 3. Framework calls camera3_device_t->ops->initialize() with the framework + * callback function pointers. This will only be called this one time after + * open(), before any other functions in the ops structure are called. + * + * 4. The framework calls camera3_device_t->ops->configure_streams() with a list + * of input/output streams to the HAL device. + * + * 5. <= CAMERA_DEVICE_API_VERSION_3_1: + * + * The framework allocates gralloc buffers and calls + * camera3_device_t->ops->register_stream_buffers() for at least one of the + * output streams listed in configure_streams. The same stream is registered + * only once. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * camera3_device_t->ops->register_stream_buffers() is not called and must + * be NULL. + * + * 6. The framework requests default settings for some number of use cases with + * calls to camera3_device_t->ops->construct_default_request_settings(). This + * may occur any time after step 3. + * + * 7. The framework constructs and sends the first capture request to the HAL, + * with settings based on one of the sets of default settings, and with at + * least one output stream, which has been registered earlier by the + * framework. This is sent to the HAL with + * camera3_device_t->ops->process_capture_request(). The HAL must block the + * return of this call until it is ready for the next request to be sent. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * The buffer_handle_t provided in the camera3_stream_buffer_t array + * in the camera3_capture_request_t may be new and never-before-seen + * by the HAL on any given new request. + * + * 8. The framework continues to submit requests, and call + * construct_default_request_settings to get default settings buffers for + * other use cases. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * The framework may call register_stream_buffers() at this time for + * not-yet-registered streams. + * + * 9. When the capture of a request begins (sensor starts exposing for the + * capture) or processing a reprocess request begins, the HAL + * calls camera3_callback_ops_t->notify() with the SHUTTER event, including + * the frame number and the timestamp for start of exposure. For a reprocess + * request, the timestamp must be the start of exposure of the input image + * which can be looked up with android.sensor.timestamp from + * camera3_capture_request_t.settings when process_capture_request() is + * called. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * This notify call must be made before the first call to + * process_capture_result() for that frame number. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * The camera3_callback_ops_t->notify() call with the SHUTTER event should + * be made as early as possible since the framework will be unable to + * deliver gralloc buffers to the application layer (for that frame) until + * it has a valid timestamp for the start of exposure (or the input image's + * start of exposure for a reprocess request). + * + * Both partial metadata results and the gralloc buffers may be sent to the + * framework at any time before or after the SHUTTER event. + * + * 10. After some pipeline delay, the HAL begins to return completed captures to + * the framework with camera3_callback_ops_t->process_capture_result(). These + * are returned in the same order as the requests were submitted. Multiple + * requests can be in flight at once, depending on the pipeline depth of the + * camera HAL device. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Once a buffer is returned by process_capture_result as part of the + * camera3_stream_buffer_t array, and the fence specified by release_fence + * has been signaled (this is a no-op for -1 fences), the ownership of that + * buffer is considered to be transferred back to the framework. After that, + * the HAL must no longer retain that particular buffer, and the + * framework may clean up the memory for it immediately. + * + * process_capture_result may be called multiple times for a single frame, + * each time with a new disjoint piece of metadata and/or set of gralloc + * buffers. The framework will accumulate these partial metadata results + * into one result. + * + * In particular, it is legal for a process_capture_result to be called + * simultaneously for both a frame N and a frame N+1 as long as the + * above rule holds for gralloc buffers (both input and output). + * + * 11. After some time, the framework may stop submitting new requests, wait for + * the existing captures to complete (all buffers filled, all results + * returned), and then call configure_streams() again. This resets the camera + * hardware and pipeline for a new set of input/output streams. Some streams + * may be reused from the previous configuration; if these streams' buffers + * had already been registered with the HAL, they will not be registered + * again. The framework then continues from step 7, if at least one + * registered output stream remains (otherwise, step 5 is required first). + * + * 12. Alternatively, the framework may call camera3_device_t->common->close() + * to end the camera session. This may be called at any time when no other + * calls from the framework are active, although the call may block until all + * in-flight captures have completed (all results returned, all buffers + * filled). After the close call returns, no more calls to the + * camera3_callback_ops_t functions are allowed from the HAL. Once the + * close() call is underway, the framework may not call any other HAL device + * functions. + * + * 13. In case of an error or other asynchronous event, the HAL must call + * camera3_callback_ops_t->notify() with the appropriate error/event + * message. After returning from a fatal device-wide error notification, the + * HAL should act as if close() had been called on it. However, the HAL must + * either cancel or complete all outstanding captures before calling + * notify(), so that once notify() is called with a fatal error, the + * framework will not receive further callbacks from the device. Methods + * besides close() should return -ENODEV or NULL after the notify() method + * returns from a fatal error message. + */ + +/** + * S3. Operational modes: + * + * The camera 3 HAL device can implement one of two possible operational modes; + * limited and full. Full support is expected from new higher-end + * devices. Limited mode has hardware requirements roughly in line with those + * for a camera HAL device v1 implementation, and is expected from older or + * inexpensive devices. Full is a strict superset of limited, and they share the + * same essential operational flow, as documented above. + * + * The HAL must indicate its level of support with the + * android.info.supportedHardwareLevel static metadata entry, with 0 indicating + * limited mode, and 1 indicating full mode support. + * + * Roughly speaking, limited-mode devices do not allow for application control + * of capture settings (3A control only), high-rate capture of high-resolution + * images, raw sensor readout, or support for YUV output streams above maximum + * recording resolution (JPEG only for large images). + * + * ** Details of limited mode behavior: + * + * - Limited-mode devices do not need to implement accurate synchronization + * between capture request settings and the actual image data + * captured. Instead, changes to settings may take effect some time in the + * future, and possibly not for the same output frame for each settings + * entry. Rapid changes in settings may result in some settings never being + * used for a capture. However, captures that include high-resolution output + * buffers ( > 1080p ) have to use the settings as specified (but see below + * for processing rate). + * + * - Limited-mode devices do not need to support most of the + * settings/result/static info metadata. Specifically, only the following settings + * are expected to be consumed or produced by a limited-mode HAL device: + * + * android.control.aeAntibandingMode (controls and dynamic) + * android.control.aeExposureCompensation (controls and dynamic) + * android.control.aeLock (controls and dynamic) + * android.control.aeMode (controls and dynamic) + * android.control.aeRegions (controls and dynamic) + * android.control.aeTargetFpsRange (controls and dynamic) + * android.control.aePrecaptureTrigger (controls and dynamic) + * android.control.afMode (controls and dynamic) + * android.control.afRegions (controls and dynamic) + * android.control.awbLock (controls and dynamic) + * android.control.awbMode (controls and dynamic) + * android.control.awbRegions (controls and dynamic) + * android.control.captureIntent (controls and dynamic) + * android.control.effectMode (controls and dynamic) + * android.control.mode (controls and dynamic) + * android.control.sceneMode (controls and dynamic) + * android.control.videoStabilizationMode (controls and dynamic) + * android.control.aeAvailableAntibandingModes (static) + * android.control.aeAvailableModes (static) + * android.control.aeAvailableTargetFpsRanges (static) + * android.control.aeCompensationRange (static) + * android.control.aeCompensationStep (static) + * android.control.afAvailableModes (static) + * android.control.availableEffects (static) + * android.control.availableSceneModes (static) + * android.control.availableVideoStabilizationModes (static) + * android.control.awbAvailableModes (static) + * android.control.maxRegions (static) + * android.control.sceneModeOverrides (static) + * android.control.aeState (dynamic) + * android.control.afState (dynamic) + * android.control.awbState (dynamic) + * + * android.flash.mode (controls and dynamic) + * android.flash.info.available (static) + * + * android.info.supportedHardwareLevel (static) + * + * android.jpeg.gpsCoordinates (controls and dynamic) + * android.jpeg.gpsProcessingMethod (controls and dynamic) + * android.jpeg.gpsTimestamp (controls and dynamic) + * android.jpeg.orientation (controls and dynamic) + * android.jpeg.quality (controls and dynamic) + * android.jpeg.thumbnailQuality (controls and dynamic) + * android.jpeg.thumbnailSize (controls and dynamic) + * android.jpeg.availableThumbnailSizes (static) + * android.jpeg.maxSize (static) + * + * android.lens.info.minimumFocusDistance (static) + * + * android.request.id (controls and dynamic) + * + * android.scaler.cropRegion (controls and dynamic) + * android.scaler.availableStreamConfigurations (static) + * android.scaler.availableMinFrameDurations (static) + * android.scaler.availableStallDurations (static) + * android.scaler.availableMaxDigitalZoom (static) + * android.scaler.maxDigitalZoom (static) + * android.scaler.croppingType (static) + * + * android.sensor.orientation (static) + * android.sensor.timestamp (dynamic) + * + * android.statistics.faceDetectMode (controls and dynamic) + * android.statistics.info.availableFaceDetectModes (static) + * android.statistics.faceIds (dynamic) + * android.statistics.faceLandmarks (dynamic) + * android.statistics.faceRectangles (dynamic) + * android.statistics.faceScores (dynamic) + * + * android.sync.frameNumber (dynamic) + * android.sync.maxLatency (static) + * + * - Captures in limited mode that include high-resolution (> 1080p) output + * buffers may block in process_capture_request() until all the output buffers + * have been filled. A full-mode HAL device must process sequences of + * high-resolution requests at the rate indicated in the static metadata for + * that pixel format. The HAL must still call process_capture_result() to + * provide the output; the framework must simply be prepared for + * process_capture_request() to block until after process_capture_result() for + * that request completes for high-resolution captures for limited-mode + * devices. + * + * - Full-mode devices must support below additional capabilities: + * - 30fps at maximum resolution is preferred, more than 20fps is required. + * - Per frame control (android.sync.maxLatency == PER_FRAME_CONTROL). + * - Sensor manual control metadata. See MANUAL_SENSOR defined in + * android.request.availableCapabilities. + * - Post-processing manual control metadata. See MANUAL_POST_PROCESSING defined + * in android.request.availableCapabilities. + * + */ + +/** + * S4. 3A modes and state machines: + * + * While the actual 3A algorithms are up to the HAL implementation, a high-level + * state machine description is defined by the HAL interface, to allow the HAL + * device and the framework to communicate about the current state of 3A, and to + * trigger 3A events. + * + * When the device is opened, all the individual 3A states must be + * STATE_INACTIVE. Stream configuration does not reset 3A. For example, locked + * focus must be maintained across the configure() call. + * + * Triggering a 3A action involves simply setting the relevant trigger entry in + * the settings for the next request to indicate start of trigger. For example, + * the trigger for starting an autofocus scan is setting the entry + * ANDROID_CONTROL_AF_TRIGGER to ANDROID_CONTROL_AF_TRIGGER_START for one + * request, and cancelling an autofocus scan is triggered by setting + * ANDROID_CONTROL_AF_TRIGGER to ANDROID_CONTRL_AF_TRIGGER_CANCEL. Otherwise, + * the entry will not exist, or be set to ANDROID_CONTROL_AF_TRIGGER_IDLE. Each + * request with a trigger entry set to a non-IDLE value will be treated as an + * independent triggering event. + * + * At the top level, 3A is controlled by the ANDROID_CONTROL_MODE setting, which + * selects between no 3A (ANDROID_CONTROL_MODE_OFF), normal AUTO mode + * (ANDROID_CONTROL_MODE_AUTO), and using the scene mode setting + * (ANDROID_CONTROL_USE_SCENE_MODE). + * + * - In OFF mode, each of the individual AE/AF/AWB modes are effectively OFF, + * and none of the capture controls may be overridden by the 3A routines. + * + * - In AUTO mode, Auto-focus, auto-exposure, and auto-whitebalance all run + * their own independent algorithms, and have their own mode, state, and + * trigger metadata entries, as listed in the next section. + * + * - In USE_SCENE_MODE, the value of the ANDROID_CONTROL_SCENE_MODE entry must + * be used to determine the behavior of 3A routines. In SCENE_MODEs other than + * FACE_PRIORITY, the HAL must override the values of + * ANDROId_CONTROL_AE/AWB/AF_MODE to be the mode it prefers for the selected + * SCENE_MODE. For example, the HAL may prefer SCENE_MODE_NIGHT to use + * CONTINUOUS_FOCUS AF mode. Any user selection of AE/AWB/AF_MODE when scene + * must be ignored for these scene modes. + * + * - For SCENE_MODE_FACE_PRIORITY, the AE/AWB/AF_MODE controls work as in + * ANDROID_CONTROL_MODE_AUTO, but the 3A routines must bias toward metering + * and focusing on any detected faces in the scene. + * + * S4.1. Auto-focus settings and result entries: + * + * Main metadata entries: + * + * ANDROID_CONTROL_AF_MODE: Control for selecting the current autofocus + * mode. Set by the framework in the request settings. + * + * AF_MODE_OFF: AF is disabled; the framework/app directly controls lens + * position. + * + * AF_MODE_AUTO: Single-sweep autofocus. No lens movement unless AF is + * triggered. + * + * AF_MODE_MACRO: Single-sweep up-close autofocus. No lens movement unless + * AF is triggered. + * + * AF_MODE_CONTINUOUS_VIDEO: Smooth continuous focusing, for recording + * video. Triggering immediately locks focus in current + * position. Canceling resumes cotinuous focusing. + * + * AF_MODE_CONTINUOUS_PICTURE: Fast continuous focusing, for + * zero-shutter-lag still capture. Triggering locks focus once currently + * active sweep concludes. Canceling resumes continuous focusing. + * + * AF_MODE_EDOF: Advanced extended depth of field focusing. There is no + * autofocus scan, so triggering one or canceling one has no effect. + * Images are focused automatically by the HAL. + * + * ANDROID_CONTROL_AF_STATE: Dynamic metadata describing the current AF + * algorithm state, reported by the HAL in the result metadata. + * + * AF_STATE_INACTIVE: No focusing has been done, or algorithm was + * reset. Lens is not moving. Always the state for MODE_OFF or MODE_EDOF. + * When the device is opened, it must start in this state. + * + * AF_STATE_PASSIVE_SCAN: A continuous focus algorithm is currently scanning + * for good focus. The lens is moving. + * + * AF_STATE_PASSIVE_FOCUSED: A continuous focus algorithm believes it is + * well focused. The lens is not moving. The HAL may spontaneously leave + * this state. + * + * AF_STATE_PASSIVE_UNFOCUSED: A continuous focus algorithm believes it is + * not well focused. The lens is not moving. The HAL may spontaneously + * leave this state. + * + * AF_STATE_ACTIVE_SCAN: A scan triggered by the user is underway. + * + * AF_STATE_FOCUSED_LOCKED: The AF algorithm believes it is focused. The + * lens is not moving. + * + * AF_STATE_NOT_FOCUSED_LOCKED: The AF algorithm has been unable to + * focus. The lens is not moving. + * + * ANDROID_CONTROL_AF_TRIGGER: Control for starting an autofocus scan, the + * meaning of which is mode- and state- dependent. Set by the framework in + * the request settings. + * + * AF_TRIGGER_IDLE: No current trigger. + * + * AF_TRIGGER_START: Trigger start of AF scan. Effect is mode and state + * dependent. + * + * AF_TRIGGER_CANCEL: Cancel current AF scan if any, and reset algorithm to + * default. + * + * Additional metadata entries: + * + * ANDROID_CONTROL_AF_REGIONS: Control for selecting the regions of the FOV + * that should be used to determine good focus. This applies to all AF + * modes that scan for focus. Set by the framework in the request + * settings. + * + * S4.2. Auto-exposure settings and result entries: + * + * Main metadata entries: + * + * ANDROID_CONTROL_AE_MODE: Control for selecting the current auto-exposure + * mode. Set by the framework in the request settings. + * + * AE_MODE_OFF: Autoexposure is disabled; the user controls exposure, gain, + * frame duration, and flash. + * + * AE_MODE_ON: Standard autoexposure, with flash control disabled. User may + * set flash to fire or to torch mode. + * + * AE_MODE_ON_AUTO_FLASH: Standard autoexposure, with flash on at HAL's + * discretion for precapture and still capture. User control of flash + * disabled. + * + * AE_MODE_ON_ALWAYS_FLASH: Standard autoexposure, with flash always fired + * for capture, and at HAL's discretion for precapture.. User control of + * flash disabled. + * + * AE_MODE_ON_AUTO_FLASH_REDEYE: Standard autoexposure, with flash on at + * HAL's discretion for precapture and still capture. Use a flash burst + * at end of precapture sequence to reduce redeye in the final + * picture. User control of flash disabled. + * + * ANDROID_CONTROL_AE_STATE: Dynamic metadata describing the current AE + * algorithm state, reported by the HAL in the result metadata. + * + * AE_STATE_INACTIVE: Initial AE state after mode switch. When the device is + * opened, it must start in this state. + * + * AE_STATE_SEARCHING: AE is not converged to a good value, and is adjusting + * exposure parameters. + * + * AE_STATE_CONVERGED: AE has found good exposure values for the current + * scene, and the exposure parameters are not changing. HAL may + * spontaneously leave this state to search for better solution. + * + * AE_STATE_LOCKED: AE has been locked with the AE_LOCK control. Exposure + * values are not changing. + * + * AE_STATE_FLASH_REQUIRED: The HAL has converged exposure, but believes + * flash is required for a sufficiently bright picture. Used for + * determining if a zero-shutter-lag frame can be used. + * + * AE_STATE_PRECAPTURE: The HAL is in the middle of a precapture + * sequence. Depending on AE mode, this mode may involve firing the + * flash for metering, or a burst of flash pulses for redeye reduction. + * + * ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER: Control for starting a metering + * sequence before capturing a high-quality image. Set by the framework in + * the request settings. + * + * PRECAPTURE_TRIGGER_IDLE: No current trigger. + * + * PRECAPTURE_TRIGGER_START: Start a precapture sequence. The HAL should + * use the subsequent requests to measure good exposure/white balance + * for an upcoming high-resolution capture. + * + * Additional metadata entries: + * + * ANDROID_CONTROL_AE_LOCK: Control for locking AE controls to their current + * values + * + * ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION: Control for adjusting AE + * algorithm target brightness point. + * + * ANDROID_CONTROL_AE_TARGET_FPS_RANGE: Control for selecting the target frame + * rate range for the AE algorithm. The AE routine cannot change the frame + * rate to be outside these bounds. + * + * ANDROID_CONTROL_AE_REGIONS: Control for selecting the regions of the FOV + * that should be used to determine good exposure levels. This applies to + * all AE modes besides OFF. + * + * S4.3. Auto-whitebalance settings and result entries: + * + * Main metadata entries: + * + * ANDROID_CONTROL_AWB_MODE: Control for selecting the current white-balance + * mode. + * + * AWB_MODE_OFF: Auto-whitebalance is disabled. User controls color matrix. + * + * AWB_MODE_AUTO: Automatic white balance is enabled; 3A controls color + * transform, possibly using more complex transforms than a simple + * matrix. + * + * AWB_MODE_INCANDESCENT: Fixed white balance settings good for indoor + * incandescent (tungsten) lighting, roughly 2700K. + * + * AWB_MODE_FLUORESCENT: Fixed white balance settings good for fluorescent + * lighting, roughly 5000K. + * + * AWB_MODE_WARM_FLUORESCENT: Fixed white balance settings good for + * fluorescent lighting, roughly 3000K. + * + * AWB_MODE_DAYLIGHT: Fixed white balance settings good for daylight, + * roughly 5500K. + * + * AWB_MODE_CLOUDY_DAYLIGHT: Fixed white balance settings good for clouded + * daylight, roughly 6500K. + * + * AWB_MODE_TWILIGHT: Fixed white balance settings good for + * near-sunset/sunrise, roughly 15000K. + * + * AWB_MODE_SHADE: Fixed white balance settings good for areas indirectly + * lit by the sun, roughly 7500K. + * + * ANDROID_CONTROL_AWB_STATE: Dynamic metadata describing the current AWB + * algorithm state, reported by the HAL in the result metadata. + * + * AWB_STATE_INACTIVE: Initial AWB state after mode switch. When the device + * is opened, it must start in this state. + * + * AWB_STATE_SEARCHING: AWB is not converged to a good value, and is + * changing color adjustment parameters. + * + * AWB_STATE_CONVERGED: AWB has found good color adjustment values for the + * current scene, and the parameters are not changing. HAL may + * spontaneously leave this state to search for better solution. + * + * AWB_STATE_LOCKED: AWB has been locked with the AWB_LOCK control. Color + * adjustment values are not changing. + * + * Additional metadata entries: + * + * ANDROID_CONTROL_AWB_LOCK: Control for locking AWB color adjustments to + * their current values. + * + * ANDROID_CONTROL_AWB_REGIONS: Control for selecting the regions of the FOV + * that should be used to determine good color balance. This applies only + * to auto-WB mode. + * + * S4.4. General state machine transition notes + * + * Switching between AF, AE, or AWB modes always resets the algorithm's state + * to INACTIVE. Similarly, switching between CONTROL_MODE or + * CONTROL_SCENE_MODE if CONTROL_MODE == USE_SCENE_MODE resets all the + * algorithm states to INACTIVE. + * + * The tables below are per-mode. + * + * S4.5. AF state machines + * + * when enabling AF or changing AF mode + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| Any | AF mode change| INACTIVE | | + *+--------------------+---------------+--------------------+------------------+ + * + * mode = AF_MODE_OFF or AF_MODE_EDOF + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | | INACTIVE | Never changes | + *+--------------------+---------------+--------------------+------------------+ + * + * mode = AF_MODE_AUTO or AF_MODE_MACRO + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | AF_TRIGGER | ACTIVE_SCAN | Start AF sweep | + *| | | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| ACTIVE_SCAN | AF sweep done | FOCUSED_LOCKED | If AF successful | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| ACTIVE_SCAN | AF sweep done | NOT_FOCUSED_LOCKED | If AF successful | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| ACTIVE_SCAN | AF_CANCEL | INACTIVE | Cancel/reset AF | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| FOCUSED_LOCKED | AF_CANCEL | INACTIVE | Cancel/reset AF | + *+--------------------+---------------+--------------------+------------------+ + *| FOCUSED_LOCKED | AF_TRIGGER | ACTIVE_SCAN | Start new sweep | + *| | | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| NOT_FOCUSED_LOCKED | AF_CANCEL | INACTIVE | Cancel/reset AF | + *+--------------------+---------------+--------------------+------------------+ + *| NOT_FOCUSED_LOCKED | AF_TRIGGER | ACTIVE_SCAN | Start new sweep | + *| | | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| All states | mode change | INACTIVE | | + *+--------------------+---------------+--------------------+------------------+ + * + * mode = AF_MODE_CONTINUOUS_VIDEO + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | HAL initiates | PASSIVE_SCAN | Start AF scan | + *| | new scan | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | AF_TRIGGER | NOT_FOCUSED_LOCKED | AF state query | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | HAL completes | PASSIVE_FOCUSED | End AF scan | + *| | current scan | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | HAL fails | PASSIVE_UNFOCUSED | End AF scan | + *| | current scan | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | AF_TRIGGER | FOCUSED_LOCKED | Immediate trans. | + *| | | | if focus is good | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | AF_TRIGGER | NOT_FOCUSED_LOCKED | Immediate trans. | + *| | | | if focus is bad | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | AF_CANCEL | INACTIVE | Reset lens | + *| | | | position | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_FOCUSED | HAL initiates | PASSIVE_SCAN | Start AF scan | + *| | new scan | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_UNFOCUSED | HAL initiates | PASSIVE_SCAN | Start AF scan | + *| | new scan | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_FOCUSED | AF_TRIGGER | FOCUSED_LOCKED | Immediate trans. | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_UNFOCUSED | AF_TRIGGER | NOT_FOCUSED_LOCKED | Immediate trans. | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| FOCUSED_LOCKED | AF_TRIGGER | FOCUSED_LOCKED | No effect | + *+--------------------+---------------+--------------------+------------------+ + *| FOCUSED_LOCKED | AF_CANCEL | INACTIVE | Restart AF scan | + *+--------------------+---------------+--------------------+------------------+ + *| NOT_FOCUSED_LOCKED | AF_TRIGGER | NOT_FOCUSED_LOCKED | No effect | + *+--------------------+---------------+--------------------+------------------+ + *| NOT_FOCUSED_LOCKED | AF_CANCEL | INACTIVE | Restart AF scan | + *+--------------------+---------------+--------------------+------------------+ + * + * mode = AF_MODE_CONTINUOUS_PICTURE + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | HAL initiates | PASSIVE_SCAN | Start AF scan | + *| | new scan | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | AF_TRIGGER | NOT_FOCUSED_LOCKED | AF state query | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | HAL completes | PASSIVE_FOCUSED | End AF scan | + *| | current scan | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | HAL fails | PASSIVE_UNFOCUSED | End AF scan | + *| | current scan | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | AF_TRIGGER | FOCUSED_LOCKED | Eventual trans. | + *| | | | once focus good | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | AF_TRIGGER | NOT_FOCUSED_LOCKED | Eventual trans. | + *| | | | if cannot focus | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_SCAN | AF_CANCEL | INACTIVE | Reset lens | + *| | | | position | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_FOCUSED | HAL initiates | PASSIVE_SCAN | Start AF scan | + *| | new scan | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_UNFOCUSED | HAL initiates | PASSIVE_SCAN | Start AF scan | + *| | new scan | | Lens now moving | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_FOCUSED | AF_TRIGGER | FOCUSED_LOCKED | Immediate trans. | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| PASSIVE_UNFOCUSED | AF_TRIGGER | NOT_FOCUSED_LOCKED | Immediate trans. | + *| | | | Lens now locked | + *+--------------------+---------------+--------------------+------------------+ + *| FOCUSED_LOCKED | AF_TRIGGER | FOCUSED_LOCKED | No effect | + *+--------------------+---------------+--------------------+------------------+ + *| FOCUSED_LOCKED | AF_CANCEL | INACTIVE | Restart AF scan | + *+--------------------+---------------+--------------------+------------------+ + *| NOT_FOCUSED_LOCKED | AF_TRIGGER | NOT_FOCUSED_LOCKED | No effect | + *+--------------------+---------------+--------------------+------------------+ + *| NOT_FOCUSED_LOCKED | AF_CANCEL | INACTIVE | Restart AF scan | + *+--------------------+---------------+--------------------+------------------+ + * + * S4.6. AE and AWB state machines + * + * The AE and AWB state machines are mostly identical. AE has additional + * FLASH_REQUIRED and PRECAPTURE states. So rows below that refer to those two + * states should be ignored for the AWB state machine. + * + * when enabling AE/AWB or changing AE/AWB mode + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| Any | mode change | INACTIVE | | + *+--------------------+---------------+--------------------+------------------+ + * + * mode = AE_MODE_OFF / AWB mode not AUTO + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | | INACTIVE | AE/AWB disabled | + *+--------------------+---------------+--------------------+------------------+ + * + * mode = AE_MODE_ON_* / AWB_MODE_AUTO + *| state | trans. cause | new state | notes | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | HAL initiates | SEARCHING | | + *| | AE/AWB scan | | | + *+--------------------+---------------+--------------------+------------------+ + *| INACTIVE | AE/AWB_LOCK | LOCKED | values locked | + *| | on | | | + *+--------------------+---------------+--------------------+------------------+ + *| SEARCHING | HAL finishes | CONVERGED | good values, not | + *| | AE/AWB scan | | changing | + *+--------------------+---------------+--------------------+------------------+ + *| SEARCHING | HAL finishes | FLASH_REQUIRED | converged but too| + *| | AE scan | | dark w/o flash | + *+--------------------+---------------+--------------------+------------------+ + *| SEARCHING | AE/AWB_LOCK | LOCKED | values locked | + *| | on | | | + *+--------------------+---------------+--------------------+------------------+ + *| CONVERGED | HAL initiates | SEARCHING | values locked | + *| | AE/AWB scan | | | + *+--------------------+---------------+--------------------+------------------+ + *| CONVERGED | AE/AWB_LOCK | LOCKED | values locked | + *| | on | | | + *+--------------------+---------------+--------------------+------------------+ + *| FLASH_REQUIRED | HAL initiates | SEARCHING | values locked | + *| | AE/AWB scan | | | + *+--------------------+---------------+--------------------+------------------+ + *| FLASH_REQUIRED | AE/AWB_LOCK | LOCKED | values locked | + *| | on | | | + *+--------------------+---------------+--------------------+------------------+ + *| LOCKED | AE/AWB_LOCK | SEARCHING | values not good | + *| | off | | after unlock | + *+--------------------+---------------+--------------------+------------------+ + *| LOCKED | AE/AWB_LOCK | CONVERGED | values good | + *| | off | | after unlock | + *+--------------------+---------------+--------------------+------------------+ + *| LOCKED | AE_LOCK | FLASH_REQUIRED | exposure good, | + *| | off | | but too dark | + *+--------------------+---------------+--------------------+------------------+ + *| All AE states | PRECAPTURE_ | PRECAPTURE | Start precapture | + *| | START | | sequence | + *+--------------------+---------------+--------------------+------------------+ + *| PRECAPTURE | Sequence done.| CONVERGED | Ready for high- | + *| | AE_LOCK off | | quality capture | + *+--------------------+---------------+--------------------+------------------+ + *| PRECAPTURE | Sequence done.| LOCKED | Ready for high- | + *| | AE_LOCK on | | quality capture | + *+--------------------+---------------+--------------------+------------------+ + * + */ + +/** + * S5. Cropping: + * + * Cropping of the full pixel array (for digital zoom and other use cases where + * a smaller FOV is desirable) is communicated through the + * ANDROID_SCALER_CROP_REGION setting. This is a per-request setting, and can + * change on a per-request basis, which is critical for implementing smooth + * digital zoom. + * + * The region is defined as a rectangle (x, y, width, height), with (x, y) + * describing the top-left corner of the rectangle. The rectangle is defined on + * the coordinate system of the sensor active pixel array, with (0,0) being the + * top-left pixel of the active pixel array. Therefore, the width and height + * cannot be larger than the dimensions reported in the + * ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY static info field. The minimum allowed + * width and height are reported by the HAL through the + * ANDROID_SCALER_MAX_DIGITAL_ZOOM static info field, which describes the + * maximum supported zoom factor. Therefore, the minimum crop region width and + * height are: + * + * {width, height} = + * { floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[0] / + * ANDROID_SCALER_MAX_DIGITAL_ZOOM), + * floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[1] / + * ANDROID_SCALER_MAX_DIGITAL_ZOOM) } + * + * If the crop region needs to fulfill specific requirements (for example, it + * needs to start on even coordinates, and its width/height needs to be even), + * the HAL must do the necessary rounding and write out the final crop region + * used in the output result metadata. Similarly, if the HAL implements video + * stabilization, it must adjust the result crop region to describe the region + * actually included in the output after video stabilization is applied. In + * general, a camera-using application must be able to determine the field of + * view it is receiving based on the crop region, the dimensions of the image + * sensor, and the lens focal length. + * + * It is assumed that the cropping is applied after raw to other color space + * conversion. Raw streams (RAW16 and RAW_OPAQUE) don't have this conversion stage, + * and are not croppable. Therefore, the crop region must be ignored by the HAL + * for raw streams. + * + * Since the crop region applies to all non-raw streams, which may have different aspect + * ratios than the crop region, the exact sensor region used for each stream may + * be smaller than the crop region. Specifically, each stream should maintain + * square pixels and its aspect ratio by minimally further cropping the defined + * crop region. If the stream's aspect ratio is wider than the crop region, the + * stream should be further cropped vertically, and if the stream's aspect ratio + * is narrower than the crop region, the stream should be further cropped + * horizontally. + * + * In all cases, the stream crop must be centered within the full crop region, + * and each stream is only either cropped horizontally or vertical relative to + * the full crop region, never both. + * + * For example, if two streams are defined, a 640x480 stream (4:3 aspect), and a + * 1280x720 stream (16:9 aspect), below demonstrates the expected output regions + * for each stream for a few sample crop regions, on a hypothetical 3 MP (2000 x + * 1500 pixel array) sensor. + * + * Crop region: (500, 375, 1000, 750) (4:3 aspect ratio) + * + * 640x480 stream crop: (500, 375, 1000, 750) (equal to crop region) + * 1280x720 stream crop: (500, 469, 1000, 562) (marked with =) + * + * 0 1000 2000 + * +---------+---------+---------+----------+ + * | Active pixel array | + * | | + * | | + * + +-------------------+ + 375 + * | | | | + * | O===================O | + * | I 1280x720 stream I | + * + I I + 750 + * | I I | + * | O===================O | + * | | | | + * + +-------------------+ + 1125 + * | Crop region, 640x480 stream | + * | | + * | | + * +---------+---------+---------+----------+ 1500 + * + * Crop region: (500, 375, 1333, 750) (16:9 aspect ratio) + * + * 640x480 stream crop: (666, 375, 1000, 750) (marked with =) + * 1280x720 stream crop: (500, 375, 1333, 750) (equal to crop region) + * + * 0 1000 2000 + * +---------+---------+---------+----------+ + * | Active pixel array | + * | | + * | | + * + +---O==================O---+ + 375 + * | | I 640x480 stream I | | + * | | I I | | + * | | I I | | + * + | I I | + 750 + * | | I I | | + * | | I I | | + * | | I I | | + * + +---O==================O---+ + 1125 + * | Crop region, 1280x720 stream | + * | | + * | | + * +---------+---------+---------+----------+ 1500 + * + * Crop region: (500, 375, 750, 750) (1:1 aspect ratio) + * + * 640x480 stream crop: (500, 469, 750, 562) (marked with =) + * 1280x720 stream crop: (500, 543, 750, 414) (marged with #) + * + * 0 1000 2000 + * +---------+---------+---------+----------+ + * | Active pixel array | + * | | + * | | + * + +--------------+ + 375 + * | O==============O | + * | ################ | + * | # # | + * + # # + 750 + * | # # | + * | ################ 1280x720 | + * | O==============O 640x480 | + * + +--------------+ + 1125 + * | Crop region | + * | | + * | | + * +---------+---------+---------+----------+ 1500 + * + * And a final example, a 1024x1024 square aspect ratio stream instead of the + * 480p stream: + * + * Crop region: (500, 375, 1000, 750) (4:3 aspect ratio) + * + * 1024x1024 stream crop: (625, 375, 750, 750) (marked with #) + * 1280x720 stream crop: (500, 469, 1000, 562) (marked with =) + * + * 0 1000 2000 + * +---------+---------+---------+----------+ + * | Active pixel array | + * | | + * | 1024x1024 stream | + * + +--###############--+ + 375 + * | | # # | | + * | O===================O | + * | I 1280x720 stream I | + * + I I + 750 + * | I I | + * | O===================O | + * | | # # | | + * + +--###############--+ + 1125 + * | Crop region | + * | | + * | | + * +---------+---------+---------+----------+ 1500 + * + */ + +/** + * S6. Error management: + * + * Camera HAL device ops functions that have a return value will all return + * -ENODEV / NULL in case of a serious error. This means the device cannot + * continue operation, and must be closed by the framework. Once this error is + * returned by some method, or if notify() is called with ERROR_DEVICE, only + * the close() method can be called successfully. All other methods will return + * -ENODEV / NULL. + * + * If a device op is called in the wrong sequence, for example if the framework + * calls configure_streams() is called before initialize(), the device must + * return -ENOSYS from the call, and do nothing. + * + * Transient errors in image capture must be reported through notify() as follows: + * + * - The failure of an entire capture to occur must be reported by the HAL by + * calling notify() with ERROR_REQUEST. Individual errors for the result + * metadata or the output buffers must not be reported in this case. + * + * - If the metadata for a capture cannot be produced, but some image buffers + * were filled, the HAL must call notify() with ERROR_RESULT. + * + * - If an output image buffer could not be filled, but either the metadata was + * produced or some other buffers were filled, the HAL must call notify() with + * ERROR_BUFFER for each failed buffer. + * + * In each of these transient failure cases, the HAL must still call + * process_capture_result, with valid output and input (if an input buffer was + * submitted) buffer_handle_t. If the result metadata could not be produced, it + * should be NULL. If some buffers could not be filled, they must be returned with + * process_capture_result in the error state, their release fences must be set to + * the acquire fences passed by the framework, or -1 if they have been waited on by + * the HAL already. + * + * Invalid input arguments result in -EINVAL from the appropriate methods. In + * that case, the framework must act as if that call had never been made. + * + */ + +/** + * S7. Key Performance Indicator (KPI) glossary: + * + * This includes some critical definitions that are used by KPI metrics. + * + * Pipeline Latency: + * For a given capture request, the duration from the framework calling + * process_capture_request to the HAL sending capture result and all buffers + * back by process_capture_result call. To make the Pipeline Latency measure + * independent of frame rate, it is measured by frame count. + * + * For example, when frame rate is 30 (fps), the frame duration (time interval + * between adjacent frame capture time) is 33 (ms). + * If it takes 5 frames for framework to get the result and buffers back for + * a given request, then the Pipeline Latency is 5 (frames), instead of + * 5 x 33 = 165 (ms). + * + * The Pipeline Latency is determined by android.request.pipelineDepth and + * android.request.pipelineMaxDepth, see their definitions for more details. + * + */ + +/** + * S8. Sample Use Cases: + * + * This includes some typical use case examples the camera HAL may support. + * + * S8.1 Zero Shutter Lag (ZSL) with CAMERA3_STREAM_BIDIRECTIONAL stream. + * + * For this use case, the bidirectional stream will be used by the framework as follows: + * + * 1. The framework includes a buffer from this stream as output buffer in a + * request as normal. + * + * 2. Once the HAL device returns a filled output buffer to the framework, + * the framework may do one of two things with the filled buffer: + * + * 2. a. The framework uses the filled data, and returns the now-used buffer + * to the stream queue for reuse. This behavior exactly matches the + * OUTPUT type of stream. + * + * 2. b. The framework wants to reprocess the filled data, and uses the + * buffer as an input buffer for a request. Once the HAL device has + * used the reprocessing buffer, it then returns it to the + * framework. The framework then returns the now-used buffer to the + * stream queue for reuse. + * + * 3. The HAL device will be given the buffer again as an output buffer for + * a request at some future point. + * + * For ZSL use case, the pixel format for bidirectional stream will be + * HAL_PIXEL_FORMAT_RAW_OPAQUE or HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED if it + * is listed in android.scaler.availableInputOutputFormatsMap. When + * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, the gralloc + * usage flags for the consumer endpoint will be set to GRALLOC_USAGE_HW_CAMERA_ZSL. + * A configuration stream list that has BIDIRECTIONAL stream used as input, will + * usually also have a distinct OUTPUT stream to get the reprocessing data. For example, + * for the ZSL use case, the stream list might be configured with the following: + * + * - A HAL_PIXEL_FORMAT_RAW_OPAQUE bidirectional stream is used + * as input. + * - And a HAL_PIXEL_FORMAT_BLOB (JPEG) output stream. + * + * S8.2 ZSL (OPAQUE) reprocessing with CAMERA3_STREAM_INPUT stream. + * + * CAMERA_DEVICE_API_VERSION_3_3: + * When OPAQUE_REPROCESSING capability is supported by the camera device, the INPUT stream + * can be used for application/framework implemented use case like Zero Shutter Lag (ZSL). + * This kind of stream will be used by the framework as follows: + * + * 1. Application/framework configures an opaque (RAW or YUV based) format output stream that is + * used to produce the ZSL output buffers. The stream pixel format will be + * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. + * + * 2. Application/framework configures an opaque format input stream that is used to + * send the reprocessing ZSL buffers to the HAL. The stream pixel format will + * also be HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. + * + * 3. Application/framework configures a YUV/JPEG output stream that is used to receive the + * reprocessed data. The stream pixel format will be YCbCr_420/HAL_PIXEL_FORMAT_BLOB. + * + * 4. Application/framework picks a ZSL buffer from the ZSL output stream when a ZSL capture is + * issued by the application, and sends the data back as an input buffer in a + * reprocessing request, then sends to the HAL for reprocessing. + * + * 5. The HAL sends back the output YUV/JPEG result to framework. + * + * The HAL can select the actual opaque buffer format and configure the ISP pipeline + * appropriately based on the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED format and + * the gralloc usage flag GRALLOC_USAGE_HW_CAMERA_ZSL. + + * S8.3 YUV reprocessing with CAMERA3_STREAM_INPUT stream. + * + * When YUV reprocessing is supported by the HAL, the INPUT stream + * can be used for the YUV reprocessing use cases like lucky-shot and image fusion. + * This kind of stream will be used by the framework as follows: + * + * 1. Application/framework configures an YCbCr_420 format output stream that is + * used to produce the output buffers. + * + * 2. Application/framework configures an YCbCr_420 format input stream that is used to + * send the reprocessing YUV buffers to the HAL. + * + * 3. Application/framework configures a YUV/JPEG output stream that is used to receive the + * reprocessed data. The stream pixel format will be YCbCr_420/HAL_PIXEL_FORMAT_BLOB. + * + * 4. Application/framework processes the output buffers (could be as simple as picking + * an output buffer directly) from the output stream when a capture is issued, and sends + * the data back as an input buffer in a reprocessing request, then sends to the HAL + * for reprocessing. + * + * 5. The HAL sends back the output YUV/JPEG result to framework. + * + */ + +/** + * S9. Notes on Controls and Metadata + * + * This section contains notes about the interpretation and usage of various metadata tags. + * + * S9.1 HIGH_QUALITY and FAST modes. + * + * Many camera post-processing blocks may be listed as having HIGH_QUALITY, + * FAST, and OFF operating modes. These blocks will typically also have an + * 'available modes' tag representing which of these operating modes are + * available on a given device. The general policy regarding implementing + * these modes is as follows: + * + * 1. Operating mode controls of hardware blocks that cannot be disabled + * must not list OFF in their corresponding 'available modes' tags. + * + * 2. OFF will always be included in their corresponding 'available modes' + * tag if it is possible to disable that hardware block. + * + * 3. FAST must always be included in the 'available modes' tags for all + * post-processing blocks supported on the device. If a post-processing + * block also has a slower and higher quality operating mode that does + * not meet the framerate requirements for FAST mode, HIGH_QUALITY should + * be included in the 'available modes' tag to represent this operating + * mode. + */ + +/** + * S10. Reprocessing flow and controls + * + * This section describes the OPAQUE and YUV reprocessing flow and controls. OPAQUE reprocessing + * uses an opaque format that is not directly application-visible, and the application can + * only select some of the output buffers and send back to HAL for reprocessing, while YUV + * reprocessing gives the application opportunity to process the buffers before reprocessing. + * + * S8 gives the stream configurations for the typical reprocessing uses cases, + * this section specifies the buffer flow and controls in more details. + * + * S10.1 OPAQUE (typically for ZSL use case) reprocessing flow and controls + * + * For OPAQUE reprocessing (e.g. ZSL) use case, after the application creates the specific + * output and input streams, runtime buffer flow and controls are specified as below: + * + * 1. Application starts output streaming by sending repeating requests for output + * opaque buffers and preview. The buffers are held by an application + * maintained circular buffer. The requests are based on CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG + * capture template, which should have all necessary settings that guarantee output + * frame rate is not slowed down relative to sensor output frame rate. + * + * 2. When a capture is issued, the application selects one output buffer based + * on application buffer selection logic, e.g. good AE and AF statistics etc. + * Application then creates an reprocess request based on the capture result associated + * with this selected buffer. The selected output buffer is now added to this reprocess + * request as an input buffer, the output buffer of this reprocess request should be + * either JPEG output buffer or YUV output buffer, or both, depending on the application + * choice. + * + * 3. Application then alters the reprocess settings to get best image quality. The HAL must + * support and only support below controls if the HAL support OPAQUE_REPROCESSING capability: + * - android.jpeg.* (if JPEG buffer is included as one of the output) + * - android.noiseReduction.mode (change to HIGH_QUALITY if it is supported) + * - android.edge.mode (change to HIGH_QUALITY if it is supported) + * All other controls must be ignored by the HAL. + * 4. HAL processed the input buffer and return the output buffers in the capture results + * as normal. + * + * S10.2 YUV reprocessing flow and controls + * + * The YUV reprocessing buffer flow is similar as OPAQUE reprocessing, with below difference: + * + * 1. Application may want to have finer granularity control of the intermediate YUV images + * (before reprocessing). For example, application may choose + * - android.noiseReduction.mode == MINIMAL + * to make sure the no YUV domain noise reduction has applied to the output YUV buffers, + * then it can do its own advanced noise reduction on them. For OPAQUE reprocessing case, this + * doesn't matter, as long as the final reprocessed image has the best quality. + * 2. Application may modify the YUV output buffer data. For example, for image fusion use + * case, where multiple output images are merged together to improve the signal-to-noise + * ratio (SNR). The input buffer may be generated from multiple buffers by the application. + * To avoid excessive amount of noise reduction and insufficient amount of edge enhancement + * being applied to the input buffer, the application can hint the HAL how much effective + * exposure time improvement has been done by the application, then the HAL can adjust the + * noise reduction and edge enhancement paramters to get best reprocessed image quality. + * Below tag can be used for this purpose: + * - android.reprocess.effectiveExposureFactor + * The value would be exposure time increase factor applied to the original output image, + * for example, if there are N image merged, the exposure time increase factor would be up + * to sqrt(N). See this tag spec for more details. + * + * S10.3 Reprocessing pipeline characteristics + * + * Reprocessing pipeline has below different characteristics comparing with normal output + * pipeline: + * + * 1. The reprocessing result can be returned ahead of the pending normal output results. But + * the FIFO ordering must be maintained for all reprocessing results. For example, there are + * below requests (A stands for output requests, B stands for reprocessing requests) + * being processed by the HAL: + * A1, A2, A3, A4, B1, A5, B2, A6... + * result of B1 can be returned before A1-A4, but result of B2 must be returned after B1. + * 2. Single input rule: For a given reprocessing request, all output buffers must be from the + * input buffer, rather than sensor output. For example, if a reprocess request include both + * JPEG and preview buffers, all output buffers must be produced from the input buffer + * included by the reprocessing request, rather than sensor. The HAL must not output preview + * buffers from sensor, while output JPEG buffer from the input buffer. + * 3. Input buffer will be from camera output directly (ZSL case) or indirectly(image fusion + * case). For the case where buffer is modified, the size will remain same. The HAL can + * notify CAMERA3_MSG_ERROR_REQUEST if buffer from unknown source is sent. + * 4. Result as reprocessing request: The HAL can expect that a reprocessing request is a copy + * of one of the output results with minor allowed setting changes. The HAL can notify + * CAMERA3_MSG_ERROR_REQUEST if a request from unknown source is issued. + * 5. Output buffers may not be used as inputs across the configure stream boundary, This is + * because an opaque stream like the ZSL output stream may have different actual image size + * inside of the ZSL buffer to save power and bandwidth for smaller resolution JPEG capture. + * The HAL may notify CAMERA3_MSG_ERROR_REQUEST if this case occurs. + * 6. HAL Reprocess requests error reporting during flush should follow the same rule specified + * by flush() method. + * + */ + +__BEGIN_DECLS + +struct camera3_device; + +/********************************************************************** + * + * Camera3 stream and stream buffer definitions. + * + * These structs and enums define the handles and contents of the input and + * output streams connecting the HAL to various framework and application buffer + * consumers. Each stream is backed by a gralloc buffer queue. + * + */ + +/** + * camera3_stream_type_t: + * + * The type of the camera stream, which defines whether the camera HAL device is + * the producer or the consumer for that stream, and how the buffers of the + * stream relate to the other streams. + */ +typedef enum camera3_stream_type { + /** + * This stream is an output stream; the camera HAL device will be + * responsible for filling buffers from this stream with newly captured or + * reprocessed image data. + */ + CAMERA3_STREAM_OUTPUT = 0, + + /** + * This stream is an input stream; the camera HAL device will be responsible + * for reading buffers from this stream and sending them through the camera + * processing pipeline, as if the buffer was a newly captured image from the + * imager. + * + * The pixel format for input stream can be any format reported by + * android.scaler.availableInputOutputFormatsMap. The pixel format of the + * output stream that is used to produce the reprocessing data may be any + * format reported by android.scaler.availableStreamConfigurations. The + * supported input/output stream combinations depends the camera device + * capabilities, see android.scaler.availableInputOutputFormatsMap for + * stream map details. + * + * This kind of stream is generally used to reprocess data into higher + * quality images (that otherwise would cause a frame rate performance + * loss), or to do off-line reprocessing. + * + * CAMERA_DEVICE_API_VERSION_3_3: + * The typical use cases are OPAQUE (typically ZSL) and YUV reprocessing, + * see S8.2, S8.3 and S10 for more details. + */ + CAMERA3_STREAM_INPUT = 1, + + /** + * This stream can be used for input and output. Typically, the stream is + * used as an output stream, but occasionally one already-filled buffer may + * be sent back to the HAL device for reprocessing. + * + * This kind of stream is meant generally for Zero Shutter Lag (ZSL) + * features, where copying the captured image from the output buffer to the + * reprocessing input buffer would be expensive. See S8.1 for more details. + * + * Note that the HAL will always be reprocessing data it produced. + * + */ + CAMERA3_STREAM_BIDIRECTIONAL = 2, + + /** + * Total number of framework-defined stream types + */ + CAMERA3_NUM_STREAM_TYPES + +} camera3_stream_type_t; + +/** + * camera3_stream_rotation_t: + * + * The required counterclockwise rotation of camera stream. + */ +typedef enum camera3_stream_rotation { + /* No rotation */ + CAMERA3_STREAM_ROTATION_0 = 0, + + /* Rotate by 90 degree counterclockwise */ + CAMERA3_STREAM_ROTATION_90 = 1, + + /* Rotate by 180 degree counterclockwise */ + CAMERA3_STREAM_ROTATION_180 = 2, + + /* Rotate by 270 degree counterclockwise */ + CAMERA3_STREAM_ROTATION_270 = 3 +} camera3_stream_rotation_t; + +/** + * camera3_stream_configuration_mode_t: + * + * This defines the general operation mode for the HAL (for a given stream configuration), where + * modes besides NORMAL have different semantics, and usually limit the generality of the API in + * exchange for higher performance in some particular area. + */ +typedef enum camera3_stream_configuration_mode { + /** + * Normal stream configuration operation mode. This is the default camera operation mode, + * where all semantics of HAL APIs and metadata controls apply. + */ + CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE = 0, + + /** + * Special constrained high speed operation mode for devices that can not support high + * speed output in NORMAL mode. All streams in this configuration are operating at high speed + * mode and have different characteristics and limitations to achieve high speed output. + * The NORMAL mode can still be used for high speed output if the HAL can support high speed + * output while satisfying all the semantics of HAL APIs and metadata controls. It is + * recommended for the HAL to support high speed output in NORMAL mode (by advertising the high + * speed FPS ranges in android.control.aeAvailableTargetFpsRanges) if possible. + * + * This mode has below limitations/requirements: + * + * 1. The HAL must support up to 2 streams with sizes reported by + * android.control.availableHighSpeedVideoConfigurations. + * 2. In this mode, the HAL is expected to output up to 120fps or higher. This mode must + * support the targeted FPS range and size configurations reported by + * android.control.availableHighSpeedVideoConfigurations. + * 3. The HAL must support HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED output stream format. + * 4. To achieve efficient high speed streaming, the HAL may have to aggregate + * multiple frames together and send to camera device for processing where the request + * controls are same for all the frames in this batch (batch mode). The HAL must support + * max batch size and the max batch size requirements defined by + * android.control.availableHighSpeedVideoConfigurations. + * 5. In this mode, the HAL must override aeMode, awbMode, and afMode to ON, ON, and + * CONTINUOUS_VIDEO, respectively. All post-processing block mode controls must be + * overridden to be FAST. Therefore, no manual control of capture and post-processing + * parameters is possible. All other controls operate the same as when + * android.control.mode == AUTO. This means that all other android.control.* fields + * must continue to work, such as + * + * android.control.aeTargetFpsRange + * android.control.aeExposureCompensation + * android.control.aeLock + * android.control.awbLock + * android.control.effectMode + * android.control.aeRegions + * android.control.afRegions + * android.control.awbRegions + * android.control.afTrigger + * android.control.aePrecaptureTrigger + * + * Outside of android.control.*, the following controls must work: + * + * android.flash.mode (TORCH mode only, automatic flash for still capture will not work + * since aeMode is ON) + * android.lens.opticalStabilizationMode (if it is supported) + * android.scaler.cropRegion + * android.statistics.faceDetectMode (if it is supported) + * + * For more details about high speed stream requirements, see + * android.control.availableHighSpeedVideoConfigurations and CONSTRAINED_HIGH_SPEED_VIDEO + * capability defined in android.request.availableCapabilities. + * + * This mode only needs to be supported by HALs that include CONSTRAINED_HIGH_SPEED_VIDEO in + * the android.request.availableCapabilities static metadata. + */ + CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE = 1, + + /** + * First value for vendor-defined stream configuration modes. + */ + CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START = 0x8000 +} camera3_stream_configuration_mode_t; + +/** + * camera3_stream_t: + * + * A handle to a single camera input or output stream. A stream is defined by + * the framework by its buffer resolution and format, and additionally by the + * HAL with the gralloc usage flags and the maximum in-flight buffer count. + * + * The stream structures are owned by the framework, but pointers to a + * camera3_stream passed into the HAL by configure_streams() are valid until the + * end of the first subsequent configure_streams() call that _does not_ include + * that camera3_stream as an argument, or until the end of the close() call. + * + * All camera3_stream framework-controlled members are immutable once the + * camera3_stream is passed into configure_streams(). The HAL may only change + * the HAL-controlled parameters during a configure_streams() call, except for + * the contents of the private pointer. + * + * If a configure_streams() call returns a non-fatal error, all active streams + * remain valid as if configure_streams() had not been called. + * + * The endpoint of the stream is not visible to the camera HAL device. + * In DEVICE_API_VERSION_3_1, this was changed to share consumer usage flags + * on streams where the camera is a producer (OUTPUT and BIDIRECTIONAL stream + * types) see the usage field below. + */ +typedef struct camera3_stream { + + /***** + * Set by framework before configure_streams() + */ + + /** + * The type of the stream, one of the camera3_stream_type_t values. + */ + int stream_type; + + /** + * The width in pixels of the buffers in this stream + */ + uint32_t width; + + /** + * The height in pixels of the buffers in this stream + */ + uint32_t height; + + /** + * The pixel format for the buffers in this stream. Format is a value from + * the HAL_PIXEL_FORMAT_* list in system/core/include/system/graphics.h, or + * from device-specific headers. + * + * If HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform + * gralloc module will select a format based on the usage flags provided by + * the camera device and the other endpoint of the stream. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * The camera HAL device must inspect the buffers handed to it in the + * subsequent register_stream_buffers() call to obtain the + * implementation-specific format details, if necessary. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * register_stream_buffers() won't be called by the framework, so the HAL + * should configure the ISP and sensor pipeline based purely on the sizes, + * usage flags, and formats for the configured streams. + */ + int format; + + /***** + * Set by HAL during configure_streams(). + */ + + /** + * The gralloc usage flags for this stream, as needed by the HAL. The usage + * flags are defined in gralloc.h (GRALLOC_USAGE_*), or in device-specific + * headers. + * + * For output streams, these are the HAL's producer usage flags. For input + * streams, these are the HAL's consumer usage flags. The usage flags from + * the producer and the consumer will be combined together and then passed + * to the platform gralloc HAL module for allocating the gralloc buffers for + * each stream. + * + * Version information: + * + * == CAMERA_DEVICE_API_VERSION_3_0: + * + * No initial value guaranteed when passed via configure_streams(). + * HAL may not use this field as input, and must write over this field + * with its usage flags. + * + * >= CAMERA_DEVICE_API_VERSION_3_1: + * + * For stream_type OUTPUT and BIDIRECTIONAL, when passed via + * configure_streams(), the initial value of this is the consumer's + * usage flags. The HAL may use these consumer flags to decide stream + * configuration. + * For stream_type INPUT, when passed via configure_streams(), the initial + * value of this is 0. + * For all streams passed via configure_streams(), the HAL must write + * over this field with its usage flags. + */ + uint32_t usage; + + /** + * The maximum number of buffers the HAL device may need to have dequeued at + * the same time. The HAL device may not have more buffers in-flight from + * this stream than this value. + */ + uint32_t max_buffers; + + /** + * A handle to HAL-private information for the stream. Will not be inspected + * by the framework code. + */ + void *priv; + + /** + * A field that describes the contents of the buffer. The format and buffer + * dimensions define the memory layout and structure of the stream buffers, + * while dataSpace defines the meaning of the data within the buffer. + * + * For most formats, dataSpace defines the color space of the image data. + * In addition, for some formats, dataSpace indicates whether image- or + * depth-based data is requested. See system/core/include/system/graphics.h + * for details of formats and valid dataSpace values for each format. + * + * Version information: + * + * < CAMERA_DEVICE_API_VERSION_3_3: + * + * Not defined and should not be accessed. dataSpace should be assumed to + * be HAL_DATASPACE_UNKNOWN, and the appropriate color space, etc, should + * be determined from the usage flags and the format. + * + * >= CAMERA_DEVICE_API_VERSION_3_3: + * + * Always set by the camera service. HAL must use this dataSpace to + * configure the stream to the correct colorspace, or to select between + * color and depth outputs if supported. + */ + android_dataspace_t data_space; + + /** + * The required output rotation of the stream, one of + * the camera3_stream_rotation_t values. This must be inspected by HAL along + * with stream width and height. For example, if the rotation is 90 degree + * and the stream width and height is 720 and 1280 respectively, camera service + * will supply buffers of size 720x1280, and HAL should capture a 1280x720 image + * and rotate the image by 90 degree counterclockwise. The rotation field is + * no-op when the stream type is input. Camera HAL must ignore the rotation + * field for an input stream. + * + * <= CAMERA_DEVICE_API_VERSION_3_2: + * + * Not defined and must not be accessed. HAL must not apply any rotation + * on output images. + * + * >= CAMERA_DEVICE_API_VERSION_3_3: + * + * Always set by camera service. HAL must inspect this field during stream + * configuration and returns -EINVAL if HAL cannot perform such rotation. + * HAL must always support CAMERA3_STREAM_ROTATION_0, so a + * configure_streams() call must not fail for unsupported rotation if + * rotation field of all streams is CAMERA3_STREAM_ROTATION_0. + * + */ + int rotation; + + /* reserved for future use */ + void *reserved[7]; + +} camera3_stream_t; + +/** + * camera3_stream_configuration_t: + * + * A structure of stream definitions, used by configure_streams(). This + * structure defines all the output streams and the reprocessing input + * stream for the current camera use case. + */ +typedef struct camera3_stream_configuration { + /** + * The total number of streams requested by the framework. This includes + * both input and output streams. The number of streams will be at least 1, + * and there will be at least one output-capable stream. + */ + uint32_t num_streams; + + /** + * An array of camera stream pointers, defining the input/output + * configuration for the camera HAL device. + * + * At most one input-capable stream may be defined (INPUT or BIDIRECTIONAL) + * in a single configuration. + * + * At least one output-capable stream must be defined (OUTPUT or + * BIDIRECTIONAL). + */ + camera3_stream_t **streams; + + /** + * >= CAMERA_DEVICE_API_VERSION_3_3: + * + * The operation mode of streams in this configuration, one of the value defined in + * camera3_stream_configuration_mode_t. + * The HAL can use this mode as an indicator to set the stream property (e.g., + * camera3_stream->max_buffers) appropriately. For example, if the configuration is + * CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE, the HAL may want to set aside more + * buffers for batch mode operation (see android.control.availableHighSpeedVideoConfigurations + * for batch mode definition). + * + */ + uint32_t operation_mode; +} camera3_stream_configuration_t; + +/** + * camera3_buffer_status_t: + * + * The current status of a single stream buffer. + */ +typedef enum camera3_buffer_status { + /** + * The buffer is in a normal state, and can be used after waiting on its + * sync fence. + */ + CAMERA3_BUFFER_STATUS_OK = 0, + + /** + * The buffer does not contain valid data, and the data in it should not be + * used. The sync fence must still be waited on before reusing the buffer. + */ + CAMERA3_BUFFER_STATUS_ERROR = 1 + +} camera3_buffer_status_t; + +/** + * camera3_stream_buffer_t: + * + * A single buffer from a camera3 stream. It includes a handle to its parent + * stream, the handle to the gralloc buffer itself, and sync fences + * + * The buffer does not specify whether it is to be used for input or output; + * that is determined by its parent stream type and how the buffer is passed to + * the HAL device. + */ +typedef struct camera3_stream_buffer { + /** + * The handle of the stream this buffer is associated with + */ + camera3_stream_t *stream; + + /** + * The native handle to the buffer + */ + buffer_handle_t *buffer; + + /** + * Current state of the buffer, one of the camera3_buffer_status_t + * values. The framework will not pass buffers to the HAL that are in an + * error state. In case a buffer could not be filled by the HAL, it must + * have its status set to CAMERA3_BUFFER_STATUS_ERROR when returned to the + * framework with process_capture_result(). + */ + int status; + + /** + * The acquire sync fence for this buffer. The HAL must wait on this fence + * fd before attempting to read from or write to this buffer. + * + * The framework may be set to -1 to indicate that no waiting is necessary + * for this buffer. + * + * When the HAL returns an output buffer to the framework with + * process_capture_result(), the acquire_fence must be set to -1. If the HAL + * never waits on the acquire_fence due to an error in filling a buffer, + * when calling process_capture_result() the HAL must set the release_fence + * of the buffer to be the acquire_fence passed to it by the framework. This + * will allow the framework to wait on the fence before reusing the buffer. + * + * For input buffers, the HAL must not change the acquire_fence field during + * the process_capture_request() call. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * When the HAL returns an input buffer to the framework with + * process_capture_result(), the acquire_fence must be set to -1. If the HAL + * never waits on input buffer acquire fence due to an error, the sync + * fences should be handled similarly to the way they are handled for output + * buffers. + */ + int acquire_fence; + + /** + * The release sync fence for this buffer. The HAL must set this fence when + * returning buffers to the framework, or write -1 to indicate that no + * waiting is required for this buffer. + * + * For the output buffers, the fences must be set in the output_buffers + * array passed to process_capture_result(). + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * For the input buffer, the release fence must be set by the + * process_capture_request() call. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * For the input buffer, the fences must be set in the input_buffer + * passed to process_capture_result(). + * + * After signaling the release_fence for this buffer, the HAL + * should not make any further attempts to access this buffer as the + * ownership has been fully transferred back to the framework. + * + * If a fence of -1 was specified then the ownership of this buffer + * is transferred back immediately upon the call of process_capture_result. + */ + int release_fence; + +} camera3_stream_buffer_t; + +/** + * camera3_stream_buffer_set_t: + * + * The complete set of gralloc buffers for a stream. This structure is given to + * register_stream_buffers() to allow the camera HAL device to register/map/etc + * newly allocated stream buffers. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Deprecated (and not used). In particular, + * register_stream_buffers is also deprecated and will never be invoked. + * + */ +typedef struct camera3_stream_buffer_set { + /** + * The stream handle for the stream these buffers belong to + */ + camera3_stream_t *stream; + + /** + * The number of buffers in this stream. It is guaranteed to be at least + * stream->max_buffers. + */ + uint32_t num_buffers; + + /** + * The array of gralloc buffer handles for this stream. If the stream format + * is set to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, the camera HAL device + * should inspect the passed-in buffers to determine any platform-private + * pixel format information. + */ + buffer_handle_t **buffers; + +} camera3_stream_buffer_set_t; + +/** + * camera3_jpeg_blob: + * + * Transport header for compressed JPEG buffers in output streams. + * + * To capture JPEG images, a stream is created using the pixel format + * HAL_PIXEL_FORMAT_BLOB. The buffer size for the stream is calculated by the + * framework, based on the static metadata field android.jpeg.maxSize. Since + * compressed JPEG images are of variable size, the HAL needs to include the + * final size of the compressed image using this structure inside the output + * stream buffer. The JPEG blob ID field must be set to CAMERA3_JPEG_BLOB_ID. + * + * Transport header should be at the end of the JPEG output stream buffer. That + * means the jpeg_blob_id must start at byte[buffer_size - + * sizeof(camera3_jpeg_blob)], where the buffer_size is the size of gralloc buffer. + * Any HAL using this transport header must account for it in android.jpeg.maxSize + * The JPEG data itself starts at the beginning of the buffer and should be + * jpeg_size bytes long. + */ +typedef struct camera3_jpeg_blob { + uint16_t jpeg_blob_id; + uint32_t jpeg_size; +} camera3_jpeg_blob_t; + +enum { + CAMERA3_JPEG_BLOB_ID = 0x00FF +}; + +/********************************************************************** + * + * Message definitions for the HAL notify() callback. + * + * These definitions are used for the HAL notify callback, to signal + * asynchronous events from the HAL device to the Android framework. + * + */ + +/** + * camera3_msg_type: + * + * Indicates the type of message sent, which specifies which member of the + * message union is valid. + * + */ +typedef enum camera3_msg_type { + /** + * An error has occurred. camera3_notify_msg.message.error contains the + * error information. + */ + CAMERA3_MSG_ERROR = 1, + + /** + * The exposure of a given request or processing a reprocess request has + * begun. camera3_notify_msg.message.shutter contains the information + * the capture. + */ + CAMERA3_MSG_SHUTTER = 2, + + /** + * Number of framework message types + */ + CAMERA3_NUM_MESSAGES + +} camera3_msg_type_t; + +/** + * Defined error codes for CAMERA_MSG_ERROR + */ +typedef enum camera3_error_msg_code { + /** + * A serious failure occured. No further frames or buffer streams will + * be produced by the device. Device should be treated as closed. The + * client must reopen the device to use it again. The frame_number field + * is unused. + */ + CAMERA3_MSG_ERROR_DEVICE = 1, + + /** + * An error has occurred in processing a request. No output (metadata or + * buffers) will be produced for this request. The frame_number field + * specifies which request has been dropped. Subsequent requests are + * unaffected, and the device remains operational. + */ + CAMERA3_MSG_ERROR_REQUEST = 2, + + /** + * An error has occurred in producing an output result metadata buffer + * for a request, but output stream buffers for it will still be + * available. Subsequent requests are unaffected, and the device remains + * operational. The frame_number field specifies the request for which + * result metadata won't be available. + */ + CAMERA3_MSG_ERROR_RESULT = 3, + + /** + * An error has occurred in placing an output buffer into a stream for a + * request. The frame metadata and other buffers may still be + * available. Subsequent requests are unaffected, and the device remains + * operational. The frame_number field specifies the request for which the + * buffer was dropped, and error_stream contains a pointer to the stream + * that dropped the frame.u + */ + CAMERA3_MSG_ERROR_BUFFER = 4, + + /** + * Number of error types + */ + CAMERA3_MSG_NUM_ERRORS + +} camera3_error_msg_code_t; + +/** + * camera3_error_msg_t: + * + * Message contents for CAMERA3_MSG_ERROR + */ +typedef struct camera3_error_msg { + /** + * Frame number of the request the error applies to. 0 if the frame number + * isn't applicable to the error. + */ + uint32_t frame_number; + + /** + * Pointer to the stream that had a failure. NULL if the stream isn't + * applicable to the error. + */ + camera3_stream_t *error_stream; + + /** + * The code for this error; one of the CAMERA_MSG_ERROR enum values. + */ + int error_code; + +} camera3_error_msg_t; + +/** + * camera3_shutter_msg_t: + * + * Message contents for CAMERA3_MSG_SHUTTER + */ +typedef struct camera3_shutter_msg { + /** + * Frame number of the request that has begun exposure or reprocessing. + */ + uint32_t frame_number; + + /** + * Timestamp for the start of capture. For a reprocess request, this must + * be input image's start of capture. This must match the capture result + * metadata's sensor exposure start timestamp. + */ + uint64_t timestamp; + +} camera3_shutter_msg_t; + +/** + * camera3_notify_msg_t: + * + * The message structure sent to camera3_callback_ops_t.notify() + */ +typedef struct camera3_notify_msg { + + /** + * The message type. One of camera3_notify_msg_type, or a private extension. + */ + int type; + + union { + /** + * Error message contents. Valid if type is CAMERA3_MSG_ERROR + */ + camera3_error_msg_t error; + + /** + * Shutter message contents. Valid if type is CAMERA3_MSG_SHUTTER + */ + camera3_shutter_msg_t shutter; + + /** + * Generic message contents. Used to ensure a minimum size for custom + * message types. + */ + uint8_t generic[32]; + } message; + +} camera3_notify_msg_t; + +/********************************************************************** + * + * Capture request/result definitions for the HAL process_capture_request() + * method, and the process_capture_result() callback. + * + */ + +/** + * camera3_request_template_t: + * + * Available template types for + * camera3_device_ops.construct_default_request_settings() + */ +typedef enum camera3_request_template { + /** + * Standard camera preview operation with 3A on auto. + */ + CAMERA3_TEMPLATE_PREVIEW = 1, + + /** + * Standard camera high-quality still capture with 3A and flash on auto. + */ + CAMERA3_TEMPLATE_STILL_CAPTURE = 2, + + /** + * Standard video recording plus preview with 3A on auto, torch off. + */ + CAMERA3_TEMPLATE_VIDEO_RECORD = 3, + + /** + * High-quality still capture while recording video. Application will + * include preview, video record, and full-resolution YUV or JPEG streams in + * request. Must not cause stuttering on video stream. 3A on auto. + */ + CAMERA3_TEMPLATE_VIDEO_SNAPSHOT = 4, + + /** + * Zero-shutter-lag mode. Application will request preview and + * full-resolution data for each frame, and reprocess it to JPEG when a + * still image is requested by user. Settings should provide highest-quality + * full-resolution images without compromising preview frame rate. 3A on + * auto. + */ + CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG = 5, + + /** + * A basic template for direct application control of capture + * parameters. All automatic control is disabled (auto-exposure, auto-white + * balance, auto-focus), and post-processing parameters are set to preview + * quality. The manual capture parameters (exposure, sensitivity, etc.) + * are set to reasonable defaults, but should be overridden by the + * application depending on the intended use case. + */ + CAMERA3_TEMPLATE_MANUAL = 6, + + /* Total number of templates */ + CAMERA3_TEMPLATE_COUNT, + + /** + * First value for vendor-defined request templates + */ + CAMERA3_VENDOR_TEMPLATE_START = 0x40000000 + +} camera3_request_template_t; + +/** + * camera3_capture_request_t: + * + * A single request for image capture/buffer reprocessing, sent to the Camera + * HAL device by the framework in process_capture_request(). + * + * The request contains the settings to be used for this capture, and the set of + * output buffers to write the resulting image data in. It may optionally + * contain an input buffer, in which case the request is for reprocessing that + * input buffer instead of capturing a new image with the camera sensor. The + * capture is identified by the frame_number. + * + * In response, the camera HAL device must send a camera3_capture_result + * structure asynchronously to the framework, using the process_capture_result() + * callback. + */ +typedef struct camera3_capture_request { + /** + * The frame number is an incrementing integer set by the framework to + * uniquely identify this capture. It needs to be returned in the result + * call, and is also used to identify the request in asynchronous + * notifications sent to camera3_callback_ops_t.notify(). + */ + uint32_t frame_number; + + /** + * The settings buffer contains the capture and processing parameters for + * the request. As a special case, a NULL settings buffer indicates that the + * settings are identical to the most-recently submitted capture request. A + * NULL buffer cannot be used as the first submitted request after a + * configure_streams() call. + */ + const camera_metadata_t *settings; + + /** + * The input stream buffer to use for this request, if any. + * + * If input_buffer is NULL, then the request is for a new capture from the + * imager. If input_buffer is valid, the request is for reprocessing the + * image contained in input_buffer. + * + * In the latter case, the HAL must set the release_fence of the + * input_buffer to a valid sync fence, or to -1 if the HAL does not support + * sync, before process_capture_request() returns. + * + * The HAL is required to wait on the acquire sync fence of the input buffer + * before accessing it. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * Any input buffer included here will have been registered with the HAL + * through register_stream_buffers() before its inclusion in a request. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * The buffers will not have been pre-registered with the HAL. + * Subsequent requests may reuse buffers, or provide entirely new buffers. + */ + camera3_stream_buffer_t *input_buffer; + + /** + * The number of output buffers for this capture request. Must be at least + * 1. + */ + uint32_t num_output_buffers; + + /** + * An array of num_output_buffers stream buffers, to be filled with image + * data from this capture/reprocess. The HAL must wait on the acquire fences + * of each stream buffer before writing to them. + * + * The HAL takes ownership of the actual buffer_handle_t entries in + * output_buffers; the framework does not access them until they are + * returned in a camera3_capture_result_t. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * All the buffers included here will have been registered with the HAL + * through register_stream_buffers() before their inclusion in a request. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Any or all of the buffers included here may be brand new in this + * request (having never before seen by the HAL). + */ + const camera3_stream_buffer_t *output_buffers; + +} camera3_capture_request_t; + +/** + * camera3_capture_result_t: + * + * The result of a single capture/reprocess by the camera HAL device. This is + * sent to the framework asynchronously with process_capture_result(), in + * response to a single capture request sent to the HAL with + * process_capture_request(). Multiple process_capture_result() calls may be + * performed by the HAL for each request. + * + * Each call, all with the same frame + * number, may contain some subset of the output buffers, and/or the result + * metadata. The metadata may only be provided once for a given frame number; + * all other calls must set the result metadata to NULL. + * + * The result structure contains the output metadata from this capture, and the + * set of output buffers that have been/will be filled for this capture. Each + * output buffer may come with a release sync fence that the framework will wait + * on before reading, in case the buffer has not yet been filled by the HAL. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * The metadata may be provided multiple times for a single frame number. The + * framework will accumulate together the final result set by combining each + * partial result together into the total result set. + * + * If an input buffer is given in a request, the HAL must return it in one of + * the process_capture_result calls, and the call may be to just return the input + * buffer, without metadata and output buffers; the sync fences must be handled + * the same way they are done for output buffers. + * + * + * Performance considerations: + * + * Applications will also receive these partial results immediately, so sending + * partial results is a highly recommended performance optimization to avoid + * the total pipeline latency before sending the results for what is known very + * early on in the pipeline. + * + * A typical use case might be calculating the AF state halfway through the + * pipeline; by sending the state back to the framework immediately, we get a + * 50% performance increase and perceived responsiveness of the auto-focus. + * + */ +typedef struct camera3_capture_result { + /** + * The frame number is an incrementing integer set by the framework in the + * submitted request to uniquely identify this capture. It is also used to + * identify the request in asynchronous notifications sent to + * camera3_callback_ops_t.notify(). + */ + uint32_t frame_number; + + /** + * The result metadata for this capture. This contains information about the + * final capture parameters, the state of the capture and post-processing + * hardware, the state of the 3A algorithms, if enabled, and the output of + * any enabled statistics units. + * + * Only one call to process_capture_result() with a given frame_number may + * include the result metadata. All other calls for the same frame_number + * must set this to NULL. + * + * If there was an error producing the result metadata, result must be an + * empty metadata buffer, and notify() must be called with ERROR_RESULT. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Multiple calls to process_capture_result() with a given frame_number + * may include the result metadata. + * + * Partial metadata submitted should not include any metadata key returned + * in a previous partial result for a given frame. Each new partial result + * for that frame must also set a distinct partial_result value. + * + * If notify has been called with ERROR_RESULT, all further partial + * results for that frame are ignored by the framework. + */ + const camera_metadata_t *result; + + /** + * The number of output buffers returned in this result structure. Must be + * less than or equal to the matching capture request's count. If this is + * less than the buffer count in the capture request, at least one more call + * to process_capture_result with the same frame_number must be made, to + * return the remaining output buffers to the framework. This may only be + * zero if the structure includes valid result metadata or an input buffer + * is returned in this result. + */ + uint32_t num_output_buffers; + + /** + * The handles for the output stream buffers for this capture. They may not + * yet be filled at the time the HAL calls process_capture_result(); the + * framework will wait on the release sync fences provided by the HAL before + * reading the buffers. + * + * The HAL must set the stream buffer's release sync fence to a valid sync + * fd, or to -1 if the buffer has already been filled. + * + * If the HAL encounters an error while processing the buffer, and the + * buffer is not filled, the buffer's status field must be set to + * CAMERA3_BUFFER_STATUS_ERROR. If the HAL did not wait on the acquire fence + * before encountering the error, the acquire fence should be copied into + * the release fence, to allow the framework to wait on the fence before + * reusing the buffer. + * + * The acquire fence must be set to -1 for all output buffers. If + * num_output_buffers is zero, this may be NULL. In that case, at least one + * more process_capture_result call must be made by the HAL to provide the + * output buffers. + * + * When process_capture_result is called with a new buffer for a frame, + * all previous frames' buffers for that corresponding stream must have been + * already delivered (the fences need not have yet been signaled). + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Gralloc buffers for a frame may be sent to framework before the + * corresponding SHUTTER-notify. + * + * Performance considerations: + * + * Buffers delivered to the framework will not be dispatched to the + * application layer until a start of exposure timestamp has been received + * via a SHUTTER notify() call. It is highly recommended to + * dispatch that call as early as possible. + */ + const camera3_stream_buffer_t *output_buffers; + + /** + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * The handle for the input stream buffer for this capture. It may not + * yet be consumed at the time the HAL calls process_capture_result(); the + * framework will wait on the release sync fences provided by the HAL before + * reusing the buffer. + * + * The HAL should handle the sync fences the same way they are done for + * output_buffers. + * + * Only one input buffer is allowed to be sent per request. Similarly to + * output buffers, the ordering of returned input buffers must be + * maintained by the HAL. + * + * Performance considerations: + * + * The input buffer should be returned as early as possible. If the HAL + * supports sync fences, it can call process_capture_result to hand it back + * with sync fences being set appropriately. If the sync fences are not + * supported, the buffer can only be returned when it is consumed, which + * may take long time; the HAL may choose to copy this input buffer to make + * the buffer return sooner. + */ + const camera3_stream_buffer_t *input_buffer; + + /** + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * In order to take advantage of partial results, the HAL must set the + * static metadata android.request.partialResultCount to the number of + * partial results it will send for each frame. + * + * Each new capture result with a partial result must set + * this field (partial_result) to a distinct inclusive value between + * 1 and android.request.partialResultCount. + * + * HALs not wishing to take advantage of this feature must not + * set an android.request.partialResultCount or partial_result to a value + * other than 1. + * + * This value must be set to 0 when a capture result contains buffers only + * and no metadata. + */ + uint32_t partial_result; + +} camera3_capture_result_t; + +/********************************************************************** + * + * Callback methods for the HAL to call into the framework. + * + * These methods are used to return metadata and image buffers for a completed + * or failed captures, and to notify the framework of asynchronous events such + * as errors. + * + * The framework will not call back into the HAL from within these callbacks, + * and these calls will not block for extended periods. + * + */ +typedef struct camera3_callback_ops { + + /** + * process_capture_result: + * + * Send results from a completed capture to the framework. + * process_capture_result() may be invoked multiple times by the HAL in + * response to a single capture request. This allows, for example, the + * metadata and low-resolution buffers to be returned in one call, and + * post-processed JPEG buffers in a later call, once it is available. Each + * call must include the frame number of the request it is returning + * metadata or buffers for. + * + * A component (buffer or metadata) of the complete result may only be + * included in one process_capture_result call. A buffer for each stream, + * and the result metadata, must be returned by the HAL for each request in + * one of the process_capture_result calls, even in case of errors producing + * some of the output. A call to process_capture_result() with neither + * output buffers or result metadata is not allowed. + * + * The order of returning metadata and buffers for a single result does not + * matter, but buffers for a given stream must be returned in FIFO order. So + * the buffer for request 5 for stream A must always be returned before the + * buffer for request 6 for stream A. This also applies to the result + * metadata; the metadata for request 5 must be returned before the metadata + * for request 6. + * + * However, different streams are independent of each other, so it is + * acceptable and expected that the buffer for request 5 for stream A may be + * returned after the buffer for request 6 for stream B is. And it is + * acceptable that the result metadata for request 6 for stream B is + * returned before the buffer for request 5 for stream A is. + * + * The HAL retains ownership of result structure, which only needs to be + * valid to access during this call. The framework will copy whatever it + * needs before this call returns. + * + * The output buffers do not need to be filled yet; the framework will wait + * on the stream buffer release sync fence before reading the buffer + * data. Therefore, this method should be called by the HAL as soon as + * possible, even if some or all of the output buffers are still in + * being filled. The HAL must include valid release sync fences into each + * output_buffers stream buffer entry, or -1 if that stream buffer is + * already filled. + * + * If the result buffer cannot be constructed for a request, the HAL should + * return an empty metadata buffer, but still provide the output buffers and + * their sync fences. In addition, notify() must be called with an + * ERROR_RESULT message. + * + * If an output buffer cannot be filled, its status field must be set to + * STATUS_ERROR. In addition, notify() must be called with a ERROR_BUFFER + * message. + * + * If the entire capture has failed, then this method still needs to be + * called to return the output buffers to the framework. All the buffer + * statuses should be STATUS_ERROR, and the result metadata should be an + * empty buffer. In addition, notify() must be called with a ERROR_REQUEST + * message. In this case, individual ERROR_RESULT/ERROR_BUFFER messages + * should not be sent. + * + * Performance requirements: + * + * This is a non-blocking call. The framework will return this call in 5ms. + * + * The pipeline latency (see S7 for definition) should be less than or equal to + * 4 frame intervals, and must be less than or equal to 8 frame intervals. + * + */ + void (*process_capture_result)(const struct camera3_callback_ops *, + const camera3_capture_result_t *result); + + /** + * notify: + * + * Asynchronous notification callback from the HAL, fired for various + * reasons. Only for information independent of frame capture, or that + * require specific timing. The ownership of the message structure remains + * with the HAL, and the msg only needs to be valid for the duration of this + * call. + * + * Multiple threads may call notify() simultaneously. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * The notification for the start of exposure for a given request must be + * sent by the HAL before the first call to process_capture_result() for + * that request is made. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Buffers delivered to the framework will not be dispatched to the + * application layer until a start of exposure timestamp (or input image's + * start of exposure timestamp for a reprocess request) has been received + * via a SHUTTER notify() call. It is highly recommended to dispatch this + * call as early as possible. + * + * ------------------------------------------------------------------------ + * Performance requirements: + * + * This is a non-blocking call. The framework will return this call in 5ms. + */ + void (*notify)(const struct camera3_callback_ops *, + const camera3_notify_msg_t *msg); + +} camera3_callback_ops_t; + +/********************************************************************** + * + * Camera device operations + * + */ +typedef struct camera3_device_ops { + + /** + * initialize: + * + * One-time initialization to pass framework callback function pointers to + * the HAL. Will be called once after a successful open() call, before any + * other functions are called on the camera3_device_ops structure. + * + * Performance requirements: + * + * This should be a non-blocking call. The HAL should return from this call + * in 5ms, and must return from this call in 10ms. + * + * Return values: + * + * 0: On successful initialization + * + * -ENODEV: If initialization fails. Only close() can be called successfully + * by the framework after this. + */ + int (*initialize)(const struct camera3_device *, + const camera3_callback_ops_t *callback_ops); + + /********************************************************************** + * Stream management + */ + + /** + * configure_streams: + * + * CAMERA_DEVICE_API_VERSION_3_0 only: + * + * Reset the HAL camera device processing pipeline and set up new input and + * output streams. This call replaces any existing stream configuration with + * the streams defined in the stream_list. This method will be called at + * least once after initialize() before a request is submitted with + * process_capture_request(). + * + * The stream_list must contain at least one output-capable stream, and may + * not contain more than one input-capable stream. + * + * The stream_list may contain streams that are also in the currently-active + * set of streams (from the previous call to configure_stream()). These + * streams will already have valid values for usage, max_buffers, and the + * private pointer. + * + * If such a stream has already had its buffers registered, + * register_stream_buffers() will not be called again for the stream, and + * buffers from the stream can be immediately included in input requests. + * + * If the HAL needs to change the stream configuration for an existing + * stream due to the new configuration, it may rewrite the values of usage + * and/or max_buffers during the configure call. + * + * The framework will detect such a change, and will then reallocate the + * stream buffers, and call register_stream_buffers() again before using + * buffers from that stream in a request. + * + * If a currently-active stream is not included in stream_list, the HAL may + * safely remove any references to that stream. It will not be reused in a + * later configure() call by the framework, and all the gralloc buffers for + * it will be freed after the configure_streams() call returns. + * + * The stream_list structure is owned by the framework, and may not be + * accessed once this call completes. The address of an individual + * camera3_stream_t structure will remain valid for access by the HAL until + * the end of the first configure_stream() call which no longer includes + * that camera3_stream_t in the stream_list argument. The HAL may not change + * values in the stream structure outside of the private pointer, except for + * the usage and max_buffers members during the configure_streams() call + * itself. + * + * If the stream is new, the usage, max_buffer, and private pointer fields + * of the stream structure will all be set to 0. The HAL device must set + * these fields before the configure_streams() call returns. These fields + * are then used by the framework and the platform gralloc module to + * allocate the gralloc buffers for each stream. + * + * Before such a new stream can have its buffers included in a capture + * request, the framework will call register_stream_buffers() with that + * stream. However, the framework is not required to register buffers for + * _all_ streams before submitting a request. This allows for quick startup + * of (for example) a preview stream, with allocation for other streams + * happening later or concurrently. + * + * ------------------------------------------------------------------------ + * CAMERA_DEVICE_API_VERSION_3_1 only: + * + * Reset the HAL camera device processing pipeline and set up new input and + * output streams. This call replaces any existing stream configuration with + * the streams defined in the stream_list. This method will be called at + * least once after initialize() before a request is submitted with + * process_capture_request(). + * + * The stream_list must contain at least one output-capable stream, and may + * not contain more than one input-capable stream. + * + * The stream_list may contain streams that are also in the currently-active + * set of streams (from the previous call to configure_stream()). These + * streams will already have valid values for usage, max_buffers, and the + * private pointer. + * + * If such a stream has already had its buffers registered, + * register_stream_buffers() will not be called again for the stream, and + * buffers from the stream can be immediately included in input requests. + * + * If the HAL needs to change the stream configuration for an existing + * stream due to the new configuration, it may rewrite the values of usage + * and/or max_buffers during the configure call. + * + * The framework will detect such a change, and will then reallocate the + * stream buffers, and call register_stream_buffers() again before using + * buffers from that stream in a request. + * + * If a currently-active stream is not included in stream_list, the HAL may + * safely remove any references to that stream. It will not be reused in a + * later configure() call by the framework, and all the gralloc buffers for + * it will be freed after the configure_streams() call returns. + * + * The stream_list structure is owned by the framework, and may not be + * accessed once this call completes. The address of an individual + * camera3_stream_t structure will remain valid for access by the HAL until + * the end of the first configure_stream() call which no longer includes + * that camera3_stream_t in the stream_list argument. The HAL may not change + * values in the stream structure outside of the private pointer, except for + * the usage and max_buffers members during the configure_streams() call + * itself. + * + * If the stream is new, max_buffer, and private pointer fields of the + * stream structure will all be set to 0. The usage will be set to the + * consumer usage flags. The HAL device must set these fields before the + * configure_streams() call returns. These fields are then used by the + * framework and the platform gralloc module to allocate the gralloc + * buffers for each stream. + * + * Before such a new stream can have its buffers included in a capture + * request, the framework will call register_stream_buffers() with that + * stream. However, the framework is not required to register buffers for + * _all_ streams before submitting a request. This allows for quick startup + * of (for example) a preview stream, with allocation for other streams + * happening later or concurrently. + * + * ------------------------------------------------------------------------ + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * Reset the HAL camera device processing pipeline and set up new input and + * output streams. This call replaces any existing stream configuration with + * the streams defined in the stream_list. This method will be called at + * least once after initialize() before a request is submitted with + * process_capture_request(). + * + * The stream_list must contain at least one output-capable stream, and may + * not contain more than one input-capable stream. + * + * The stream_list may contain streams that are also in the currently-active + * set of streams (from the previous call to configure_stream()). These + * streams will already have valid values for usage, max_buffers, and the + * private pointer. + * + * If the HAL needs to change the stream configuration for an existing + * stream due to the new configuration, it may rewrite the values of usage + * and/or max_buffers during the configure call. + * + * The framework will detect such a change, and may then reallocate the + * stream buffers before using buffers from that stream in a request. + * + * If a currently-active stream is not included in stream_list, the HAL may + * safely remove any references to that stream. It will not be reused in a + * later configure() call by the framework, and all the gralloc buffers for + * it will be freed after the configure_streams() call returns. + * + * The stream_list structure is owned by the framework, and may not be + * accessed once this call completes. The address of an individual + * camera3_stream_t structure will remain valid for access by the HAL until + * the end of the first configure_stream() call which no longer includes + * that camera3_stream_t in the stream_list argument. The HAL may not change + * values in the stream structure outside of the private pointer, except for + * the usage and max_buffers members during the configure_streams() call + * itself. + * + * If the stream is new, max_buffer, and private pointer fields of the + * stream structure will all be set to 0. The usage will be set to the + * consumer usage flags. The HAL device must set these fields before the + * configure_streams() call returns. These fields are then used by the + * framework and the platform gralloc module to allocate the gralloc + * buffers for each stream. + * + * Newly allocated buffers may be included in a capture request at any time + * by the framework. Once a gralloc buffer is returned to the framework + * with process_capture_result (and its respective release_fence has been + * signaled) the framework may free or reuse it at any time. + * + * ------------------------------------------------------------------------ + * + * Preconditions: + * + * The framework will only call this method when no captures are being + * processed. That is, all results have been returned to the framework, and + * all in-flight input and output buffers have been returned and their + * release sync fences have been signaled by the HAL. The framework will not + * submit new requests for capture while the configure_streams() call is + * underway. + * + * Postconditions: + * + * The HAL device must configure itself to provide maximum possible output + * frame rate given the sizes and formats of the output streams, as + * documented in the camera device's static metadata. + * + * Performance requirements: + * + * This call is expected to be heavyweight and possibly take several hundred + * milliseconds to complete, since it may require resetting and + * reconfiguring the image sensor and the camera processing pipeline. + * Nevertheless, the HAL device should attempt to minimize the + * reconfiguration delay to minimize the user-visible pauses during + * application operational mode changes (such as switching from still + * capture to video recording). + * + * The HAL should return from this call in 500ms, and must return from this + * call in 1000ms. + * + * Return values: + * + * 0: On successful stream configuration + * + * -EINVAL: If the requested stream configuration is invalid. Some examples + * of invalid stream configurations include: + * + * - Including more than 1 input-capable stream (INPUT or + * BIDIRECTIONAL) + * + * - Not including any output-capable streams (OUTPUT or + * BIDIRECTIONAL) + * + * - Including streams with unsupported formats, or an unsupported + * size for that format. + * + * - Including too many output streams of a certain format. + * + * - Unsupported rotation configuration (only applies to + * devices with version >= CAMERA_DEVICE_API_VERSION_3_3) + * + * - Stream sizes/formats don't satisfy the + * camera3_stream_configuration_t->operation_mode requirements for non-NORMAL mode, + * or the requested operation_mode is not supported by the HAL. + * (only applies to devices with version >= CAMERA_DEVICE_API_VERSION_3_3) + * + * Note that the framework submitting an invalid stream + * configuration is not normal operation, since stream + * configurations are checked before configure. An invalid + * configuration means that a bug exists in the framework code, or + * there is a mismatch between the HAL's static metadata and the + * requirements on streams. + * + * -ENODEV: If there has been a fatal error and the device is no longer + * operational. Only close() can be called successfully by the + * framework after this error is returned. + */ + int (*configure_streams)(const struct camera3_device *, + camera3_stream_configuration_t *stream_list); + + /** + * register_stream_buffers: + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * DEPRECATED. This will not be called and must be set to NULL. + * + * <= CAMERA_DEVICE_API_VERSION_3_1: + * + * Register buffers for a given stream with the HAL device. This method is + * called by the framework after a new stream is defined by + * configure_streams, and before buffers from that stream are included in a + * capture request. If the same stream is listed in a subsequent + * configure_streams() call, register_stream_buffers will _not_ be called + * again for that stream. + * + * The framework does not need to register buffers for all configured + * streams before it submits the first capture request. This allows quick + * startup for preview (or similar use cases) while other streams are still + * being allocated. + * + * This method is intended to allow the HAL device to map or otherwise + * prepare the buffers for later use. The buffers passed in will already be + * locked for use. At the end of the call, all the buffers must be ready to + * be returned to the stream. The buffer_set argument is only valid for the + * duration of this call. + * + * If the stream format was set to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + * the camera HAL should inspect the passed-in buffers here to determine any + * platform-private pixel format information. + * + * Performance requirements: + * + * This should be a non-blocking call. The HAL should return from this call + * in 1ms, and must return from this call in 5ms. + * + * Return values: + * + * 0: On successful registration of the new stream buffers + * + * -EINVAL: If the stream_buffer_set does not refer to a valid active + * stream, or if the buffers array is invalid. + * + * -ENOMEM: If there was a failure in registering the buffers. The framework + * must consider all the stream buffers to be unregistered, and can + * try to register again later. + * + * -ENODEV: If there is a fatal error, and the device is no longer + * operational. Only close() can be called successfully by the + * framework after this error is returned. + */ + int (*register_stream_buffers)(const struct camera3_device *, + const camera3_stream_buffer_set_t *buffer_set); + + /********************************************************************** + * Request creation and submission + */ + + /** + * construct_default_request_settings: + * + * Create capture settings for standard camera use cases. + * + * The device must return a settings buffer that is configured to meet the + * requested use case, which must be one of the CAMERA3_TEMPLATE_* + * enums. All request control fields must be included. + * + * The HAL retains ownership of this structure, but the pointer to the + * structure must be valid until the device is closed. The framework and the + * HAL may not modify the buffer once it is returned by this call. The same + * buffer may be returned for subsequent calls for the same template, or for + * other templates. + * + * Performance requirements: + * + * This should be a non-blocking call. The HAL should return from this call + * in 1ms, and must return from this call in 5ms. + * + * Return values: + * + * Valid metadata: On successful creation of a default settings + * buffer. + * + * NULL: In case of a fatal error. After this is returned, only + * the close() method can be called successfully by the + * framework. + */ + const camera_metadata_t* (*construct_default_request_settings)( + const struct camera3_device *, + int type); + + /** + * process_capture_request: + * + * Send a new capture request to the HAL. The HAL should not return from + * this call until it is ready to accept the next request to process. Only + * one call to process_capture_request() will be made at a time by the + * framework, and the calls will all be from the same thread. The next call + * to process_capture_request() will be made as soon as a new request and + * its associated buffers are available. In a normal preview scenario, this + * means the function will be called again by the framework almost + * instantly. + * + * The actual request processing is asynchronous, with the results of + * capture being returned by the HAL through the process_capture_result() + * call. This call requires the result metadata to be available, but output + * buffers may simply provide sync fences to wait on. Multiple requests are + * expected to be in flight at once, to maintain full output frame rate. + * + * The framework retains ownership of the request structure. It is only + * guaranteed to be valid during this call. The HAL device must make copies + * of the information it needs to retain for the capture processing. The HAL + * is responsible for waiting on and closing the buffers' fences and + * returning the buffer handles to the framework. + * + * The HAL must write the file descriptor for the input buffer's release + * sync fence into input_buffer->release_fence, if input_buffer is not + * NULL. If the HAL returns -1 for the input buffer release sync fence, the + * framework is free to immediately reuse the input buffer. Otherwise, the + * framework will wait on the sync fence before refilling and reusing the + * input buffer. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * + * The input/output buffers provided by the framework in each request + * may be brand new (having never before seen by the HAL). + * + * ------------------------------------------------------------------------ + * Performance considerations: + * + * Handling a new buffer should be extremely lightweight and there should be + * no frame rate degradation or frame jitter introduced. + * + * This call must return fast enough to ensure that the requested frame + * rate can be sustained, especially for streaming cases (post-processing + * quality settings set to FAST). The HAL should return this call in 1 + * frame interval, and must return from this call in 4 frame intervals. + * + * Return values: + * + * 0: On a successful start to processing the capture request + * + * -EINVAL: If the input is malformed (the settings are NULL when not + * allowed, there are 0 output buffers, etc) and capture processing + * cannot start. Failures during request processing should be + * handled by calling camera3_callback_ops_t.notify(). In case of + * this error, the framework will retain responsibility for the + * stream buffers' fences and the buffer handles; the HAL should + * not close the fences or return these buffers with + * process_capture_result. + * + * -ENODEV: If the camera device has encountered a serious error. After this + * error is returned, only the close() method can be successfully + * called by the framework. + * + */ + int (*process_capture_request)(const struct camera3_device *, + camera3_capture_request_t *request); + + /********************************************************************** + * Miscellaneous methods + */ + + /** + * get_metadata_vendor_tag_ops: + * + * Get methods to query for vendor extension metadata tag information. The + * HAL should fill in all the vendor tag operation methods, or leave ops + * unchanged if no vendor tags are defined. + * + * The definition of vendor_tag_query_ops_t can be found in + * system/media/camera/include/system/camera_metadata.h. + * + * >= CAMERA_DEVICE_API_VERSION_3_2: + * DEPRECATED. This function has been deprecated and should be set to + * NULL by the HAL. Please implement get_vendor_tag_ops in camera_common.h + * instead. + */ + void (*get_metadata_vendor_tag_ops)(const struct camera3_device*, + vendor_tag_query_ops_t* ops); + + /** + * dump: + * + * Print out debugging state for the camera device. This will be called by + * the framework when the camera service is asked for a debug dump, which + * happens when using the dumpsys tool, or when capturing a bugreport. + * + * The passed-in file descriptor can be used to write debugging text using + * dprintf() or write(). The text should be in ASCII encoding only. + * + * Performance requirements: + * + * This must be a non-blocking call. The HAL should return from this call + * in 1ms, must return from this call in 10ms. This call must avoid + * deadlocks, as it may be called at any point during camera operation. + * Any synchronization primitives used (such as mutex locks or semaphores) + * should be acquired with a timeout. + */ + void (*dump)(const struct camera3_device *, int fd); + + /** + * flush: + * + * Flush all currently in-process captures and all buffers in the pipeline + * on the given device. The framework will use this to dump all state as + * quickly as possible in order to prepare for a configure_streams() call. + * + * No buffers are required to be successfully returned, so every buffer + * held at the time of flush() (whether successfully filled or not) may be + * returned with CAMERA3_BUFFER_STATUS_ERROR. Note the HAL is still allowed + * to return valid (CAMERA3_BUFFER_STATUS_OK) buffers during this call, + * provided they are successfully filled. + * + * All requests currently in the HAL are expected to be returned as soon as + * possible. Not-in-process requests should return errors immediately. Any + * interruptible hardware blocks should be stopped, and any uninterruptible + * blocks should be waited on. + * + * flush() may be called concurrently to process_capture_request(), with the expectation that + * process_capture_request will return quickly and the request submitted in that + * process_capture_request call is treated like all other in-flight requests. Due to + * concurrency issues, it is possible that from the HAL's point of view, a + * process_capture_request() call may be started after flush has been invoked but has not + * returned yet. If such a call happens before flush() returns, the HAL should treat the new + * capture request like other in-flight pending requests (see #4 below). + * + * More specifically, the HAL must follow below requirements for various cases: + * + * 1. For captures that are too late for the HAL to cancel/stop, and will be + * completed normally by the HAL; i.e. the HAL can send shutter/notify and + * process_capture_result and buffers as normal. + * + * 2. For pending requests that have not done any processing, the HAL must call notify + * CAMERA3_MSG_ERROR_REQUEST, and return all the output buffers with + * process_capture_result in the error state (CAMERA3_BUFFER_STATUS_ERROR). + * The HAL must not place the release fence into an error state, instead, + * the release fences must be set to the acquire fences passed by the framework, + * or -1 if they have been waited on by the HAL already. This is also the path + * to follow for any captures for which the HAL already called notify() with + * CAMERA3_MSG_SHUTTER but won't be producing any metadata/valid buffers for. + * After CAMERA3_MSG_ERROR_REQUEST, for a given frame, only process_capture_results with + * buffers in CAMERA3_BUFFER_STATUS_ERROR are allowed. No further notifys or + * process_capture_result with non-null metadata is allowed. + * + * 3. For partially completed pending requests that will not have all the output + * buffers or perhaps missing metadata, the HAL should follow below: + * + * 3.1. Call notify with CAMERA3_MSG_ERROR_RESULT if some of the expected result + * metadata (i.e. one or more partial metadata) won't be available for the capture. + * + * 3.2. Call notify with CAMERA3_MSG_ERROR_BUFFER for every buffer that won't + * be produced for the capture. + * + * 3.3 Call notify with CAMERA3_MSG_SHUTTER with the capture timestamp before + * any buffers/metadata are returned with process_capture_result. + * + * 3.4 For captures that will produce some results, the HAL must not call + * CAMERA3_MSG_ERROR_REQUEST, since that indicates complete failure. + * + * 3.5. Valid buffers/metadata should be passed to the framework as normal. + * + * 3.6. Failed buffers should be returned to the framework as described for case 2. + * But failed buffers do not have to follow the strict ordering valid buffers do, + * and may be out-of-order with respect to valid buffers. For example, if buffers + * A, B, C, D, E are sent, D and E are failed, then A, E, B, D, C is an acceptable + * return order. + * + * 3.7. For fully-missing metadata, calling CAMERA3_MSG_ERROR_RESULT is sufficient, no + * need to call process_capture_result with NULL metadata or equivalent. + * + * 4. If a flush() is invoked while a process_capture_request() invocation is active, that + * process call should return as soon as possible. In addition, if a process_capture_request() + * call is made after flush() has been invoked but before flush() has returned, the + * capture request provided by the late process_capture_request call should be treated like + * a pending request in case #2 above. + * + * flush() should only return when there are no more outstanding buffers or + * requests left in the HAL. The framework may call configure_streams (as + * the HAL state is now quiesced) or may issue new requests. + * + * Note that it's sufficient to only support fully-succeeded and fully-failed result cases. + * However, it is highly desirable to support the partial failure cases as well, as it + * could help improve the flush call overall performance. + * + * Performance requirements: + * + * The HAL should return from this call in 100ms, and must return from this + * call in 1000ms. And this call must not be blocked longer than pipeline + * latency (see S7 for definition). + * + * Version information: + * + * only available if device version >= CAMERA_DEVICE_API_VERSION_3_1. + * + * Return values: + * + * 0: On a successful flush of the camera HAL. + * + * -EINVAL: If the input is malformed (the device is not valid). + * + * -ENODEV: If the camera device has encountered a serious error. After this + * error is returned, only the close() method can be successfully + * called by the framework. + */ + int (*flush)(const struct camera3_device *); + + /* reserved for future use */ + void *reserved[8]; +} camera3_device_ops_t; + +/********************************************************************** + * + * Camera device definition + * + */ +typedef struct camera3_device { + /** + * common.version must equal CAMERA_DEVICE_API_VERSION_3_0 to identify this + * device as implementing version 3.0 of the camera device HAL. + * + * Performance requirements: + * + * Camera open (common.module->common.methods->open) should return in 200ms, and must return + * in 500ms. + * Camera close (common.close) should return in 200ms, and must return in 500ms. + * + */ + hw_device_t common; + camera3_device_ops_t *ops; + void *priv; +} camera3_device_t; + +__END_DECLS + +#endif /* #ifdef ANDROID_INCLUDE_CAMERA3_H */
diff --git a/libhardware/include/hardware/camera_common.h b/libhardware/include/hardware/camera_common.h new file mode 100644 index 0000000..7658dd4 --- /dev/null +++ b/libhardware/include/hardware/camera_common.h
@@ -0,0 +1,916 @@ +/* + * Copyright (C) 2012 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. + */ + +// FIXME: add well-defined names for cameras + +#ifndef ANDROID_INCLUDE_CAMERA_COMMON_H +#define ANDROID_INCLUDE_CAMERA_COMMON_H + +#include <stdint.h> +#include <stdbool.h> +#include <sys/cdefs.h> +#include <sys/types.h> +#include <cutils/native_handle.h> +#include <system/camera.h> +#include <system/camera_vendor_tags.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define CAMERA_HARDWARE_MODULE_ID "camera" + +/** + * Module versioning information for the Camera hardware module, based on + * camera_module_t.common.module_api_version. The two most significant hex + * digits represent the major version, and the two least significant represent + * the minor version. + * + ******************************************************************************* + * Versions: 0.X - 1.X [CAMERA_MODULE_API_VERSION_1_0] + * + * Camera modules that report these version numbers implement the initial + * camera module HAL interface. All camera devices openable through this + * module support only version 1 of the camera device HAL. The device_version + * and static_camera_characteristics fields of camera_info are not valid. Only + * the android.hardware.Camera API can be supported by this module and its + * devices. + * + ******************************************************************************* + * Version: 2.0 [CAMERA_MODULE_API_VERSION_2_0] + * + * Camera modules that report this version number implement the second version + * of the camera module HAL interface. Camera devices openable through this + * module may support either version 1.0 or version 2.0 of the camera device + * HAL interface. The device_version field of camera_info is always valid; the + * static_camera_characteristics field of camera_info is valid if the + * device_version field is 2.0 or higher. + * + ******************************************************************************* + * Version: 2.1 [CAMERA_MODULE_API_VERSION_2_1] + * + * This camera module version adds support for asynchronous callbacks to the + * framework from the camera HAL module, which is used to notify the framework + * about changes to the camera module state. Modules that provide a valid + * set_callbacks() method must report at least this version number. + * + ******************************************************************************* + * Version: 2.2 [CAMERA_MODULE_API_VERSION_2_2] + * + * This camera module version adds vendor tag support from the module, and + * deprecates the old vendor_tag_query_ops that were previously only + * accessible with a device open. + * + ******************************************************************************* + * Version: 2.3 [CAMERA_MODULE_API_VERSION_2_3] + * + * This camera module version adds open legacy camera HAL device support. + * Framework can use it to open the camera device as lower device HAL version + * HAL device if the same device can support multiple device API versions. + * The standard hardware module open call (common.methods->open) continues + * to open the camera device with the latest supported version, which is + * also the version listed in camera_info_t.device_version. + * + ******************************************************************************* + * Version: 2.4 [CAMERA_MODULE_API_VERSION_2_4] + * + * This camera module version adds below API changes: + * + * 1. Torch mode support. The framework can use it to turn on torch mode for + * any camera device that has a flash unit, without opening a camera device. The + * camera device has a higher priority accessing the flash unit than the camera + * module; opening a camera device will turn off the torch if it had been enabled + * through the module interface. When there are any resource conflicts, such as + * open() is called to open a camera device, the camera HAL module must notify the + * framework through the torch mode status callback that the torch mode has been + * turned off. + * + * 2. External camera (e.g. USB hot-plug camera) support. The API updates specify that + * the camera static info is only available when camera is connected and ready to + * use for external hot-plug cameras. Calls to get static info will be invalid + * calls when camera status is not CAMERA_DEVICE_STATUS_PRESENT. The frameworks + * will only count on device status change callbacks to manage the available external + * camera list. + * + * 3. Camera arbitration hints. This module version adds support for explicitly + * indicating the number of camera devices that can be simultaneously opened and used. + * To specify valid combinations of devices, the resource_cost and conflicting_devices + * fields should always be set in the camera_info structure returned by the + * get_camera_info call. + * + * 4. Module initialization method. This will be called by the camera service + * right after the HAL module is loaded, to allow for one-time initialization + * of the HAL. It is called before any other module methods are invoked. + */ + +/** + * Predefined macros for currently-defined version numbers + */ + +/** + * All module versions <= HARDWARE_MODULE_API_VERSION(1, 0xFF) must be treated + * as CAMERA_MODULE_API_VERSION_1_0 + */ +#define CAMERA_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define CAMERA_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0) +#define CAMERA_MODULE_API_VERSION_2_1 HARDWARE_MODULE_API_VERSION(2, 1) +#define CAMERA_MODULE_API_VERSION_2_2 HARDWARE_MODULE_API_VERSION(2, 2) +#define CAMERA_MODULE_API_VERSION_2_3 HARDWARE_MODULE_API_VERSION(2, 3) +#define CAMERA_MODULE_API_VERSION_2_4 HARDWARE_MODULE_API_VERSION(2, 4) + +#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_4 + +/** + * All device versions <= HARDWARE_DEVICE_API_VERSION(1, 0xFF) must be treated + * as CAMERA_DEVICE_API_VERSION_1_0 + */ +#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define CAMERA_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) +#define CAMERA_DEVICE_API_VERSION_2_1 HARDWARE_DEVICE_API_VERSION(2, 1) +#define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0) +#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1) +#define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2) +#define CAMERA_DEVICE_API_VERSION_3_3 HARDWARE_DEVICE_API_VERSION(3, 3) + +// Device version 3.3 is current, older HAL camera device versions are not +// recommended for new devices. +#define CAMERA_DEVICE_API_VERSION_CURRENT CAMERA_DEVICE_API_VERSION_3_3 + +/** + * Defined in /system/media/camera/include/system/camera_metadata.h + */ +typedef struct camera_metadata camera_metadata_t; + +typedef struct camera_info { + /** + * The direction that the camera faces to. See system/core/include/system/camera.h + * for camera facing definitions. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * It should be CAMERA_FACING_BACK or CAMERA_FACING_FRONT. + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * It should be CAMERA_FACING_BACK, CAMERA_FACING_FRONT or + * CAMERA_FACING_EXTERNAL. + */ + int facing; + + /** + * The orientation of the camera image. The value is the angle that the + * camera image needs to be rotated clockwise so it shows correctly on the + * display in its natural orientation. It should be 0, 90, 180, or 270. + * + * For example, suppose a device has a naturally tall screen. The + * back-facing camera sensor is mounted in landscape. You are looking at the + * screen. If the top side of the camera sensor is aligned with the right + * edge of the screen in natural orientation, the value should be 90. If the + * top side of a front-facing camera sensor is aligned with the right of the + * screen, the value should be 270. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * Valid in all camera_module versions. + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * Valid if camera facing is CAMERA_FACING_BACK or CAMERA_FACING_FRONT, + * not valid if camera facing is CAMERA_FACING_EXTERNAL. + */ + int orientation; + + /** + * The value of camera_device_t.common.version. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_0: + * + * Not valid. Can be assumed to be CAMERA_DEVICE_API_VERSION_1_0. Do + * not read this field. + * + * CAMERA_MODULE_API_VERSION_2_0 or higher: + * + * Always valid + * + */ + uint32_t device_version; + + /** + * The camera's fixed characteristics, which include all static camera metadata + * specified in system/media/camera/docs/docs.html. This should be a sorted metadata + * buffer, and may not be modified or freed by the caller. The pointer should remain + * valid for the lifetime of the camera module, and values in it may not + * change after it is returned by get_camera_info(). + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_0: + * + * Not valid. Extra characteristics are not available. Do not read this + * field. + * + * CAMERA_MODULE_API_VERSION_2_0 or higher: + * + * Valid if device_version >= CAMERA_DEVICE_API_VERSION_2_0. Do not read + * otherwise. + * + */ + const camera_metadata_t *static_camera_characteristics; + + /** + * The total resource "cost" of using this camera, represented as an integer + * value in the range [0, 100] where 100 represents total usage of the shared + * resource that is the limiting bottleneck of the camera subsystem. This may + * be a very rough estimate, and is used as a hint to the camera service to + * determine when to disallow multiple applications from simultaneously + * opening different cameras advertised by the camera service. + * + * The camera service must be able to simultaneously open and use any + * combination of camera devices exposed by the HAL where the sum of + * the resource costs of these cameras is <= 100. For determining cost, + * each camera device must be assumed to be configured and operating at + * the maximally resource-consuming framerate and stream size settings + * available in the configuration settings exposed for that device through + * the camera metadata. + * + * The camera service may still attempt to simultaneously open combinations + * of camera devices with a total resource cost > 100. This may succeed or + * fail. If this succeeds, combinations of configurations that are not + * supported due to resource constraints from having multiple open devices + * should fail during the configure calls. If the total resource cost is + * <= 100, open and configure should never fail for any stream configuration + * settings or other device capabilities that would normally succeed for a + * device when it is the only open camera device. + * + * This field will be used to determine whether background applications are + * allowed to use this camera device while other applications are using other + * camera devices. Note: multiple applications will never be allowed by the + * camera service to simultaneously open the same camera device. + * + * Example use cases: + * + * Ex. 1: Camera Device 0 = Back Camera + * Camera Device 1 = Front Camera + * - Using both camera devices causes a large framerate slowdown due to + * limited ISP bandwidth. + * + * Configuration: + * + * Camera Device 0 - resource_cost = 51 + * conflicting_devices = null + * Camera Device 1 - resource_cost = 51 + * conflicting_devices = null + * + * Result: + * + * Since the sum of the resource costs is > 100, if a higher-priority + * application has either device open, no lower-priority applications will be + * allowed by the camera service to open either device. If a lower-priority + * application is using a device that a higher-priority subsequently attempts + * to open, the lower-priority application will be forced to disconnect the + * the device. + * + * If the highest-priority application chooses, it may still attempt to open + * both devices (since these devices are not listed as conflicting in the + * conflicting_devices fields), but usage of these devices may fail in the + * open or configure calls. + * + * Ex. 2: Camera Device 0 = Left Back Camera + * Camera Device 1 = Right Back Camera + * Camera Device 2 = Combined stereo camera using both right and left + * back camera sensors used by devices 0, and 1 + * Camera Device 3 = Front Camera + * - Due to do hardware constraints, up to two cameras may be open at once. The + * combined stereo camera may never be used at the same time as either of the + * two back camera devices (device 0, 1), and typically requires too much + * bandwidth to use at the same time as the front camera (device 3). + * + * Configuration: + * + * Camera Device 0 - resource_cost = 50 + * conflicting_devices = { 2 } + * Camera Device 1 - resource_cost = 50 + * conflicting_devices = { 2 } + * Camera Device 2 - resource_cost = 100 + * conflicting_devices = { 0, 1 } + * Camera Device 3 - resource_cost = 50 + * conflicting_devices = null + * + * Result: + * + * Based on the conflicting_devices fields, the camera service guarantees that + * the following sets of open devices will never be allowed: { 1, 2 }, { 0, 2 }. + * + * Based on the resource_cost fields, if a high-priority foreground application + * is using camera device 0, a background application would be allowed to open + * camera device 1 or 3 (but would be forced to disconnect it again if the + * foreground application opened another device). + * + * The highest priority application may still attempt to simultaneously open + * devices 0, 2, and 3, but the HAL may fail in open or configure calls for + * this combination. + * + * Ex. 3: Camera Device 0 = Back Camera + * Camera Device 1 = Front Camera + * Camera Device 2 = Low-power Front Camera that uses the same + * sensor as device 1, but only exposes image stream + * resolutions that can be used in low-power mode + * - Using both front cameras (device 1, 2) at the same time is impossible due + * a shared physical sensor. Using the back and "high-power" front camera + * (device 1) may be impossible for some stream configurations due to hardware + * limitations, but the "low-power" front camera option may always be used as + * it has special dedicated hardware. + * + * Configuration: + * + * Camera Device 0 - resource_cost = 100 + * conflicting_devices = null + * Camera Device 1 - resource_cost = 100 + * conflicting_devices = { 2 } + * Camera Device 2 - resource_cost = 0 + * conflicting_devices = { 1 } + * Result: + * + * Based on the conflicting_devices fields, the camera service guarantees that + * the following sets of open devices will never be allowed: { 1, 2 }. + * + * Based on the resource_cost fields, only the highest priority application + * may attempt to open both device 0 and 1 at the same time. If a higher-priority + * application is not using device 1 or 2, a low-priority background application + * may open device 2 (but will be forced to disconnect it if a higher-priority + * application subsequently opens device 1 or 2). + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * Not valid. Can be assumed to be 100. Do not read this field. + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * Always valid. + */ + int resource_cost; + + /** + * An array of camera device IDs represented as NULL-terminated strings + * indicating other devices that cannot be simultaneously opened while this + * camera device is in use. + * + * This field is intended to be used to indicate that this camera device + * is a composite of several other camera devices, or otherwise has + * hardware dependencies that prohibit simultaneous usage. If there are no + * dependencies, a NULL may be returned in this field to indicate this. + * + * The camera service will never simultaneously open any of the devices + * in this list while this camera device is open. + * + * The strings pointed to in this field will not be cleaned up by the camera + * service, and must remain while this device is plugged in. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * Not valid. Can be assumed to be NULL. Do not read this field. + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * Always valid. + */ + char** conflicting_devices; + + /** + * The length of the array given in the conflicting_devices field. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * Not valid. Can be assumed to be 0. Do not read this field. + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * Always valid. + */ + size_t conflicting_devices_length; + +} camera_info_t; + +/** + * camera_device_status_t: + * + * The current status of the camera device, as provided by the HAL through the + * camera_module_callbacks.camera_device_status_change() call. + * + * At module load time, the framework will assume all camera devices are in the + * CAMERA_DEVICE_STATUS_PRESENT state. The HAL should invoke + * camera_module_callbacks::camera_device_status_change to inform the framework + * of any initially NOT_PRESENT devices. + * + * Allowed transitions: + * PRESENT -> NOT_PRESENT + * NOT_PRESENT -> ENUMERATING + * NOT_PRESENT -> PRESENT + * ENUMERATING -> PRESENT + * ENUMERATING -> NOT_PRESENT + */ +typedef enum camera_device_status { + /** + * The camera device is not currently connected, and opening it will return + * failure. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * Calls to get_camera_info must still succeed, and provide the same information + * it would if the camera were connected. + * + * CAMERA_MODULE_API_VERSION_2_4: + * + * The camera device at this status must return -EINVAL for get_camera_info call, + * as the device is not connected. + */ + CAMERA_DEVICE_STATUS_NOT_PRESENT = 0, + + /** + * The camera device is connected, and opening it will succeed. + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * The information returned by get_camera_info cannot change due to this status + * change. By default, the framework will assume all devices are in this state. + * + * CAMERA_MODULE_API_VERSION_2_4: + * + * The information returned by get_camera_info will become valid after a device's + * status changes to this. By default, the framework will assume all devices are in + * this state. + */ + CAMERA_DEVICE_STATUS_PRESENT = 1, + + /** + * The camera device is connected, but it is undergoing an enumeration and + * so opening the device will return -EBUSY. + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * Calls to get_camera_info must still succeed, as if the camera was in the + * PRESENT status. + * + * CAMERA_MODULE_API_VERSION_2_4: + * + * The camera device at this status must return -EINVAL for get_camera_info for call, + * as the device is not ready. + */ + CAMERA_DEVICE_STATUS_ENUMERATING = 2, + +} camera_device_status_t; + +/** + * torch_mode_status_t: + * + * The current status of the torch mode, as provided by the HAL through the + * camera_module_callbacks.torch_mode_status_change() call. + * + * The torch mode status of a camera device is applicable only when the camera + * device is present. The framework will not call set_torch_mode() to turn on + * torch mode of a camera device if the camera device is not present. At module + * load time, the framework will assume torch modes are in the + * TORCH_MODE_STATUS_AVAILABLE_OFF state if the camera device is present and + * android.flash.info.available is reported as true via get_camera_info() call. + * + * The behaviors of the camera HAL module that the framework expects in the + * following situations when a camera device's status changes: + * 1. A previously-disconnected camera device becomes connected. + * After camera_module_callbacks::camera_device_status_change() is invoked + * to inform the framework that the camera device is present, the framework + * will assume the camera device's torch mode is in + * TORCH_MODE_STATUS_AVAILABLE_OFF state. The camera HAL module does not need + * to invoke camera_module_callbacks::torch_mode_status_change() unless the + * flash unit is unavailable to use by set_torch_mode(). + * + * 2. A previously-connected camera becomes disconnected. + * After camera_module_callbacks::camera_device_status_change() is invoked + * to inform the framework that the camera device is not present, the + * framework will not call set_torch_mode() for the disconnected camera + * device until its flash unit becomes available again. The camera HAL + * module does not need to invoke + * camera_module_callbacks::torch_mode_status_change() separately to inform + * that the flash unit has become unavailable. + * + * 3. open() is called to open a camera device. + * The camera HAL module must invoke + * camera_module_callbacks::torch_mode_status_change() for all flash units + * that have entered TORCH_MODE_STATUS_NOT_AVAILABLE state and can not be + * turned on by calling set_torch_mode() anymore due to this open() call. + * open() must not trigger TORCH_MODE_STATUS_AVAILABLE_OFF before + * TORCH_MODE_STATUS_NOT_AVAILABLE for all flash units that have become + * unavailable. + * + * 4. close() is called to close a camera device. + * The camera HAL module must invoke + * camera_module_callbacks::torch_mode_status_change() for all flash units + * that have entered TORCH_MODE_STATUS_AVAILABLE_OFF state and can be turned + * on by calling set_torch_mode() again because of enough resources freed + * up by this close() call. + * + * Note that the framework calling set_torch_mode() successfully must trigger + * TORCH_MODE_STATUS_AVAILABLE_OFF or TORCH_MODE_STATUS_AVAILABLE_ON callback + * for the given camera device. Additionally it must trigger + * TORCH_MODE_STATUS_AVAILABLE_OFF callbacks for other previously-on torch + * modes if HAL cannot keep multiple torch modes on simultaneously. + */ +typedef enum torch_mode_status { + + /** + * The flash unit is no longer available and the torch mode can not be + * turned on by calling set_torch_mode(). If the torch mode is on, it + * will be turned off by HAL before HAL calls torch_mode_status_change(). + */ + TORCH_MODE_STATUS_NOT_AVAILABLE = 0, + + /** + * A torch mode has become off and available to be turned on via + * set_torch_mode(). This may happen in the following + * cases: + * 1. After the resources to turn on the torch mode have become available. + * 2. After set_torch_mode() is called to turn off the torch mode. + * 3. After the framework turned on the torch mode of some other camera + * device and HAL had to turn off the torch modes of any camera devices + * that were previously on. + */ + TORCH_MODE_STATUS_AVAILABLE_OFF = 1, + + /** + * A torch mode has become on and available to be turned off via + * set_torch_mode(). This can happen only after set_torch_mode() is called + * to turn on the torch mode. + */ + TORCH_MODE_STATUS_AVAILABLE_ON = 2, + +} torch_mode_status_t; + +/** + * Callback functions for the camera HAL module to use to inform the framework + * of changes to the camera subsystem. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * Each callback is called only by HAL modules implementing the indicated + * version or higher of the HAL module API interface. + * + * CAMERA_MODULE_API_VERSION_2_1: + * camera_device_status_change() + * + * CAMERA_MODULE_API_VERSION_2_4: + * torch_mode_status_change() + + */ +typedef struct camera_module_callbacks { + + /** + * camera_device_status_change: + * + * Callback to the framework to indicate that the state of a specific camera + * device has changed. At module load time, the framework will assume all + * camera devices are in the CAMERA_DEVICE_STATUS_PRESENT state. The HAL + * must call this method to inform the framework of any initially + * NOT_PRESENT devices. + * + * This callback is added for CAMERA_MODULE_API_VERSION_2_1. + * + * camera_module_callbacks: The instance of camera_module_callbacks_t passed + * to the module with set_callbacks. + * + * camera_id: The ID of the camera device that has a new status. + * + * new_status: The new status code, one of the camera_device_status_t enums, + * or a platform-specific status. + * + */ + void (*camera_device_status_change)(const struct camera_module_callbacks*, + int camera_id, + int new_status); + + /** + * torch_mode_status_change: + * + * Callback to the framework to indicate that the state of the torch mode + * of the flash unit associated with a specific camera device has changed. + * At module load time, the framework will assume the torch modes are in + * the TORCH_MODE_STATUS_AVAILABLE_OFF state if android.flash.info.available + * is reported as true via get_camera_info() call. + * + * This callback is added for CAMERA_MODULE_API_VERSION_2_4. + * + * camera_module_callbacks: The instance of camera_module_callbacks_t + * passed to the module with set_callbacks. + * + * camera_id: The ID of camera device whose flash unit has a new torch mode + * status. + * + * new_status: The new status code, one of the torch_mode_status_t enums. + */ + void (*torch_mode_status_change)(const struct camera_module_callbacks*, + const char* camera_id, + int new_status); + + +} camera_module_callbacks_t; + +typedef struct camera_module { + /** + * Common methods of the camera module. This *must* be the first member of + * camera_module as users of this structure will cast a hw_module_t to + * camera_module pointer in contexts where it's known the hw_module_t + * references a camera_module. + * + * The return values for common.methods->open for camera_module are: + * + * 0: On a successful open of the camera device. + * + * -ENODEV: The camera device cannot be opened due to an internal + * error. + * + * -EINVAL: The input arguments are invalid, i.e. the id is invalid, + * and/or the module is invalid. + * + * -EBUSY: The camera device was already opened for this camera id + * (by using this method or open_legacy), + * regardless of the device HAL version it was opened as. + * + * -EUSERS: The maximal number of camera devices that can be + * opened concurrently were opened already, either by + * this method or the open_legacy method. + * + * All other return values from common.methods->open will be treated as + * -ENODEV. + */ + hw_module_t common; + + /** + * get_number_of_cameras: + * + * Returns the number of camera devices accessible through the camera + * module. The camera devices are numbered 0 through N-1, where N is the + * value returned by this call. The name of the camera device for open() is + * simply the number converted to a string. That is, "0" for camera ID 0, + * "1" for camera ID 1. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_3 or lower: + * + * The value here must be static, and cannot change after the first call + * to this method. + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * The value here must be static, and must count only built-in cameras, + * which have CAMERA_FACING_BACK or CAMERA_FACING_FRONT camera facing values + * (camera_info.facing). The HAL must not include the external cameras + * (camera_info.facing == CAMERA_FACING_EXTERNAL) into the return value + * of this call. Frameworks will use camera_device_status_change callback + * to manage number of external cameras. + */ + int (*get_number_of_cameras)(void); + + /** + * get_camera_info: + * + * Return the static camera information for a given camera device. This + * information may not change for a camera device. + * + * Return values: + * + * 0: On a successful operation + * + * -ENODEV: The information cannot be provided due to an internal + * error. + * + * -EINVAL: The input arguments are invalid, i.e. the id is invalid, + * and/or the module is invalid. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_2_4 or higher: + * + * When a camera is disconnected, its camera id becomes invalid. Calling this + * this method with this invalid camera id will get -EINVAL and NULL camera + * static metadata (camera_info.static_camera_characteristics). + */ + int (*get_camera_info)(int camera_id, struct camera_info *info); + + /** + * set_callbacks: + * + * Provide callback function pointers to the HAL module to inform framework + * of asynchronous camera module events. The framework will call this + * function once after initial camera HAL module load, after the + * get_number_of_cameras() method is called for the first time, and before + * any other calls to the module. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_0, CAMERA_MODULE_API_VERSION_2_0: + * + * Not provided by HAL module. Framework may not call this function. + * + * CAMERA_MODULE_API_VERSION_2_1: + * + * Valid to be called by the framework. + * + * Return values: + * + * 0: On a successful operation + * + * -ENODEV: The operation cannot be completed due to an internal + * error. + * + * -EINVAL: The input arguments are invalid, i.e. the callbacks are + * null + */ + int (*set_callbacks)(const camera_module_callbacks_t *callbacks); + + /** + * get_vendor_tag_ops: + * + * Get methods to query for vendor extension metadata tag information. The + * HAL should fill in all the vendor tag operation methods, or leave ops + * unchanged if no vendor tags are defined. + * + * The vendor_tag_ops structure used here is defined in: + * system/media/camera/include/system/vendor_tags.h + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1: + * Not provided by HAL module. Framework may not call this function. + * + * CAMERA_MODULE_API_VERSION_2_2: + * Valid to be called by the framework. + */ + void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops); + + /** + * open_legacy: + * + * Open a specific legacy camera HAL device if multiple device HAL API + * versions are supported by this camera HAL module. For example, if the + * camera module supports both CAMERA_DEVICE_API_VERSION_1_0 and + * CAMERA_DEVICE_API_VERSION_3_2 device API for the same camera id, + * framework can call this function to open the camera device as + * CAMERA_DEVICE_API_VERSION_1_0 device. + * + * This is an optional method. A Camera HAL module does not need to support + * more than one device HAL version per device, and such modules may return + * -ENOSYS for all calls to this method. For all older HAL device API + * versions that are not supported, it may return -EOPNOTSUPP. When above + * cases occur, The normal open() method (common.methods->open) will be + * used by the framework instead. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2: + * Not provided by HAL module. Framework will not call this function. + * + * CAMERA_MODULE_API_VERSION_2_3: + * Valid to be called by the framework. + * + * Return values: + * + * 0: On a successful open of the camera device. + * + * -ENOSYS This method is not supported. + * + * -EOPNOTSUPP: The requested HAL version is not supported by this method. + * + * -EINVAL: The input arguments are invalid, i.e. the id is invalid, + * and/or the module is invalid. + * + * -EBUSY: The camera device was already opened for this camera id + * (by using this method or common.methods->open method), + * regardless of the device HAL version it was opened as. + * + * -EUSERS: The maximal number of camera devices that can be + * opened concurrently were opened already, either by + * this method or common.methods->open method. + */ + int (*open_legacy)(const struct hw_module_t* module, const char* id, + uint32_t halVersion, struct hw_device_t** device); + + /** + * set_torch_mode: + * + * Turn on or off the torch mode of the flash unit associated with a given + * camera ID. If the operation is successful, HAL must notify the framework + * torch state by invoking + * camera_module_callbacks.torch_mode_status_change() with the new state. + * + * The camera device has a higher priority accessing the flash unit. When + * there are any resource conflicts, such as open() is called to open a + * camera device, HAL module must notify the framework through + * camera_module_callbacks.torch_mode_status_change() that the + * torch mode has been turned off and the torch mode state has become + * TORCH_MODE_STATUS_NOT_AVAILABLE. When resources to turn on torch mode + * become available again, HAL module must notify the framework through + * camera_module_callbacks.torch_mode_status_change() that the torch mode + * state has become TORCH_MODE_STATUS_AVAILABLE_OFF for set_torch_mode() to + * be called. + * + * When the framework calls set_torch_mode() to turn on the torch mode of a + * flash unit, if HAL cannot keep multiple torch modes on simultaneously, + * HAL should turn off the torch mode that was turned on by + * a previous set_torch_mode() call and notify the framework that the torch + * mode state of that flash unit has become TORCH_MODE_STATUS_AVAILABLE_OFF. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2/2_3: + * Not provided by HAL module. Framework will not call this function. + * + * CAMERA_MODULE_API_VERSION_2_4: + * Valid to be called by the framework. + * + * Return values: + * + * 0: On a successful operation. + * + * -ENOSYS: The camera device does not support this operation. It is + * returned if and only if android.flash.info.available is + * false. + * + * -EBUSY: The camera device is already in use. + * + * -EUSERS: The resources needed to turn on the torch mode are not + * available, typically because other camera devices are + * holding the resources to make using the flash unit not + * possible. + * + * -EINVAL: camera_id is invalid. + * + */ + int (*set_torch_mode)(const char* camera_id, bool enabled); + + /** + * init: + * + * This method is called by the camera service before any other methods + * are invoked, right after the camera HAL library has been successfully + * loaded. It may be left as NULL by the HAL module, if no initialization + * in needed. + * + * It can be used by HAL implementations to perform initialization and + * other one-time operations. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2/2_3: + * Not provided by HAL module. Framework will not call this function. + * + * CAMERA_MODULE_API_VERSION_2_4: + * If not NULL, will always be called by the framework once after the HAL + * module is loaded, before any other HAL module method is called. + * + * Return values: + * + * 0: On a successful operation. + * + * -ENODEV: Initialization cannot be completed due to an internal + * error. The HAL must be assumed to be in a nonfunctional + * state. + * + */ + int (*init)(); + + /* reserved for future use */ + void* reserved[5]; +} camera_module_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_CAMERA_COMMON_H */
diff --git a/libhardware/include/hardware/consumerir.h b/libhardware/include/hardware/consumerir.h new file mode 100644 index 0000000..15334c1 --- /dev/null +++ b/libhardware/include/hardware/consumerir.h
@@ -0,0 +1,92 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_CONSUMERIR_H +#define ANDROID_INCLUDE_HARDWARE_CONSUMERIR_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <hardware/hardware.h> +#include <hardware/hwcomposer_defs.h> + +#define CONSUMERIR_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define CONSUMERIR_HARDWARE_MODULE_ID "consumerir" +#define CONSUMERIR_TRANSMITTER "transmitter" + +typedef struct consumerir_freq_range { + int min; + int max; +} consumerir_freq_range_t; + +typedef struct consumerir_module { + /** + * Common methods of the consumer IR module. This *must* be the first member of + * consumerir_module as users of this structure will cast a hw_module_t to + * consumerir_module pointer in contexts where it's known the hw_module_t references a + * consumerir_module. + */ + struct hw_module_t common; +} consumerir_module_t; + +typedef struct consumerir_device { + /** + * Common methods of the consumer IR device. This *must* be the first member of + * consumerir_device as users of this structure will cast a hw_device_t to + * consumerir_device pointer in contexts where it's known the hw_device_t references a + * consumerir_device. + */ + struct hw_device_t common; + + /* + * (*transmit)() is called to by the ConsumerIrService to send an IR pattern + * at a given carrier_freq. + * + * The pattern is alternating series of carrier on and off periods measured in + * microseconds. The carrier should be turned off at the end of a transmit + * even if there are and odd number of entries in the pattern array. + * + * This call should return when the transmit is complete or encounters an error. + * + * returns: 0 on success. A negative error code on error. + */ + int (*transmit)(struct consumerir_device *dev, int carrier_freq, + const int pattern[], int pattern_len); + + /* + * (*get_num_carrier_freqs)() is called by the ConsumerIrService to get the + * number of carrier freqs to allocate space for, which is then filled by + * a subsequent call to (*get_carrier_freqs)(). + * + * returns: the number of ranges on success. A negative error code on error. + */ + int (*get_num_carrier_freqs)(struct consumerir_device *dev); + + /* + * (*get_carrier_freqs)() is called by the ConsumerIrService to enumerate + * which frequencies the IR transmitter supports. The HAL implementation + * should fill an array of consumerir_freq_range structs with the + * appropriate values for the transmitter, up to len elements. + * + * returns: the number of ranges on success. A negative error code on error. + */ + int (*get_carrier_freqs)(struct consumerir_device *dev, + size_t len, consumerir_freq_range_t *ranges); + + /* Reserved for future use. Must be NULL. */ + void* reserved[8 - 3]; +} consumerir_device_t; + +#endif /* ANDROID_INCLUDE_HARDWARE_CONSUMERIR_H */
diff --git a/libhardware/include/hardware/fb.h b/libhardware/include/hardware/fb.h new file mode 100644 index 0000000..9df9416 --- /dev/null +++ b/libhardware/include/hardware/fb.h
@@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_FB_INTERFACE_H +#define ANDROID_FB_INTERFACE_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <cutils/native_handle.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define GRALLOC_HARDWARE_FB0 "fb0" + +/*****************************************************************************/ + + +/*****************************************************************************/ + +typedef struct framebuffer_device_t { + /** + * Common methods of the framebuffer device. This *must* be the first member of + * framebuffer_device_t as users of this structure will cast a hw_device_t to + * framebuffer_device_t pointer in contexts where it's known the hw_device_t references a + * framebuffer_device_t. + */ + struct hw_device_t common; + + /* flags describing some attributes of the framebuffer */ + const uint32_t flags; + + /* dimensions of the framebuffer in pixels */ + const uint32_t width; + const uint32_t height; + + /* frambuffer stride in pixels */ + const int stride; + + /* framebuffer pixel format */ + const int format; + + /* resolution of the framebuffer's display panel in pixel per inch*/ + const float xdpi; + const float ydpi; + + /* framebuffer's display panel refresh rate in frames per second */ + const float fps; + + /* min swap interval supported by this framebuffer */ + const int minSwapInterval; + + /* max swap interval supported by this framebuffer */ + const int maxSwapInterval; + + /* Number of framebuffers supported*/ + const int numFramebuffers; + + int reserved[7]; + + /* + * requests a specific swap-interval (same definition than EGL) + * + * Returns 0 on success or -errno on error. + */ + int (*setSwapInterval)(struct framebuffer_device_t* window, + int interval); + + /* + * This hook is OPTIONAL. + * + * It is non NULL If the framebuffer driver supports "update-on-demand" + * and the given rectangle is the area of the screen that gets + * updated during (*post)(). + * + * This is useful on devices that are able to DMA only a portion of + * the screen to the display panel, upon demand -- as opposed to + * constantly refreshing the panel 60 times per second, for instance. + * + * Only the area defined by this rectangle is guaranteed to be valid, that + * is, the driver is not allowed to post anything outside of this + * rectangle. + * + * The rectangle evaluated during (*post)() and specifies which area + * of the buffer passed in (*post)() shall to be posted. + * + * return -EINVAL if width or height <=0, or if left or top < 0 + */ + int (*setUpdateRect)(struct framebuffer_device_t* window, + int left, int top, int width, int height); + + /* + * Post <buffer> to the display (display it on the screen) + * The buffer must have been allocated with the + * GRALLOC_USAGE_HW_FB usage flag. + * buffer must be the same width and height as the display and must NOT + * be locked. + * + * The buffer is shown during the next VSYNC. + * + * If the same buffer is posted again (possibly after some other buffer), + * post() will block until the the first post is completed. + * + * Internally, post() is expected to lock the buffer so that a + * subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or + * USAGE_*_WRITE will block until it is safe; that is typically once this + * buffer is shown and another buffer has been posted. + * + * Returns 0 on success or -errno on error. + */ + int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer); + + + /* + * The (*compositionComplete)() method must be called after the + * compositor has finished issuing GL commands for client buffers. + */ + + int (*compositionComplete)(struct framebuffer_device_t* dev); + + /* + * This hook is OPTIONAL. + * + * If non NULL it will be caused by SurfaceFlinger on dumpsys + */ + void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len); + + /* + * (*enableScreen)() is used to either blank (enable=0) or + * unblank (enable=1) the screen this framebuffer is attached to. + * + * Returns 0 on success or -errno on error. + */ + int (*enableScreen)(struct framebuffer_device_t* dev, int enable); + + void* reserved_proc[6]; + +} framebuffer_device_t; + + +/** convenience API for opening and closing a supported device */ + +static inline int framebuffer_open(const struct hw_module_t* module, + struct framebuffer_device_t** device) { + return module->methods->open(module, + GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device); +} + +static inline int framebuffer_close(struct framebuffer_device_t* device) { + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_FB_INTERFACE_H
diff --git a/libhardware/include/hardware/fingerprint.h b/libhardware/include/hardware/fingerprint.h new file mode 100644 index 0000000..ac88c10 --- /dev/null +++ b/libhardware/include/hardware/fingerprint.h
@@ -0,0 +1,266 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H +#define ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H + +#include <hardware/hw_auth_token.h> + +#define FINGERPRINT_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define FINGERPRINT_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0) +#define FINGERPRINT_HARDWARE_MODULE_ID "fingerprint" + +typedef enum fingerprint_msg_type { + FINGERPRINT_ERROR = -1, + FINGERPRINT_ACQUIRED = 1, + FINGERPRINT_TEMPLATE_ENROLLING = 3, + FINGERPRINT_TEMPLATE_REMOVED = 4, + FINGERPRINT_AUTHENTICATED = 5 +} fingerprint_msg_type_t; + +/* + * Fingerprint errors are meant to tell the framework to terminate the current operation and ask + * for the user to correct the situation. These will almost always result in messaging and user + * interaction to correct the problem. + * + * For example, FINGERPRINT_ERROR_CANCELED should follow any acquisition message that results in + * a situation where the current operation can't continue without user interaction. For example, + * if the sensor is dirty during enrollment and no further enrollment progress can be made, + * send FINGERPRINT_ACQUIRED_IMAGER_DIRTY followed by FINGERPRINT_ERROR_CANCELED. + */ +typedef enum fingerprint_error { + FINGERPRINT_ERROR_HW_UNAVAILABLE = 1, /* The hardware has an error that can't be resolved. */ + FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2, /* Bad data; operation can't continue */ + FINGERPRINT_ERROR_TIMEOUT = 3, /* The operation has timed out waiting for user input. */ + FINGERPRINT_ERROR_NO_SPACE = 4, /* No space available to store a template */ + FINGERPRINT_ERROR_CANCELED = 5, /* The current operation can't proceed. See above. */ + FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6, /* fingerprint with given id can't be removed */ + FINGERPRINT_ERROR_VENDOR_BASE = 1000 /* vendor-specific error messages start here */ +} fingerprint_error_t; + +/* + * Fingerprint acquisition info is meant as feedback for the current operation. Anything but + * FINGERPRINT_ACQUIRED_GOOD will be shown to the user as feedback on how to take action on the + * current operation. For example, FINGERPRINT_ACQUIRED_IMAGER_DIRTY can be used to tell the user + * to clean the sensor. If this will cause the current operation to fail, an additional + * FINGERPRINT_ERROR_CANCELED can be sent to stop the operation in progress (e.g. enrollment). + * In general, these messages will result in a "Try again" message. + */ +typedef enum fingerprint_acquired_info { + FINGERPRINT_ACQUIRED_GOOD = 0, + FINGERPRINT_ACQUIRED_PARTIAL = 1, /* sensor needs more data, i.e. longer swipe. */ + FINGERPRINT_ACQUIRED_INSUFFICIENT = 2, /* image doesn't contain enough detail for recognition*/ + FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3, /* sensor needs to be cleaned */ + FINGERPRINT_ACQUIRED_TOO_SLOW = 4, /* mostly swipe-type sensors; not enough data collected */ + FINGERPRINT_ACQUIRED_TOO_FAST = 5, /* for swipe and area sensors; tell user to slow down*/ + FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000 /* vendor-specific acquisition messages start here */ +} fingerprint_acquired_info_t; + +typedef struct fingerprint_finger_id { + uint32_t gid; + uint32_t fid; +} fingerprint_finger_id_t; + +typedef struct fingerprint_enroll { + fingerprint_finger_id_t finger; + /* samples_remaining goes from N (no data collected, but N scans needed) + * to 0 (no more data is needed to build a template). */ + uint32_t samples_remaining; + uint64_t msg; /* Vendor specific message. Used for user guidance */ +} fingerprint_enroll_t; + +typedef struct fingerprint_removed { + fingerprint_finger_id_t finger; +} fingerprint_removed_t; + +typedef struct fingerprint_acquired { + fingerprint_acquired_info_t acquired_info; /* information about the image */ +} fingerprint_acquired_t; + +typedef struct fingerprint_authenticated { + fingerprint_finger_id_t finger; + hw_auth_token_t hat; +} fingerprint_authenticated_t; + +typedef struct fingerprint_msg { + fingerprint_msg_type_t type; + union { + fingerprint_error_t error; + fingerprint_enroll_t enroll; + fingerprint_removed_t removed; + fingerprint_acquired_t acquired; + fingerprint_authenticated_t authenticated; + } data; +} fingerprint_msg_t; + +/* Callback function type */ +typedef void (*fingerprint_notify_t)(const fingerprint_msg_t *msg); + +/* Synchronous operation */ +typedef struct fingerprint_device { + /** + * Common methods of the fingerprint device. This *must* be the first member + * of fingerprint_device as users of this structure will cast a hw_device_t + * to fingerprint_device pointer in contexts where it's known + * the hw_device_t references a fingerprint_device. + */ + struct hw_device_t common; + + /* + * Client provided callback function to receive notifications. + * Do not set by hand, use the function above instead. + */ + fingerprint_notify_t notify; + + /* + * Set notification callback: + * Registers a user function that would receive notifications from the HAL + * The call will block if the HAL state machine is in busy state until HAL + * leaves the busy state. + * + * Function return: 0 if callback function is successfuly registered + * or a negative number in case of error, generally from the errno.h set. + */ + int (*set_notify)(struct fingerprint_device *dev, fingerprint_notify_t notify); + + /* + * Fingerprint pre-enroll enroll request: + * Generates a unique token to upper layers to indicate the start of an enrollment transaction. + * This token will be wrapped by security for verification and passed to enroll() for + * verification before enrollment will be allowed. This is to ensure adding a new fingerprint + * template was preceded by some kind of credential confirmation (e.g. device password). + * + * Function return: 0 if function failed + * otherwise, a uint64_t of token + */ + uint64_t (*pre_enroll)(struct fingerprint_device *dev); + + /* + * Fingerprint enroll request: + * Switches the HAL state machine to collect and store a new fingerprint + * template. Switches back as soon as enroll is complete + * (fingerprint_msg.type == FINGERPRINT_TEMPLATE_ENROLLING && + * fingerprint_msg.data.enroll.samples_remaining == 0) + * or after timeout_sec seconds. + * The fingerprint template will be assigned to the group gid. User has a choice + * to supply the gid or set it to 0 in which case a unique group id will be generated. + * + * Function return: 0 if enrollment process can be successfully started + * or a negative number in case of error, generally from the errno.h set. + * A notify() function may be called indicating the error condition. + */ + int (*enroll)(struct fingerprint_device *dev, const hw_auth_token_t *hat, + uint32_t gid, uint32_t timeout_sec); + + /* + * Finishes the enroll operation and invalidates the pre_enroll() generated challenge. + * This will be called at the end of a multi-finger enrollment session to indicate + * that no more fingers will be added. + * + * Function return: 0 if the request is accepted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*post_enroll)(struct fingerprint_device *dev); + + /* + * get_authenticator_id: + * Returns a token associated with the current fingerprint set. This value will + * change whenever a new fingerprint is enrolled, thus creating a new fingerprint + * set. + * + * Function return: current authenticator id or 0 if function failed. + */ + uint64_t (*get_authenticator_id)(struct fingerprint_device *dev); + + /* + * Cancel pending enroll or authenticate, sending FINGERPRINT_ERROR_CANCELED + * to all running clients. Switches the HAL state machine back to the idle state. + * Unlike enroll_done() doesn't invalidate the pre_enroll() challenge. + * + * Function return: 0 if cancel request is accepted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*cancel)(struct fingerprint_device *dev); + + /* + * Enumerate all the fingerprint templates found in the directory set by + * set_active_group() + * This is a synchronous call. The function takes: + * - A pointer to an array of fingerprint_finger_id_t. + * - The size of the array provided, in fingerprint_finger_id_t elements. + * Max_size is a bi-directional parameter and returns the actual number + * of elements copied to the caller supplied array. + * In the absence of errors the function returns the total number of templates + * in the user directory. + * If the caller has no good guess on the size of the array he should call this + * function witn *max_size == 0 and use the return value for the array allocation. + * The caller of this function has a complete list of the templates when *max_size + * is the same as the function return. + * + * Function return: Total number of fingerprint templates in the current storage directory. + * or a negative number in case of error, generally from the errno.h set. + */ + int (*enumerate)(struct fingerprint_device *dev, fingerprint_finger_id_t *results, + uint32_t *max_size); + + /* + * Fingerprint remove request: + * Deletes a fingerprint template. + * Works only within a path set by set_active_group(). + * notify() will be called with details on the template deleted. + * fingerprint_msg.type == FINGERPRINT_TEMPLATE_REMOVED and + * fingerprint_msg.data.removed.id indicating the template id removed. + * + * Function return: 0 if fingerprint template(s) can be successfully deleted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*remove)(struct fingerprint_device *dev, uint32_t gid, uint32_t fid); + + /* + * Restricts the HAL operation to a set of fingerprints belonging to a + * group provided. + * The caller must provide a path to a storage location within the user's + * data directory. + * + * Function return: 0 on success + * or a negative number in case of error, generally from the errno.h set. + */ + int (*set_active_group)(struct fingerprint_device *dev, uint32_t gid, + const char *store_path); + + /* + * Authenticates an operation identifed by operation_id + * + * Function return: 0 on success + * or a negative number in case of error, generally from the errno.h set. + */ + int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid); + + /* Reserved for backward binary compatibility */ + void *reserved[4]; +} fingerprint_device_t; + +typedef struct fingerprint_module { + /** + * Common methods of the fingerprint module. This *must* be the first member + * of fingerprint_module as users of this structure will cast a hw_module_t + * to fingerprint_module pointer in contexts where it's known + * the hw_module_t references a fingerprint_module. + */ + struct hw_module_t common; +} fingerprint_module_t; + +#endif /* ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H */
diff --git a/libhardware/include/hardware/fused_location.h b/libhardware/include/hardware/fused_location.h new file mode 100644 index 0000000..73360a1 --- /dev/null +++ b/libhardware/include/hardware/fused_location.h
@@ -0,0 +1,825 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H +#define ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H + +#include <hardware/hardware.h> + + +/** + * This header file defines the interface of the Fused Location Provider. + * Fused Location Provider is designed to fuse data from various sources + * like GPS, Wifi, Cell, Sensors, Bluetooth etc to provide a fused location to the + * upper layers. The advantage of doing fusion in hardware is power savings. + * The goal is to do this without waking up the AP to get additional data. + * The software implementation of FLP will decide when to use + * the hardware fused location. Other location features like geofencing will + * also be implemented using fusion in hardware. + */ +__BEGIN_DECLS + +#define FLP_HEADER_VERSION 1 +#define FLP_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define FLP_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION_2(0, 1, FLP_HEADER_VERSION) + +/** + * The id of this module + */ +#define FUSED_LOCATION_HARDWARE_MODULE_ID "flp" + +/** + * Name for the FLP location interface + */ +#define FLP_LOCATION_INTERFACE "flp_location" + +/** + * Name for the FLP location interface + */ +#define FLP_DIAGNOSTIC_INTERFACE "flp_diagnostic" + +/** + * Name for the FLP_Geofencing interface. + */ +#define FLP_GEOFENCING_INTERFACE "flp_geofencing" + +/** + * Name for the FLP_device context interface. + */ +#define FLP_DEVICE_CONTEXT_INTERFACE "flp_device_context" + +/** + * Constants to indicate the various subsystems + * that will be used. + */ +#define FLP_TECH_MASK_GNSS (1U<<0) +#define FLP_TECH_MASK_WIFI (1U<<1) +#define FLP_TECH_MASK_SENSORS (1U<<2) +#define FLP_TECH_MASK_CELL (1U<<3) +#define FLP_TECH_MASK_BLUETOOTH (1U<<4) + +/** + * Set when your implementation can produce GNNS-derived locations, + * for use with flp_capabilities_callback. + * + * GNNS is a required capability for a particular feature to be used + * (batching or geofencing). If not supported that particular feature + * won't be used by the upper layer. + */ +#define CAPABILITY_GNSS (1U<<0) +/** + * Set when your implementation can produce WiFi-derived locations, for + * use with flp_capabilities_callback. + */ +#define CAPABILITY_WIFI (1U<<1) +/** + * Set when your implementation can produce cell-derived locations, for + * use with flp_capabilities_callback. + */ +#define CAPABILITY_CELL (1U<<3) + +/** + * Status to return in flp_status_callback when your implementation transitions + * from being unsuccessful in determining location to being successful. + */ +#define FLP_STATUS_LOCATION_AVAILABLE 0 +/** + * Status to return in flp_status_callback when your implementation transitions + * from being successful in determining location to being unsuccessful. + */ +#define FLP_STATUS_LOCATION_UNAVAILABLE 1 + +/** + * This constant is used with the batched locations + * APIs. Batching is mandatory when FLP implementation + * is supported. If the flag is set, the hardware implementation + * will wake up the application processor when the FIFO is full, + * If the flag is not set, the hardware implementation will drop + * the oldest data when the FIFO is full. + */ +#define FLP_BATCH_WAKEUP_ON_FIFO_FULL 0x0000001 + +/** + * While batching, the implementation should not call the + * flp_location_callback on every location fix. However, + * sometimes in high power mode, the system might need + * a location callback every single time the location + * fix has been obtained. This flag controls that option. + * Its the responsibility of the upper layers (caller) to switch + * it off, if it knows that the AP might go to sleep. + * When this bit is on amidst a batching session, batching should + * continue while location fixes are reported in real time. + */ +#define FLP_BATCH_CALLBACK_ON_LOCATION_FIX 0x0000002 + +/** Flags to indicate which values are valid in a FlpLocation. */ +typedef uint16_t FlpLocationFlags; + +// IMPORTANT: Note that the following values must match +// constants in the corresponding java file. + +/** FlpLocation has valid latitude and longitude. */ +#define FLP_LOCATION_HAS_LAT_LONG (1U<<0) +/** FlpLocation has valid altitude. */ +#define FLP_LOCATION_HAS_ALTITUDE (1U<<1) +/** FlpLocation has valid speed. */ +#define FLP_LOCATION_HAS_SPEED (1U<<2) +/** FlpLocation has valid bearing. */ +#define FLP_LOCATION_HAS_BEARING (1U<<4) +/** FlpLocation has valid accuracy. */ +#define FLP_LOCATION_HAS_ACCURACY (1U<<8) + + +typedef int64_t FlpUtcTime; + +/** Represents a location. */ +typedef struct { + /** set to sizeof(FlpLocation) */ + size_t size; + + /** Flags associated with the location object. */ + FlpLocationFlags flags; + + /** Represents latitude in degrees. */ + double latitude; + + /** Represents longitude in degrees. */ + double longitude; + + /** + * Represents altitude in meters above the WGS 84 reference + * ellipsoid. */ + double altitude; + + /** Represents speed in meters per second. */ + float speed; + + /** Represents heading in degrees. */ + float bearing; + + /** Represents expected accuracy in meters. */ + float accuracy; + + /** Timestamp for the location fix. */ + FlpUtcTime timestamp; + + /** Sources used, will be Bitwise OR of the FLP_TECH_MASK bits. */ + uint32_t sources_used; +} FlpLocation; + +typedef enum { + ASSOCIATE_JVM, + DISASSOCIATE_JVM, +} ThreadEvent; + +/** + * Callback with location information. + * Can only be called from a thread associated to JVM using set_thread_event_cb. + * Parameters: + * num_locations is the number of batched locations available. + * location is the pointer to an array of pointers to location objects. + */ +typedef void (*flp_location_callback)(int32_t num_locations, FlpLocation** location); + +/** + * Callback utility for acquiring a wakelock. + * This can be used to prevent the CPU from suspending while handling FLP events. + */ +typedef void (*flp_acquire_wakelock)(); + +/** + * Callback utility for releasing the FLP wakelock. + */ +typedef void (*flp_release_wakelock)(); + +/** + * Callback for associating a thread that can call into the Java framework code. + * This must be used to initialize any threads that report events up to the framework. + * Return value: + * FLP_RESULT_SUCCESS on success. + * FLP_RESULT_ERROR if the association failed in the current thread. + */ +typedef int (*flp_set_thread_event)(ThreadEvent event); + +/** + * Callback for technologies supported by this implementation. + * + * Parameters: capabilities is a bitmask of FLP_CAPABILITY_* values describing + * which features your implementation supports. You should support + * CAPABILITY_GNSS at a minimum for your implementation to be utilized. You can + * return 0 in FlpGeofenceCallbacks to indicate you don't support geofencing, + * or 0 in FlpCallbacks to indicate you don't support location batching. + */ +typedef void (*flp_capabilities_callback)(int capabilities); + +/** + * Callback with status information on the ability to compute location. + * To avoid waking up the application processor you should only send + * changes in status (you shouldn't call this method twice in a row + * with the same status value). As a guideline you should not call this + * more frequently then the requested batch period set with period_ns + * in FlpBatchOptions. For example if period_ns is set to 5 minutes and + * the status changes many times in that interval, you should only report + * one status change every 5 minutes. + * + * Parameters: + * status is one of FLP_STATUS_LOCATION_AVAILABLE + * or FLP_STATUS_LOCATION_UNAVAILABLE. + */ +typedef void (*flp_status_callback)(int32_t status); + +/** FLP callback structure. */ +typedef struct { + /** set to sizeof(FlpCallbacks) */ + size_t size; + flp_location_callback location_cb; + flp_acquire_wakelock acquire_wakelock_cb; + flp_release_wakelock release_wakelock_cb; + flp_set_thread_event set_thread_event_cb; + flp_capabilities_callback flp_capabilities_cb; + flp_status_callback flp_status_cb; +} FlpCallbacks; + + +/** Options with the batching FLP APIs */ +typedef struct { + /** + * Maximum power in mW that the underlying implementation + * can use for this batching call. + * If max_power_allocation_mW is 0, only fixes that are generated + * at no additional cost of power shall be reported. + */ + double max_power_allocation_mW; + + /** Bitwise OR of the FLP_TECH_MASKS to use */ + uint32_t sources_to_use; + + /** + * FLP_BATCH_WAKEUP_ON_FIFO_FULL - If set the hardware + * will wake up the AP when the buffer is full. If not set, the + * hardware will drop the oldest location object. + * + * FLP_BATCH_CALLBACK_ON_LOCATION_FIX - If set the location + * callback will be called every time there is a location fix. + * Its the responsibility of the upper layers (caller) to switch + * it off, if it knows that the AP might go to sleep. When this + * bit is on amidst a batching session, batching should continue + * while location fixes are reported in real time. + * + * Other flags to be bitwised ORed in the future. + */ + uint32_t flags; + + /** + * Frequency with which location needs to be batched in nano + * seconds. + */ + int64_t period_ns; + + /** + * The smallest displacement between reported locations in meters. + * + * If set to 0, then you should report locations at the requested + * interval even if the device is stationary. If positive, you + * can use this parameter as a hint to save power (e.g. throttling + * location period if the user hasn't traveled close to the displacement + * threshold). Even small positive values can be interpreted to mean + * that you don't have to compute location when the device is stationary. + * + * There is no need to filter location delivery based on this parameter. + * Locations can be delivered even if they have a displacement smaller than + * requested. This parameter can safely be ignored at the cost of potential + * power savings. + */ + float smallest_displacement_meters; +} FlpBatchOptions; + +#define FLP_RESULT_SUCCESS 0 +#define FLP_RESULT_ERROR -1 +#define FLP_RESULT_INSUFFICIENT_MEMORY -2 +#define FLP_RESULT_TOO_MANY_GEOFENCES -3 +#define FLP_RESULT_ID_EXISTS -4 +#define FLP_RESULT_ID_UNKNOWN -5 +#define FLP_RESULT_INVALID_GEOFENCE_TRANSITION -6 + +/** + * Represents the standard FLP interface. + */ +typedef struct { + /** + * set to sizeof(FlpLocationInterface) + */ + size_t size; + + /** + * Opens the interface and provides the callback routines + * to the implementation of this interface. Once called you should respond + * by calling the flp_capabilities_callback in FlpCallbacks to + * specify the capabilities that your implementation supports. + */ + int (*init)(FlpCallbacks* callbacks ); + + /** + * Return the batch size (in number of FlpLocation objects) + * available in the hardware. Note, different HW implementations + * may have different sample sizes. This shall return number + * of samples defined in the format of FlpLocation. + * This will be used by the upper layer, to decide on the batching + * interval and whether the AP should be woken up or not. + */ + int (*get_batch_size)(); + + /** + * Start batching locations. This API is primarily used when the AP is + * asleep and the device can batch locations in the hardware. + * flp_location_callback is used to return the locations. When the buffer + * is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is used, the AP is woken up. + * When the buffer is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is not set, + * the oldest location object is dropped. In this case the AP will not be + * woken up. The upper layer will use get_batched_location + * API to explicitly ask for the location. + * If FLP_BATCH_CALLBACK_ON_LOCATION_FIX is set, the implementation + * will call the flp_location_callback every single time there is a location + * fix. This overrides FLP_BATCH_WAKEUP_ON_FIFO_FULL flag setting. + * It's the responsibility of the upper layers (caller) to switch + * it off, if it knows that the AP might go to sleep. This is useful + * for nagivational applications when the system is in high power mode. + * Parameters: + * id - Id for the request. + * options - See FlpBatchOptions struct definition. + * Return value: + * FLP_RESULT_SUCCESS on success, FLP_RESULT_INSUFFICIENT_MEMORY, + * FLP_RESULT_ID_EXISTS, FLP_RESULT_ERROR on failure. + */ + int (*start_batching)(int id, FlpBatchOptions* options); + + /** + * Update FlpBatchOptions associated with a batching request. + * When a batching operation is in progress and a batching option + * such as FLP_BATCH_WAKEUP_ON_FIFO_FULL needs to be updated, this API + * will be used. For instance, this can happen when the AP is awake and + * the maps application is being used. + * Parameters: + * id - Id of an existing batch request. + * new_options - Updated FlpBatchOptions + * Return value: + * FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN, + * FLP_RESULT_ERROR on error. + */ + int (*update_batching_options)(int id, FlpBatchOptions* new_options); + + /** + * Stop batching. + * Parameters: + * id - Id for the request. + * Return Value: + * FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN or + * FLP_RESULT_ERROR on failure. + */ + int (*stop_batching)(int id); + + /** + * Closes the interface. If any batch operations are in progress, + * they should be stopped. + */ + void (*cleanup)(); + + /** + * Get the fused location that was batched. + * flp_location_callback is used to return the location. The location object + * is dropped from the buffer only when the buffer is full. Do not remove it + * from the buffer just because it has been returned using the callback. + * In other words, when there is no new location object, two calls to + * get_batched_location(1) should return the same location object. + * Parameters: + * last_n_locations - Number of locations to get. This can be one or many. + * If the last_n_locations is 1, you get the latest location known to the + * hardware. + */ + void (*get_batched_location)(int last_n_locations); + + /** + * Injects current location from another location provider + * latitude and longitude are measured in degrees + * expected accuracy is measured in meters + * Parameters: + * location - The location object being injected. + * Return value: FLP_RESULT_SUCCESS or FLP_RESULT_ERROR. + */ + int (*inject_location)(FlpLocation* location); + + /** + * Get a pointer to extension information. + */ + const void* (*get_extension)(const char* name); + + /** + * Retrieve all batched locations currently stored and clear the buffer. + * flp_location_callback MUST be called in response, even if there are + * no locations to flush (in which case num_locations should be 0). + * Subsequent calls to get_batched_location or flush_batched_locations + * should not return any of the locations returned in this call. + */ + void (*flush_batched_locations)(); +} FlpLocationInterface; + +struct flp_device_t { + struct hw_device_t common; + + /** + * Get a handle to the FLP Interface. + */ + const FlpLocationInterface* (*get_flp_interface)(struct flp_device_t* dev); +}; + +/** + * Callback for reports diagnostic data into the Java framework code. +*/ +typedef void (*report_data)(char* data, int length); + +/** + * FLP diagnostic callback structure. + * Currently, not used - but this for future extension. + */ +typedef struct { + /** set to sizeof(FlpDiagnosticCallbacks) */ + size_t size; + + flp_set_thread_event set_thread_event_cb; + + /** reports diagnostic data into the Java framework code */ + report_data data_cb; +} FlpDiagnosticCallbacks; + +/** Extended interface for diagnostic support. */ +typedef struct { + /** set to sizeof(FlpDiagnosticInterface) */ + size_t size; + + /** + * Opens the diagnostic interface and provides the callback routines + * to the implemenation of this interface. + */ + void (*init)(FlpDiagnosticCallbacks* callbacks); + + /** + * Injects diagnostic data into the FLP subsystem. + * Return 0 on success, -1 on error. + **/ + int (*inject_data)(char* data, int length ); +} FlpDiagnosticInterface; + +/** + * Context setting information. + * All these settings shall be injected to FLP HAL at FLP init time. + * Following that, only the changed setting need to be re-injected + * upon changes. + */ + +#define FLP_DEVICE_CONTEXT_GPS_ENABLED (1U<<0) +#define FLP_DEVICE_CONTEXT_AGPS_ENABLED (1U<<1) +#define FLP_DEVICE_CONTEXT_NETWORK_POSITIONING_ENABLED (1U<<2) +#define FLP_DEVICE_CONTEXT_WIFI_CONNECTIVITY_ENABLED (1U<<3) +#define FLP_DEVICE_CONTEXT_WIFI_POSITIONING_ENABLED (1U<<4) +#define FLP_DEVICE_CONTEXT_HW_NETWORK_POSITIONING_ENABLED (1U<<5) +#define FLP_DEVICE_CONTEXT_AIRPLANE_MODE_ON (1U<<6) +#define FLP_DEVICE_CONTEXT_DATA_ENABLED (1U<<7) +#define FLP_DEVICE_CONTEXT_ROAMING_ENABLED (1U<<8) +#define FLP_DEVICE_CONTEXT_CURRENTLY_ROAMING (1U<<9) +#define FLP_DEVICE_CONTEXT_SENSOR_ENABLED (1U<<10) +#define FLP_DEVICE_CONTEXT_BLUETOOTH_ENABLED (1U<<11) +#define FLP_DEVICE_CONTEXT_CHARGER_ON (1U<<12) + +/** Extended interface for device context support. */ +typedef struct { + /** set to sizeof(FlpDeviceContextInterface) */ + size_t size; + + /** + * Injects debug data into the FLP subsystem. + * Return 0 on success, -1 on error. + **/ + int (*inject_device_context)(uint32_t enabledMask); +} FlpDeviceContextInterface; + + +/** + * There are 3 states associated with a Geofence: Inside, Outside, Unknown. + * There are 3 transitions: ENTERED, EXITED, UNCERTAIN. + * + * An example state diagram with confidence level: 95% and Unknown time limit + * set as 30 secs is shown below. (confidence level and Unknown time limit are + * explained latter) + * ____________________________ + * | Unknown (30 secs) | + * """""""""""""""""""""""""""" + * ^ | | ^ + * UNCERTAIN| |ENTERED EXITED| |UNCERTAIN + * | v v | + * ________ EXITED _________ + * | Inside | -----------> | Outside | + * | | <----------- | | + * """""""" ENTERED """"""""" + * + * Inside state: We are 95% confident that the user is inside the geofence. + * Outside state: We are 95% confident that the user is outside the geofence + * Unknown state: Rest of the time. + * + * The Unknown state is better explained with an example: + * + * __________ + * | c| + * | ___ | _______ + * | |a| | | b | + * | """ | """"""" + * | | + * """""""""" + * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy + * circle reported by the FLP subsystem. Now with regard to "b", the system is + * confident that the user is outside. But with regard to "a" is not confident + * whether it is inside or outside the geofence. If the accuracy remains the + * same for a sufficient period of time, the UNCERTAIN transition would be + * triggered with the state set to Unknown. If the accuracy improves later, an + * appropriate transition should be triggered. This "sufficient period of time" + * is defined by the parameter in the add_geofence_area API. + * In other words, Unknown state can be interpreted as a state in which the + * FLP subsystem isn't confident enough that the user is either inside or + * outside the Geofence. It moves to Unknown state only after the expiry of the + * timeout. + * + * The geofence callback needs to be triggered for the ENTERED and EXITED + * transitions, when the FLP system is confident that the user has entered + * (Inside state) or exited (Outside state) the Geofence. An implementation + * which uses a value of 95% as the confidence is recommended. The callback + * should be triggered only for the transitions requested by the + * add_geofence_area call. + * + * Even though the diagram and explanation talks about states and transitions, + * the callee is only interested in the transistions. The states are mentioned + * here for illustrative purposes. + * + * Startup Scenario: When the device boots up, if an application adds geofences, + * and then we get an accurate FLP location fix, it needs to trigger the + * appropriate (ENTERED or EXITED) transition for every Geofence it knows about. + * By default, all the Geofences will be in the Unknown state. + * + * When the FLP system is unavailable, flp_geofence_status_callback should be + * called to inform the upper layers of the same. Similarly, when it becomes + * available the callback should be called. This is a global state while the + * UNKNOWN transition described above is per geofence. + * + */ +#define FLP_GEOFENCE_TRANSITION_ENTERED (1L<<0) +#define FLP_GEOFENCE_TRANSITION_EXITED (1L<<1) +#define FLP_GEOFENCE_TRANSITION_UNCERTAIN (1L<<2) + +#define FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE (1L<<0) +#define FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE (1L<<1) + +/** + * The callback associated with the geofence. + * Parameters: + * geofence_id - The id associated with the add_geofence_area. + * location - The current location as determined by the FLP subsystem. + * transition - Can be one of FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED, + * FLP_GEOFENCE_TRANSITION_UNCERTAIN. + * timestamp - Timestamp when the transition was detected; -1 if not available. + * sources_used - Bitwise OR of FLP_TECH_MASK flags indicating which + * subsystems were used. + * + * The callback should only be called when the caller is interested in that + * particular transition. For instance, if the caller is interested only in + * ENTERED transition, then the callback should NOT be called with the EXITED + * transition. + * + * IMPORTANT: If a transition is triggered resulting in this callback, the + * subsystem will wake up the application processor, if its in suspend state. + */ +typedef void (*flp_geofence_transition_callback) (int32_t geofence_id, FlpLocation* location, + int32_t transition, FlpUtcTime timestamp, uint32_t sources_used); + +/** + * The callback associated with the availablity of one the sources used for geofence + * monitoring by the FLP sub-system For example, if the GPS system determines that it cannot + * monitor geofences because of lack of reliability or unavailability of the GPS signals, + * it will call this callback with FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE parameter and the + * source set to FLP_TECH_MASK_GNSS. + * + * Parameters: + * status - FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE or FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE. + * source - One of the FLP_TECH_MASKS + * last_location - Last known location. + */ +typedef void (*flp_geofence_monitor_status_callback) (int32_t status, uint32_t source, + FlpLocation* last_location); + +/** + * The callback associated with the add_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * result - FLP_RESULT_SUCCESS + * FLP_RESULT_ERROR_TOO_MANY_GEOFENCES - geofence limit has been reached. + * FLP_RESULT_ID_EXISTS - geofence with id already exists + * FLP_RESULT_INVALID_GEOFENCE_TRANSITION - the monitorTransition contains an + * invalid transition + * FLP_RESULT_ERROR - for other errors. + */ +typedef void (*flp_geofence_add_callback) (int32_t geofence_id, int32_t result); + +/** + * The callback associated with the remove_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * result - FLP_RESULT_SUCCESS + * FLP_RESULT_ID_UNKNOWN - for invalid id + * FLP_RESULT_ERROR for others. + */ +typedef void (*flp_geofence_remove_callback) (int32_t geofence_id, int32_t result); + + +/** + * The callback associated with the pause_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * result - FLP_RESULT_SUCCESS + * FLP_RESULT__ID_UNKNOWN - for invalid id + * FLP_RESULT_INVALID_TRANSITION - + * when monitor_transitions is invalid + * FLP_RESULT_ERROR for others. + */ +typedef void (*flp_geofence_pause_callback) (int32_t geofence_id, int32_t result); + +/** + * The callback associated with the resume_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * result - FLP_RESULT_SUCCESS + * FLP_RESULT_ID_UNKNOWN - for invalid id + * FLP_RESULT_ERROR for others. + */ +typedef void (*flp_geofence_resume_callback) (int32_t geofence_id, int32_t result); + +typedef struct { + /** set to sizeof(FlpGeofenceCallbacks) */ + size_t size; + flp_geofence_transition_callback geofence_transition_callback; + flp_geofence_monitor_status_callback geofence_status_callback; + flp_geofence_add_callback geofence_add_callback; + flp_geofence_remove_callback geofence_remove_callback; + flp_geofence_pause_callback geofence_pause_callback; + flp_geofence_resume_callback geofence_resume_callback; + flp_set_thread_event set_thread_event_cb; + flp_capabilities_callback flp_capabilities_cb; +} FlpGeofenceCallbacks; + + +/** Type of geofence */ +typedef enum { + TYPE_CIRCLE = 0, +} GeofenceType; + +/** Circular geofence is represented by lat / long / radius */ +typedef struct { + double latitude; + double longitude; + double radius_m; +} GeofenceCircle; + +/** Represents the type of geofence and data */ +typedef struct { + GeofenceType type; + union { + GeofenceCircle circle; + } geofence; +} GeofenceData; + +/** Geofence Options */ +typedef struct { + /** + * The current state of the geofence. For example, if + * the system already knows that the user is inside the geofence, + * this will be set to FLP_GEOFENCE_TRANSITION_ENTERED. In most cases, it + * will be FLP_GEOFENCE_TRANSITION_UNCERTAIN. */ + int last_transition; + + /** + * Transitions to monitor. Bitwise OR of + * FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and + * FLP_GEOFENCE_TRANSITION_UNCERTAIN. + */ + int monitor_transitions; + + /** + * Defines the best-effort description + * of how soon should the callback be called when the transition + * associated with the Geofence is triggered. For instance, if set + * to 1000 millseconds with FLP_GEOFENCE_TRANSITION_ENTERED, the callback + * should be called 1000 milliseconds within entering the geofence. + * This parameter is defined in milliseconds. + * NOTE: This is not to be confused with the rate that the GPS is + * polled at. It is acceptable to dynamically vary the rate of + * sampling the GPS for power-saving reasons; thus the rate of + * sampling may be faster or slower than this. + */ + int notification_responsivenes_ms; + + /** + * The time limit after which the UNCERTAIN transition + * should be triggered. This paramter is defined in milliseconds. + */ + int unknown_timer_ms; + + /** + * The sources to use for monitoring geofences. Its a BITWISE-OR + * of FLP_TECH_MASK flags. + */ + uint32_t sources_to_use; +} GeofenceOptions; + +/** Geofence struct */ +typedef struct { + int32_t geofence_id; + GeofenceData* data; + GeofenceOptions* options; +} Geofence; + +/** Extended interface for FLP_Geofencing support */ +typedef struct { + /** set to sizeof(FlpGeofencingInterface) */ + size_t size; + + /** + * Opens the geofence interface and provides the callback routines + * to the implemenation of this interface. Once called you should respond + * by calling the flp_capabilities_callback in FlpGeofenceCallbacks to + * specify the capabilities that your implementation supports. + */ + void (*init)( FlpGeofenceCallbacks* callbacks ); + + /** + * Add a list of geofences. + * Parameters: + * number_of_geofences - The number of geofences that needed to be added. + * geofences - Pointer to array of pointers to Geofence structure. + */ + void (*add_geofences) (int32_t number_of_geofences, Geofence** geofences); + + /** + * Pause monitoring a particular geofence. + * Parameters: + * geofence_id - The id for the geofence. + */ + void (*pause_geofence) (int32_t geofence_id); + + /** + * Resume monitoring a particular geofence. + * Parameters: + * geofence_id - The id for the geofence. + * monitor_transitions - Which transitions to monitor. Bitwise OR of + * FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and + * FLP_GEOFENCE_TRANSITION_UNCERTAIN. + * This supersedes the value associated provided in the + * add_geofence_area call. + */ + void (*resume_geofence) (int32_t geofence_id, int monitor_transitions); + + /** + * Modify a particular geofence option. + * Parameters: + * geofence_id - The id for the geofence. + * options - Various options associated with the geofence. See + * GeofenceOptions structure for details. + */ + void (*modify_geofence_option) (int32_t geofence_id, GeofenceOptions* options); + + /** + * Remove a list of geofences. After the function returns, no notifications + * should be sent. + * Parameter: + * number_of_geofences - The number of geofences that needed to be added. + * geofence_id - Pointer to array of geofence_ids to be removed. + */ + void (*remove_geofences) (int32_t number_of_geofences, int32_t* geofence_id); +} FlpGeofencingInterface; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_FLP_H */ +
diff --git a/libhardware/include/hardware/gatekeeper.h b/libhardware/include/hardware/gatekeeper.h new file mode 100644 index 0000000..2bb2b08 --- /dev/null +++ b/libhardware/include/hardware/gatekeeper.h
@@ -0,0 +1,190 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_GATEKEEPER_H +#define ANDROID_HARDWARE_GATEKEEPER_H + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define GATEKEEPER_HARDWARE_MODULE_ID "gatekeeper" + +#define GATEKEEPER_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +#define HARDWARE_GATEKEEPER "gatekeeper" + +struct gatekeeper_module { + /** + * Comon methods of the gatekeeper module. This *must* be the first member of + * gatekeeper_module as users of this structure will cast a hw_module_t to + * a gatekeeper_module pointer in the appropriate context. + */ + hw_module_t common; +}; + +struct gatekeeper_device { + /** + * Common methods of the gatekeeper device. As above, this must be the first + * member of keymaster_device. + */ + hw_device_t common; + + /** + * Enrolls desired_password, which should be derived from a user selected pin or password, + * with the authentication factor private key used only for enrolling authentication + * factor data. + * + * If there was already a password enrolled, it should be provided in + * current_password_handle, along with the current password in current_password + * that should validate against current_password_handle. + * + * Parameters: + * - dev: pointer to gatekeeper_device acquired via calls to gatekeeper_open + * - uid: the Android user identifier + * + * - current_password_handle: the currently enrolled password handle the user + * wants to replace. May be null if there's no currently enrolled password. + * - current_password_handle_length: the length in bytes of the buffer pointed + * at by current_password_handle. Must be 0 if current_password_handle is NULL. + * + * - current_password: the user's current password in plain text. If presented, + * it MUST verify against current_password_handle. + * - current_password_length: the size in bytes of the buffer pointed at by + * current_password. Must be 0 if the current_password is NULL. + * + * - desired_password: the new password the user wishes to enroll in plain-text. + * Cannot be NULL. + * - desired_password_length: the length in bytes of the buffer pointed at by + * desired_password. + * + * - enrolled_password_handle: on success, a buffer will be allocated with the + * new password handle referencing the password provided in desired_password. + * This buffer can be used on subsequent calls to enroll or verify. + * The caller is responsible for deallocating this buffer via a call to delete[] + * - enrolled_password_handle_length: pointer to the length in bytes of the buffer allocated + * by this function and pointed to by *enrolled_password_handle_length. + * + * Returns: + * - 0 on success + * - An error code < 0 on failure, or + * - A timeout value T > 0 if the call should not be re-attempted until T milliseconds + * have elapsed. + * + * On error, enrolled_password_handle will not be allocated. + */ + int (*enroll)(const struct gatekeeper_device *dev, uint32_t uid, + const uint8_t *current_password_handle, uint32_t current_password_handle_length, + const uint8_t *current_password, uint32_t current_password_length, + const uint8_t *desired_password, uint32_t desired_password_length, + uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length); + + /** + * Verifies provided_password matches enrolled_password_handle. + * + * Implementations of this module may retain the result of this call + * to attest to the recency of authentication. + * + * On success, writes the address of a verification token to auth_token, + * usable to attest password verification to other trusted services. Clients + * may pass NULL for this value. + * + * Parameters: + * - dev: pointer to gatekeeper_device acquired via calls to gatekeeper_open + * - uid: the Android user identifier + * + * - challenge: An optional challenge to authenticate against, or 0. Used when a separate + * authenticator requests password verification, or for transactional + * password authentication. + * + * - enrolled_password_handle: the currently enrolled password handle that the + * user wishes to verify against. + * - enrolled_password_handle_length: the length in bytes of the buffer pointed + * to by enrolled_password_handle + * + * - provided_password: the plaintext password to be verified against the + * enrolled_password_handle + * - provided_password_length: the length in bytes of the buffer pointed to by + * provided_password + * + * - auth_token: on success, a buffer containing the authentication token + * resulting from this verification is assigned to *auth_token. The caller + * is responsible for deallocating this memory via a call to delete[] + * - auth_token_length: on success, the length in bytes of the authentication + * token assigned to *auth_token will be assigned to *auth_token_length + * + * - request_reenroll: a request to the upper layers to re-enroll the verified + * password due to a version change. Not set if verification fails. + * + * Returns: + * - 0 on success + * - An error code < 0 on failure, or + * - A timeout value T > 0 if the call should not be re-attempted until T milliseconds + * have elapsed. + * On error, auth token will not be allocated + */ + int (*verify)(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge, + const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, + const uint8_t *provided_password, uint32_t provided_password_length, + uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll); + + /* + * Deletes the enrolled_password_handle associated wth the uid. Once deleted + * the user cannot be verified anymore. + * This function is optional and should be set to NULL if it is not implemented. + * + * Parameters + * - dev: pointer to gatekeeper_device acquired via calls to gatekeeper_open + * - uid: the Android user identifier + * + * Returns: + * - 0 on success + * - An error code < 0 on failure + */ + int (*delete_user)(const struct gatekeeper_device *dev, uint32_t uid); + + /* + * Deletes all the enrolled_password_handles for all uid's. Once called, + * no users will be enrolled on the device. + * This function is optional and should be set to NULL if it is not implemented. + * + * Parameters + * - dev: pointer to gatekeeper_device acquired via calls to gatekeeper_open + * + * Returns: + * - 0 on success + * - An error code < 0 on failure + */ + int (*delete_all_users)(const struct gatekeeper_device *dev); +}; + +typedef struct gatekeeper_device gatekeeper_device_t; + +static inline int gatekeeper_open(const struct hw_module_t *module, + gatekeeper_device_t **device) { + return module->methods->open(module, HARDWARE_GATEKEEPER, + (struct hw_device_t **) device); +} + +static inline int gatekeeper_close(gatekeeper_device_t *device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_HARDWARE_GATEKEEPER_H
diff --git a/libhardware/include/hardware/gps.h b/libhardware/include/hardware/gps.h new file mode 100644 index 0000000..76b6cb7 --- /dev/null +++ b/libhardware/include/hardware/gps.h
@@ -0,0 +1,1871 @@ +/* + * 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. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H +#define ANDROID_INCLUDE_HARDWARE_GPS_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> +#include <pthread.h> +#include <sys/socket.h> +#include <stdbool.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define GPS_HARDWARE_MODULE_ID "gps" + + +/** Milliseconds since January 1, 1970 */ +typedef int64_t GpsUtcTime; + +/** Maximum number of SVs for gps_sv_status_callback(). */ +#define GPS_MAX_SVS 32 + +/** Maximum number of Measurements in gps_measurement_callback(). */ +#define GPS_MAX_MEASUREMENT 32 + +/** Requested operational mode for GPS operation. */ +typedef uint32_t GpsPositionMode; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** Mode for running GPS standalone (no assistance). */ +#define GPS_POSITION_MODE_STANDALONE 0 +/** AGPS MS-Based mode. */ +#define GPS_POSITION_MODE_MS_BASED 1 +/** + * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore. + * It is strongly recommended to use GPS_POSITION_MODE_MS_BASE instead. + */ +#define GPS_POSITION_MODE_MS_ASSISTED 2 + +/** Requested recurrence mode for GPS operation. */ +typedef uint32_t GpsPositionRecurrence; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** Receive GPS fixes on a recurring basis at a specified period. */ +#define GPS_POSITION_RECURRENCE_PERIODIC 0 +/** Request a single shot GPS fix. */ +#define GPS_POSITION_RECURRENCE_SINGLE 1 + +/** GPS status event values. */ +typedef uint16_t GpsStatusValue; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** GPS status unknown. */ +#define GPS_STATUS_NONE 0 +/** GPS has begun navigating. */ +#define GPS_STATUS_SESSION_BEGIN 1 +/** GPS has stopped navigating. */ +#define GPS_STATUS_SESSION_END 2 +/** GPS has powered on but is not navigating. */ +#define GPS_STATUS_ENGINE_ON 3 +/** GPS is powered off. */ +#define GPS_STATUS_ENGINE_OFF 4 + +/** Flags to indicate which values are valid in a GpsLocation. */ +typedef uint16_t GpsLocationFlags; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** GpsLocation has valid latitude and longitude. */ +#define GPS_LOCATION_HAS_LAT_LONG 0x0001 +/** GpsLocation has valid altitude. */ +#define GPS_LOCATION_HAS_ALTITUDE 0x0002 +/** GpsLocation has valid speed. */ +#define GPS_LOCATION_HAS_SPEED 0x0004 +/** GpsLocation has valid bearing. */ +#define GPS_LOCATION_HAS_BEARING 0x0008 +/** GpsLocation has valid accuracy. */ +#define GPS_LOCATION_HAS_ACCURACY 0x0010 + +/** Flags for the gps_set_capabilities callback. */ + +/** GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. + If this is not set, then the framework will use 1000ms for min_interval + and will start and call start() and stop() to schedule the GPS. + */ +#define GPS_CAPABILITY_SCHEDULING 0x0000001 +/** GPS supports MS-Based AGPS mode */ +#define GPS_CAPABILITY_MSB 0x0000002 +/** GPS supports MS-Assisted AGPS mode */ +#define GPS_CAPABILITY_MSA 0x0000004 +/** GPS supports single-shot fixes */ +#define GPS_CAPABILITY_SINGLE_SHOT 0x0000008 +/** GPS supports on demand time injection */ +#define GPS_CAPABILITY_ON_DEMAND_TIME 0x0000010 +/** GPS supports Geofencing */ +#define GPS_CAPABILITY_GEOFENCING 0x0000020 +/** GPS supports Measurements */ +#define GPS_CAPABILITY_MEASUREMENTS 0x0000040 +/** GPS supports Navigation Messages */ +#define GPS_CAPABILITY_NAV_MESSAGES 0x0000080 + +/** Flags used to specify which aiding data to delete + when calling delete_aiding_data(). */ +typedef uint16_t GpsAidingData; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +#define GPS_DELETE_EPHEMERIS 0x0001 +#define GPS_DELETE_ALMANAC 0x0002 +#define GPS_DELETE_POSITION 0x0004 +#define GPS_DELETE_TIME 0x0008 +#define GPS_DELETE_IONO 0x0010 +#define GPS_DELETE_UTC 0x0020 +#define GPS_DELETE_HEALTH 0x0040 +#define GPS_DELETE_SVDIR 0x0080 +#define GPS_DELETE_SVSTEER 0x0100 +#define GPS_DELETE_SADATA 0x0200 +#define GPS_DELETE_RTI 0x0400 +#define GPS_DELETE_CELLDB_INFO 0x8000 +#define GPS_DELETE_ALL 0xFFFF + +/** AGPS type */ +typedef uint16_t AGpsType; +#define AGPS_TYPE_SUPL 1 +#define AGPS_TYPE_C2K 2 + +typedef uint16_t AGpsSetIDType; +#define AGPS_SETID_TYPE_NONE 0 +#define AGPS_SETID_TYPE_IMSI 1 +#define AGPS_SETID_TYPE_MSISDN 2 + +typedef uint16_t ApnIpType; +#define APN_IP_INVALID 0 +#define APN_IP_IPV4 1 +#define APN_IP_IPV6 2 +#define APN_IP_IPV4V6 3 + +/** + * String length constants + */ +#define GPS_NI_SHORT_STRING_MAXLEN 256 +#define GPS_NI_LONG_STRING_MAXLEN 2048 + +/** + * GpsNiType constants + */ +typedef uint32_t GpsNiType; +#define GPS_NI_TYPE_VOICE 1 +#define GPS_NI_TYPE_UMTS_SUPL 2 +#define GPS_NI_TYPE_UMTS_CTRL_PLANE 3 + +/** + * GpsNiNotifyFlags constants + */ +typedef uint32_t GpsNiNotifyFlags; +/** NI requires notification */ +#define GPS_NI_NEED_NOTIFY 0x0001 +/** NI requires verification */ +#define GPS_NI_NEED_VERIFY 0x0002 +/** NI requires privacy override, no notification/minimal trace */ +#define GPS_NI_PRIVACY_OVERRIDE 0x0004 + +/** + * GPS NI responses, used to define the response in + * NI structures + */ +typedef int GpsUserResponseType; +#define GPS_NI_RESPONSE_ACCEPT 1 +#define GPS_NI_RESPONSE_DENY 2 +#define GPS_NI_RESPONSE_NORESP 3 + +/** + * NI data encoding scheme + */ +typedef int GpsNiEncodingType; +#define GPS_ENC_NONE 0 +#define GPS_ENC_SUPL_GSM_DEFAULT 1 +#define GPS_ENC_SUPL_UTF8 2 +#define GPS_ENC_SUPL_UCS2 3 +#define GPS_ENC_UNKNOWN -1 + +/** AGPS status event values. */ +typedef uint16_t AGpsStatusValue; +/** GPS requests data connection for AGPS. */ +#define GPS_REQUEST_AGPS_DATA_CONN 1 +/** GPS releases the AGPS data connection. */ +#define GPS_RELEASE_AGPS_DATA_CONN 2 +/** AGPS data connection initiated */ +#define GPS_AGPS_DATA_CONNECTED 3 +/** AGPS data connection completed */ +#define GPS_AGPS_DATA_CONN_DONE 4 +/** AGPS data connection failed */ +#define GPS_AGPS_DATA_CONN_FAILED 5 + +#define AGPS_REF_LOCATION_TYPE_GSM_CELLID 1 +#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID 2 +#define AGPS_REG_LOCATION_TYPE_MAC 3 + +/** Network types for update_network_state "type" parameter */ +#define AGPS_RIL_NETWORK_TYPE_MOBILE 0 +#define AGPS_RIL_NETWORK_TYPE_WIFI 1 +#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS 2 +#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL 3 +#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN 4 +#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5 +#define AGPS_RIL_NETWORK_TTYPE_WIMAX 6 + +/** + * Flags to indicate what fields in GpsClock are valid. + */ +typedef uint16_t GpsClockFlags; +/** A valid 'leap second' is stored in the data structure. */ +#define GPS_CLOCK_HAS_LEAP_SECOND (1<<0) +/** A valid 'time uncertainty' is stored in the data structure. */ +#define GPS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1) +/** A valid 'full bias' is stored in the data structure. */ +#define GPS_CLOCK_HAS_FULL_BIAS (1<<2) +/** A valid 'bias' is stored in the data structure. */ +#define GPS_CLOCK_HAS_BIAS (1<<3) +/** A valid 'bias uncertainty' is stored in the data structure. */ +#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4) +/** A valid 'drift' is stored in the data structure. */ +#define GPS_CLOCK_HAS_DRIFT (1<<5) +/** A valid 'drift uncertainty' is stored in the data structure. */ +#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6) + +/** + * Enumeration of the available values for the GPS Clock type. + */ +typedef uint8_t GpsClockType; +/** The type is not available ot it is unknown. */ +#define GPS_CLOCK_TYPE_UNKNOWN 0 +/** The source of the time value reported by GPS clock is the local hardware clock. */ +#define GPS_CLOCK_TYPE_LOCAL_HW_TIME 1 +/** + * The source of the time value reported by GPS clock is the GPS time derived from satellites + * (epoch = Jan 6, 1980) + */ +#define GPS_CLOCK_TYPE_GPS_TIME 2 + +/** + * Flags to indicate what fields in GpsMeasurement are valid. + */ +typedef uint32_t GpsMeasurementFlags; +/** A valid 'snr' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_SNR (1<<0) +/** A valid 'elevation' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_ELEVATION (1<<1) +/** A valid 'elevation uncertainty' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2) +/** A valid 'azimuth' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_AZIMUTH (1<<3) +/** A valid 'azimuth uncertainty' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4) +/** A valid 'pseudorange' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5) +/** A valid 'pseudorange uncertainty' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6) +/** A valid 'code phase' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7) +/** A valid 'code phase uncertainty' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8) +/** A valid 'carrier frequency' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9) +/** A valid 'carrier cycles' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10) +/** A valid 'carrier phase' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11) +/** A valid 'carrier phase uncertainty' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12) +/** A valid 'bit number' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13) +/** A valid 'time from last bit' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14) +/** A valid 'doppler shift' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15) +/** A valid 'doppler shift uncertainty' is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16) +/** A valid 'used in fix' flag is stored in the data structure. */ +#define GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17) +/** The value of 'pseudorange rate' is uncorrected. */ +#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE (1<<18) + +/** + * Enumeration of the available values for the GPS Measurement's loss of lock. + */ +typedef uint8_t GpsLossOfLock; +/** The indicator is not available or it is unknown. */ +#define GPS_LOSS_OF_LOCK_UNKNOWN 0 +/** The measurement does not present any indication of loss of lock. */ +#define GPS_LOSS_OF_LOCK_OK 1 +/** Loss of lock between previous and current observation: cycle slip possible. */ +#define GPS_LOSS_OF_LOCK_CYCLE_SLIP 2 + +/** + * Enumeration of available values for the GPS Measurement's multipath indicator. + */ +typedef uint8_t GpsMultipathIndicator; +/** The indicator is not available or unknown. */ +#define GPS_MULTIPATH_INDICATOR_UNKNOWN 0 +/** The measurement has been indicated to use multipath. */ +#define GPS_MULTIPATH_INDICATOR_DETECTED 1 +/** The measurement has been indicated Not to use multipath. */ +#define GPS_MULTIPATH_INDICATOR_NOT_USED 2 + +/** + * Flags indicating the GPS measurement state. + * The expected behavior here is for GPS HAL to set all the flags that applies. For + * example, if the state for a satellite is only C/A code locked and bit synchronized, + * and there is still millisecond ambiguity, the state should be set as: + * GPS_MEASUREMENT_STATE_CODE_LOCK|GPS_MEASUREMENT_STATE_BIT_SYNC|GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS + * If GPS is still searching for a satellite, the corresponding state should be set to + * GPS_MEASUREMENT_STATE_UNKNOWN(0). + */ +typedef uint16_t GpsMeasurementState; +#define GPS_MEASUREMENT_STATE_UNKNOWN 0 +#define GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0) +#define GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1) +#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2) +#define GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3) +#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4) + +/** + * Flags indicating the Accumulated Delta Range's states. + */ +typedef uint16_t GpsAccumulatedDeltaRangeState; +#define GPS_ADR_STATE_UNKNOWN 0 +#define GPS_ADR_STATE_VALID (1<<0) +#define GPS_ADR_STATE_RESET (1<<1) +#define GPS_ADR_STATE_CYCLE_SLIP (1<<2) + +/** + * Enumeration of available values to indicate the available GPS Navigation message types. + */ +typedef uint8_t GpsNavigationMessageType; +/** The message type is unknown. */ +#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0 +/** L1 C/A message contained in the structure. */ +#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA 1 +/** L2-CNAV message contained in the structure. */ +#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV 2 +/** L5-CNAV message contained in the structure. */ +#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV 3 +/** CNAV-2 message contained in the structure. */ +#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2 4 + +/** + * Status of Navigation Message + * When a message is received properly without any parity error in its navigation words, the + * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received + * with words that failed parity check, but GPS is able to correct those words, the status + * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT. + * No need to send any navigation message that contains words with parity error and cannot be + * corrected. + */ +typedef uint16_t NavigationMessageStatus; +#define NAV_MESSAGE_STATUS_UNKONW 0 +#define NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0) +#define NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1) + +/** + * Name for the GPS XTRA interface. + */ +#define GPS_XTRA_INTERFACE "gps-xtra" + +/** + * Name for the GPS DEBUG interface. + */ +#define GPS_DEBUG_INTERFACE "gps-debug" + +/** + * Name for the AGPS interface. + */ +#define AGPS_INTERFACE "agps" + +/** + * Name of the Supl Certificate interface. + */ +#define SUPL_CERTIFICATE_INTERFACE "supl-certificate" + +/** + * Name for NI interface + */ +#define GPS_NI_INTERFACE "gps-ni" + +/** + * Name for the AGPS-RIL interface. + */ +#define AGPS_RIL_INTERFACE "agps_ril" + +/** + * Name for the GPS_Geofencing interface. + */ +#define GPS_GEOFENCING_INTERFACE "gps_geofencing" + +/** + * Name of the GPS Measurements interface. + */ +#define GPS_MEASUREMENT_INTERFACE "gps_measurement" + +/** + * Name of the GPS navigation message interface. + */ +#define GPS_NAVIGATION_MESSAGE_INTERFACE "gps_navigation_message" + +/** + * Name of the GNSS/GPS configuration interface. + */ +#define GNSS_CONFIGURATION_INTERFACE "gnss_configuration" + + +/** Represents a location. */ +typedef struct { + /** set to sizeof(GpsLocation) */ + size_t size; + /** Contains GpsLocationFlags bits. */ + uint16_t flags; + /** Represents latitude in degrees. */ + double latitude; + /** Represents longitude in degrees. */ + double longitude; + /** Represents altitude in meters above the WGS 84 reference + * ellipsoid. */ + double altitude; + /** Represents speed in meters per second. */ + float speed; + /** Represents heading in degrees. */ + float bearing; + /** Represents expected accuracy in meters. */ + float accuracy; + /** Timestamp for the location fix. */ + GpsUtcTime timestamp; +} GpsLocation; + +/** Represents the status. */ +typedef struct { + /** set to sizeof(GpsStatus) */ + size_t size; + GpsStatusValue status; +} GpsStatus; + +/** Represents SV information. */ +typedef struct { + /** set to sizeof(GpsSvInfo) */ + size_t size; + /** Pseudo-random number for the SV. */ + int prn; + /** Signal to noise ratio. */ + float snr; + /** Elevation of SV in degrees. */ + float elevation; + /** Azimuth of SV in degrees. */ + float azimuth; +} GpsSvInfo; + +/** Represents SV status. */ +typedef struct { + /** set to sizeof(GpsSvStatus) */ + size_t size; + + /** Number of SVs currently visible. */ + int num_svs; + + /** Contains an array of SV information. */ + GpsSvInfo sv_list[GPS_MAX_SVS]; + + /** Represents a bit mask indicating which SVs + * have ephemeris data. + */ + uint32_t ephemeris_mask; + + /** Represents a bit mask indicating which SVs + * have almanac data. + */ + uint32_t almanac_mask; + + /** + * Represents a bit mask indicating which SVs + * were used for computing the most recent position fix. + */ + uint32_t used_in_fix_mask; +} GpsSvStatus; + + +/* 2G and 3G */ +/* In 3G lac is discarded */ +typedef struct { + uint16_t type; + uint16_t mcc; + uint16_t mnc; + uint16_t lac; + uint32_t cid; +} AGpsRefLocationCellID; + +typedef struct { + uint8_t mac[6]; +} AGpsRefLocationMac; + +/** Represents ref locations */ +typedef struct { + uint16_t type; + union { + AGpsRefLocationCellID cellID; + AGpsRefLocationMac mac; + } u; +} AGpsRefLocation; + +/** Callback with location information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_location_callback)(GpsLocation* location); + +/** Callback with status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_status_callback)(GpsStatus* status); + +/** + * Callback with SV status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info); + +/** Callback for reporting NMEA sentences. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length); + +/** Callback to inform framework of the GPS engine's capabilities. + * Capability parameter is a bit field of GPS_CAPABILITY_* flags. + */ +typedef void (* gps_set_capabilities)(uint32_t capabilities); + +/** Callback utility for acquiring the GPS wakelock. + * This can be used to prevent the CPU from suspending while handling GPS events. + */ +typedef void (* gps_acquire_wakelock)(); + +/** Callback utility for releasing the GPS wakelock. */ +typedef void (* gps_release_wakelock)(); + +/** Callback for requesting NTP time */ +typedef void (* gps_request_utc_time)(); + +/** Callback for creating a thread that can call into the Java framework code. + * This must be used to create any threads that report events up to the framework. + */ +typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg); + +/** GPS callback structure. */ +typedef struct { + /** set to sizeof(GpsCallbacks) */ + size_t size; + gps_location_callback location_cb; + gps_status_callback status_cb; + gps_sv_status_callback sv_status_cb; + gps_nmea_callback nmea_cb; + gps_set_capabilities set_capabilities_cb; + gps_acquire_wakelock acquire_wakelock_cb; + gps_release_wakelock release_wakelock_cb; + gps_create_thread create_thread_cb; + gps_request_utc_time request_utc_time_cb; +} GpsCallbacks; + + +/** Represents the standard GPS interface. */ +typedef struct { + /** set to sizeof(GpsInterface) */ + size_t size; + /** + * Opens the interface and provides the callback routines + * to the implementation of this interface. + */ + int (*init)( GpsCallbacks* callbacks ); + + /** Starts navigating. */ + int (*start)( void ); + + /** Stops navigating. */ + int (*stop)( void ); + + /** Closes the interface. */ + void (*cleanup)( void ); + + /** Injects the current time. */ + int (*inject_time)(GpsUtcTime time, int64_t timeReference, + int uncertainty); + + /** Injects current location from another location provider + * (typically cell ID). + * latitude and longitude are measured in degrees + * expected accuracy is measured in meters + */ + int (*inject_location)(double latitude, double longitude, float accuracy); + + /** + * Specifies that the next call to start will not use the + * information defined in the flags. GPS_DELETE_ALL is passed for + * a cold start. + */ + void (*delete_aiding_data)(GpsAidingData flags); + + /** + * min_interval represents the time between fixes in milliseconds. + * preferred_accuracy represents the requested fix accuracy in meters. + * preferred_time represents the requested time to first fix in milliseconds. + * + * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASE + * or GPS_POSITION_MODE_STANDALONE. + * It is allowed by the platform (and it is recommended) to fallback to + * GPS_POSITION_MODE_MS_BASE if GPS_POSITION_MODE_MS_ASSISTED is passed in, and + * GPS_POSITION_MODE_MS_BASED is supported. + */ + int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence, + uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time); + + /** Get a pointer to extension information. */ + const void* (*get_extension)(const char* name); +} GpsInterface; + +/** Callback to request the client to download XTRA data. + * The client should download XTRA data and inject it by calling inject_xtra_data(). + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_xtra_download_request)(); + +/** Callback structure for the XTRA interface. */ +typedef struct { + gps_xtra_download_request download_request_cb; + gps_create_thread create_thread_cb; +} GpsXtraCallbacks; + +/** Extended interface for XTRA support. */ +typedef struct { + /** set to sizeof(GpsXtraInterface) */ + size_t size; + /** + * Opens the XTRA interface and provides the callback routines + * to the implementation of this interface. + */ + int (*init)( GpsXtraCallbacks* callbacks ); + /** Injects XTRA data into the GPS. */ + int (*inject_xtra_data)( char* data, int length ); +} GpsXtraInterface; + +/** Extended interface for DEBUG support. */ +typedef struct { + /** set to sizeof(GpsDebugInterface) */ + size_t size; + + /** + * This function should return any information that the native + * implementation wishes to include in a bugreport. + */ + size_t (*get_internal_state)(char* buffer, size_t bufferSize); +} GpsDebugInterface; + +#pragma pack(push,4) +// We need to keep the alignment of this data structure to 4-bytes, to ensure that in 64-bit +// environments the size of this legacy definition does not collide with _v2. Implementations should +// be using _v2 and _v3, so it's OK to pay the 'unaligned' penalty in 64-bit if an old +// implementation is still in use. + +/** Represents the status of AGPS. */ +typedef struct { + /** set to sizeof(AGpsStatus_v1) */ + size_t size; + + AGpsType type; + AGpsStatusValue status; +} AGpsStatus_v1; + +#pragma pack(pop) + +/** Represents the status of AGPS augmented with a IPv4 address field. */ +typedef struct { + /** set to sizeof(AGpsStatus_v2) */ + size_t size; + + AGpsType type; + AGpsStatusValue status; + uint32_t ipaddr; +} AGpsStatus_v2; + +/* Represents the status of AGPS augmented to support IPv4 and IPv6. */ +typedef struct { + /** set to sizeof(AGpsStatus_v3) */ + size_t size; + + AGpsType type; + AGpsStatusValue status; + + /** + * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4 + * address, or set to INADDR_NONE otherwise. + */ + uint32_t ipaddr; + + /** + * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report. + * Any other value of addr.ss_family will be rejected. + * */ + struct sockaddr_storage addr; +} AGpsStatus_v3; + +typedef AGpsStatus_v3 AGpsStatus; + +/** Callback with AGPS status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* agps_status_callback)(AGpsStatus* status); + +/** Callback structure for the AGPS interface. */ +typedef struct { + agps_status_callback status_cb; + gps_create_thread create_thread_cb; +} AGpsCallbacks; + + +/** Extended interface for AGPS support. */ +typedef struct { + /** set to sizeof(AGpsInterface_v1) */ + size_t size; + + /** + * Opens the AGPS interface and provides the callback routines + * to the implementation of this interface. + */ + void (*init)( AGpsCallbacks* callbacks ); + /** + * Notifies that a data connection is available and sets + * the name of the APN to be used for SUPL. + */ + int (*data_conn_open)( const char* apn ); + /** + * Notifies that the AGPS data connection has been closed. + */ + int (*data_conn_closed)(); + /** + * Notifies that a data connection is not available for AGPS. + */ + int (*data_conn_failed)(); + /** + * Sets the hostname and port for the AGPS server. + */ + int (*set_server)( AGpsType type, const char* hostname, int port ); +} AGpsInterface_v1; + +/** + * Extended interface for AGPS support, it is augmented to enable to pass + * extra APN data. + */ +typedef struct { + /** set to sizeof(AGpsInterface_v2) */ + size_t size; + + /** + * Opens the AGPS interface and provides the callback routines to the + * implementation of this interface. + */ + void (*init)(AGpsCallbacks* callbacks); + /** + * Deprecated. + * If the HAL supports AGpsInterface_v2 this API will not be used, see + * data_conn_open_with_apn_ip_type for more information. + */ + int (*data_conn_open)(const char* apn); + /** + * Notifies that the AGPS data connection has been closed. + */ + int (*data_conn_closed)(); + /** + * Notifies that a data connection is not available for AGPS. + */ + int (*data_conn_failed)(); + /** + * Sets the hostname and port for the AGPS server. + */ + int (*set_server)(AGpsType type, const char* hostname, int port); + + /** + * Notifies that a data connection is available and sets the name of the + * APN, and its IP type, to be used for SUPL connections. + */ + int (*data_conn_open_with_apn_ip_type)( + const char* apn, + ApnIpType apnIpType); +} AGpsInterface_v2; + +typedef AGpsInterface_v2 AGpsInterface; + +/** Error codes associated with certificate operations */ +#define AGPS_CERTIFICATE_OPERATION_SUCCESS 0 +#define AGPS_CERTIFICATE_ERROR_GENERIC -100 +#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES -101 + +/** A data structure that represents an X.509 certificate using DER encoding */ +typedef struct { + size_t length; + u_char* data; +} DerEncodedCertificate; + +/** + * A type definition for SHA1 Fingerprints used to identify X.509 Certificates + * The Fingerprint is a digest of the DER Certificate that uniquely identifies it. + */ +typedef struct { + u_char data[20]; +} Sha1CertificateFingerprint; + +/** AGPS Interface to handle SUPL certificate operations */ +typedef struct { + /** set to sizeof(SuplCertificateInterface) */ + size_t size; + + /** + * Installs a set of Certificates used for SUPL connections to the AGPS server. + * If needed the HAL should find out internally any certificates that need to be removed to + * accommodate the certificates to install. + * The certificates installed represent a full set of valid certificates needed to connect to + * AGPS SUPL servers. + * The list of certificates is required, and all must be available at the same time, when trying + * to establish a connection with the AGPS Server. + * + * Parameters: + * certificates - A pointer to an array of DER encoded certificates that are need to be + * installed in the HAL. + * length - The number of certificates to install. + * Returns: + * AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully + * AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of + * certificates attempted to be installed, the state of the certificates stored should + * remain the same as before on this error case. + * + * IMPORTANT: + * If needed the HAL should find out internally the set of certificates that need to be + * removed to accommodate the certificates to install. + */ + int (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length ); + + /** + * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is + * expected that the given set of certificates is removed from the internal store of the HAL. + * + * Parameters: + * fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of + * certificates to revoke. + * length - The number of fingerprints provided. + * Returns: + * AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully. + * + * IMPORTANT: + * If any of the certificates provided (through its fingerprint) is not known by the HAL, + * it should be ignored and continue revoking/deleting the rest of them. + */ + int (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length ); +} SuplCertificateInterface; + +/** Represents an NI request */ +typedef struct { + /** set to sizeof(GpsNiNotification) */ + size_t size; + + /** + * An ID generated by HAL to associate NI notifications and UI + * responses + */ + int notification_id; + + /** + * An NI type used to distinguish different categories of NI + * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ... + */ + GpsNiType ni_type; + + /** + * Notification/verification options, combinations of GpsNiNotifyFlags constants + */ + GpsNiNotifyFlags notify_flags; + + /** + * Timeout period to wait for user response. + * Set to 0 for no time out limit. + */ + int timeout; + + /** + * Default response when time out. + */ + GpsUserResponseType default_response; + + /** + * Requestor ID + */ + char requestor_id[GPS_NI_SHORT_STRING_MAXLEN]; + + /** + * Notification message. It can also be used to store client_id in some cases + */ + char text[GPS_NI_LONG_STRING_MAXLEN]; + + /** + * Client name decoding scheme + */ + GpsNiEncodingType requestor_id_encoding; + + /** + * Client name decoding scheme + */ + GpsNiEncodingType text_encoding; + + /** + * A pointer to extra data. Format: + * key_1 = value_1 + * key_2 = value_2 + */ + char extras[GPS_NI_LONG_STRING_MAXLEN]; + +} GpsNiNotification; + +/** Callback with NI notification. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification); + +/** GPS NI callback structure. */ +typedef struct +{ + /** + * Sends the notification request from HAL to GPSLocationProvider. + */ + gps_ni_notify_callback notify_cb; + gps_create_thread create_thread_cb; +} GpsNiCallbacks; + +/** + * Extended interface for Network-initiated (NI) support. + */ +typedef struct +{ + /** set to sizeof(GpsNiInterface) */ + size_t size; + + /** Registers the callbacks for HAL to use. */ + void (*init) (GpsNiCallbacks *callbacks); + + /** Sends a response to HAL. */ + void (*respond) (int notif_id, GpsUserResponseType user_response); +} GpsNiInterface; + +struct gps_device_t { + struct hw_device_t common; + + /** + * Set the provided lights to the provided values. + * + * Returns: 0 on succes, error code on failure. + */ + const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev); +}; + +#define AGPS_RIL_REQUEST_SETID_IMSI (1<<0L) +#define AGPS_RIL_REQUEST_SETID_MSISDN (1<<1L) + +#define AGPS_RIL_REQUEST_REFLOC_CELLID (1<<0L) +#define AGPS_RIL_REQUEST_REFLOC_MAC (1<<1L) + +typedef void (*agps_ril_request_set_id)(uint32_t flags); +typedef void (*agps_ril_request_ref_loc)(uint32_t flags); + +typedef struct { + agps_ril_request_set_id request_setid; + agps_ril_request_ref_loc request_refloc; + gps_create_thread create_thread_cb; +} AGpsRilCallbacks; + +/** Extended interface for AGPS_RIL support. */ +typedef struct { + /** set to sizeof(AGpsRilInterface) */ + size_t size; + /** + * Opens the AGPS interface and provides the callback routines + * to the implementation of this interface. + */ + void (*init)( AGpsRilCallbacks* callbacks ); + + /** + * Sets the reference location. + */ + void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct); + /** + * Sets the set ID. + */ + void (*set_set_id) (AGpsSetIDType type, const char* setid); + + /** + * Send network initiated message. + */ + void (*ni_message) (uint8_t *msg, size_t len); + + /** + * Notify GPS of network status changes. + * These parameters match values in the android.net.NetworkInfo class. + */ + void (*update_network_state) (int connected, int type, int roaming, const char* extra_info); + + /** + * Notify GPS of network status changes. + * These parameters match values in the android.net.NetworkInfo class. + */ + void (*update_network_availability) (int avaiable, const char* apn); +} AGpsRilInterface; + +/** + * GPS Geofence. + * There are 3 states associated with a Geofence: Inside, Outside, Unknown. + * There are 3 transitions: ENTERED, EXITED, UNCERTAIN. + * + * An example state diagram with confidence level: 95% and Unknown time limit + * set as 30 secs is shown below. (confidence level and Unknown time limit are + * explained latter) + * ____________________________ + * | Unknown (30 secs) | + * """""""""""""""""""""""""""" + * ^ | | ^ + * UNCERTAIN| |ENTERED EXITED| |UNCERTAIN + * | v v | + * ________ EXITED _________ + * | Inside | -----------> | Outside | + * | | <----------- | | + * """""""" ENTERED """"""""" + * + * Inside state: We are 95% confident that the user is inside the geofence. + * Outside state: We are 95% confident that the user is outside the geofence + * Unknown state: Rest of the time. + * + * The Unknown state is better explained with an example: + * + * __________ + * | c| + * | ___ | _______ + * | |a| | | b | + * | """ | """"""" + * | | + * """""""""" + * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy + * circle reported by the GPS subsystem. Now with regard to "b", the system is + * confident that the user is outside. But with regard to "a" is not confident + * whether it is inside or outside the geofence. If the accuracy remains the + * same for a sufficient period of time, the UNCERTAIN transition would be + * triggered with the state set to Unknown. If the accuracy improves later, an + * appropriate transition should be triggered. This "sufficient period of time" + * is defined by the parameter in the add_geofence_area API. + * In other words, Unknown state can be interpreted as a state in which the + * GPS subsystem isn't confident enough that the user is either inside or + * outside the Geofence. It moves to Unknown state only after the expiry of the + * timeout. + * + * The geofence callback needs to be triggered for the ENTERED and EXITED + * transitions, when the GPS system is confident that the user has entered + * (Inside state) or exited (Outside state) the Geofence. An implementation + * which uses a value of 95% as the confidence is recommended. The callback + * should be triggered only for the transitions requested by the + * add_geofence_area call. + * + * Even though the diagram and explanation talks about states and transitions, + * the callee is only interested in the transistions. The states are mentioned + * here for illustrative purposes. + * + * Startup Scenario: When the device boots up, if an application adds geofences, + * and then we get an accurate GPS location fix, it needs to trigger the + * appropriate (ENTERED or EXITED) transition for every Geofence it knows about. + * By default, all the Geofences will be in the Unknown state. + * + * When the GPS system is unavailable, gps_geofence_status_callback should be + * called to inform the upper layers of the same. Similarly, when it becomes + * available the callback should be called. This is a global state while the + * UNKNOWN transition described above is per geofence. + * + * An important aspect to note is that users of this API (framework), will use + * other subsystems like wifi, sensors, cell to handle Unknown case and + * hopefully provide a definitive state transition to the third party + * application. GPS Geofence will just be a signal indicating what the GPS + * subsystem knows about the Geofence. + * + */ +#define GPS_GEOFENCE_ENTERED (1<<0L) +#define GPS_GEOFENCE_EXITED (1<<1L) +#define GPS_GEOFENCE_UNCERTAIN (1<<2L) + +#define GPS_GEOFENCE_UNAVAILABLE (1<<0L) +#define GPS_GEOFENCE_AVAILABLE (1<<1L) + +#define GPS_GEOFENCE_OPERATION_SUCCESS 0 +#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100 +#define GPS_GEOFENCE_ERROR_ID_EXISTS -101 +#define GPS_GEOFENCE_ERROR_ID_UNKNOWN -102 +#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103 +#define GPS_GEOFENCE_ERROR_GENERIC -149 + +/** + * The callback associated with the geofence. + * Parameters: + * geofence_id - The id associated with the add_geofence_area. + * location - The current GPS location. + * transition - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED, + * GPS_GEOFENCE_UNCERTAIN. + * timestamp - Timestamp when the transition was detected. + * + * The callback should only be called when the caller is interested in that + * particular transition. For instance, if the caller is interested only in + * ENTERED transition, then the callback should NOT be called with the EXITED + * transition. + * + * IMPORTANT: If a transition is triggered resulting in this callback, the GPS + * subsystem will wake up the application processor, if its in suspend state. + */ +typedef void (*gps_geofence_transition_callback) (int32_t geofence_id, GpsLocation* location, + int32_t transition, GpsUtcTime timestamp); + +/** + * The callback associated with the availability of the GPS system for geofencing + * monitoring. If the GPS system determines that it cannot monitor geofences + * because of lack of reliability or unavailability of the GPS signals, it will + * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter. + * + * Parameters: + * status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE. + * last_location - Last known location. + */ +typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location); + +/** + * The callback associated with the add_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * status - GPS_GEOFENCE_OPERATION_SUCCESS + * GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES - geofence limit has been reached. + * GPS_GEOFENCE_ERROR_ID_EXISTS - geofence with id already exists + * GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an + * invalid transition + * GPS_GEOFENCE_ERROR_GENERIC - for other errors. + */ +typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status); + +/** + * The callback associated with the remove_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * status - GPS_GEOFENCE_OPERATION_SUCCESS + * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id + * GPS_GEOFENCE_ERROR_GENERIC for others. + */ +typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status); + + +/** + * The callback associated with the pause_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * status - GPS_GEOFENCE_OPERATION_SUCCESS + * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id + * GPS_GEOFENCE_ERROR_INVALID_TRANSITION - + * when monitor_transitions is invalid + * GPS_GEOFENCE_ERROR_GENERIC for others. + */ +typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status); + +/** + * The callback associated with the resume_geofence call. + * + * Parameter: + * geofence_id - Id of the geofence. + * status - GPS_GEOFENCE_OPERATION_SUCCESS + * GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id + * GPS_GEOFENCE_ERROR_GENERIC for others. + */ +typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status); + +typedef struct { + gps_geofence_transition_callback geofence_transition_callback; + gps_geofence_status_callback geofence_status_callback; + gps_geofence_add_callback geofence_add_callback; + gps_geofence_remove_callback geofence_remove_callback; + gps_geofence_pause_callback geofence_pause_callback; + gps_geofence_resume_callback geofence_resume_callback; + gps_create_thread create_thread_cb; +} GpsGeofenceCallbacks; + +/** Extended interface for GPS_Geofencing support */ +typedef struct { + /** set to sizeof(GpsGeofencingInterface) */ + size_t size; + + /** + * Opens the geofence interface and provides the callback routines + * to the implementation of this interface. + */ + void (*init)( GpsGeofenceCallbacks* callbacks ); + + /** + * Add a geofence area. This api currently supports circular geofences. + * Parameters: + * geofence_id - The id for the geofence. If a geofence with this id + * already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS) + * should be returned. + * latitude, longtitude, radius_meters - The lat, long and radius + * (in meters) for the geofence + * last_transition - The current state of the geofence. For example, if + * the system already knows that the user is inside the geofence, + * this will be set to GPS_GEOFENCE_ENTERED. In most cases, it + * will be GPS_GEOFENCE_UNCERTAIN. + * monitor_transition - Which transitions to monitor. Bitwise OR of + * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and + * GPS_GEOFENCE_UNCERTAIN. + * notification_responsiveness_ms - Defines the best-effort description + * of how soon should the callback be called when the transition + * associated with the Geofence is triggered. For instance, if set + * to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback + * should be called 1000 milliseconds within entering the geofence. + * This parameter is defined in milliseconds. + * NOTE: This is not to be confused with the rate that the GPS is + * polled at. It is acceptable to dynamically vary the rate of + * sampling the GPS for power-saving reasons; thus the rate of + * sampling may be faster or slower than this. + * unknown_timer_ms - The time limit after which the UNCERTAIN transition + * should be triggered. This parameter is defined in milliseconds. + * See above for a detailed explanation. + */ + void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude, + double radius_meters, int last_transition, int monitor_transitions, + int notification_responsiveness_ms, int unknown_timer_ms); + + /** + * Pause monitoring a particular geofence. + * Parameters: + * geofence_id - The id for the geofence. + */ + void (*pause_geofence) (int32_t geofence_id); + + /** + * Resume monitoring a particular geofence. + * Parameters: + * geofence_id - The id for the geofence. + * monitor_transitions - Which transitions to monitor. Bitwise OR of + * GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and + * GPS_GEOFENCE_UNCERTAIN. + * This supersedes the value associated provided in the + * add_geofence_area call. + */ + void (*resume_geofence) (int32_t geofence_id, int monitor_transitions); + + /** + * Remove a geofence area. After the function returns, no notifications + * should be sent. + * Parameter: + * geofence_id - The id for the geofence. + */ + void (*remove_geofence_area) (int32_t geofence_id); +} GpsGeofencingInterface; + + +/** + * Represents an estimate of the GPS clock time. + */ +typedef struct { + /** set to sizeof(GpsClock) */ + size_t size; + + /** A set of flags indicating the validity of the fields in this data structure. */ + GpsClockFlags flags; + + /** + * Leap second data. + * The sign of the value is defined by the following equation: + * utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000 + * + * If the data is available 'flags' must contain GPS_CLOCK_HAS_LEAP_SECOND. + */ + int16_t leap_second; + + /** + * Indicates the type of time reported by the 'time_ns' field. + * This is a Mandatory field. + */ + GpsClockType type; + + /** + * The GPS receiver internal clock value. This can be either the local hardware clock value + * (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver + * (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported. + * + * For local hardware clock, this value is expected to be monotonically increasing during + * the reporting session. The real GPS time can be derived by compensating the 'full bias' + * (when it is available) from this value. + * + * For GPS time, this value is expected to be the best estimation of current GPS time that GPS + * receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified. + * + * Sub-nanosecond accuracy can be provided by means of the 'bias' field. + * The value contains the 'time uncertainty' in it. + * + * This is a Mandatory field. + */ + int64_t time_ns; + + /** + * 1-Sigma uncertainty associated with the clock's time in nanoseconds. + * The uncertainty is represented as an absolute (single sided) value. + * + * This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set. + * If the data is available 'flags' must contain GPS_CLOCK_HAS_TIME_UNCERTAINTY. + */ + double time_uncertainty_ns; + + /** + * The difference between hardware clock ('time' field) inside GPS receiver and the true GPS + * time since 0000Z, January 6, 1980, in nanoseconds. + * This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver + * has solved the clock for GPS time. + * The caller is responsible for using the 'bias uncertainty' field for quality check. + * + * The sign of the value is defined by the following equation: + * true time (GPS time) = time_ns + (full_bias_ns + bias_ns) + * + * This value contains the 'bias uncertainty' in it. + * If the data is available 'flags' must contain GPS_CLOCK_HAS_FULL_BIAS. + + */ + int64_t full_bias_ns; + + /** + * Sub-nanosecond bias. + * The value contains the 'bias uncertainty' in it. + * + * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS. + */ + double bias_ns; + + /** + * 1-Sigma uncertainty associated with the clock's bias in nanoseconds. + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS_UNCERTAINTY. + */ + double bias_uncertainty_ns; + + /** + * The clock's drift in nanoseconds (per second). + * A positive value means that the frequency is higher than the nominal frequency. + * + * The value contains the 'drift uncertainty' in it. + * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT. + * + * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE, + * it is encouraged that this field is also provided. + */ + double drift_nsps; + + /** + * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second). + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT_UNCERTAINTY. + */ + double drift_uncertainty_nsps; +} GpsClock; + +/** + * Represents a GPS Measurement, it contains raw and computed information. + */ +typedef struct { + /** set to sizeof(GpsMeasurement) */ + size_t size; + + /** A set of flags indicating the validity of the fields in this data structure. */ + GpsMeasurementFlags flags; + + /** + * Pseudo-random number in the range of [1, 32] + * This is a Mandatory value. + */ + int8_t prn; + + /** + * Time offset at which the measurement was taken in nanoseconds. + * The reference receiver's time is specified by GpsData::clock::time_ns and should be + * interpreted in the same way as indicated by GpsClock::type. + * + * The sign of time_offset_ns is given by the following equation: + * measurement time = GpsClock::time_ns + time_offset_ns + * + * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy. + * This is a Mandatory value. + */ + double time_offset_ns; + + /** + * Per satellite sync state. It represents the current sync state for the associated satellite. + * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly. + * + * This is a Mandatory value. + */ + GpsMeasurementState state; + + /** + * Received GPS Time-of-Week at the measurement time, in nanoseconds. + * The value is relative to the beginning of the current GPS week. + * + * Given the highest sync state that can be achieved, per each satellite, valid range for + * this field can be: + * Searching : [ 0 ] : GPS_MEASUREMENT_STATE_UNKNOWN + * C/A code lock : [ 0 1ms ] : GPS_MEASUREMENT_STATE_CODE_LOCK is set + * Bit sync : [ 0 20ms ] : GPS_MEASUREMENT_STATE_BIT_SYNC is set + * Subframe sync : [ 0 6s ] : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set + * TOW decoded : [ 0 1week ] : GPS_MEASUREMENT_STATE_TOW_DECODED is set + * + * However, if there is any ambiguity in integer millisecond, + * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field. + * + * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN. + */ + int64_t received_gps_tow_ns; + + /** + * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds. + * + * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN. + */ + int64_t received_gps_tow_uncertainty_ns; + + /** + * Carrier-to-noise density in dB-Hz, in the range [0, 63]. + * It contains the measured C/N0 value for the signal at the antenna input. + * + * This is a Mandatory value. + */ + double c_n0_dbhz; + + /** + * Pseudorange rate at the timestamp in m/s. + * The correction of a given Pseudorange Rate value includes corrections for receiver and + * satellite clock frequency errors. + * + * If GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE is set in 'flags' field, this field must + * be populated with the 'uncorrected' reading. + * If GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE is not set in 'flags' field, this field + * must be populated with the 'corrected' reading. This is the default behavior. + * + * It is encouraged to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's + * 'drift' field as well. + * + * The value includes the 'pseudorange rate uncertainty' in it. + * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. + * + * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler + * shift' is given by the equation: + * pseudorange rate = -k * doppler shift (where k is a constant) + * + * This is a Mandatory value. + */ + double pseudorange_rate_mps; + + /** + * 1-Sigma uncertainty of the pseudurange rate in m/s. + * The uncertainty is represented as an absolute (single sided) value. + * + * This is a Mandatory value. + */ + double pseudorange_rate_uncertainty_mps; + + /** + * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip + * (indicating loss of lock). + * + * This is a Mandatory value. + */ + GpsAccumulatedDeltaRangeState accumulated_delta_range_state; + + /** + * Accumulated delta range since the last channel reset in meters. + * A positive value indicates that the SV is moving away from the receiver. + * + * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase' + * is given by the equation: + * accumulated delta range = -k * carrier phase (where k is a constant) + * + * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN. + * However, it is expected that the data is only accurate when: + * 'accumulated delta range state' == GPS_ADR_STATE_VALID. + */ + double accumulated_delta_range_m; + + /** + * 1-Sigma uncertainty of the accumulated delta range in meters. + * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN. + */ + double accumulated_delta_range_uncertainty_m; + + /** + * Best derived Pseudorange by the chip-set, in meters. + * The value contains the 'pseudorange uncertainty' in it. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE. + */ + double pseudorange_m; + + /** + * 1-Sigma uncertainty of the pseudorange in meters. + * The value contains the 'pseudorange' and 'clock' uncertainty in it. + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY. + */ + double pseudorange_uncertainty_m; + + /** + * A fraction of the current C/A code cycle, in the range [0.0, 1023.0] + * This value contains the time (in Chip units) since the last C/A code cycle (GPS Msec epoch). + * + * The reference frequency is given by the field 'carrier_frequency_hz'. + * The value contains the 'code-phase uncertainty' in it. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE. + */ + double code_phase_chips; + + /** + * 1-Sigma uncertainty of the code-phase, in a fraction of chips. + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY. + */ + double code_phase_uncertainty_chips; + + /** + * Carrier frequency at which codes and messages are modulated, it can be L1 or L2. + * If the field is not set, the carrier frequency is assumed to be L1. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY. + */ + float carrier_frequency_hz; + + /** + * The number of full carrier cycles between the satellite and the receiver. + * The reference frequency is given by the field 'carrier_frequency_hz'. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES. + */ + int64_t carrier_cycles; + + /** + * The RF phase detected by the receiver, in the range [0.0, 1.0]. + * This is usually the fractional part of the complete carrier phase measurement. + * + * The reference frequency is given by the field 'carrier_frequency_hz'. + * The value contains the 'carrier-phase uncertainty' in it. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE. + */ + double carrier_phase; + + /** + * 1-Sigma uncertainty of the carrier-phase. + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY. + */ + double carrier_phase_uncertainty; + + /** + * An enumeration that indicates the 'loss of lock' state of the event. + */ + GpsLossOfLock loss_of_lock; + + /** + * The number of GPS bits transmitted since Sat-Sun midnight (GPS week). + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_BIT_NUMBER. + */ + int32_t bit_number; + + /** + * The elapsed time since the last received bit in milliseconds, in the range [0, 20] + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT. + */ + int16_t time_from_last_bit_ms; + + /** + * Doppler shift in Hz. + * A positive value indicates that the SV is moving toward the receiver. + * + * The reference frequency is given by the field 'carrier_frequency_hz'. + * The value contains the 'doppler shift uncertainty' in it. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT. + */ + double doppler_shift_hz; + + /** + * 1-Sigma uncertainty of the doppler shift in Hz. + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY. + */ + double doppler_shift_uncertainty_hz; + + /** + * An enumeration that indicates the 'multipath' state of the event. + */ + GpsMultipathIndicator multipath_indicator; + + /** + * Signal-to-noise ratio in dB. + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR. + */ + double snr_db; + + /** + * Elevation in degrees, the valid range is [-90, 90]. + * The value contains the 'elevation uncertainty' in it. + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION. + */ + double elevation_deg; + + /** + * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90]. + * The uncertainty is represented as the absolute (single sided) value. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY. + */ + double elevation_uncertainty_deg; + + /** + * Azimuth in degrees, in the range [0, 360). + * The value contains the 'azimuth uncertainty' in it. + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH. + * */ + double azimuth_deg; + + /** + * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180]. + * The uncertainty is represented as an absolute (single sided) value. + * + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY. + */ + double azimuth_uncertainty_deg; + + /** + * Whether the GPS represented by the measurement was used for computing the most recent fix. + * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_USED_IN_FIX. + */ + bool used_in_fix; +} GpsMeasurement; + +/** Represents a reading of GPS measurements. */ +typedef struct { + /** set to sizeof(GpsData) */ + size_t size; + + /** Number of measurements. */ + size_t measurement_count; + + /** The array of measurements. */ + GpsMeasurement measurements[GPS_MAX_MEASUREMENT]; + + /** The GPS clock time reading. */ + GpsClock clock; +} GpsData; + +/** + * The callback for to report measurements from the HAL. + * + * Parameters: + * data - A data structure containing the measurements. + */ +typedef void (*gps_measurement_callback) (GpsData* data); + +typedef struct { + /** set to sizeof(GpsMeasurementCallbacks) */ + size_t size; + gps_measurement_callback measurement_callback; +} GpsMeasurementCallbacks; + +#define GPS_MEASUREMENT_OPERATION_SUCCESS 0 +#define GPS_MEASUREMENT_ERROR_ALREADY_INIT -100 +#define GPS_MEASUREMENT_ERROR_GENERIC -101 + +/** + * Extended interface for GPS Measurements support. + */ +typedef struct { + /** Set to sizeof(GpsMeasurementInterface) */ + size_t size; + + /** + * Initializes the interface and registers the callback routines with the HAL. + * After a successful call to 'init' the HAL must begin to provide updates at its own phase. + * + * Status: + * GPS_MEASUREMENT_OPERATION_SUCCESS + * GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a + * corresponding call to 'close' + * GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL + * will not generate any updates upon returning this error code. + */ + int (*init) (GpsMeasurementCallbacks* callbacks); + + /** + * Stops updates from the HAL, and unregisters the callback routines. + * After a call to stop, the previously registered callbacks must be considered invalid by the + * HAL. + * If stop is invoked without a previous 'init', this function should perform no work. + */ + void (*close) (); + +} GpsMeasurementInterface; + + +/** Represents a GPS navigation message (or a fragment of it). */ +typedef struct { + /** set to sizeof(GpsNavigationMessage) */ + size_t size; + + /** + * Pseudo-random number in the range of [1, 32] + * This is a Mandatory value. + */ + int8_t prn; + + /** + * The type of message contained in the structure. + * This is a Mandatory value. + */ + GpsNavigationMessageType type; + + /** + * The status of the received navigation message. + * No need to send any navigation message that contains words with parity error and cannot be + * corrected. + */ + NavigationMessageStatus status; + + /** + * Message identifier. + * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A + * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message. + * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1. + */ + int16_t message_id; + + /** + * Sub-message identifier. + * If required by the message 'type', this value contains a sub-index within the current + * message (or frame) that is being transmitted. + * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message. + */ + int16_t submessage_id; + + /** + * The length of the data (in bytes) contained in the current message. + * If this value is different from zero, 'data' must point to an array of the same size. + * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word). + * + * This is a Mandatory value. + */ + size_t data_length; + + /** + * The data of the reported GPS message. + * The bytes (or words) specified using big endian format (MSB first). + * + * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be + * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first. + */ + uint8_t* data; + +} GpsNavigationMessage; + +/** + * The callback to report an available fragment of a GPS navigation messages from the HAL. + * + * Parameters: + * message - The GPS navigation submessage/subframe representation. + */ +typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message); + +typedef struct { + /** set to sizeof(GpsNavigationMessageCallbacks) */ + size_t size; + gps_navigation_message_callback navigation_message_callback; +} GpsNavigationMessageCallbacks; + +#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS 0 +#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT -100 +#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC -101 + +/** + * Extended interface for GPS navigation message reporting support. + */ +typedef struct { + /** Set to sizeof(GpsNavigationMessageInterface) */ + size_t size; + + /** + * Initializes the interface and registers the callback routines with the HAL. + * After a successful call to 'init' the HAL must begin to provide updates as they become + * available. + * + * Status: + * GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS + * GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered + * without a corresponding call to 'close'. + * GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that + * the HAL will not generate any updates upon returning this error code. + */ + int (*init) (GpsNavigationMessageCallbacks* callbacks); + + /** + * Stops updates from the HAL, and unregisters the callback routines. + * After a call to stop, the previously registered callbacks must be considered invalid by the + * HAL. + * If stop is invoked without a previous 'init', this function should perform no work. + */ + void (*close) (); + +} GpsNavigationMessageInterface; + +/** + * Interface for passing GNSS configuration contents from platform to HAL. + */ +typedef struct { + /** Set to sizeof(GnssConfigurationInterface) */ + size_t size; + + /** + * Deliver GNSS configuration contents to HAL. + * Parameters: + * config_data - a pointer to a char array which holds what usually is expected from + file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'. + * length - total number of UTF8 characters in configuraiton data. + * + * IMPORTANT: + * GPS HAL should expect this function can be called multiple times. And it may be + * called even when GpsLocationProvider is already constructed and enabled. GPS HAL + * should maintain the existing requests for various callback regardless the change + * in configuration data. + */ + void (*configuration_update) (const char* config_data, int32_t length); +} GnssConfigurationInterface; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */ +
diff --git a/libhardware/include/hardware/gralloc.h b/libhardware/include/hardware/gralloc.h new file mode 100644 index 0000000..ef86f90 --- /dev/null +++ b/libhardware/include/hardware/gralloc.h
@@ -0,0 +1,384 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_GRALLOC_INTERFACE_H +#define ANDROID_GRALLOC_INTERFACE_H + +#include <system/window.h> +#include <system/graphics.h> +#include <hardware/hardware.h> + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <cutils/native_handle.h> + +#include <hardware/hardware.h> +#include <hardware/fb.h> + +__BEGIN_DECLS + +/** + * Module versioning information for the Gralloc hardware module, based on + * gralloc_module_t.common.module_api_version. + * + * Version History: + * + * GRALLOC_MODULE_API_VERSION_0_1: + * Initial Gralloc hardware module API. + * + * GRALLOC_MODULE_API_VERSION_0_2: + * Add support for flexible YCbCr format with (*lock_ycbcr)() method. + * + * GRALLOC_MODULE_API_VERSION_0_3: + * Add support for fence passing to/from lock/unlock. + */ + +#define GRALLOC_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define GRALLOC_MODULE_API_VERSION_0_2 HARDWARE_MODULE_API_VERSION(0, 2) +#define GRALLOC_MODULE_API_VERSION_0_3 HARDWARE_MODULE_API_VERSION(0, 3) + +#define GRALLOC_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION(0, 1) + +/** + * The id of this module + */ +#define GRALLOC_HARDWARE_MODULE_ID "gralloc" + +/** + * Name of the graphics device to open + */ + +#define GRALLOC_HARDWARE_GPU0 "gpu0" + +enum { + /* buffer is never read in software */ + GRALLOC_USAGE_SW_READ_NEVER = 0x00000000, + /* buffer is rarely read in software */ + GRALLOC_USAGE_SW_READ_RARELY = 0x00000002, + /* buffer is often read in software */ + GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003, + /* mask for the software read values */ + GRALLOC_USAGE_SW_READ_MASK = 0x0000000F, + + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000, + /* buffer is rarely written in software */ + GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020, + /* buffer is often written in software */ + GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030, + /* mask for the software write values */ + GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0, + + /* buffer will be used as an OpenGL ES texture */ + GRALLOC_USAGE_HW_TEXTURE = 0x00000100, + /* buffer will be used as an OpenGL ES render target */ + GRALLOC_USAGE_HW_RENDER = 0x00000200, + /* buffer will be used by the 2D hardware blitter */ + GRALLOC_USAGE_HW_2D = 0x00000400, + /* buffer will be used by the HWComposer HAL module */ + GRALLOC_USAGE_HW_COMPOSER = 0x00000800, + /* buffer will be used with the framebuffer device */ + GRALLOC_USAGE_HW_FB = 0x00001000, + + /* buffer should be displayed full-screen on an external display when + * possible */ + GRALLOC_USAGE_EXTERNAL_DISP = 0x00002000, + + /* Must have a hardware-protected path to external display sink for + * this buffer. If a hardware-protected path is not available, then + * either don't composite only this buffer (preferred) to the + * external sink, or (less desirable) do not route the entire + * composition to the external sink. */ + GRALLOC_USAGE_PROTECTED = 0x00004000, + + /* buffer may be used as a cursor */ + GRALLOC_USAGE_CURSOR = 0x00008000, + + /* buffer will be used with the HW video encoder */ + GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000, + /* buffer will be written by the HW camera pipeline */ + GRALLOC_USAGE_HW_CAMERA_WRITE = 0x00020000, + /* buffer will be read by the HW camera pipeline */ + GRALLOC_USAGE_HW_CAMERA_READ = 0x00040000, + /* buffer will be used as part of zero-shutter-lag queue */ + GRALLOC_USAGE_HW_CAMERA_ZSL = 0x00060000, + /* mask for the camera access values */ + GRALLOC_USAGE_HW_CAMERA_MASK = 0x00060000, + /* mask for the software usage bit-mask */ + GRALLOC_USAGE_HW_MASK = 0x00071F00, + + /* buffer will be used as a RenderScript Allocation */ + GRALLOC_USAGE_RENDERSCRIPT = 0x00100000, + + /* Set by the consumer to indicate to the producer that they may attach a + * buffer that they did not detach from the BufferQueue. Will be filtered + * out by GRALLOC_USAGE_ALLOC_MASK, so gralloc modules will not need to + * handle this flag. */ + GRALLOC_USAGE_FOREIGN_BUFFERS = 0x00200000, + + /* Mask of all flags which could be passed to a gralloc module for buffer + * allocation. Any flags not in this mask do not need to be handled by + * gralloc modules. */ + GRALLOC_USAGE_ALLOC_MASK = ~(GRALLOC_USAGE_FOREIGN_BUFFERS), + + /* implementation-specific private usage flags */ + GRALLOC_USAGE_PRIVATE_0 = 0x10000000, + GRALLOC_USAGE_PRIVATE_1 = 0x20000000, + GRALLOC_USAGE_PRIVATE_2 = 0x40000000, + GRALLOC_USAGE_PRIVATE_3 = 0x80000000, + GRALLOC_USAGE_PRIVATE_MASK = 0xF0000000, +}; + +/*****************************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct gralloc_module_t { + struct hw_module_t common; + + /* + * (*registerBuffer)() must be called before a buffer_handle_t that has not + * been created with (*alloc_device_t::alloc)() can be used. + * + * This is intended to be used with buffer_handle_t's that have been + * received in this process through IPC. + * + * This function checks that the handle is indeed a valid one and prepares + * it for use with (*lock)() and (*unlock)(). + * + * It is not necessary to call (*registerBuffer)() on a handle created + * with (*alloc_device_t::alloc)(). + * + * returns an error if this buffer_handle_t is not valid. + */ + int (*registerBuffer)(struct gralloc_module_t const* module, + buffer_handle_t handle); + + /* + * (*unregisterBuffer)() is called once this handle is no longer needed in + * this process. After this call, it is an error to call (*lock)(), + * (*unlock)(), or (*registerBuffer)(). + * + * This function doesn't close or free the handle itself; this is done + * by other means, usually through libcutils's native_handle_close() and + * native_handle_free(). + * + * It is an error to call (*unregisterBuffer)() on a buffer that wasn't + * explicitly registered first. + */ + int (*unregisterBuffer)(struct gralloc_module_t const* module, + buffer_handle_t handle); + + /* + * The (*lock)() method is called before a buffer is accessed for the + * specified usage. This call may block, for instance if the h/w needs + * to finish rendering or if CPU caches need to be synchronized. + * + * The caller promises to modify only pixels in the area specified + * by (l,t,w,h). + * + * The content of the buffer outside of the specified area is NOT modified + * by this call. + * + * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address + * of the buffer in virtual memory. + * + * Note calling (*lock)() on HAL_PIXEL_FORMAT_YCbCr_*_888 buffers will fail + * and return -EINVAL. These buffers must be locked with (*lock_ycbcr)() + * instead. + * + * THREADING CONSIDERATIONS: + * + * It is legal for several different threads to lock a buffer from + * read access, none of the threads are blocked. + * + * However, locking a buffer simultaneously for write or read/write is + * undefined, but: + * - shall not result in termination of the process + * - shall not block the caller + * It is acceptable to return an error or to leave the buffer's content + * into an indeterminate state. + * + * If the buffer was created with a usage mask incompatible with the + * requested usage flags here, -EINVAL is returned. + * + */ + + int (*lock)(struct gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr); + + + /* + * The (*unlock)() method must be called after all changes to the buffer + * are completed. + */ + + int (*unlock)(struct gralloc_module_t const* module, + buffer_handle_t handle); + + + /* reserved for future use */ + int (*perform)(struct gralloc_module_t const* module, + int operation, ... ); + + /* + * The (*lock_ycbcr)() method is like the (*lock)() method, with the + * difference that it fills a struct ycbcr with a description of the buffer + * layout, and zeroes out the reserved fields. + * + * If the buffer format is not compatible with a flexible YUV format (e.g. + * the buffer layout cannot be represented with the ycbcr struct), it + * will return -EINVAL. + * + * This method must work on buffers with HAL_PIXEL_FORMAT_YCbCr_*_888 + * if supported by the device, as well as with any other format that is + * requested by the multimedia codecs when they are configured with a + * flexible-YUV-compatible color-format with android native buffers. + * + * Note that this method may also be called on buffers of other formats, + * including non-YUV formats. + * + * Added in GRALLOC_MODULE_API_VERSION_0_2. + */ + + int (*lock_ycbcr)(struct gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + struct android_ycbcr *ycbcr); + + /* + * The (*lockAsync)() method is like the (*lock)() method except + * that the buffer's sync fence object is passed into the lock + * call instead of requiring the caller to wait for completion. + * + * The gralloc implementation takes ownership of the fenceFd and + * is responsible for closing it when no longer needed. + * + * Added in GRALLOC_MODULE_API_VERSION_0_3. + */ + int (*lockAsync)(struct gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr, int fenceFd); + + /* + * The (*unlockAsync)() method is like the (*unlock)() method + * except that a buffer sync fence object is returned from the + * lock call, representing the completion of any pending work + * performed by the gralloc implementation. + * + * The caller takes ownership of the fenceFd and is responsible + * for closing it when no longer needed. + * + * Added in GRALLOC_MODULE_API_VERSION_0_3. + */ + int (*unlockAsync)(struct gralloc_module_t const* module, + buffer_handle_t handle, int* fenceFd); + + /* + * The (*lockAsync_ycbcr)() method is like the (*lock_ycbcr)() + * method except that the buffer's sync fence object is passed + * into the lock call instead of requiring the caller to wait for + * completion. + * + * The gralloc implementation takes ownership of the fenceFd and + * is responsible for closing it when no longer needed. + * + * Added in GRALLOC_MODULE_API_VERSION_0_3. + */ + int (*lockAsync_ycbcr)(struct gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + struct android_ycbcr *ycbcr, int fenceFd); + + /* reserved for future use */ + void* reserved_proc[3]; +} gralloc_module_t; + +/*****************************************************************************/ + +/** + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ + +typedef struct alloc_device_t { + struct hw_device_t common; + + /* + * (*alloc)() Allocates a buffer in graphic memory with the requested + * parameters and returns a buffer_handle_t and the stride in pixels to + * allow the implementation to satisfy hardware constraints on the width + * of a pixmap (eg: it may have to be multiple of 8 pixels). + * The CALLER TAKES OWNERSHIP of the buffer_handle_t. + * + * If format is HAL_PIXEL_FORMAT_YCbCr_420_888, the returned stride must be + * 0, since the actual strides are available from the android_ycbcr + * structure. + * + * Returns 0 on success or -errno on error. + */ + + int (*alloc)(struct alloc_device_t* dev, + int w, int h, int format, int usage, + buffer_handle_t* handle, int* stride); + + /* + * (*free)() Frees a previously allocated buffer. + * Behavior is undefined if the buffer is still mapped in any process, + * but shall not result in termination of the program or security breaches + * (allowing a process to get access to another process' buffers). + * THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes + * invalid after the call. + * + * Returns 0 on success or -errno on error. + */ + int (*free)(struct alloc_device_t* dev, + buffer_handle_t handle); + + /* This hook is OPTIONAL. + * + * If non NULL it will be caused by SurfaceFlinger on dumpsys + */ + void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len); + + void* reserved_proc[7]; +} alloc_device_t; + + +/** convenience API for opening and closing a supported device */ + +static inline int gralloc_open(const struct hw_module_t* module, + struct alloc_device_t** device) { + return module->methods->open(module, + GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device); +} + +static inline int gralloc_close(struct alloc_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_GRALLOC_INTERFACE_H
diff --git a/libhardware/include/hardware/hardware.h b/libhardware/include/hardware/hardware.h new file mode 100644 index 0000000..74f57aa --- /dev/null +++ b/libhardware/include/hardware/hardware.h
@@ -0,0 +1,238 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_HARDWARE_H +#define ANDROID_INCLUDE_HARDWARE_HARDWARE_H + +#include <stdint.h> +#include <sys/cdefs.h> + +#include <cutils/native_handle.h> +#include <system/graphics.h> + +__BEGIN_DECLS + +/* + * Value for the hw_module_t.tag field + */ + +#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D)) + +#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T') +#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T') + +#define HARDWARE_MAKE_API_VERSION(maj,min) \ + ((((maj) & 0xff) << 8) | ((min) & 0xff)) + +#define HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) \ + ((((maj) & 0xff) << 24) | (((min) & 0xff) << 16) | ((hdr) & 0xffff)) +#define HARDWARE_API_VERSION_2_MAJ_MIN_MASK 0xffff0000 +#define HARDWARE_API_VERSION_2_HEADER_MASK 0x0000ffff + + +/* + * The current HAL API version. + * + * All module implementations must set the hw_module_t.hal_api_version field + * to this value when declaring the module with HAL_MODULE_INFO_SYM. + * + * Note that previous implementations have always set this field to 0. + * Therefore, libhardware HAL API will always consider versions 0.0 and 1.0 + * to be 100% binary compatible. + * + */ +#define HARDWARE_HAL_API_VERSION HARDWARE_MAKE_API_VERSION(1, 0) + +/* + * Helper macros for module implementors. + * + * The derived modules should provide convenience macros for supported + * versions so that implementations can explicitly specify module/device + * versions at definition time. + * + * Use this macro to set the hw_module_t.module_api_version field. + */ +#define HARDWARE_MODULE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min) +#define HARDWARE_MODULE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) + +/* + * Use this macro to set the hw_device_t.version field + */ +#define HARDWARE_DEVICE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min) +#define HARDWARE_DEVICE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) + +struct hw_module_t; +struct hw_module_methods_t; +struct hw_device_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct hw_module_t { + /** tag must be initialized to HARDWARE_MODULE_TAG */ + uint32_t tag; + + /** + * The API version of the implemented module. The module owner is + * responsible for updating the version when a module interface has + * changed. + * + * The derived modules such as gralloc and audio own and manage this field. + * The module user must interpret the version field to decide whether or + * not to inter-operate with the supplied module implementation. + * For example, SurfaceFlinger is responsible for making sure that + * it knows how to manage different versions of the gralloc-module API, + * and AudioFlinger must know how to do the same for audio-module API. + * + * The module API version should include a major and a minor component. + * For example, version 1.0 could be represented as 0x0100. This format + * implies that versions 0x0100-0x01ff are all API-compatible. + * + * In the future, libhardware will expose a hw_get_module_version() + * (or equivalent) function that will take minimum/maximum supported + * versions as arguments and would be able to reject modules with + * versions outside of the supplied range. + */ + uint16_t module_api_version; +#define version_major module_api_version + /** + * version_major/version_minor defines are supplied here for temporary + * source code compatibility. They will be removed in the next version. + * ALL clients must convert to the new version format. + */ + + /** + * The API version of the HAL module interface. This is meant to + * version the hw_module_t, hw_module_methods_t, and hw_device_t + * structures and definitions. + * + * The HAL interface owns this field. Module users/implementations + * must NOT rely on this value for version information. + * + * Presently, 0 is the only valid value. + */ + uint16_t hal_api_version; +#define version_minor hal_api_version + + /** Identifier of module */ + const char *id; + + /** Name of this module */ + const char *name; + + /** Author/owner/implementor of the module */ + const char *author; + + /** Modules methods */ + struct hw_module_methods_t* methods; + + /** module's dso */ + void* dso; + +#ifdef __LP64__ + uint64_t reserved[32-7]; +#else + /** padding to 128 bytes, reserved for future use */ + uint32_t reserved[32-7]; +#endif + +} hw_module_t; + +typedef struct hw_module_methods_t { + /** Open a specific device */ + int (*open)(const struct hw_module_t* module, const char* id, + struct hw_device_t** device); + +} hw_module_methods_t; + +/** + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ +typedef struct hw_device_t { + /** tag must be initialized to HARDWARE_DEVICE_TAG */ + uint32_t tag; + + /** + * Version of the module-specific device API. This value is used by + * the derived-module user to manage different device implementations. + * + * The module user is responsible for checking the module_api_version + * and device version fields to ensure that the user is capable of + * communicating with the specific module implementation. + * + * One module can support multiple devices with different versions. This + * can be useful when a device interface changes in an incompatible way + * but it is still necessary to support older implementations at the same + * time. One such example is the Camera 2.0 API. + * + * This field is interpreted by the module user and is ignored by the + * HAL interface itself. + */ + uint32_t version; + + /** reference to the module this device belongs to */ + struct hw_module_t* module; + + /** padding reserved for future use */ +#ifdef __LP64__ + uint64_t reserved[12]; +#else + uint32_t reserved[12]; +#endif + + /** Close this device */ + int (*close)(struct hw_device_t* device); + +} hw_device_t; + +/** + * Name of the hal_module_info + */ +#define HAL_MODULE_INFO_SYM HMI + +/** + * Name of the hal_module_info as a string + */ +#define HAL_MODULE_INFO_SYM_AS_STR "HMI" + +/** + * Get the module info associated with a module by id. + * + * @return: 0 == success, <0 == error and *module == NULL + */ +int hw_get_module(const char *id, const struct hw_module_t **module); + +/** + * Get the module info associated with a module instance by class 'class_id' + * and instance 'inst'. + * + * Some modules types necessitate multiple instances. For example audio supports + * multiple concurrent interfaces and thus 'audio' is the module class + * and 'primary' or 'a2dp' are module interfaces. This implies that the files + * providing these modules would be named audio.primary.<variant>.so and + * audio.a2dp.<variant>.so + * + * @return: 0 == success, <0 == error and *module == NULL + */ +int hw_get_module_by_class(const char *class_id, const char *inst, + const struct hw_module_t **module); + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */
diff --git a/libhardware/include/hardware/hdmi_cec.h b/libhardware/include/hardware/hdmi_cec.h new file mode 100644 index 0000000..ab70f92 --- /dev/null +++ b/libhardware/include/hardware/hdmi_cec.h
@@ -0,0 +1,429 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_HDMI_CEC_H +#define ANDROID_INCLUDE_HARDWARE_HDMI_CEC_H + +#include <stdint.h> +#include <sys/cdefs.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define HDMI_CEC_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define HDMI_CEC_MODULE_API_VERSION_CURRENT HDMI_MODULE_API_VERSION_1_0 + +#define HDMI_CEC_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define HDMI_CEC_DEVICE_API_VERSION_CURRENT HDMI_DEVICE_API_VERSION_1_0 + +#define HDMI_CEC_HARDWARE_MODULE_ID "hdmi_cec" +#define HDMI_CEC_HARDWARE_INTERFACE "hdmi_cec_hw_if" + +typedef enum cec_device_type { + CEC_DEVICE_INACTIVE = -1, + CEC_DEVICE_TV = 0, + CEC_DEVICE_RECORDER = 1, + CEC_DEVICE_RESERVED = 2, + CEC_DEVICE_TUNER = 3, + CEC_DEVICE_PLAYBACK = 4, + CEC_DEVICE_AUDIO_SYSTEM = 5, + CEC_DEVICE_MAX = CEC_DEVICE_AUDIO_SYSTEM +} cec_device_type_t; + +typedef enum cec_logical_address { + CEC_ADDR_TV = 0, + CEC_ADDR_RECORDER_1 = 1, + CEC_ADDR_RECORDER_2 = 2, + CEC_ADDR_TUNER_1 = 3, + CEC_ADDR_PLAYBACK_1 = 4, + CEC_ADDR_AUDIO_SYSTEM = 5, + CEC_ADDR_TUNER_2 = 6, + CEC_ADDR_TUNER_3 = 7, + CEC_ADDR_PLAYBACK_2 = 8, + CEC_ADDR_RECORDER_3 = 9, + CEC_ADDR_TUNER_4 = 10, + CEC_ADDR_PLAYBACK_3 = 11, + CEC_ADDR_RESERVED_1 = 12, + CEC_ADDR_RESERVED_2 = 13, + CEC_ADDR_FREE_USE = 14, + CEC_ADDR_UNREGISTERED = 15, + CEC_ADDR_BROADCAST = 15 +} cec_logical_address_t; + +/* + * HDMI CEC messages + */ +enum cec_message_type { + CEC_MESSAGE_FEATURE_ABORT = 0x00, + CEC_MESSAGE_IMAGE_VIEW_ON = 0x04, + CEC_MESSAGE_TUNER_STEP_INCREMENT = 0x05, + CEC_MESSAGE_TUNER_STEP_DECREMENT = 0x06, + CEC_MESSAGE_TUNER_DEVICE_STATUS = 0x07, + CEC_MESSAGE_GIVE_TUNER_DEVICE_STATUS = 0x08, + CEC_MESSAGE_RECORD_ON = 0x09, + CEC_MESSAGE_RECORD_STATUS = 0x0A, + CEC_MESSAGE_RECORD_OFF = 0x0B, + CEC_MESSAGE_TEXT_VIEW_ON = 0x0D, + CEC_MESSAGE_RECORD_TV_SCREEN = 0x0F, + CEC_MESSAGE_GIVE_DECK_STATUS = 0x1A, + CEC_MESSAGE_DECK_STATUS = 0x1B, + CEC_MESSAGE_SET_MENU_LANGUAGE = 0x32, + CEC_MESSAGE_CLEAR_ANALOG_TIMER = 0x33, + CEC_MESSAGE_SET_ANALOG_TIMER = 0x34, + CEC_MESSAGE_TIMER_STATUS = 0x35, + CEC_MESSAGE_STANDBY = 0x36, + CEC_MESSAGE_PLAY = 0x41, + CEC_MESSAGE_DECK_CONTROL = 0x42, + CEC_MESSAGE_TIMER_CLEARED_STATUS = 0x043, + CEC_MESSAGE_USER_CONTROL_PRESSED = 0x44, + CEC_MESSAGE_USER_CONTROL_RELEASED = 0x45, + CEC_MESSAGE_GIVE_OSD_NAME = 0x46, + CEC_MESSAGE_SET_OSD_NAME = 0x47, + CEC_MESSAGE_SET_OSD_STRING = 0x64, + CEC_MESSAGE_SET_TIMER_PROGRAM_TITLE = 0x67, + CEC_MESSAGE_SYSTEM_AUDIO_MODE_REQUEST = 0x70, + CEC_MESSAGE_GIVE_AUDIO_STATUS = 0x71, + CEC_MESSAGE_SET_SYSTEM_AUDIO_MODE = 0x72, + CEC_MESSAGE_REPORT_AUDIO_STATUS = 0x7A, + CEC_MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, + CEC_MESSAGE_SYSTEM_AUDIO_MODE_STATUS = 0x7E, + CEC_MESSAGE_ROUTING_CHANGE = 0x80, + CEC_MESSAGE_ROUTING_INFORMATION = 0x81, + CEC_MESSAGE_ACTIVE_SOURCE = 0x82, + CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS = 0x83, + CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS = 0x84, + CEC_MESSAGE_REQUEST_ACTIVE_SOURCE = 0x85, + CEC_MESSAGE_SET_STREAM_PATH = 0x86, + CEC_MESSAGE_DEVICE_VENDOR_ID = 0x87, + CEC_MESSAGE_VENDOR_COMMAND = 0x89, + CEC_MESSAGE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A, + CEC_MESSAGE_VENDOR_REMOTE_BUTTON_UP = 0x8B, + CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID = 0x8C, + CEC_MESSAGE_MENU_REQUEST = 0x8D, + CEC_MESSAGE_MENU_STATUS = 0x8E, + CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS = 0x8F, + CEC_MESSAGE_REPORT_POWER_STATUS = 0x90, + CEC_MESSAGE_GET_MENU_LANGUAGE = 0x91, + CEC_MESSAGE_SELECT_ANALOG_SERVICE = 0x92, + CEC_MESSAGE_SELECT_DIGITAL_SERVICE = 0x93, + CEC_MESSAGE_SET_DIGITAL_TIMER = 0x97, + CEC_MESSAGE_CLEAR_DIGITAL_TIMER = 0x99, + CEC_MESSAGE_SET_AUDIO_RATE = 0x9A, + CEC_MESSAGE_INACTIVE_SOURCE = 0x9D, + CEC_MESSAGE_CEC_VERSION = 0x9E, + CEC_MESSAGE_GET_CEC_VERSION = 0x9F, + CEC_MESSAGE_VENDOR_COMMAND_WITH_ID = 0xA0, + CEC_MESSAGE_CLEAR_EXTERNAL_TIMER = 0xA1, + CEC_MESSAGE_SET_EXTERNAL_TIMER = 0xA2, + CEC_MESSAGE_INITIATE_ARC = 0xC0, + CEC_MESSAGE_REPORT_ARC_INITIATED = 0xC1, + CEC_MESSAGE_REPORT_ARC_TERMINATED = 0xC2, + CEC_MESSAGE_REQUEST_ARC_INITIATION = 0xC3, + CEC_MESSAGE_REQUEST_ARC_TERMINATION = 0xC4, + CEC_MESSAGE_TERMINATE_ARC = 0xC5, + CEC_MESSAGE_ABORT = 0xFF +}; + +/* + * Operand description [Abort Reason] + */ +enum abort_reason { + ABORT_UNRECOGNIZED_MODE = 0, + ABORT_NOT_IN_CORRECT_MODE = 1, + ABORT_CANNOT_PROVIDE_SOURCE = 2, + ABORT_INVALID_OPERAND = 3, + ABORT_REFUSED = 4, + ABORT_UNABLE_TO_DETERMINE = 5 +}; + +/* + * HDMI event type. used for hdmi_event_t. + */ +enum { + HDMI_EVENT_CEC_MESSAGE = 1, + HDMI_EVENT_HOT_PLUG = 2, +}; + +/* + * HDMI hotplug event type. Used when the event + * type is HDMI_EVENT_HOT_PLUG. + */ +enum { + HDMI_NOT_CONNECTED = 0, + HDMI_CONNECTED = 1 +}; + +/* + * error code used for send_message. + */ +enum { + HDMI_RESULT_SUCCESS = 0, + HDMI_RESULT_NACK = 1, /* not acknowledged */ + HDMI_RESULT_BUSY = 2, /* bus is busy */ + HDMI_RESULT_FAIL = 3, +}; + +/* + * HDMI port type. + */ +typedef enum hdmi_port_type { + HDMI_INPUT = 0, + HDMI_OUTPUT = 1 +} hdmi_port_type_t; + +/* + * Flags used for set_option() + */ +enum { + /* When set to false, HAL does not wake up the system upon receiving + * <Image View On> or <Text View On>. Used when user changes the TV + * settings to disable the auto TV on functionality. + * True by default. + */ + HDMI_OPTION_WAKEUP = 1, + + /* When set to false, all the CEC commands are discarded. Used when + * user changes the TV settings to disable CEC functionality. + * True by default. + */ + HDMI_OPTION_ENABLE_CEC = 2, + + /* Setting this flag to false means Android system will stop handling + * CEC service and yield the control over to the microprocessor that is + * powered on through the standby mode. When set to true, the system + * will gain the control over, hence telling the microprocessor to stop + * handling the cec commands. This is called when system goes + * in and out of standby mode to notify the microprocessor that it should + * start/stop handling CEC commands on behalf of the system. + * False by default. + */ + HDMI_OPTION_SYSTEM_CEC_CONTROL = 3, + + /* Option 4 not used */ + + /* Passes the updated language information of Android system. + * Contains 3-byte ASCII code as defined in ISO/FDIS 639-2. Can be + * used for HAL to respond to <Get Menu Language> while in standby mode. + * English(eng), for example, is converted to 0x656e67. + */ + HDMI_OPTION_SET_LANG = 5, +}; + +/* + * Maximum length in bytes of cec message body (exclude header block), + * should not exceed 16 (spec CEC 6 Frame Description) + */ +#define CEC_MESSAGE_BODY_MAX_LENGTH 16 + +typedef struct cec_message { + /* logical address of sender */ + cec_logical_address_t initiator; + + /* logical address of receiver */ + cec_logical_address_t destination; + + /* Length in bytes of body, range [0, CEC_MESSAGE_BODY_MAX_LENGTH] */ + size_t length; + unsigned char body[CEC_MESSAGE_BODY_MAX_LENGTH]; +} cec_message_t; + +typedef struct hotplug_event { + /* + * true if the cable is connected; otherwise false. + */ + int connected; + int port_id; +} hotplug_event_t; + +typedef struct tx_status_event { + int status; + int opcode; /* CEC opcode */ +} tx_status_event_t; + +/* + * HDMI event generated from HAL. + */ +typedef struct hdmi_event { + int type; + struct hdmi_cec_device* dev; + union { + cec_message_t cec; + hotplug_event_t hotplug; + }; +} hdmi_event_t; + +/* + * HDMI port descriptor + */ +typedef struct hdmi_port_info { + hdmi_port_type_t type; + // Port ID should start from 1 which corresponds to HDMI "port 1". + int port_id; + int cec_supported; + int arc_supported; + uint16_t physical_address; +} hdmi_port_info_t; + +/* + * Callback function type that will be called by HAL implementation. + * Services can not close/open the device in the callback. + */ +typedef void (*event_callback_t)(const hdmi_event_t* event, void* arg); + +typedef struct hdmi_cec_module { + /** + * Common methods of the HDMI CEC module. This *must* be the first member of + * hdmi_cec_module as users of this structure will cast a hw_module_t to hdmi_cec_module + * pointer in contexts where it's known the hw_module_t references a hdmi_cec_module. + */ + struct hw_module_t common; +} hdmi_module_t; + +/* + * HDMI-CEC HAL interface definition. + */ +typedef struct hdmi_cec_device { + /** + * Common methods of the HDMI CEC device. This *must* be the first member of + * hdmi_cec_device as users of this structure will cast a hw_device_t to hdmi_cec_device + * pointer in contexts where it's known the hw_device_t references a hdmi_cec_device. + */ + struct hw_device_t common; + + /* + * (*add_logical_address)() passes the logical address that will be used + * in this system. + * + * HAL may use it to configure the hardware so that the CEC commands addressed + * the given logical address can be filtered in. This method can be called + * as many times as necessary in order to support multiple logical devices. + * addr should be in the range of valid logical addresses for the call + * to succeed. + * + * Returns 0 on success or -errno on error. + */ + int (*add_logical_address)(const struct hdmi_cec_device* dev, cec_logical_address_t addr); + + /* + * (*clear_logical_address)() tells HAL to reset all the logical addresses. + * + * It is used when the system doesn't need to process CEC command any more, + * hence to tell HAL to stop receiving commands from the CEC bus, and change + * the state back to the beginning. + */ + void (*clear_logical_address)(const struct hdmi_cec_device* dev); + + /* + * (*get_physical_address)() returns the CEC physical address. The + * address is written to addr. + * + * The physical address depends on the topology of the network formed + * by connected HDMI devices. It is therefore likely to change if the cable + * is plugged off and on again. It is advised to call get_physical_address + * to get the updated address when hot plug event takes place. + * + * Returns 0 on success or -errno on error. + */ + int (*get_physical_address)(const struct hdmi_cec_device* dev, uint16_t* addr); + + /* + * (*send_message)() transmits HDMI-CEC message to other HDMI device. + * + * The method should be designed to return in a certain amount of time not + * hanging forever, which can happen if CEC signal line is pulled low for + * some reason. HAL implementation should take the situation into account + * so as not to wait forever for the message to get sent out. + * + * It should try retransmission at least once as specified in the standard. + * + * Returns error code. See HDMI_RESULT_SUCCESS, HDMI_RESULT_NACK, and + * HDMI_RESULT_BUSY. + */ + int (*send_message)(const struct hdmi_cec_device* dev, const cec_message_t*); + + /* + * (*register_event_callback)() registers a callback that HDMI-CEC HAL + * can later use for incoming CEC messages or internal HDMI events. + * When calling from C++, use the argument arg to pass the calling object. + * It will be passed back when the callback is invoked so that the context + * can be retrieved. + */ + void (*register_event_callback)(const struct hdmi_cec_device* dev, + event_callback_t callback, void* arg); + + /* + * (*get_version)() returns the CEC version supported by underlying hardware. + */ + void (*get_version)(const struct hdmi_cec_device* dev, int* version); + + /* + * (*get_vendor_id)() returns the identifier of the vendor. It is + * the 24-bit unique company ID obtained from the IEEE Registration + * Authority Committee (RAC). + */ + void (*get_vendor_id)(const struct hdmi_cec_device* dev, uint32_t* vendor_id); + + /* + * (*get_port_info)() returns the hdmi port information of underlying hardware. + * info is the list of HDMI port information, and 'total' is the number of + * HDMI ports in the system. + */ + void (*get_port_info)(const struct hdmi_cec_device* dev, + struct hdmi_port_info* list[], int* total); + + /* + * (*set_option)() passes flags controlling the way HDMI-CEC service works down + * to HAL implementation. Those flags will be used in case the feature needs + * update in HAL itself, firmware or microcontroller. + */ + void (*set_option)(const struct hdmi_cec_device* dev, int flag, int value); + + /* + * (*set_audio_return_channel)() configures ARC circuit in the hardware logic + * to start or stop the feature. Flag can be either 1 to start the feature + * or 0 to stop it. + * + * Returns 0 on success or -errno on error. + */ + void (*set_audio_return_channel)(const struct hdmi_cec_device* dev, int port_id, int flag); + + /* + * (*is_connected)() returns the connection status of the specified port. + * Returns HDMI_CONNECTED if a device is connected, otherwise HDMI_NOT_CONNECTED. + * The HAL should watch for +5V power signal to determine the status. + */ + int (*is_connected)(const struct hdmi_cec_device* dev, int port_id); + + /* Reserved for future use to maximum 16 functions. Must be NULL. */ + void* reserved[16 - 11]; +} hdmi_cec_device_t; + +/** convenience API for opening and closing a device */ + +static inline int hdmi_cec_open(const struct hw_module_t* module, + struct hdmi_cec_device** device) { + return module->methods->open(module, + HDMI_CEC_HARDWARE_INTERFACE, (struct hw_device_t**)device); +} + +static inline int hdmi_cec_close(struct hdmi_cec_device* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HDMI_CEC_H */
diff --git a/libhardware/include/hardware/hw_auth_token.h b/libhardware/include/hardware/hw_auth_token.h new file mode 100644 index 0000000..f471d1a --- /dev/null +++ b/libhardware/include/hardware/hw_auth_token.h
@@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 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 <stdint.h> + +#ifndef ANDROID_HARDWARE_HW_AUTH_TOKEN_H +#define ANDROID_HARDWARE_HW_AUTH_TOKEN_H + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +const uint8_t HW_AUTH_TOKEN_VERSION = 0; + +typedef enum { + HW_AUTH_NONE = 0, + HW_AUTH_PASSWORD = 1 << 0, + HW_AUTH_FINGERPRINT = 1 << 1, + // Additional entries should be powers of 2. + HW_AUTH_ANY = UINT32_MAX, +} hw_authenticator_type_t; + +/** + * Data format for an authentication record used to prove successful authentication. + */ +typedef struct __attribute__((__packed__)) { + uint8_t version; // Current version is 0 + uint64_t challenge; + uint64_t user_id; // secure user ID, not Android user ID + uint64_t authenticator_id; // secure authenticator ID + uint32_t authenticator_type; // hw_authenticator_type_t, in network order + uint64_t timestamp; // in network order + uint8_t hmac[32]; +} hw_auth_token_t; + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // ANDROID_HARDWARE_HW_AUTH_TOKEN_H
diff --git a/libhardware/include/hardware/hwcomposer.h b/libhardware/include/hardware/hwcomposer.h new file mode 100644 index 0000000..aa466b3 --- /dev/null +++ b/libhardware/include/hardware/hwcomposer.h
@@ -0,0 +1,833 @@ +/* + * 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. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_H +#define ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_H + +#include <stdint.h> +#include <sys/cdefs.h> + +#include <hardware/gralloc.h> +#include <hardware/hardware.h> +#include <cutils/native_handle.h> + +#include <hardware/hwcomposer_defs.h> + +__BEGIN_DECLS + +/*****************************************************************************/ + +/* for compatibility */ +#define HWC_MODULE_API_VERSION HWC_MODULE_API_VERSION_0_1 +#define HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_1 +#define HWC_API_VERSION HWC_DEVICE_API_VERSION + +/*****************************************************************************/ + +/** + * The id of this module + */ +#define HWC_HARDWARE_MODULE_ID "hwcomposer" + +/** + * Name of the sensors device to open + */ +#define HWC_HARDWARE_COMPOSER "composer" + +typedef struct hwc_rect { + int left; + int top; + int right; + int bottom; +} hwc_rect_t; + +typedef struct hwc_frect { + float left; + float top; + float right; + float bottom; +} hwc_frect_t; + +typedef struct hwc_region { + size_t numRects; + hwc_rect_t const* rects; +} hwc_region_t; + +typedef struct hwc_color { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +} hwc_color_t; + +typedef struct hwc_layer_1 { + /* + * compositionType is used to specify this layer's type and is set by either + * the hardware composer implementation, or by the caller (see below). + * + * This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER + * before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is + * also set, otherwise, this field is preserved between (*prepare)() + * calls. + * + * HWC_BACKGROUND + * Always set by the caller before calling (*prepare)(), this value + * indicates this is a special "background" layer. The only valid field + * is backgroundColor. + * The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT + * handle the background color. + * + * + * HWC_FRAMEBUFFER_TARGET + * Always set by the caller before calling (*prepare)(), this value + * indicates this layer is the framebuffer surface used as the target of + * OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY + * or HWC_BACKGROUND, then no OpenGL ES composition will be done, and + * this layer should be ignored during set(). + * + * This flag (and the framebuffer surface layer) will only be used if the + * HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions, + * the OpenGL ES target surface is communicated by the (dpy, sur) fields + * in hwc_compositor_device_1_t. + * + * This value cannot be set by the HWC implementation. + * + * + * HWC_FRAMEBUFFER + * Set by the caller before calling (*prepare)() ONLY when the + * HWC_GEOMETRY_CHANGED flag is also set. + * + * Set by the HWC implementation during (*prepare)(), this indicates + * that the layer will be drawn into the framebuffer using OpenGL ES. + * The HWC can toggle this value to HWC_OVERLAY to indicate it will + * handle the layer. + * + * + * HWC_OVERLAY + * Set by the HWC implementation during (*prepare)(), this indicates + * that the layer will be handled by the HWC (ie: it must not be + * composited with OpenGL ES). + * + * + * HWC_SIDEBAND + * Set by the caller before calling (*prepare)(), this value indicates + * the contents of this layer come from a sideband video stream. + * + * The h/w composer is responsible for receiving new image buffers from + * the stream at the appropriate time (e.g. synchronized to a separate + * audio stream), compositing them with the current contents of other + * layers, and displaying the resulting image. This happens + * independently of the normal prepare/set cycle. The prepare/set calls + * only happen when other layers change, or when properties of the + * sideband layer such as position or size change. + * + * If the h/w composer can't handle the layer as a sideband stream for + * some reason (e.g. unsupported scaling/blending/rotation, or too many + * sideband layers) it can set compositionType to HWC_FRAMEBUFFER in + * (*prepare)(). However, doing so will result in the layer being shown + * as a solid color since the platform is not currently able to composite + * sideband layers with the GPU. This may be improved in future + * versions of the platform. + * + * + * HWC_CURSOR_OVERLAY + * Set by the HWC implementation during (*prepare)(), this value + * indicates the layer's composition will now be handled by the HWC. + * Additionally, the client can now asynchronously update the on-screen + * position of this layer using the setCursorPositionAsync() api. + */ + int32_t compositionType; + + /* + * hints is bit mask set by the HWC implementation during (*prepare)(). + * It is preserved between (*prepare)() calls, unless the + * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0. + * + * see hwc_layer_t::hints + */ + uint32_t hints; + + /* see hwc_layer_t::flags */ + uint32_t flags; + + union { + /* color of the background. hwc_color_t.a is ignored */ + hwc_color_t backgroundColor; + + struct { + union { + /* When compositionType is HWC_FRAMEBUFFER, HWC_OVERLAY, + * HWC_FRAMEBUFFER_TARGET, this is the handle of the buffer to + * compose. This handle is guaranteed to have been allocated + * from gralloc using the GRALLOC_USAGE_HW_COMPOSER usage flag. + * If the layer's handle is unchanged across two consecutive + * prepare calls and the HWC_GEOMETRY_CHANGED flag is not set + * for the second call then the HWComposer implementation may + * assume that the contents of the buffer have not changed. */ + buffer_handle_t handle; + + /* When compositionType is HWC_SIDEBAND, this is the handle + * of the sideband video stream to compose. */ + const native_handle_t* sidebandStream; + }; + + /* transformation to apply to the buffer during composition */ + uint32_t transform; + + /* blending to apply during composition */ + int32_t blending; + + /* area of the source to consider, the origin is the top-left corner of + * the buffer. As of HWC_DEVICE_API_VERSION_1_3, sourceRect uses floats. + * If the h/w can't support a non-integer source crop rectangle, it should + * punt to OpenGL ES composition. + */ + union { + // crop rectangle in integer (pre HWC_DEVICE_API_VERSION_1_3) + hwc_rect_t sourceCropi; + hwc_rect_t sourceCrop; // just for source compatibility + // crop rectangle in floats (as of HWC_DEVICE_API_VERSION_1_3) + hwc_frect_t sourceCropf; + }; + + /* where to composite the sourceCrop onto the display. The sourceCrop + * is scaled using linear filtering to the displayFrame. The origin is the + * top-left corner of the screen. + */ + hwc_rect_t displayFrame; + + /* visible region in screen space. The origin is the + * top-left corner of the screen. + * The visible region INCLUDES areas overlapped by a translucent layer. + */ + hwc_region_t visibleRegionScreen; + + /* Sync fence object that will be signaled when the buffer's + * contents are available. May be -1 if the contents are already + * available. This field is only valid during set(), and should be + * ignored during prepare(). The set() call must not wait for the + * fence to be signaled before returning, but the HWC must wait for + * all buffers to be signaled before reading from them. + * + * HWC_FRAMEBUFFER layers will never have an acquire fence, since + * reads from them are complete before the framebuffer is ready for + * display. + * + * HWC_SIDEBAND layers will never have an acquire fence, since + * synchronization is handled through implementation-defined + * sideband mechanisms. + * + * The HWC takes ownership of the acquireFenceFd and is responsible + * for closing it when no longer needed. + */ + int acquireFenceFd; + + /* During set() the HWC must set this field to a file descriptor for + * a sync fence object that will signal after the HWC has finished + * reading from the buffer. The field is ignored by prepare(). Each + * layer should have a unique file descriptor, even if more than one + * refer to the same underlying fence object; this allows each to be + * closed independently. + * + * If buffer reads can complete at significantly different times, + * then using independent fences is preferred. For example, if the + * HWC handles some layers with a blit engine and others with + * overlays, then the blit layers can be reused immediately after + * the blit completes, but the overlay layers can't be reused until + * a subsequent frame has been displayed. + * + * Since HWC doesn't read from HWC_FRAMEBUFFER layers, it shouldn't + * produce a release fence for them. The releaseFenceFd will be -1 + * for these layers when set() is called. + * + * Since HWC_SIDEBAND buffers don't pass through the HWC client, + * the HWC shouldn't produce a release fence for them. The + * releaseFenceFd will be -1 for these layers when set() is called. + * + * The HWC client taks ownership of the releaseFenceFd and is + * responsible for closing it when no longer needed. + */ + int releaseFenceFd; + + /* + * Availability: HWC_DEVICE_API_VERSION_1_2 + * + * Alpha value applied to the whole layer. The effective + * value of each pixel is computed as: + * + * if (blending == HWC_BLENDING_PREMULT) + * pixel.rgb = pixel.rgb * planeAlpha / 255 + * pixel.a = pixel.a * planeAlpha / 255 + * + * Then blending proceeds as usual according to the "blending" + * field above. + * + * NOTE: planeAlpha applies to YUV layers as well: + * + * pixel.rgb = yuv_to_rgb(pixel.yuv) + * if (blending == HWC_BLENDING_PREMULT) + * pixel.rgb = pixel.rgb * planeAlpha / 255 + * pixel.a = planeAlpha + * + * + * IMPLEMENTATION NOTE: + * + * If the source image doesn't have an alpha channel, then + * the h/w can use the HWC_BLENDING_COVERAGE equations instead of + * HWC_BLENDING_PREMULT and simply set the alpha channel to + * planeAlpha. + * + * e.g.: + * + * if (blending == HWC_BLENDING_PREMULT) + * blending = HWC_BLENDING_COVERAGE; + * pixel.a = planeAlpha; + * + */ + uint8_t planeAlpha; + + /* Pad to 32 bits */ + uint8_t _pad[3]; + + /* + * Availability: HWC_DEVICE_API_VERSION_1_5 + * + * This defines the region of the source buffer that has been + * modified since the last frame. + * + * If surfaceDamage.numRects > 0, then it may be assumed that any + * portion of the source buffer not covered by one of the rects has + * not been modified this frame. If surfaceDamage.numRects == 0, + * then the whole source buffer must be treated as if it had been + * modified. + * + * If the layer's contents are not modified relative to the prior + * prepare/set cycle, surfaceDamage will contain exactly one empty + * rect ([0, 0, 0, 0]). + * + * The damage rects are relative to the pre-transformed buffer, and + * their origin is the top-left corner. + */ + hwc_region_t surfaceDamage; + }; + }; + +#ifdef __LP64__ + /* + * For 64-bit mode, this struct is 120 bytes (and 8-byte aligned), and needs + * to be padded as such to maintain binary compatibility. + */ + uint8_t reserved[120 - 112]; +#else + /* + * For 32-bit mode, this struct is 96 bytes, and needs to be padded as such + * to maintain binary compatibility. + */ + uint8_t reserved[96 - 84]; +#endif + +} hwc_layer_1_t; + +/* This represents a display, typically an EGLDisplay object */ +typedef void* hwc_display_t; + +/* This represents a surface, typically an EGLSurface object */ +typedef void* hwc_surface_t; + +/* + * hwc_display_contents_1_t::flags values + */ +enum { + /* + * HWC_GEOMETRY_CHANGED is set by SurfaceFlinger to indicate that the list + * passed to (*prepare)() has changed by more than just the buffer handles + * and acquire fences. + */ + HWC_GEOMETRY_CHANGED = 0x00000001, +}; + +/* + * Description of the contents to output on a display. + * + * This is the top-level structure passed to the prepare and set calls to + * negotiate and commit the composition of a display image. + */ +typedef struct hwc_display_contents_1 { + /* File descriptor referring to a Sync HAL fence object which will signal + * when this composition is retired. For a physical display, a composition + * is retired when it has been replaced on-screen by a subsequent set. For + * a virtual display, the composition is retired when the writes to + * outputBuffer are complete and can be read. The fence object is created + * and returned by the set call; this field will be -1 on entry to prepare + * and set. SurfaceFlinger will close the returned file descriptor. + */ + int retireFenceFd; + + union { + /* Fields only relevant for HWC_DEVICE_VERSION_1_0. */ + struct { + /* (dpy, sur) is the target of SurfaceFlinger's OpenGL ES + * composition for HWC_DEVICE_VERSION_1_0. They aren't relevant to + * prepare. The set call should commit this surface atomically to + * the display along with any overlay layers. + */ + hwc_display_t dpy; + hwc_surface_t sur; + }; + + /* These fields are used for virtual displays when the h/w composer + * version is at least HWC_DEVICE_VERSION_1_3. */ + struct { + /* outbuf is the buffer that receives the composed image for + * virtual displays. Writes to the outbuf must wait until + * outbufAcquireFenceFd signals. A fence that will signal when + * writes to outbuf are complete should be returned in + * retireFenceFd. + * + * This field is set before prepare(), so properties of the buffer + * can be used to decide which layers can be handled by h/w + * composer. + * + * If prepare() sets all layers to FRAMEBUFFER, then GLES + * composition will happen directly to the output buffer. In this + * case, both outbuf and the FRAMEBUFFER_TARGET layer's buffer will + * be the same, and set() has no work to do besides managing fences. + * + * If the TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS board config + * variable is defined (not the default), then this behavior is + * changed: if all layers are marked for FRAMEBUFFER, GLES + * composition will take place to a scratch framebuffer, and + * h/w composer must copy it to the output buffer. This allows the + * h/w composer to do format conversion if there are cases where + * that is more desirable than doing it in the GLES driver or at the + * virtual display consumer. + * + * If some or all layers are marked OVERLAY, then the framebuffer + * and output buffer will be different. As with physical displays, + * the framebuffer handle will not change between frames if all + * layers are marked for OVERLAY. + */ + buffer_handle_t outbuf; + + /* File descriptor for a fence that will signal when outbuf is + * ready to be written. The h/w composer is responsible for closing + * this when no longer needed. + * + * Will be -1 whenever outbuf is NULL, or when the outbuf can be + * written immediately. + */ + int outbufAcquireFenceFd; + }; + }; + + /* List of layers that will be composed on the display. The buffer handles + * in the list will be unique. If numHwLayers is 0, all composition will be + * performed by SurfaceFlinger. + */ + uint32_t flags; + size_t numHwLayers; + hwc_layer_1_t hwLayers[0]; + +} hwc_display_contents_1_t; + +/* see hwc_composer_device::registerProcs() + * All of the callbacks are required and non-NULL unless otherwise noted. + */ +typedef struct hwc_procs { + /* + * (*invalidate)() triggers a screen refresh, in particular prepare and set + * will be called shortly after this call is made. Note that there is + * NO GUARANTEE that the screen refresh will happen after invalidate() + * returns (in particular, it could happen before). + * invalidate() is GUARANTEED TO NOT CALL BACK into the h/w composer HAL and + * it is safe to call invalidate() from any of hwc_composer_device + * hooks, unless noted otherwise. + */ + void (*invalidate)(const struct hwc_procs* procs); + + /* + * (*vsync)() is called by the h/w composer HAL when a vsync event is + * received and HWC_EVENT_VSYNC is enabled on a display + * (see: hwc_event_control). + * + * the "disp" parameter indicates which display the vsync event is for. + * the "timestamp" parameter is the system monotonic clock timestamp in + * nanosecond of when the vsync event happened. + * + * vsync() is GUARANTEED TO NOT CALL BACK into the h/w composer HAL. + * + * It is expected that vsync() is called from a thread of at least + * HAL_PRIORITY_URGENT_DISPLAY with as little latency as possible, + * typically less than 0.5 ms. + * + * It is a (silent) error to have HWC_EVENT_VSYNC enabled when calling + * hwc_composer_device.set(..., 0, 0, 0) (screen off). The implementation + * can either stop or continue to process VSYNC events, but must not + * crash or cause other problems. + */ + void (*vsync)(const struct hwc_procs* procs, int disp, int64_t timestamp); + + /* + * (*hotplug)() is called by the h/w composer HAL when a display is + * connected or disconnected. The PRIMARY display is always connected and + * the hotplug callback should not be called for it. + * + * The disp parameter indicates which display type this event is for. + * The connected parameter indicates whether the display has just been + * connected (1) or disconnected (0). + * + * The hotplug() callback may call back into the h/w composer on the same + * thread to query refresh rate and dpi for the display. Additionally, + * other threads may be calling into the h/w composer while the callback + * is in progress. + * + * The h/w composer must serialize calls to the hotplug callback; only + * one thread may call it at a time. + * + * This callback will be NULL if the h/w composer is using + * HWC_DEVICE_API_VERSION_1_0. + */ + void (*hotplug)(const struct hwc_procs* procs, int disp, int connected); + +} hwc_procs_t; + + +/*****************************************************************************/ + +typedef struct hwc_module { + /** + * Common methods of the hardware composer module. This *must* be the first member of + * hwc_module as users of this structure will cast a hw_module_t to + * hwc_module pointer in contexts where it's known the hw_module_t references a + * hwc_module. + */ + struct hw_module_t common; +} hwc_module_t; + +typedef struct hwc_composer_device_1 { + /** + * Common methods of the hardware composer device. This *must* be the first member of + * hwc_composer_device_1 as users of this structure will cast a hw_device_t to + * hwc_composer_device_1 pointer in contexts where it's known the hw_device_t references a + * hwc_composer_device_1. + */ + struct hw_device_t common; + + /* + * (*prepare)() is called for each frame before composition and is used by + * SurfaceFlinger to determine what composition steps the HWC can handle. + * + * (*prepare)() can be called more than once, the last call prevails. + * + * The HWC responds by setting the compositionType field in each layer to + * either HWC_FRAMEBUFFER, HWC_OVERLAY, or HWC_CURSOR_OVERLAY. For the + * HWC_FRAMEBUFFER type, composition for the layer is handled by + * SurfaceFlinger with OpenGL ES. For the latter two overlay types, + * the HWC will have to handle the layer's composition. compositionType + * and hints are preserved between (*prepare)() calles unless the + * HWC_GEOMETRY_CHANGED flag is set. + * + * (*prepare)() is called with HWC_GEOMETRY_CHANGED to indicate that the + * list's geometry has changed, that is, when more than just the buffer's + * handles have been updated. Typically this happens (but is not limited to) + * when a window is added, removed, resized or moved. In this case + * compositionType and hints are reset to their default value. + * + * For HWC 1.0, numDisplays will always be one, and displays[0] will be + * non-NULL. + * + * For HWC 1.1, numDisplays will always be HWC_NUM_PHYSICAL_DISPLAY_TYPES. + * Entries for unsupported or disabled/disconnected display types will be + * NULL. + * + * In HWC 1.3, numDisplays may be up to HWC_NUM_DISPLAY_TYPES. The extra + * entries correspond to enabled virtual displays, and will be non-NULL. + * + * returns: 0 on success. An negative error code on error. If an error is + * returned, SurfaceFlinger will assume that none of the layer will be + * handled by the HWC. + */ + int (*prepare)(struct hwc_composer_device_1 *dev, + size_t numDisplays, hwc_display_contents_1_t** displays); + + /* + * (*set)() is used in place of eglSwapBuffers(), and assumes the same + * functionality, except it also commits the work list atomically with + * the actual eglSwapBuffers(). + * + * The layer lists are guaranteed to be the same as the ones returned from + * the last call to (*prepare)(). + * + * When this call returns the caller assumes that the displays will be + * updated in the near future with the content of their work lists, without + * artifacts during the transition from the previous frame. + * + * A display with zero layers indicates that the entire composition has + * been handled by SurfaceFlinger with OpenGL ES. In this case, (*set)() + * behaves just like eglSwapBuffers(). + * + * For HWC 1.0, numDisplays will always be one, and displays[0] will be + * non-NULL. + * + * For HWC 1.1, numDisplays will always be HWC_NUM_PHYSICAL_DISPLAY_TYPES. + * Entries for unsupported or disabled/disconnected display types will be + * NULL. + * + * In HWC 1.3, numDisplays may be up to HWC_NUM_DISPLAY_TYPES. The extra + * entries correspond to enabled virtual displays, and will be non-NULL. + * + * IMPORTANT NOTE: There is an implicit layer containing opaque black + * pixels behind all the layers in the list. It is the responsibility of + * the hwcomposer module to make sure black pixels are output (or blended + * from). + * + * IMPORTANT NOTE: In the event of an error this call *MUST* still cause + * any fences returned in the previous call to set to eventually become + * signaled. The caller may have already issued wait commands on these + * fences, and having set return without causing those fences to signal + * will likely result in a deadlock. + * + * returns: 0 on success. A negative error code on error: + * HWC_EGL_ERROR: eglGetError() will provide the proper error code (only + * allowed prior to HWComposer 1.1) + * Another code for non EGL errors. + */ + int (*set)(struct hwc_composer_device_1 *dev, + size_t numDisplays, hwc_display_contents_1_t** displays); + + /* + * eventControl(..., event, enabled) + * Enables or disables h/w composer events for a display. + * + * eventControl can be called from any thread and takes effect + * immediately. + * + * Supported events are: + * HWC_EVENT_VSYNC + * + * returns -EINVAL if the "event" parameter is not one of the value above + * or if the "enabled" parameter is not 0 or 1. + */ + int (*eventControl)(struct hwc_composer_device_1* dev, int disp, + int event, int enabled); + + union { + /* + * For HWC 1.3 and earlier, the blank() interface is used. + * + * blank(..., blank) + * Blanks or unblanks a display's screen. + * + * Turns the screen off when blank is nonzero, on when blank is zero. + * Multiple sequential calls with the same blank value must be + * supported. + * The screen state transition must be be complete when the function + * returns. + * + * returns 0 on success, negative on error. + */ + int (*blank)(struct hwc_composer_device_1* dev, int disp, int blank); + + /* + * For HWC 1.4 and above, setPowerMode() will be used in place of + * blank(). + * + * setPowerMode(..., mode) + * Sets the display screen's power state. + * + * Refer to the documentation of the HWC_POWER_MODE_* constants + * for information about each power mode. + * + * The functionality is similar to the blank() command in previous + * versions of HWC, but with support for more power states. + * + * The display driver is expected to retain and restore the low power + * state of the display while entering and exiting from suspend. + * + * Multiple sequential calls with the same mode value must be supported. + * + * The screen state transition must be be complete when the function + * returns. + * + * returns 0 on success, negative on error. + */ + int (*setPowerMode)(struct hwc_composer_device_1* dev, int disp, + int mode); + }; + + /* + * Used to retrieve information about the h/w composer + * + * Returns 0 on success or -errno on error. + */ + int (*query)(struct hwc_composer_device_1* dev, int what, int* value); + + /* + * (*registerProcs)() registers callbacks that the h/w composer HAL can + * later use. It will be called immediately after the composer device is + * opened with non-NULL procs. It is FORBIDDEN to call any of the callbacks + * from within registerProcs(). registerProcs() must save the hwc_procs_t + * pointer which is needed when calling a registered callback. + */ + void (*registerProcs)(struct hwc_composer_device_1* dev, + hwc_procs_t const* procs); + + /* + * This field is OPTIONAL and can be NULL. + * + * If non NULL it will be called by SurfaceFlinger on dumpsys + */ + void (*dump)(struct hwc_composer_device_1* dev, char *buff, int buff_len); + + /* + * (*getDisplayConfigs)() returns handles for the configurations available + * on the connected display. These handles must remain valid as long as the + * display is connected. + * + * Configuration handles are written to configs. The number of entries + * allocated by the caller is passed in *numConfigs; getDisplayConfigs must + * not try to write more than this number of config handles. On return, the + * total number of configurations available for the display is returned in + * *numConfigs. If *numConfigs is zero on entry, then configs may be NULL. + * + * Hardware composers implementing HWC_DEVICE_API_VERSION_1_3 or prior + * shall choose one configuration to activate and report it as the first + * entry in the returned list. Reporting the inactive configurations is not + * required. + * + * HWC_DEVICE_API_VERSION_1_4 and later provide configuration management + * through SurfaceFlinger, and hardware composers implementing these APIs + * must also provide getActiveConfig and setActiveConfig. Hardware composers + * implementing these API versions may choose not to activate any + * configuration, leaving configuration selection to higher levels of the + * framework. + * + * Returns 0 on success or a negative error code on error. If disp is a + * hotpluggable display type and no display is connected, an error shall be + * returned. + * + * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_1 and later. + * It shall be NULL for previous versions. + */ + int (*getDisplayConfigs)(struct hwc_composer_device_1* dev, int disp, + uint32_t* configs, size_t* numConfigs); + + /* + * (*getDisplayAttributes)() returns attributes for a specific config of a + * connected display. The config parameter is one of the config handles + * returned by getDisplayConfigs. + * + * The list of attributes to return is provided in the attributes + * parameter, terminated by HWC_DISPLAY_NO_ATTRIBUTE. The value for each + * requested attribute is written in order to the values array. The + * HWC_DISPLAY_NO_ATTRIBUTE attribute does not have a value, so the values + * array will have one less value than the attributes array. + * + * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_1 and later. + * It shall be NULL for previous versions. + * + * If disp is a hotpluggable display type and no display is connected, + * or if config is not a valid configuration for the display, a negative + * error code shall be returned. + */ + int (*getDisplayAttributes)(struct hwc_composer_device_1* dev, int disp, + uint32_t config, const uint32_t* attributes, int32_t* values); + + /* + * (*getActiveConfig)() returns the index of the configuration that is + * currently active on the connected display. The index is relative to + * the list of configuration handles returned by getDisplayConfigs. If there + * is no active configuration, -1 shall be returned. + * + * Returns the configuration index on success or -1 on error. + * + * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_4 and later. + * It shall be NULL for previous versions. + */ + int (*getActiveConfig)(struct hwc_composer_device_1* dev, int disp); + + /* + * (*setActiveConfig)() instructs the hardware composer to switch to the + * display configuration at the given index in the list of configuration + * handles returned by getDisplayConfigs. + * + * If this function returns without error, any subsequent calls to + * getActiveConfig shall return the index set by this function until one + * of the following occurs: + * 1) Another successful call of this function + * 2) The display is disconnected + * + * Returns 0 on success or a negative error code on error. If disp is a + * hotpluggable display type and no display is connected, or if index is + * outside of the range of hardware configurations returned by + * getDisplayConfigs, an error shall be returned. + * + * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_4 and later. + * It shall be NULL for previous versions. + */ + int (*setActiveConfig)(struct hwc_composer_device_1* dev, int disp, + int index); + /* + * Asynchronously update the location of the cursor layer. + * + * Within the standard prepare()/set() composition loop, the client + * (surfaceflinger) can request that a given layer uses dedicated cursor + * composition hardware by specifiying the HWC_IS_CURSOR_LAYER flag. Only + * one layer per display can have this flag set. If the layer is suitable + * for the platform's cursor hardware, hwcomposer will return from prepare() + * a composition type of HWC_CURSOR_OVERLAY for that layer. This indicates + * not only that the client is not responsible for compositing that layer, + * but also that the client can continue to update the position of that layer + * after a call to set(). This can reduce the visible latency of mouse + * movement to visible, on-screen cursor updates. Calls to + * setCursorPositionAsync() may be made from a different thread doing the + * prepare()/set() composition loop, but care must be taken to not interleave + * calls of setCursorPositionAsync() between calls of set()/prepare(). + * + * Notes: + * - Only one layer per display can be specified as a cursor layer with + * HWC_IS_CURSOR_LAYER. + * - hwcomposer will only return one layer per display as HWC_CURSOR_OVERLAY + * - This returns 0 on success or -errno on error. + * - This field is optional for HWC_DEVICE_API_VERSION_1_4 and later. It + * should be null for previous versions. + */ + int (*setCursorPositionAsync)(struct hwc_composer_device_1 *dev, int disp, int x_pos, int y_pos); + + /* + * Reserved for future use. Must be NULL. + */ + void* reserved_proc[1]; + +} hwc_composer_device_1_t; + +/** convenience API for opening and closing a device */ + +static inline int hwc_open_1(const struct hw_module_t* module, + hwc_composer_device_1_t** device) { + return module->methods->open(module, + HWC_HARDWARE_COMPOSER, (struct hw_device_t**)device); +} + +static inline int hwc_close_1(hwc_composer_device_1_t* device) { + return device->common.close(&device->common); +} + +/*****************************************************************************/ + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_H */
diff --git a/libhardware/include/hardware/hwcomposer_defs.h b/libhardware/include/hardware/hwcomposer_defs.h new file mode 100644 index 0000000..a19a26c --- /dev/null +++ b/libhardware/include/hardware/hwcomposer_defs.h
@@ -0,0 +1,252 @@ +/* + * 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. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_DEFS_H +#define ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_DEFS_H + +#include <stdint.h> +#include <sys/cdefs.h> + +#include <hardware/gralloc.h> +#include <hardware/hardware.h> +#include <cutils/native_handle.h> + +__BEGIN_DECLS + +/*****************************************************************************/ + +#define HWC_HEADER_VERSION 1 + +#define HWC_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +#define HWC_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION_2(1, 0, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_1 HARDWARE_DEVICE_API_VERSION_2(1, 1, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION_2(1, 2, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_3 HARDWARE_DEVICE_API_VERSION_2(1, 3, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_4 HARDWARE_DEVICE_API_VERSION_2(1, 4, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_5 HARDWARE_DEVICE_API_VERSION_2(1, 5, HWC_HEADER_VERSION) + +enum { + /* hwc_composer_device_t::set failed in EGL */ + HWC_EGL_ERROR = -1 +}; + +/* + * hwc_layer_t::hints values + * Hints are set by the HAL and read by SurfaceFlinger + */ +enum { + /* + * HWC can set the HWC_HINT_TRIPLE_BUFFER hint to indicate to SurfaceFlinger + * that it should triple buffer this layer. Typically HWC does this when + * the layer will be unavailable for use for an extended period of time, + * e.g. if the display will be fetching data directly from the layer and + * the layer can not be modified until after the next set(). + */ + HWC_HINT_TRIPLE_BUFFER = 0x00000001, + + /* + * HWC sets HWC_HINT_CLEAR_FB to tell SurfaceFlinger that it should clear the + * framebuffer with transparent pixels where this layer would be. + * SurfaceFlinger will only honor this flag when the layer has no blending + * + */ + HWC_HINT_CLEAR_FB = 0x00000002 +}; + +/* + * hwc_layer_t::flags values + * Flags are set by SurfaceFlinger and read by the HAL + */ +enum { + /* + * HWC_SKIP_LAYER is set by SurfaceFlnger to indicate that the HAL + * shall not consider this layer for composition as it will be handled + * by SurfaceFlinger (just as if compositionType was set to HWC_OVERLAY). + */ + HWC_SKIP_LAYER = 0x00000001, + + /* + * HWC_IS_CURSOR_LAYER is set by surfaceflinger to indicate that this + * layer is being used as a cursor on this particular display, and that + * surfaceflinger can potentially perform asynchronous position updates for + * this layer. If a call to prepare() returns HWC_CURSOR_OVERLAY for the + * composition type of this layer, then the hwcomposer will allow async + * position updates to this layer via setCursorPositionAsync(). + */ + HWC_IS_CURSOR_LAYER = 0x00000002 +}; + +/* + * hwc_layer_t::compositionType values + */ +enum { + /* this layer is to be drawn into the framebuffer by SurfaceFlinger */ + HWC_FRAMEBUFFER = 0, + + /* this layer will be handled in the HWC */ + HWC_OVERLAY = 1, + + /* this is the background layer. it's used to set the background color. + * there is only a single background layer */ + HWC_BACKGROUND = 2, + + /* this layer holds the result of compositing the HWC_FRAMEBUFFER layers. + * Added in HWC_DEVICE_API_VERSION_1_1. */ + HWC_FRAMEBUFFER_TARGET = 3, + + /* this layer's contents are taken from a sideband buffer stream. + * Added in HWC_DEVICE_API_VERSION_1_4. */ + HWC_SIDEBAND = 4, + + /* this layer's composition will be handled by hwcomposer by dedicated + cursor overlay hardware. hwcomposer will also all async position updates + of this layer outside of the normal prepare()/set() loop. Added in + HWC_DEVICE_API_VERSION_1_4. */ + HWC_CURSOR_OVERLAY = 5 + }; +/* + * hwc_layer_t::blending values + */ +enum { + /* no blending */ + HWC_BLENDING_NONE = 0x0100, + + /* ONE / ONE_MINUS_SRC_ALPHA */ + HWC_BLENDING_PREMULT = 0x0105, + + /* SRC_ALPHA / ONE_MINUS_SRC_ALPHA */ + HWC_BLENDING_COVERAGE = 0x0405 +}; + +/* + * hwc_layer_t::transform values + */ +enum { + /* flip source image horizontally */ + HWC_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H, + /* flip source image vertically */ + HWC_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V, + /* rotate source image 90 degrees clock-wise */ + HWC_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90, + /* rotate source image 180 degrees */ + HWC_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180, + /* rotate source image 270 degrees clock-wise */ + HWC_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270, +}; + +/* attributes queriable with query() */ +enum { + /* + * Must return 1 if the background layer is supported, 0 otherwise. + */ + HWC_BACKGROUND_LAYER_SUPPORTED = 0, + + /* + * Returns the vsync period in nanoseconds. + * + * This query is not used for HWC_DEVICE_API_VERSION_1_1 and later. + * Instead, the per-display attribute HWC_DISPLAY_VSYNC_PERIOD is used. + */ + HWC_VSYNC_PERIOD = 1, + + /* + * Availability: HWC_DEVICE_API_VERSION_1_1 + * Returns a mask of supported display types. + */ + HWC_DISPLAY_TYPES_SUPPORTED = 2, +}; + +/* display attributes returned by getDisplayAttributes() */ +enum { + /* Indicates the end of an attribute list */ + HWC_DISPLAY_NO_ATTRIBUTE = 0, + + /* The vsync period in nanoseconds */ + HWC_DISPLAY_VSYNC_PERIOD = 1, + + /* The number of pixels in the horizontal and vertical directions. */ + HWC_DISPLAY_WIDTH = 2, + HWC_DISPLAY_HEIGHT = 3, + + /* The number of pixels per thousand inches of this configuration. + * + * Scaling DPI by 1000 allows it to be stored in an int without losing + * too much precision. + * + * If the DPI for a configuration is unavailable or the HWC implementation + * considers it unreliable, it should set these attributes to zero. + */ + HWC_DISPLAY_DPI_X = 4, + HWC_DISPLAY_DPI_Y = 5, + + /* Indicates which of the vendor-defined color transforms is provided by + * this configuration. */ + HWC_DISPLAY_COLOR_TRANSFORM = 6, +}; + +/* Allowed events for hwc_methods::eventControl() */ +enum { + HWC_EVENT_VSYNC = 0 +}; + +/* Display types and associated mask bits. */ +enum { + HWC_DISPLAY_PRIMARY = 0, + HWC_DISPLAY_EXTERNAL = 1, // HDMI, DP, etc. + HWC_DISPLAY_VIRTUAL = 2, + + HWC_NUM_PHYSICAL_DISPLAY_TYPES = 2, + HWC_NUM_DISPLAY_TYPES = 3, +}; + +enum { + HWC_DISPLAY_PRIMARY_BIT = 1 << HWC_DISPLAY_PRIMARY, + HWC_DISPLAY_EXTERNAL_BIT = 1 << HWC_DISPLAY_EXTERNAL, + HWC_DISPLAY_VIRTUAL_BIT = 1 << HWC_DISPLAY_VIRTUAL, +}; + +/* Display power modes */ +enum { + /* The display is turned off (blanked). */ + HWC_POWER_MODE_OFF = 0, + /* The display is turned on and configured in a low power state + * that is suitable for presenting ambient information to the user, + * possibly with lower fidelity than normal but greater efficiency. */ + HWC_POWER_MODE_DOZE = 1, + /* The display is turned on normally. */ + HWC_POWER_MODE_NORMAL = 2, + /* The display is configured as in HWC_POWER_MODE_DOZE but may + * stop applying frame buffer updates from the graphics subsystem. + * This power mode is effectively a hint from the doze dream to + * tell the hardware that it is done drawing to the display for the + * time being and that the display should remain on in a low power + * state and continue showing its current contents indefinitely + * until the mode changes. + * + * This mode may also be used as a signal to enable hardware-based doze + * functionality. In this case, the doze dream is effectively + * indicating that the hardware is free to take over the display + * and manage it autonomously to implement low power always-on display + * functionality. */ + HWC_POWER_MODE_DOZE_SUSPEND = 3, +}; + +/*****************************************************************************/ + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_DEFS_H */
diff --git a/libhardware/include/hardware/input.h b/libhardware/include/hardware/input.h new file mode 100644 index 0000000..969b8ce --- /dev/null +++ b/libhardware/include/hardware/input.h
@@ -0,0 +1,549 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_INPUT_H +#define ANDROID_INCLUDE_HARDWARE_INPUT_H + +#include <hardware/hardware.h> +#include <stdint.h> + +__BEGIN_DECLS + +#define INPUT_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define INPUT_HARDWARE_MODULE_ID "input" + +#define INPUT_INSTANCE_EVDEV "evdev" + +typedef enum input_bus { + INPUT_BUS_BT, + INPUT_BUS_USB, + INPUT_BUS_SERIAL, + INPUT_BUS_BUILTIN +} input_bus_t; + +typedef struct input_host input_host_t; + +typedef struct input_device_handle input_device_handle_t; + +typedef struct input_device_identifier input_device_identifier_t; + +typedef struct input_device_definition input_device_definition_t; + +typedef struct input_report_definition input_report_definition_t; + +typedef struct input_report input_report_t; + +typedef struct input_collection input_collection_t; + +typedef struct input_property_map input_property_map_t; + +typedef struct input_property input_property_t; + +typedef enum { + // keycodes + INPUT_USAGE_KEYCODE_UNKNOWN, + INPUT_USAGE_KEYCODE_SOFT_LEFT, + INPUT_USAGE_KEYCODE_SOFT_RIGHT, + INPUT_USAGE_KEYCODE_HOME, + INPUT_USAGE_KEYCODE_BACK, + INPUT_USAGE_KEYCODE_CALL, + INPUT_USAGE_KEYCODE_ENDCALL, + INPUT_USAGE_KEYCODE_0, + INPUT_USAGE_KEYCODE_1, + INPUT_USAGE_KEYCODE_2, + INPUT_USAGE_KEYCODE_3, + INPUT_USAGE_KEYCODE_4, + INPUT_USAGE_KEYCODE_5, + INPUT_USAGE_KEYCODE_6, + INPUT_USAGE_KEYCODE_7, + INPUT_USAGE_KEYCODE_8, + INPUT_USAGE_KEYCODE_9, + INPUT_USAGE_KEYCODE_STAR, + INPUT_USAGE_KEYCODE_POUND, + INPUT_USAGE_KEYCODE_DPAD_UP, + INPUT_USAGE_KEYCODE_DPAD_DOWN, + INPUT_USAGE_KEYCODE_DPAD_LEFT, + INPUT_USAGE_KEYCODE_DPAD_RIGHT, + INPUT_USAGE_KEYCODE_DPAD_CENTER, + INPUT_USAGE_KEYCODE_VOLUME_UP, + INPUT_USAGE_KEYCODE_VOLUME_DOWN, + INPUT_USAGE_KEYCODE_POWER, + INPUT_USAGE_KEYCODE_CAMERA, + INPUT_USAGE_KEYCODE_CLEAR, + INPUT_USAGE_KEYCODE_A, + INPUT_USAGE_KEYCODE_B, + INPUT_USAGE_KEYCODE_C, + INPUT_USAGE_KEYCODE_D, + INPUT_USAGE_KEYCODE_E, + INPUT_USAGE_KEYCODE_F, + INPUT_USAGE_KEYCODE_G, + INPUT_USAGE_KEYCODE_H, + INPUT_USAGE_KEYCODE_I, + INPUT_USAGE_KEYCODE_J, + INPUT_USAGE_KEYCODE_K, + INPUT_USAGE_KEYCODE_L, + INPUT_USAGE_KEYCODE_M, + INPUT_USAGE_KEYCODE_N, + INPUT_USAGE_KEYCODE_O, + INPUT_USAGE_KEYCODE_P, + INPUT_USAGE_KEYCODE_Q, + INPUT_USAGE_KEYCODE_R, + INPUT_USAGE_KEYCODE_S, + INPUT_USAGE_KEYCODE_T, + INPUT_USAGE_KEYCODE_U, + INPUT_USAGE_KEYCODE_V, + INPUT_USAGE_KEYCODE_W, + INPUT_USAGE_KEYCODE_X, + INPUT_USAGE_KEYCODE_Y, + INPUT_USAGE_KEYCODE_Z, + INPUT_USAGE_KEYCODE_COMMA, + INPUT_USAGE_KEYCODE_PERIOD, + INPUT_USAGE_KEYCODE_ALT_LEFT, + INPUT_USAGE_KEYCODE_ALT_RIGHT, + INPUT_USAGE_KEYCODE_SHIFT_LEFT, + INPUT_USAGE_KEYCODE_SHIFT_RIGHT, + INPUT_USAGE_KEYCODE_TAB, + INPUT_USAGE_KEYCODE_SPACE, + INPUT_USAGE_KEYCODE_SYM, + INPUT_USAGE_KEYCODE_EXPLORER, + INPUT_USAGE_KEYCODE_ENVELOPE, + INPUT_USAGE_KEYCODE_ENTER, + INPUT_USAGE_KEYCODE_DEL, + INPUT_USAGE_KEYCODE_GRAVE, + INPUT_USAGE_KEYCODE_MINUS, + INPUT_USAGE_KEYCODE_EQUALS, + INPUT_USAGE_KEYCODE_LEFT_BRACKET, + INPUT_USAGE_KEYCODE_RIGHT_BRACKET, + INPUT_USAGE_KEYCODE_BACKSLASH, + INPUT_USAGE_KEYCODE_SEMICOLON, + INPUT_USAGE_KEYCODE_APOSTROPHE, + INPUT_USAGE_KEYCODE_SLASH, + INPUT_USAGE_KEYCODE_AT, + INPUT_USAGE_KEYCODE_NUM, + INPUT_USAGE_KEYCODE_HEADSETHOOK, + INPUT_USAGE_KEYCODE_FOCUS, // *Camera* focus + INPUT_USAGE_KEYCODE_PLUS, + INPUT_USAGE_KEYCODE_MENU, + INPUT_USAGE_KEYCODE_NOTIFICATION, + INPUT_USAGE_KEYCODE_SEARCH, + INPUT_USAGE_KEYCODE_MEDIA_PLAY_PAUSE, + INPUT_USAGE_KEYCODE_MEDIA_STOP, + INPUT_USAGE_KEYCODE_MEDIA_NEXT, + INPUT_USAGE_KEYCODE_MEDIA_PREVIOUS, + INPUT_USAGE_KEYCODE_MEDIA_REWIND, + INPUT_USAGE_KEYCODE_MEDIA_FAST_FORWARD, + INPUT_USAGE_KEYCODE_MUTE, + INPUT_USAGE_KEYCODE_PAGE_UP, + INPUT_USAGE_KEYCODE_PAGE_DOWN, + INPUT_USAGE_KEYCODE_PICTSYMBOLS, + INPUT_USAGE_KEYCODE_SWITCH_CHARSET, + INPUT_USAGE_KEYCODE_BUTTON_A, + INPUT_USAGE_KEYCODE_BUTTON_B, + INPUT_USAGE_KEYCODE_BUTTON_C, + INPUT_USAGE_KEYCODE_BUTTON_X, + INPUT_USAGE_KEYCODE_BUTTON_Y, + INPUT_USAGE_KEYCODE_BUTTON_Z, + INPUT_USAGE_KEYCODE_BUTTON_L1, + INPUT_USAGE_KEYCODE_BUTTON_R1, + INPUT_USAGE_KEYCODE_BUTTON_L2, + INPUT_USAGE_KEYCODE_BUTTON_R2, + INPUT_USAGE_KEYCODE_BUTTON_THUMBL, + INPUT_USAGE_KEYCODE_BUTTON_THUMBR, + INPUT_USAGE_KEYCODE_BUTTON_START, + INPUT_USAGE_KEYCODE_BUTTON_SELECT, + INPUT_USAGE_KEYCODE_BUTTON_MODE, + INPUT_USAGE_KEYCODE_ESCAPE, + INPUT_USAGE_KEYCODE_FORWARD_DEL, + INPUT_USAGE_KEYCODE_CTRL_LEFT, + INPUT_USAGE_KEYCODE_CTRL_RIGHT, + INPUT_USAGE_KEYCODE_CAPS_LOCK, + INPUT_USAGE_KEYCODE_SCROLL_LOCK, + INPUT_USAGE_KEYCODE_META_LEFT, + INPUT_USAGE_KEYCODE_META_RIGHT, + INPUT_USAGE_KEYCODE_FUNCTION, + INPUT_USAGE_KEYCODE_SYSRQ, + INPUT_USAGE_KEYCODE_BREAK, + INPUT_USAGE_KEYCODE_MOVE_HOME, + INPUT_USAGE_KEYCODE_MOVE_END, + INPUT_USAGE_KEYCODE_INSERT, + INPUT_USAGE_KEYCODE_FORWARD, + INPUT_USAGE_KEYCODE_MEDIA_PLAY, + INPUT_USAGE_KEYCODE_MEDIA_PAUSE, + INPUT_USAGE_KEYCODE_MEDIA_CLOSE, + INPUT_USAGE_KEYCODE_MEDIA_EJECT, + INPUT_USAGE_KEYCODE_MEDIA_RECORD, + INPUT_USAGE_KEYCODE_F1, + INPUT_USAGE_KEYCODE_F2, + INPUT_USAGE_KEYCODE_F3, + INPUT_USAGE_KEYCODE_F4, + INPUT_USAGE_KEYCODE_F5, + INPUT_USAGE_KEYCODE_F6, + INPUT_USAGE_KEYCODE_F7, + INPUT_USAGE_KEYCODE_F8, + INPUT_USAGE_KEYCODE_F9, + INPUT_USAGE_KEYCODE_F10, + INPUT_USAGE_KEYCODE_F11, + INPUT_USAGE_KEYCODE_F12, + INPUT_USAGE_KEYCODE_NUM_LOCK, + INPUT_USAGE_KEYCODE_NUMPAD_0, + INPUT_USAGE_KEYCODE_NUMPAD_1, + INPUT_USAGE_KEYCODE_NUMPAD_2, + INPUT_USAGE_KEYCODE_NUMPAD_3, + INPUT_USAGE_KEYCODE_NUMPAD_4, + INPUT_USAGE_KEYCODE_NUMPAD_5, + INPUT_USAGE_KEYCODE_NUMPAD_6, + INPUT_USAGE_KEYCODE_NUMPAD_7, + INPUT_USAGE_KEYCODE_NUMPAD_8, + INPUT_USAGE_KEYCODE_NUMPAD_9, + INPUT_USAGE_KEYCODE_NUMPAD_DIVIDE, + INPUT_USAGE_KEYCODE_NUMPAD_MULTIPLY, + INPUT_USAGE_KEYCODE_NUMPAD_SUBTRACT, + INPUT_USAGE_KEYCODE_NUMPAD_ADD, + INPUT_USAGE_KEYCODE_NUMPAD_DOT, + INPUT_USAGE_KEYCODE_NUMPAD_COMMA, + INPUT_USAGE_KEYCODE_NUMPAD_ENTER, + INPUT_USAGE_KEYCODE_NUMPAD_EQUALS, + INPUT_USAGE_KEYCODE_NUMPAD_LEFT_PAREN, + INPUT_USAGE_KEYCODE_NUMPAD_RIGHT_PAREN, + INPUT_USAGE_KEYCODE_VOLUME_MUTE, + INPUT_USAGE_KEYCODE_INFO, + INPUT_USAGE_KEYCODE_CHANNEL_UP, + INPUT_USAGE_KEYCODE_CHANNEL_DOWN, + INPUT_USAGE_KEYCODE_ZOOM_IN, + INPUT_USAGE_KEYCODE_ZOOM_OUT, + INPUT_USAGE_KEYCODE_TV, + INPUT_USAGE_KEYCODE_WINDOW, + INPUT_USAGE_KEYCODE_GUIDE, + INPUT_USAGE_KEYCODE_DVR, + INPUT_USAGE_KEYCODE_BOOKMARK, + INPUT_USAGE_KEYCODE_CAPTIONS, + INPUT_USAGE_KEYCODE_SETTINGS, + INPUT_USAGE_KEYCODE_TV_POWER, + INPUT_USAGE_KEYCODE_TV_INPUT, + INPUT_USAGE_KEYCODE_STB_POWER, + INPUT_USAGE_KEYCODE_STB_INPUT, + INPUT_USAGE_KEYCODE_AVR_POWER, + INPUT_USAGE_KEYCODE_AVR_INPUT, + INPUT_USAGE_KEYCODE_PROG_RED, + INPUT_USAGE_KEYCODE_PROG_GREEN, + INPUT_USAGE_KEYCODE_PROG_YELLOW, + INPUT_USAGE_KEYCODE_PROG_BLUE, + INPUT_USAGE_KEYCODE_APP_SWITCH, + INPUT_USAGE_KEYCODE_BUTTON_1, + INPUT_USAGE_KEYCODE_BUTTON_2, + INPUT_USAGE_KEYCODE_BUTTON_3, + INPUT_USAGE_KEYCODE_BUTTON_4, + INPUT_USAGE_KEYCODE_BUTTON_5, + INPUT_USAGE_KEYCODE_BUTTON_6, + INPUT_USAGE_KEYCODE_BUTTON_7, + INPUT_USAGE_KEYCODE_BUTTON_8, + INPUT_USAGE_KEYCODE_BUTTON_9, + INPUT_USAGE_KEYCODE_BUTTON_10, + INPUT_USAGE_KEYCODE_BUTTON_11, + INPUT_USAGE_KEYCODE_BUTTON_12, + INPUT_USAGE_KEYCODE_BUTTON_13, + INPUT_USAGE_KEYCODE_BUTTON_14, + INPUT_USAGE_KEYCODE_BUTTON_15, + INPUT_USAGE_KEYCODE_BUTTON_16, + INPUT_USAGE_KEYCODE_LANGUAGE_SWITCH, + INPUT_USAGE_KEYCODE_MANNER_MODE, + INPUT_USAGE_KEYCODE_3D_MODE, + INPUT_USAGE_KEYCODE_CONTACTS, + INPUT_USAGE_KEYCODE_CALENDAR, + INPUT_USAGE_KEYCODE_MUSIC, + INPUT_USAGE_KEYCODE_CALCULATOR, + INPUT_USAGE_KEYCODE_ZENKAKU_HANKAKU, + INPUT_USAGE_KEYCODE_EISU, + INPUT_USAGE_KEYCODE_MUHENKAN, + INPUT_USAGE_KEYCODE_HENKAN, + INPUT_USAGE_KEYCODE_KATAKANA_HIRAGANA, + INPUT_USAGE_KEYCODE_YEN, + INPUT_USAGE_KEYCODE_RO, + INPUT_USAGE_KEYCODE_KANA, + INPUT_USAGE_KEYCODE_ASSIST, + INPUT_USAGE_KEYCODE_BRIGHTNESS_DOWN, + INPUT_USAGE_KEYCODE_BRIGHTNESS_UP, + INPUT_USAGE_KEYCODE_MEDIA_AUDIO_TRACK, + INPUT_USAGE_KEYCODE_SLEEP, + INPUT_USAGE_KEYCODE_WAKEUP, + INPUT_USAGE_KEYCODE_PAIRING, + INPUT_USAGE_KEYCODE_MEDIA_TOP_MENU, + INPUT_USAGE_KEYCODE_11, + INPUT_USAGE_KEYCODE_12, + INPUT_USAGE_KEYCODE_LAST_CHANNEL, + INPUT_USAGE_KEYCODE_TV_DATA_SERVICE, + INPUT_USAGE_KEYCODE_VOICE_ASSIST, + INPUT_USAGE_KEYCODE_TV_RADIO_SERVICE, + INPUT_USAGE_KEYCODE_TV_TELETEXT, + INPUT_USAGE_KEYCODE_TV_NUMBER_ENTRY, + INPUT_USAGE_KEYCODE_TV_TERRESTRIAL_ANALOG, + INPUT_USAGE_KEYCODE_TV_TERRESTRIAL_DIGITAL, + INPUT_USAGE_KEYCODE_TV_SATELLITE, + INPUT_USAGE_KEYCODE_TV_SATELLITE_BS, + INPUT_USAGE_KEYCODE_TV_SATELLITE_CS, + INPUT_USAGE_KEYCODE_TV_SATELLITE_SERVICE, + INPUT_USAGE_KEYCODE_TV_NETWORK, + INPUT_USAGE_KEYCODE_TV_ANTENNA_CABLE, + INPUT_USAGE_KEYCODE_TV_INPUT_HDMI_1, + INPUT_USAGE_KEYCODE_TV_INPUT_HDMI_2, + INPUT_USAGE_KEYCODE_TV_INPUT_HDMI_3, + INPUT_USAGE_KEYCODE_TV_INPUT_HDMI_4, + INPUT_USAGE_KEYCODE_TV_INPUT_COMPOSITE_1, + INPUT_USAGE_KEYCODE_TV_INPUT_COMPOSITE_2, + INPUT_USAGE_KEYCODE_TV_INPUT_COMPONENT_1, + INPUT_USAGE_KEYCODE_TV_INPUT_COMPONENT_2, + INPUT_USAGE_KEYCODE_TV_INPUT_VGA_1, + INPUT_USAGE_KEYCODE_TV_AUDIO_DESCRIPTION, + INPUT_USAGE_KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP, + INPUT_USAGE_KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN, + INPUT_USAGE_KEYCODE_TV_ZOOM_MODE, + INPUT_USAGE_KEYCODE_TV_CONTENTS_MENU, + INPUT_USAGE_KEYCODE_TV_MEDIA_CONTEXT_MENU, + INPUT_USAGE_KEYCODE_TV_TIMER_PROGRAMMING, + INPUT_USAGE_KEYCODE_HELP, + + // axes + INPUT_USAGE_AXIS_X, + INPUT_USAGE_AXIS_Y, + INPUT_USAGE_AXIS_PRESSURE, + INPUT_USAGE_AXIS_SIZE, + INPUT_USAGE_AXIS_TOUCH_MAJOR, + INPUT_USAGE_AXIS_TOUCH_MINOR, + INPUT_USAGE_AXIS_TOOL_MAJOR, + INPUT_USAGE_AXIS_TOOL_MINOR, + INPUT_USAGE_AXIS_ORIENTATION, + INPUT_USAGE_AXIS_VSCROLL, + INPUT_USAGE_AXIS_HSCROLL, + INPUT_USAGE_AXIS_Z, + INPUT_USAGE_AXIS_RX, + INPUT_USAGE_AXIS_RY, + INPUT_USAGE_AXIS_RZ, + INPUT_USAGE_AXIS_HAT_X, + INPUT_USAGE_AXIS_HAT_Y, + INPUT_USAGE_AXIS_LTRIGGER, + INPUT_USAGE_AXIS_RTRIGGER, + INPUT_USAGE_AXIS_THROTTLE, + INPUT_USAGE_AXIS_RUDDER, + INPUT_USAGE_AXIS_WHEEL, + INPUT_USAGE_AXIS_GAS, + INPUT_USAGE_AXIS_BRAKE, + INPUT_USAGE_AXIS_DISTANCE, + INPUT_USAGE_AXIS_TILT, + INPUT_USAGE_AXIS_GENERIC_1, + INPUT_USAGE_AXIS_GENERIC_2, + INPUT_USAGE_AXIS_GENERIC_3, + INPUT_USAGE_AXIS_GENERIC_4, + INPUT_USAGE_AXIS_GENERIC_5, + INPUT_USAGE_AXIS_GENERIC_6, + INPUT_USAGE_AXIS_GENERIC_7, + INPUT_USAGE_AXIS_GENERIC_8, + INPUT_USAGE_AXIS_GENERIC_9, + INPUT_USAGE_AXIS_GENERIC_10, + INPUT_USAGE_AXIS_GENERIC_11, + INPUT_USAGE_AXIS_GENERIC_12, + INPUT_USAGE_AXIS_GENERIC_13, + INPUT_USAGE_AXIS_GENERIC_14, + INPUT_USAGE_AXIS_GENERIC_15, + INPUT_USAGE_AXIS_GENERIC_16, + + // leds + INPUT_USAGE_LED_NUM_LOCK, + INPUT_USAGE_LED_CAPS_LOCK, + INPUT_USAGE_LED_SCROLL_LOCK, + INPUT_USAGE_LED_COMPOSE, + INPUT_USAGE_LED_KANA, + INPUT_USAGE_LED_SLEEP, + INPUT_USAGE_LED_SUSPEND, + INPUT_USAGE_LED_MUTE, + INPUT_USAGE_LED_MISC, + INPUT_USAGE_LED_MAIL, + INPUT_USAGE_LED_CHARGING, + INPUT_USAGE_LED_CONTROLLER_1, + INPUT_USAGE_LED_CONTROLLER_2, + INPUT_USAGE_LED_CONTROLLER_3, + INPUT_USAGE_LED_CONTROLLER_4, +} input_usage_t; + +typedef enum { + INPUT_COLLECTION_ID_TOUCH, + INPUT_COLLECTION_ID_KEYBOARD, + INPUT_COLLECTION_ID_MOUSE, + INPUT_COLLECTION_ID_TOUCHPAD, + // etc +} input_collection_id_t; + +typedef struct input_message input_message_t; + +typedef struct input_host_callbacks { + + /** + * Creates a device identifier with the given properties. + * The unique ID should be a string that precisely identifies a given piece of hardware. For + * example, an input device connected via Bluetooth could use its MAC address as its unique ID. + */ + input_device_identifier_t* (*create_device_identifier)(input_host_t* host, + const char* name, int32_t product_id, int32_t vendor_id, + input_bus_t bus, const char* unique_id); + + /** + * Allocates the device definition which will describe the input capabilities of a device. A + * device definition may be used to register as many devices as desired. + */ + input_device_definition_t* (*create_device_definition)(input_host_t* host); + + /** + * Allocate either an input report, which the HAL will use to tell the host of incoming input + * events, or an output report, which the host will use to tell the HAL of desired state + * changes (e.g. setting an LED). + */ + input_report_definition_t* (*create_input_report_definition)(input_host_t* host); + input_report_definition_t* (*create_output_report_definition)(input_host_t* host); + + /** + * Append the report to the given input device. + */ + void (*input_device_definition_add_report)(input_host_t* host, + input_device_definition_t* d, input_report_definition_t* r); + + /** + * Add a collection with the given arity and ID. A collection describes a set + * of logically grouped properties such as the X and Y coordinates of a single finger touch or + * the set of keys on a keyboard. The arity declares how many repeated instances of this + * collection will appear in whatever report it is attached to. The ID describes the type of + * grouping being represented by the collection. For example, a touchscreen capable of + * reporting up to 2 fingers simultaneously might have a collection with the X and Y + * coordinates, an arity of 2, and an ID of INPUT_COLLECTION_USAGE_TOUCHSCREEN. Any given ID + * may only be present once for a given report. + */ + void (*input_report_definition_add_collection)(input_host_t* host, + input_report_definition_t* report, input_collection_id_t id, int32_t arity); + + /** + * Declare an int usage with the given properties. The report and collection defines where the + * usage is being declared. + */ + void (*input_report_definition_declare_usage_int)(input_host_t* host, + input_report_definition_t* report, input_collection_id_t id, + input_usage_t usage, int32_t min, int32_t max, float resolution); + + /** + * Declare a set of boolean usages with the given properties. The report and collection + * defines where the usages are being declared. + */ + void (*input_report_definition_declare_usages_bool)(input_host_t* host, + input_report_definition_t* report, input_collection_id_t id, + input_usage_t* usage, size_t usage_count); + + + /** + * Register a given input device definition. This notifies the host that an input device has + * been connected and gives a description of all its capabilities. + */ + input_device_handle_t* (*register_device)(input_host_t* host, + input_device_identifier_t* id, input_device_definition_t* d); + + /** Unregister the given device */ + void (*unregister_device)(input_host_t* host, input_device_handle_t* handle); + + /** + * Allocate a report that will contain all of the state as described by the given report. + */ + input_report_t* (*input_allocate_report)(input_host_t* host, input_report_definition_t* r); + + /** + * Add an int usage value to a report. + */ + void (*input_report_set_usage_int)(input_host_t* host, input_report_t* r, + input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index); + + /** + * Add a boolean usage value to a report. + */ + void (*input_report_set_usage_bool)(input_host_t* host, input_report_t* r, + input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index); + + void (*report_event)(input_host_t* host, input_device_handle_t* d, input_report_t* report); + + /** + * Retrieve the set of properties for the device. The returned + * input_property_map_t* may be used to query specific properties via the + * input_get_device_property callback. + */ + input_property_map_t* (*input_get_device_property_map)(input_host_t* host, + input_device_identifier_t* id); + /** + * Retrieve a property for the device with the given key. Returns NULL if + * the key does not exist, or an input_property_t* that must be freed using + * input_free_device_property(). Using an input_property_t after the + * corresponding input_property_map_t is freed is undefined. + */ + input_property_t* (*input_get_device_property)(input_host_t* host, + input_property_map_t* map, const char* key); + + /** + * Get the key for the input property. Returns NULL if the property is NULL. + * The returned const char* is owned by the input_property_t. + */ + const char* (*input_get_property_key)(input_host_t* host, input_property_t* property); + + /** + * Get the value for the input property. Returns NULL if the property is + * NULL. The returned const char* is owned by the input_property_t. + */ + const char* (*input_get_property_value)(input_host_t* host, input_property_t* property); + + /** + * Frees the input_property_t*. + */ + void (*input_free_device_property)(input_host_t* host, input_property_t* property); + + /** + * Frees the input_property_map_t*. + */ + void (*input_free_device_property_map)(input_host_t* host, input_property_map_t* map); +} input_host_callbacks_t; + +typedef struct input_module input_module_t; + +struct input_module { + /** + * Common methods of the input module. This *must* be the first member + * of input_module as users of this structure will cast a hw_module_t + * to input_module pointer in contexts where it's known + * the hw_module_t references a input_module. + */ + struct hw_module_t common; + + /** + * Initialize the module with host callbacks. At this point the HAL should start up whatever + * infrastructure it needs to in order to process input events. + */ + void (*init)(const input_module_t* module, input_host_t* host, input_host_callbacks_t cb); + + /** + * Sends an output report with a new set of state the host would like the given device to + * assume. + */ + void (*notify_report)(const input_module_t* module, input_report_t* report); +}; + +static inline int input_open(const struct hw_module_t** module, const char* type) { + return hw_get_module_by_class(INPUT_HARDWARE_MODULE_ID, type, module); +} + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_INPUT_H */
diff --git a/libhardware/include/hardware/keymaster0.h b/libhardware/include/hardware/keymaster0.h new file mode 100644 index 0000000..f020e5b --- /dev/null +++ b/libhardware/include/hardware/keymaster0.h
@@ -0,0 +1,149 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_KEYMASTER_0_H +#define ANDROID_HARDWARE_KEYMASTER_0_H + +#include <hardware/keymaster_common.h> + +__BEGIN_DECLS + +/** + * Keymaster0 device definition. + */ +struct keymaster0_device { + /** + * Common methods of the keymaster device. This *must* be the first member of + * keymaster0_device as users of this structure will cast a hw_device_t to + * keymaster0_device pointer in contexts where it's known the hw_device_t references a + * keymaster0_device. + */ + struct hw_device_t common; + + /** + * THIS IS DEPRECATED. Use the new "module_api_version" and "hal_api_version" + * fields in the keymaster_module initialization instead. + */ + uint32_t client_version; + + /** + * See flags defined for keymaster0_device::flags in keymaster_common.h + */ + uint32_t flags; + + void* context; + + /** + * Generates a public and private key. The key-blob returned is opaque + * and must subsequently provided for signing and verification. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*generate_keypair)(const struct keymaster0_device* dev, + const keymaster_keypair_t key_type, const void* key_params, + uint8_t** key_blob, size_t* key_blob_length); + + /** + * Imports a public and private key pair. The imported keys will be in + * PKCS#8 format with DER encoding (Java standard). The key-blob + * returned is opaque and will be subsequently provided for signing + * and verification. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*import_keypair)(const struct keymaster0_device* dev, + const uint8_t* key, const size_t key_length, + uint8_t** key_blob, size_t* key_blob_length); + + /** + * Gets the public key part of a key pair. The public key must be in + * X.509 format (Java standard) encoded byte array. + * + * Returns: 0 on success or an error code less than 0. + * On error, x509_data should not be allocated. + */ + int (*get_keypair_public)(const struct keymaster0_device* dev, + const uint8_t* key_blob, const size_t key_blob_length, + uint8_t** x509_data, size_t* x509_data_length); + + /** + * Deletes the key pair associated with the key blob. + * + * This function is optional and should be set to NULL if it is not + * implemented. + * + * Returns 0 on success or an error code less than 0. + */ + int (*delete_keypair)(const struct keymaster0_device* dev, + const uint8_t* key_blob, const size_t key_blob_length); + + /** + * Deletes all keys in the hardware keystore. Used when keystore is + * reset completely. + * + * This function is optional and should be set to NULL if it is not + * implemented. + * + * Returns 0 on success or an error code less than 0. + */ + int (*delete_all)(const struct keymaster0_device* dev); + + /** + * Signs data using a key-blob generated before. This can use either + * an asymmetric key or a secret key. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*sign_data)(const struct keymaster0_device* dev, + const void* signing_params, + const uint8_t* key_blob, const size_t key_blob_length, + const uint8_t* data, const size_t data_length, + uint8_t** signed_data, size_t* signed_data_length); + + /** + * Verifies data signed with a key-blob. This can use either + * an asymmetric key or a secret key. + * + * Returns: 0 on successful verification or an error code less than 0. + */ + int (*verify_data)(const struct keymaster0_device* dev, + const void* signing_params, + const uint8_t* key_blob, const size_t key_blob_length, + const uint8_t* signed_data, const size_t signed_data_length, + const uint8_t* signature, const size_t signature_length); +}; +typedef struct keymaster0_device keymaster0_device_t; + + +/* Convenience API for opening and closing keymaster devices */ + +static inline int keymaster0_open(const struct hw_module_t* module, + keymaster0_device_t** device) +{ + int rc = module->methods->open(module, KEYSTORE_KEYMASTER, + (struct hw_device_t**) device); + + return rc; +} + +static inline int keymaster0_close(keymaster0_device_t* device) +{ + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_HARDWARE_KEYMASTER_0_H
diff --git a/libhardware/include/hardware/keymaster1.h b/libhardware/include/hardware/keymaster1.h new file mode 100644 index 0000000..afd202c --- /dev/null +++ b/libhardware/include/hardware/keymaster1.h
@@ -0,0 +1,548 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_KEYMASTER1_H +#define ANDROID_HARDWARE_KEYMASTER1_H + +#include <hardware/keymaster_common.h> +#include <hardware/keymaster_defs.h> + +__BEGIN_DECLS + +/** + * Keymaster1 device definition + */ +struct keymaster1_device { + /** + * Common methods of the keymaster device. This *must* be the first member of + * keymaster_device as users of this structure will cast a hw_device_t to + * keymaster_device pointer in contexts where it's known the hw_device_t references a + * keymaster_device. + */ + struct hw_device_t common; + + /** + * THIS IS DEPRECATED. Use the new "module_api_version" and "hal_api_version" + * fields in the keymaster_module initialization instead. + */ + uint32_t client_version; + + /** + * See flags defined for keymaster0_devices::flags in keymaster_common.h + */ + uint32_t flags; + + void* context; + + /** + * \deprecated Generates a public and private key. The key-blob returned is opaque and must + * subsequently provided for signing and verification. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*generate_keypair)(const struct keymaster1_device* dev, const keymaster_keypair_t key_type, + const void* key_params, uint8_t** key_blob, size_t* key_blob_length); + + /** + * \deprecated Imports a public and private key pair. The imported keys will be in PKCS#8 format + * with DER encoding (Java standard). The key-blob returned is opaque and will be subsequently + * provided for signing and verification. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*import_keypair)(const struct keymaster1_device* dev, const uint8_t* key, + const size_t key_length, uint8_t** key_blob, size_t* key_blob_length); + + /** + * \deprecated Gets the public key part of a key pair. The public key must be in X.509 format + * (Java standard) encoded byte array. + * + * Returns: 0 on success or an error code less than 0. On error, x509_data + * should not be allocated. + */ + int (*get_keypair_public)(const struct keymaster1_device* dev, const uint8_t* key_blob, + const size_t key_blob_length, uint8_t** x509_data, + size_t* x509_data_length); + + /** + * \deprecated Deletes the key pair associated with the key blob. + * + * This function is optional and should be set to NULL if it is not + * implemented. + * + * Returns 0 on success or an error code less than 0. + */ + int (*delete_keypair)(const struct keymaster1_device* dev, const uint8_t* key_blob, + const size_t key_blob_length); + + /** + * \deprecated Deletes all keys in the hardware keystore. Used when keystore is reset + * completely. + * + * This function is optional and should be set to NULL if it is not + * implemented. + * + * Returns 0 on success or an error code less than 0. + */ + int (*delete_all)(const struct keymaster1_device* dev); + + /** + * \deprecated Signs data using a key-blob generated before. This can use either an asymmetric + * key or a secret key. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*sign_data)(const struct keymaster1_device* dev, const void* signing_params, + const uint8_t* key_blob, const size_t key_blob_length, const uint8_t* data, + const size_t data_length, uint8_t** signed_data, size_t* signed_data_length); + + /** + * \deprecated Verifies data signed with a key-blob. This can use either an asymmetric key or a + * secret key. + * + * Returns: 0 on successful verification or an error code less than 0. + */ + int (*verify_data)(const struct keymaster1_device* dev, const void* signing_params, + const uint8_t* key_blob, const size_t key_blob_length, + const uint8_t* signed_data, const size_t signed_data_length, + const uint8_t* signature, const size_t signature_length); + + /** + * Gets algorithms supported. + * + * \param[in] dev The keymaster device structure. + * + * \param[out] algorithms Array of algorithms supported. The caller takes ownership of the + * array and must free() it. + * + * \param[out] algorithms_length Length of \p algorithms. + */ + keymaster_error_t (*get_supported_algorithms)(const struct keymaster1_device* dev, + keymaster_algorithm_t** algorithms, + size_t* algorithms_length); + + /** + * Gets the block modes supported for the specified algorithm. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] algorithm The algorithm for which supported modes will be returned. + * + * \param[out] modes Array of modes supported. The caller takes ownership of the array and must + * free() it. + * + * \param[out] modes_length Length of \p modes. + */ + keymaster_error_t (*get_supported_block_modes)(const struct keymaster1_device* dev, + keymaster_algorithm_t algorithm, + keymaster_purpose_t purpose, + keymaster_block_mode_t** modes, + size_t* modes_length); + + /** + * Gets the padding modes supported for the specified algorithm. Caller assumes ownership of + * the allocated array. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] algorithm The algorithm for which supported padding modes will be returned. + * + * \param[out] modes Array of padding modes supported. The caller takes ownership of the array + * and must free() it. + * + * \param[out] modes_length Length of \p modes. + */ + keymaster_error_t (*get_supported_padding_modes)(const struct keymaster1_device* dev, + keymaster_algorithm_t algorithm, + keymaster_purpose_t purpose, + keymaster_padding_t** modes, + size_t* modes_length); + + /** + * Gets the digests supported for the specified algorithm. Caller assumes ownership of the + * allocated array. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] algorithm The algorithm for which supported digests will be returned. + * + * \param[out] digests Array of digests supported. The caller takes ownership of the array and + * must free() it. + * + * \param[out] digests_length Length of \p digests. + */ + keymaster_error_t (*get_supported_digests)(const struct keymaster1_device* dev, + keymaster_algorithm_t algorithm, + keymaster_purpose_t purpose, + keymaster_digest_t** digests, + size_t* digests_length); + + /** + * Gets the key import formats supported for keys of the specified algorithm. Caller assumes + * ownership of the allocated array. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] algorithm The algorithm for which supported formats will be returned. + * + * \param[out] formats Array of formats supported. The caller takes ownership of the array and + * must free() it. + * + * \param[out] formats_length Length of \p formats. + */ + keymaster_error_t (*get_supported_import_formats)(const struct keymaster1_device* dev, + keymaster_algorithm_t algorithm, + keymaster_key_format_t** formats, + size_t* formats_length); + + /** + * Gets the key export formats supported for keys of the specified algorithm. Caller assumes + * ownership of the allocated array. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] algorithm The algorithm for which supported formats will be returned. + * + * \param[out] formats Array of formats supported. The caller takes ownership of the array and + * must free() it. + * + * \param[out] formats_length Length of \p formats. + */ + keymaster_error_t (*get_supported_export_formats)(const struct keymaster1_device* dev, + keymaster_algorithm_t algorithm, + keymaster_key_format_t** formats, + size_t* formats_length); + + /** + * Adds entropy to the RNG used by keymaster. Entropy added through this method is guaranteed + * not to be the only source of entropy used, and the mixing function is required to be secure, + * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot + * predict (or control), then the RNG output is indistinguishable from random. Thus, if the + * entropy from any source is good, the output will be good. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] data Random data to be mixed in. + * + * \param[in] data_length Length of \p data. + */ + keymaster_error_t (*add_rng_entropy)(const struct keymaster1_device* dev, const uint8_t* data, + size_t data_length); + + /** + * Generates a key, or key pair, returning a key blob and/or a description of the key. + * + * Key generation parameters are defined as keymaster tag/value pairs, provided in \p params. + * See keymaster_tag_t for the full list. Some values that are always required for generation + * of useful keys are: + * + * - KM_TAG_ALGORITHM; + * - KM_TAG_PURPOSE; and + * - (KM_TAG_USER_SECURE_ID and KM_TAG_USER_AUTH_TYPE) or KM_TAG_NO_AUTH_REQUIRED. + * + * KM_TAG_AUTH_TIMEOUT should generally be specified unless KM_TAG_NO_AUTH_REQUIRED is present, + * or the user will have to authenticate for every use. + * + * KM_TAG_BLOCK_MODE, KM_TAG_PADDING, KM_TAG_MAC_LENGTH and KM_TAG_DIGEST must be specified for + * algorithms that require them. + * + * The following tags may not be specified; their values will be provided by the implementation. + * + * - KM_TAG_ORIGIN, + * - KM_TAG_ROLLBACK_RESISTANT, + * - KM_TAG_CREATION_DATETIME + * + * \param[in] dev The keymaster device structure. + * + * \param[in] params Array of key generation parameters. + * + * \param[in] params_count Length of \p params. + * + * \param[out] key_blob returns the generated key. \p key_blob must not be NULL. The caller + * assumes ownership key_blob->key_material and must free() it. + * + * \param[out] characteristics returns the characteristics of the key that was, generated, if + * non-NULL. If non-NULL, the caller assumes ownership and must deallocate with + * keymaster_free_characteristics(). Note that KM_TAG_ROOT_OF_TRUST, KM_TAG_APPLICATION_ID and + * KM_TAG_APPLICATION_DATA are never returned. + */ + keymaster_error_t (*generate_key)(const struct keymaster1_device* dev, + const keymaster_key_param_set_t* params, + keymaster_key_blob_t* key_blob, + keymaster_key_characteristics_t** characteristics); + + /** + * Returns the characteristics of the specified key, or KM_ERROR_INVALID_KEY_BLOB if the + * key_blob is invalid (implementations must fully validate the integrity of the key). + * client_id and app_data must be the ID and data provided when the key was generated or + * imported, or empty if KM_TAG_APPLICATION_ID and/or KM_TAG_APPLICATION_DATA were not provided + * during generation. Those values are not included in the returned characteristics. The + * caller assumes ownership of the allocated characteristics object, which must be deallocated + * with keymaster_free_characteristics(). + * + * Note that KM_TAG_ROOT_OF_TRUST, KM_TAG_APPLICATION_ID and KM_TAG_APPLICATION_DATA are never + * returned. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key_blob The key to retreive characteristics from. + * + * \param[in] client_id The client ID data, or NULL if none associated. + * + * \param[in] app_id The app data, or NULL if none associated. + * + * \param[out] characteristics The key characteristics. + */ + keymaster_error_t (*get_key_characteristics)(const struct keymaster1_device* dev, + const keymaster_key_blob_t* key_blob, + const keymaster_blob_t* client_id, + const keymaster_blob_t* app_data, + keymaster_key_characteristics_t** characteristics); + + /** + * Imports a key, or key pair, returning a key blob and/or a description of the key. + * + * Most key import parameters are defined as keymaster tag/value pairs, provided in "params". + * See keymaster_tag_t for the full list. Values that are always required for import of useful + * keys are: + * + * - KM_TAG_ALGORITHM; + * - KM_TAG_PURPOSE; and + * - (KM_TAG_USER_SECURE_ID and KM_TAG_USER_AUTH_TYPE) or KM_TAG_NO_AUTH_REQUIRED. + * + * KM_TAG_AUTH_TIMEOUT should generally be specified. If unspecified, the user will have to + * authenticate for every use. + * + * The following tags will take default values if unspecified: + * + * - KM_TAG_KEY_SIZE will default to the size of the key provided. + * - KM_TAG_RSA_PUBLIC_EXPONENT will default to the value in the key provided (for RSA keys) + * + * The following tags may not be specified; their values will be provided by the implementation. + * + * - KM_TAG_ORIGIN, + * - KM_TAG_ROLLBACK_RESISTANT, + * - KM_TAG_CREATION_DATETIME + * + * \param[in] dev The keymaster device structure. + * + * \param[in] params Parameters defining the imported key. + * + * \param[in] params_count The number of entries in \p params. + * + * \param[in] key_format specifies the format of the key data in key_data. + * + * \param[out] key_blob Used to return the opaque key blob. Must be non-NULL. The caller + * assumes ownership of the contained key_material. + * + * \param[out] characteristics Used to return the characteristics of the imported key. May be + * NULL, in which case no characteristics will be returned. If non-NULL, the caller assumes + * ownership and must deallocate with keymaster_free_characteristics(). Note that + * KM_TAG_ROOT_OF_TRUST, KM_TAG_APPLICATION_ID and + * KM_TAG_APPLICATION_DATA are never returned. + */ + keymaster_error_t (*import_key)(const struct keymaster1_device* dev, + const keymaster_key_param_set_t* params, + keymaster_key_format_t key_format, + const keymaster_blob_t* key_data, + keymaster_key_blob_t* key_blob, + keymaster_key_characteristics_t** characteristics); + + /** + * Exports a public key, returning a byte array in the specified format. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] export_format The format to be used for exporting the key. + * + * \param[in] key_to_export The key to export. + * + * \param[out] export_data The exported key material. The caller assumes ownership. + * + * \param[out] export_data_length The length of \p export_data. + */ + keymaster_error_t (*export_key)(const struct keymaster1_device* dev, + keymaster_key_format_t export_format, + const keymaster_key_blob_t* key_to_export, + const keymaster_blob_t* client_id, + const keymaster_blob_t* app_data, + keymaster_blob_t* export_data); + + /** + * Deletes the key, or key pair, associated with the key blob. After calling this function it + * will be impossible to use the key for any other operations. May be applied to keys from + * foreign roots of trust (keys not usable under the current root of trust). + * + * This function is optional and should be set to NULL if it is not implemented. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key The key to be deleted. + */ + keymaster_error_t (*delete_key)(const struct keymaster1_device* dev, + const keymaster_key_blob_t* key); + + /** + * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After + * calling this function it will be impossible to use any previously generated or imported key + * blobs for any operations. + * + * This function is optional and should be set to NULL if it is not implemented. + * + * \param[in] dev The keymaster device structure. + */ + keymaster_error_t (*delete_all_keys)(const struct keymaster1_device* dev); + + /** + * Begins a cryptographic operation using the specified key. If all is well, begin() will + * return KM_ERROR_OK and create an operation handle which must be passed to subsequent calls to + * update(), finish() or abort(). + * + * It is critical that each call to begin() be paired with a subsequent call to finish() or + * abort(), to allow the keymaster implementation to clean up any internal operation state. + * Failure to do this may leak internal state space or other internal resources and may + * eventually cause begin() to return KM_ERROR_TOO_MANY_OPERATIONS when it runs out of space for + * operations. Any result other than KM_ERROR_OK from begin(), update() or finish() implicitly + * aborts the operation, in which case abort() need not be called (and will return + * KM_ERROR_INVALID_OPERATION_HANDLE if called). + * + * \param[in] dev The keymaster device structure. + * + * \param[in] purpose The purpose of the operation, one of KM_PURPOSE_ENCRYPT, + * KM_PURPOSE_DECRYPT, KM_PURPOSE_SIGN or KM_PURPOSE_VERIFY. Note that for AEAD modes, + * encryption and decryption imply signing and verification, respectively, but should be + * specified as KM_PURPOSE_ENCRYPT and KM_PURPOSE_DECRYPT. + * + * \param[in] key The key to be used for the operation. \p key must have a purpose compatible + * with \p purpose and all of its usage requirements must be satisfied, or begin() will return + * an appropriate error code. + * + * \param[in] in_params Additional parameters for the operation. This is typically used to + * provide authentication data, with KM_TAG_AUTH_TOKEN. If KM_TAG_APPLICATION_ID or + * KM_TAG_APPLICATION_DATA were provided during generation, they must be provided here, or the + * operation will fail with KM_ERROR_INVALID_KEY_BLOB. For operations that require a nonce or + * IV, on keys that were generated with KM_TAG_CALLER_NONCE, in_params may contain a tag + * KM_TAG_NONCE. For AEAD operations KM_TAG_CHUNK_SIZE is specified here. + * + * \param[out] out_params Output parameters. Used to return additional data from the operation + * initialization, notably to return the IV or nonce from operations that generate an IV or + * nonce. The caller takes ownership of the output parameters array and must free it with + * keymaster_free_param_set(). out_params may be set to NULL if no output parameters are + * expected. If out_params is NULL, and output paramaters are generated, begin() will return + * KM_ERROR_OUTPUT_PARAMETER_NULL. + * + * \param[out] operation_handle The newly-created operation handle which must be passed to + * update(), finish() or abort(). If operation_handle is NULL, begin() will return + * KM_ERROR_OUTPUT_PARAMETER_NULL. + */ + keymaster_error_t (*begin)(const struct keymaster1_device* dev, keymaster_purpose_t purpose, + const keymaster_key_blob_t* key, + const keymaster_key_param_set_t* in_params, + keymaster_key_param_set_t* out_params, + keymaster_operation_handle_t* operation_handle); + + /** + * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun + * with begin(). + * + * If operation_handle is invalid, update() will return KM_ERROR_INVALID_OPERATION_HANDLE. + * + * update() may not consume all of the data provided in the data buffer. update() will return + * the amount consumed in *data_consumed. The caller should provide the unconsumed data in a + * subsequent call. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] operation_handle The operation handle returned by begin(). + * + * \param[in] in_params Additional parameters for the operation. For AEAD modes, this is used + * to specify KM_TAG_ADDITIONAL_DATA. Note that additional data may be provided in multiple + * calls to update(), but only until input data has been provided. + * + * \param[in] input Data to be processed, per the parameters established in the call to begin(). + * Note that update() may or may not consume all of the data provided. See \p input_consumed. + * + * \param[out] input_consumed Amount of data that was consumed by update(). If this is less + * than the amount provided, the caller should provide the remainder in a subsequent call to + * update(). + * + * \param[out] out_params Output parameters. Used to return additional data from the operation + * The caller takes ownership of the output parameters array and must free it with + * keymaster_free_param_set(). out_params may be set to NULL if no output parameters are + * expected. If out_params is NULL, and output paramaters are generated, begin() will return + * KM_ERROR_OUTPUT_PARAMETER_NULL. + * + * \param[out] output The output data, if any. The caller assumes ownership of the allocated + * buffer. output must not be NULL. + * + * Note that update() may not provide any output, in which case output->data_length will be + * zero, and output->data may be either NULL or zero-length (so the caller should always free() + * it). + */ + keymaster_error_t (*update)(const struct keymaster1_device* dev, + keymaster_operation_handle_t operation_handle, + const keymaster_key_param_set_t* in_params, + const keymaster_blob_t* input, size_t* input_consumed, + keymaster_key_param_set_t* out_params, keymaster_blob_t* output); + + /** + * Finalizes a cryptographic operation begun with begin() and invalidates \p operation_handle. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] operation_handle The operation handle returned by begin(). This handle will be + * invalidated. + * + * \param[in] params Additional parameters for the operation. For AEAD modes, this is used to + * specify KM_TAG_ADDITIONAL_DATA, but only if no input data was provided to update(). + * + * \param[in] signature The signature to be verified if the purpose specified in the begin() + * call was KM_PURPOSE_VERIFY. + * + * \param[out] output The output data, if any. The caller assumes ownership of the allocated + * buffer. + * + * If the operation being finished is a signature verification or an AEAD-mode decryption and + * verification fails then finish() will return KM_ERROR_VERIFICATION_FAILED. + */ + keymaster_error_t (*finish)(const struct keymaster1_device* dev, + keymaster_operation_handle_t operation_handle, + const keymaster_key_param_set_t* in_params, + const keymaster_blob_t* signature, + keymaster_key_param_set_t* out_params, keymaster_blob_t* output); + + /** + * Aborts a cryptographic operation begun with begin(), freeing all internal resources and + * invalidating \p operation_handle. + */ + keymaster_error_t (*abort)(const struct keymaster1_device* dev, + keymaster_operation_handle_t operation_handle); +}; +typedef struct keymaster1_device keymaster1_device_t; + +/* Convenience API for opening and closing keymaster devices */ + +static inline int keymaster1_open(const struct hw_module_t* module, keymaster1_device_t** device) { + return module->methods->open(module, KEYSTORE_KEYMASTER, (struct hw_device_t**)device); +} + +static inline int keymaster1_close(keymaster1_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_HARDWARE_KEYMASTER1_H
diff --git a/libhardware/include/hardware/keymaster2.h b/libhardware/include/hardware/keymaster2.h new file mode 100644 index 0000000..dcde30e --- /dev/null +++ b/libhardware/include/hardware/keymaster2.h
@@ -0,0 +1,452 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_KEYMASTER2_H +#define ANDROID_HARDWARE_KEYMASTER2_H + +#include <hardware/keymaster_common.h> +#include <hardware/keymaster_defs.h> + +__BEGIN_DECLS + +/** + * Keymaster2 device definition + */ +struct keymaster2_device { + /** + * Common methods of the keymaster device. This *must* be the first member of + * keymaster_device as users of this structure will cast a hw_device_t to + * keymaster_device pointer in contexts where it's known the hw_device_t references a + * keymaster_device. + */ + struct hw_device_t common; + + void* context; + + /** + * See flags defined for keymaster0_devices::flags in keymaster_common.h. Used only for + * backward compatibility; keymaster2 hardware devices must set this to zero. + */ + uint32_t flags; + + /** + * Adds entropy to the RNG used by keymaster. Entropy added through this method is guaranteed + * not to be the only source of entropy used, and the mixing function is required to be secure, + * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot + * predict (or control), then the RNG output is indistinguishable from random. Thus, if the + * entropy from any source is good, the output will be good. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] data Random data to be mixed in. + * + * \param[in] data_length Length of \p data. + */ + keymaster_error_t (*add_rng_entropy)(const struct keymaster2_device* dev, const uint8_t* data, + size_t data_length); + + /** + * Generates a key, or key pair, returning a key blob and/or a description of the key. + * + * Key generation parameters are defined as keymaster tag/value pairs, provided in \p params. + * See keymaster_tag_t for the full list. Some values that are always required for generation + * of useful keys are: + * + * - KM_TAG_ALGORITHM; + * - KM_TAG_PURPOSE; and + * - (KM_TAG_USER_SECURE_ID and KM_TAG_USER_AUTH_TYPE) or KM_TAG_NO_AUTH_REQUIRED. + * + * KM_TAG_AUTH_TIMEOUT should generally be specified unless KM_TAG_NO_AUTH_REQUIRED is present, + * or the user will have to authenticate for every use. + * + * KM_TAG_BLOCK_MODE, KM_TAG_PADDING, KM_TAG_MAC_LENGTH and KM_TAG_DIGEST must be specified for + * algorithms that require them. + * + * The following tags may not be specified; their values will be provided by the implementation. + * + * - KM_TAG_ORIGIN, + * - KM_TAG_ROLLBACK_RESISTANT, + * - KM_TAG_CREATION_DATETIME + * + * \param[in] dev The keymaster device structure. + * + * \param[in] params Array of key generation param + * + * \param[out] key_blob returns the generated key. \p key_blob must not be NULL. The caller + * assumes ownership key_blob->key_material and must free() it. + * + * \param[out] characteristics returns the characteristics of the key that was, generated, if + * non-NULL. If non-NULL, the caller assumes ownership and must deallocate with + * keymaster_free_characteristics(). Note that KM_TAG_ROOT_OF_TRUST, KM_TAG_APPLICATION_ID and + * KM_TAG_APPLICATION_DATA are never returned. + */ + keymaster_error_t (*generate_key)(const struct keymaster2_device* dev, + const keymaster_key_param_set_t* params, + keymaster_key_blob_t* key_blob, + keymaster_key_characteristics_t* characteristics); + + /** + * Returns the characteristics of the specified key, or KM_ERROR_INVALID_KEY_BLOB if the + * key_blob is invalid (implementations must fully validate the integrity of the key). + * client_id and app_data must be the ID and data provided when the key was generated or + * imported, or empty if KM_TAG_APPLICATION_ID and/or KM_TAG_APPLICATION_DATA were not provided + * during generation. Those values are not included in the returned characteristics. The + * caller assumes ownership of the allocated characteristics object, which must be deallocated + * with keymaster_free_characteristics(). + * + * Note that KM_TAG_APPLICATION_ID and KM_TAG_APPLICATION_DATA are never returned. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key_blob The key to retreive characteristics from. + * + * \param[in] client_id The client ID data, or NULL if none associated. + * + * \param[in] app_id The app data, or NULL if none associated. + * + * \param[out] characteristics The key characteristics. Must not be NULL. The caller assumes + * ownership of the contents and must deallocate with keymaster_free_characteristics(). + */ + keymaster_error_t (*get_key_characteristics)(const struct keymaster2_device* dev, + const keymaster_key_blob_t* key_blob, + const keymaster_blob_t* client_id, + const keymaster_blob_t* app_data, + keymaster_key_characteristics_t* characteristics); + + /** + * Imports a key, or key pair, returning a key blob and/or a description of the key. + * + * Most key import parameters are defined as keymaster tag/value pairs, provided in "params". + * See keymaster_tag_t for the full list. Values that are always required for import of useful + * keys are: + * + * - KM_TAG_ALGORITHM; + * - KM_TAG_PURPOSE; and + * - (KM_TAG_USER_SECURE_ID and KM_TAG_USER_AUTH_TYPE) or KM_TAG_NO_AUTH_REQUIRED. + * + * KM_TAG_AUTH_TIMEOUT should generally be specified. If unspecified, the user will have to + * authenticate for every use. + * + * The following tags will take default values if unspecified: + * + * - KM_TAG_KEY_SIZE will default to the size of the key provided. + * - KM_TAG_RSA_PUBLIC_EXPONENT will default to the value in the key provided (for RSA keys) + * + * The following tags may not be specified; their values will be provided by the implementation. + * + * - KM_TAG_ORIGIN, + * - KM_TAG_ROLLBACK_RESISTANT, + * - KM_TAG_CREATION_DATETIME + * + * \param[in] dev The keymaster device structure. + * + * \param[in] params Parameters defining the imported key. + * + * \param[in] params_count The number of entries in \p params. + * + * \param[in] key_format specifies the format of the key data in key_data. + * + * \param[out] key_blob Used to return the opaque key blob. Must be non-NULL. The caller + * assumes ownership of the contained key_material. + * + * \param[out] characteristics Used to return the characteristics of the imported key. May be + * NULL, in which case no characteristics will be returned. If non-NULL, the caller assumes + * ownership of the contents and must deallocate with keymaster_free_characteristics(). Note + * that KM_TAG_APPLICATION_ID and KM_TAG_APPLICATION_DATA are never returned. + */ + keymaster_error_t (*import_key)(const struct keymaster2_device* dev, + const keymaster_key_param_set_t* params, + keymaster_key_format_t key_format, + const keymaster_blob_t* key_data, + keymaster_key_blob_t* key_blob, + keymaster_key_characteristics_t* characteristics); + + /** + * Exports a public or symmetric key, returning a byte array in the specified format. + * + * Note that symmetric key export is allowed only if the key was created with KM_TAG_EXPORTABLE, + * and only if all of the requirements for key usage (e.g. authentication) are met. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] export_format The format to be used for exporting the key. + * + * \param[in] key_to_export The key to export. + * + * \param[in] client_id Client ID blob, which must match the blob provided in + * KM_TAG_APPLICATION_ID during key generation (if any). + * + * \param[in] app_data Appliation data blob, which must match the blob provided in + * KM_TAG_APPLICATION_DATA during key generation (if any). + * + * \param[out] export_data The exported key material. The caller assumes ownership. + */ + keymaster_error_t (*export_key)(const struct keymaster2_device* dev, + keymaster_key_format_t export_format, + const keymaster_key_blob_t* key_to_export, + const keymaster_blob_t* client_id, + const keymaster_blob_t* app_data, + keymaster_blob_t* export_data); + + /** + * Derives a shared secret key from \p key, which must be an EC key, and the public key found in + * /p other_key_certificate, an X.509 certificate containing a compatible EC public key. The + * derived key's characteristics are described in \p new_key_params, which must include + * algorithm (KM_TAG_ALGORITHM), key size (KM_TAG_KEY_SIZE) and KDF (KM_TAG_KDF) as well as + * other desired key characteristics. The resulting key material is not returned directly, but + * instead a new keymaster key is created and the associated blob returned in \p key_blob. If + * \p characteristics is non-NULL, the new key's characteristics are placed there. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key The keymaster key to use for key agreement. This must be an EC key with the + * KM_PURPOSE_DERIVE_KEY purpose. + * + * \param[in] other_key_certificate An X.509 certificate or certificate fragment containing a + * SubjectPublicKey field containing an EC public key on the same curve as \p key. + * + * \param[in] new_key_params A set of parameters to define/describe the newly-derived symmetric + * key. The parameters will define how the key may be used. The set must include KM_TAG_KDF to + * specify how the raw agreed key bytes will be transformed to produce the key material. + * + * \param[out] key_blob The key blob containing the newly-derived key. The caller takes + * ownership of the returned blob. + * + * \param[out] characteristics. If non-null, will be used to return the characteristics of the + * new key blob, which will have KM_TAG_ORIGIN set to KM_ORIGIN_DERIVED. The caller takes + * ownership of the returned characteristics and must deallocate with + * keymaster_free_characteristics(). + */ + keymaster_error_t (*agree_key)(const struct keymaster2_device* dev, + const keymaster_key_blob_t* key, + const keymaster_blob_t* other_key_certificate, + const keymaster_key_param_set_t* new_key_params, + keymaster_key_blob_t* new_key_blob, + keymaster_key_characteristics_t* characteristics); + + /** + * Generates a signed X.509 certificate chain attesting to the presence of \p key_to_attest in + * keymaster (TODO(swillden): Describe certificate contents in more detail). The certificate + * will contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and value defined in + * <TODO:swillden -- insert link here> which contains the key description. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key_to_attest The keymaster key for which the attestation certificate will be + * generated. + * + * \param[in] attest_params Parameters defining how to do the attestation. At present the only + * parameter is KM_TAG_ALGORITHM, which must be either KM_ALGORITHM_EC or KM_ALGORITHM_RSA. + * This selects which of the provisioned attestation keys will be used to sign the certificate. + * + * \param[out] cert_chain An array of DER-encoded X.509 certificates. The first will be the + * certificate for \p key_to_attest. The remaining entries will chain back to the root. The + * caller takes ownership and must deallocate with keymaster_free_cert_chain. + */ + keymaster_error_t (*attest_key)(const struct keymaster2_device* dev, + const keymaster_key_blob_t* key_to_attest, + const keymaster_key_param_set_t* attest_params, + keymaster_cert_chain_t* cert_chain); + + /** + * Upgrades an old key. Keys can become "old" in two ways: Keymaster can be upgraded to a new + * version, or the system can be updated to invalidate the OS version and/or patch level. In + * either case, attempts to use an old key will result in keymaster returning + * KM_ERROR_KEY_REQUIRES_UPGRADE. This method should then be called to upgrade the key. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key_to_upgrade The keymaster key to upgrade. + * + * \param[in] upgrade_params Parameters needed to complete the upgrade. In particular, + * KM_TAG_APPLICATION_ID and KM_TAG_APPLICATION_DATA will be required if they were defined for + * the key. + * + * \param[out] upgraded_key The upgraded key blob. + */ + keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev, + const keymaster_key_blob_t* key_to_upgrade, + const keymaster_key_param_set_t* upgrade_params, + keymaster_key_blob_t* upgraded_key); + + /** + * Deletes the key, or key pair, associated with the key blob. After calling this function it + * will be impossible to use the key for any other operations. May be applied to keys from + * foreign roots of trust (keys not usable under the current root of trust). + * + * This function is optional and should be set to NULL if it is not implemented. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] key The key to be deleted. + */ + keymaster_error_t (*delete_key)(const struct keymaster2_device* dev, + const keymaster_key_blob_t* key); + + /** + * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After + * calling this function it will be impossible to use any previously generated or imported key + * blobs for any operations. + * + * This function is optional and should be set to NULL if it is not implemented. + * + * \param[in] dev The keymaster device structure. + */ + keymaster_error_t (*delete_all_keys)(const struct keymaster2_device* dev); + + /** + * Begins a cryptographic operation using the specified key. If all is well, begin() will + * return KM_ERROR_OK and create an operation handle which must be passed to subsequent calls to + * update(), finish() or abort(). + * + * It is critical that each call to begin() be paired with a subsequent call to finish() or + * abort(), to allow the keymaster implementation to clean up any internal operation state. + * Failure to do this may leak internal state space or other internal resources and may + * eventually cause begin() to return KM_ERROR_TOO_MANY_OPERATIONS when it runs out of space for + * operations. Any result other than KM_ERROR_OK from begin(), update() or finish() implicitly + * aborts the operation, in which case abort() need not be called (and will return + * KM_ERROR_INVALID_OPERATION_HANDLE if called). + * + * \param[in] dev The keymaster device structure. + * + * \param[in] purpose The purpose of the operation, one of KM_PURPOSE_ENCRYPT, + * KM_PURPOSE_DECRYPT, KM_PURPOSE_SIGN or KM_PURPOSE_VERIFY. Note that for AEAD modes, + * encryption and decryption imply signing and verification, respectively, but should be + * specified as KM_PURPOSE_ENCRYPT and KM_PURPOSE_DECRYPT. + * + * \param[in] key The key to be used for the operation. \p key must have a purpose compatible + * with \p purpose and all of its usage requirements must be satisfied, or begin() will return + * an appropriate error code. + * + * \param[in] in_params Additional parameters for the operation. This is typically used to + * provide authentication data, with KM_TAG_AUTH_TOKEN. If KM_TAG_APPLICATION_ID or + * KM_TAG_APPLICATION_DATA were provided during generation, they must be provided here, or the + * operation will fail with KM_ERROR_INVALID_KEY_BLOB. For operations that require a nonce or + * IV, on keys that were generated with KM_TAG_CALLER_NONCE, in_params may contain a tag + * KM_TAG_NONCE. + * + * \param[out] out_params Output parameters. Used to return additional data from the operation + * initialization, notably to return the IV or nonce from operations that generate an IV or + * nonce. The caller takes ownership of the output parameters array and must free it with + * keymaster_free_param_set(). out_params may be set to NULL if no output parameters are + * expected. If out_params is NULL, and output paramaters are generated, begin() will return + * KM_ERROR_OUTPUT_PARAMETER_NULL. + * + * \param[out] operation_handle The newly-created operation handle which must be passed to + * update(), finish() or abort(). If operation_handle is NULL, begin() will return + * KM_ERROR_OUTPUT_PARAMETER_NULL. + */ + keymaster_error_t (*begin)(const struct keymaster2_device* dev, keymaster_purpose_t purpose, + const keymaster_key_blob_t* key, + const keymaster_key_param_set_t* in_params, + keymaster_key_param_set_t* out_params, + keymaster_operation_handle_t* operation_handle); + + /** + * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun + * with begin(). + * + * If operation_handle is invalid, update() will return KM_ERROR_INVALID_OPERATION_HANDLE. + * + * update() may not consume all of the data provided in the data buffer. update() will return + * the amount consumed in *data_consumed. The caller should provide the unconsumed data in a + * subsequent call. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] operation_handle The operation handle returned by begin(). + * + * \param[in] in_params Additional parameters for the operation. For AEAD modes, this is used + * to specify KM_TAG_ADDITIONAL_DATA. Note that additional data may be provided in multiple + * calls to update(), but only until input data has been provided. + * + * \param[in] input Data to be processed, per the parameters established in the call to begin(). + * Note that update() may or may not consume all of the data provided. See \p input_consumed. + * + * \param[out] input_consumed Amount of data that was consumed by update(). If this is less + * than the amount provided, the caller should provide the remainder in a subsequent call to + * update(). + * + * \param[out] out_params Output parameters. Used to return additional data from the operation + * The caller takes ownership of the output parameters array and must free it with + * keymaster_free_param_set(). out_params may be set to NULL if no output parameters are + * expected. If out_params is NULL, and output paramaters are generated, begin() will return + * KM_ERROR_OUTPUT_PARAMETER_NULL. + * + * \param[out] output The output data, if any. The caller assumes ownership of the allocated + * buffer. output must not be NULL. + * + * Note that update() may not provide any output, in which case output->data_length will be + * zero, and output->data may be either NULL or zero-length (so the caller should always free() + * it). + */ + keymaster_error_t (*update)(const struct keymaster2_device* dev, + keymaster_operation_handle_t operation_handle, + const keymaster_key_param_set_t* in_params, + const keymaster_blob_t* input, size_t* input_consumed, + keymaster_key_param_set_t* out_params, keymaster_blob_t* output); + + /** + * Finalizes a cryptographic operation begun with begin() and invalidates \p operation_handle. + * + * \param[in] dev The keymaster device structure. + * + * \param[in] operation_handle The operation handle returned by begin(). This handle will be + * invalidated. + * + * \param[in] in_params Additional parameters for the operation. For AEAD modes, this is used + * to specify KM_TAG_ADDITIONAL_DATA, but only if no input data was provided to update(). + * + * \param[in] input Data to be processed, per the parameters established in the call to + * begin(). finish() must consume all provided data or return KM_ERROR_INVALID_INPUT_LENGTH. + * + * \param[in] signature The signature to be verified if the purpose specified in the begin() + * call was KM_PURPOSE_VERIFY. + * + * \param[out] output The output data, if any. The caller assumes ownership of the allocated + * buffer. + * + * If the operation being finished is a signature verification or an AEAD-mode decryption and + * verification fails then finish() will return KM_ERROR_VERIFICATION_FAILED. + */ + keymaster_error_t (*finish)(const struct keymaster2_device* dev, + keymaster_operation_handle_t operation_handle, + const keymaster_key_param_set_t* in_params, + const keymaster_blob_t* input, const keymaster_blob_t* signature, + keymaster_key_param_set_t* out_params, keymaster_blob_t* output); + + /** + * Aborts a cryptographic operation begun with begin(), freeing all internal resources and + * invalidating \p operation_handle. + */ + keymaster_error_t (*abort)(const struct keymaster2_device* dev, + keymaster_operation_handle_t operation_handle); +}; +typedef struct keymaster2_device keymaster2_device_t; + +/* Convenience API for opening and closing keymaster devices */ + +static inline int keymaster2_open(const struct hw_module_t* module, keymaster2_device_t** device) { + return module->methods->open(module, KEYSTORE_KEYMASTER, (struct hw_device_t**)device); +} + +static inline int keymaster2_close(keymaster2_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_HARDWARE_KEYMASTER2_H
diff --git a/libhardware/include/hardware/keymaster_common.h b/libhardware/include/hardware/keymaster_common.h new file mode 100644 index 0000000..c79c122 --- /dev/null +++ b/libhardware/include/hardware/keymaster_common.h
@@ -0,0 +1,191 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_KEYMASTER_COMMON_H +#define ANDROID_HARDWARE_KEYMASTER_COMMON_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define KEYSTORE_HARDWARE_MODULE_ID "keystore" + +#define KEYSTORE_KEYMASTER "keymaster" + + +/** + * Settings for "module_api_version" and "hal_api_version" + * fields in the keymaster_module initialization. + */ + +/** + * Keymaster 0.X module version provide the same APIs, but later versions add more options + * for algorithms and flags. + */ +#define KEYMASTER_MODULE_API_VERSION_0_2 HARDWARE_MODULE_API_VERSION(0, 2) +#define KEYMASTER_DEVICE_API_VERSION_0_2 HARDWARE_DEVICE_API_VERSION(0, 2) + +#define KEYMASTER_MODULE_API_VERSION_0_3 HARDWARE_MODULE_API_VERSION(0, 3) +#define KEYMASTER_DEVICE_API_VERSION_0_3 HARDWARE_DEVICE_API_VERSION(0, 3) + +/** + * Keymaster 1.0 module version provides a completely different API, incompatible with 0.X. + */ +#define KEYMASTER_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define KEYMASTER_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) + +/** + * Keymaster 2.0 module version provides third API, slightly modified and extended from 1.0. + */ +#define KEYMASTER_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0) +#define KEYMASTER_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) + +struct keystore_module { + /** + * Common methods of the keystore module. This *must* be the first member of keystore_module as + * users of this structure will cast a hw_module_t to keystore_module pointer in contexts where + * it's known the hw_module_t references a keystore_module. + */ + hw_module_t common; + + /* There are no keystore module methods other than the common ones. */ +}; + +/** + * Flags for keymaster0_device::flags + */ +enum { + /* + * Indicates this keymaster implementation does not have hardware that + * keeps private keys out of user space. + * + * This should not be implemented on anything other than the default + * implementation. + */ + KEYMASTER_SOFTWARE_ONLY = 1 << 0, + + /* + * This indicates that the key blobs returned via all the primitives + * are sufficient to operate on their own without the trusted OS + * querying userspace to retrieve some other data. Key blobs of + * this type are normally returned encrypted with a + * Key Encryption Key (KEK). + * + * This is currently used by "vold" to know whether the whole disk + * encryption secret can be unwrapped without having some external + * service started up beforehand since the "/data" partition will + * be unavailable at that point. + */ + KEYMASTER_BLOBS_ARE_STANDALONE = 1 << 1, + + /* + * Indicates that the keymaster module supports DSA keys. + */ + KEYMASTER_SUPPORTS_DSA = 1 << 2, + + /* + * Indicates that the keymaster module supports EC keys. + */ + KEYMASTER_SUPPORTS_EC = 1 << 3, +}; + +/** + * Asymmetric key pair types. + */ +typedef enum { + TYPE_RSA = 1, + TYPE_DSA = 2, + TYPE_EC = 3, +} keymaster_keypair_t; + +/** + * Parameters needed to generate an RSA key. + */ +typedef struct { + uint32_t modulus_size; + uint64_t public_exponent; +} keymaster_rsa_keygen_params_t; + +/** + * Parameters needed to generate a DSA key. + */ +typedef struct { + uint32_t key_size; + uint32_t generator_len; + uint32_t prime_p_len; + uint32_t prime_q_len; + const uint8_t* generator; + const uint8_t* prime_p; + const uint8_t* prime_q; +} keymaster_dsa_keygen_params_t; + +/** + * Parameters needed to generate an EC key. + * + * Field size is the only parameter in version 2. The sizes correspond to these required curves: + * + * 192 = NIST P-192 + * 224 = NIST P-224 + * 256 = NIST P-256 + * 384 = NIST P-384 + * 521 = NIST P-521 + * + * The parameters for these curves are available at: http://www.nsa.gov/ia/_files/nist-routines.pdf + * in Chapter 4. + */ +typedef struct { + uint32_t field_size; +} keymaster_ec_keygen_params_t; + + +/** + * Digest type. + */ +typedef enum { + DIGEST_NONE, +} keymaster_digest_algorithm_t; + +/** + * Type of padding used for RSA operations. + */ +typedef enum { + PADDING_NONE, +} keymaster_rsa_padding_t; + + +typedef struct { + keymaster_digest_algorithm_t digest_type; +} keymaster_dsa_sign_params_t; + +typedef struct { + keymaster_digest_algorithm_t digest_type; +} keymaster_ec_sign_params_t; + +typedef struct { + keymaster_digest_algorithm_t digest_type; + keymaster_rsa_padding_t padding_type; +} keymaster_rsa_sign_params_t; + +__END_DECLS + +#endif // ANDROID_HARDWARE_KEYMASTER_COMMON_H
diff --git a/libhardware/include/hardware/keymaster_defs.h b/libhardware/include/hardware/keymaster_defs.h new file mode 100644 index 0000000..fd53adf --- /dev/null +++ b/libhardware/include/hardware/keymaster_defs.h
@@ -0,0 +1,589 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_KEYMASTER_DEFS_H +#define ANDROID_HARDWARE_KEYMASTER_DEFS_H + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Authorization tags each have an associated type. This enumeration facilitates tagging each with + * a type, by using the high four bits (of an implied 32-bit unsigned enum value) to specify up to + * 16 data types. These values are ORed with tag IDs to generate the final tag ID values. + */ +typedef enum { + KM_INVALID = 0 << 28, /* Invalid type, used to designate a tag as uninitialized */ + KM_ENUM = 1 << 28, + KM_ENUM_REP = 2 << 28, /* Repeatable enumeration value. */ + KM_UINT = 3 << 28, + KM_UINT_REP = 4 << 28, /* Repeatable integer value */ + KM_ULONG = 5 << 28, + KM_DATE = 6 << 28, + KM_BOOL = 7 << 28, + KM_BIGNUM = 8 << 28, + KM_BYTES = 9 << 28, + KM_ULONG_REP = 10 << 28, /* Repeatable long value */ +} keymaster_tag_type_t; + +typedef enum { + KM_TAG_INVALID = KM_INVALID | 0, + + /* + * Tags that must be semantically enforced by hardware and software implementations. + */ + + /* Crypto parameters */ + KM_TAG_PURPOSE = KM_ENUM_REP | 1, /* keymaster_purpose_t. */ + KM_TAG_ALGORITHM = KM_ENUM | 2, /* keymaster_algorithm_t. */ + KM_TAG_KEY_SIZE = KM_UINT | 3, /* Key size in bits. */ + KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4, /* keymaster_block_mode_t. */ + KM_TAG_DIGEST = KM_ENUM_REP | 5, /* keymaster_digest_t. */ + KM_TAG_PADDING = KM_ENUM_REP | 6, /* keymaster_padding_t. */ + KM_TAG_CALLER_NONCE = KM_BOOL | 7, /* Allow caller to specify nonce or IV. */ + KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8, /* Minimum length of MAC or AEAD authentication tag in + * bits. */ + KM_TAG_KDF = KM_ENUM_REP | 9, /* keymaster_kdf_t (keymaster2) */ + KM_TAG_EC_CURVE = KM_ENUM | 10, /* keymaster_ec_curve_t (keymaster2) */ + + /* Algorithm-specific. */ + KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200, + KM_TAG_ECIES_SINGLE_HASH_MODE = KM_BOOL | 201, /* Whether the ephemeral public key is fed into + * the KDF */ + KM_TAG_INCLUDE_UNIQUE_ID = KM_BOOL | 202, /* If true, attestation certificates for this key + * will contain an application-scoped and + * time-bounded device-unique ID. (keymaster2) */ + + /* Other hardware-enforced. */ + KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 301, /* keymaster_key_blob_usage_requirements_t */ + KM_TAG_BOOTLOADER_ONLY = KM_BOOL | 302, /* Usable only by bootloader */ + + /* + * Tags that should be semantically enforced by hardware if possible and will otherwise be + * enforced by software (keystore). + */ + + /* Key validity period */ + KM_TAG_ACTIVE_DATETIME = KM_DATE | 400, /* Start of validity */ + KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401, /* Date when new "messages" should no + longer be created. */ + KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402, /* Date when existing "messages" should no + longer be trusted. */ + KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_UINT | 403, /* Minimum elapsed time between + cryptographic operations with the key. */ + KM_TAG_MAX_USES_PER_BOOT = KM_UINT | 404, /* Number of times the key can be used per + boot. */ + + /* User authentication */ + KM_TAG_ALL_USERS = KM_BOOL | 500, /* Reserved for future use -- ignore */ + KM_TAG_USER_ID = KM_UINT | 501, /* Reserved for future use -- ignore */ + KM_TAG_USER_SECURE_ID = KM_ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s). + Disallowed if KM_TAG_ALL_USERS or + KM_TAG_NO_AUTH_REQUIRED is present. */ + KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503, /* If key is usable without authentication. */ + KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504, /* Bitmask of authenticator types allowed when + * KM_TAG_USER_SECURE_ID contains a secure user ID, + * rather than a secure authenticator ID. Defined in + * hw_authenticator_type_t in hw_auth_token.h. */ + KM_TAG_AUTH_TIMEOUT = KM_UINT | 505, /* Required freshness of user authentication for + private/secret key operations, in seconds. + Public key operations require no authentication. + If absent, authentication is required for every + use. Authentication state is lost when the + device is powered off. */ + KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506, /* Allow key to be used after authentication timeout + * if device is still on-body (requires secure + * on-body sensor. */ + + /* Application access control */ + KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600, /* Specified to indicate key is usable by all + * applications. */ + KM_TAG_APPLICATION_ID = KM_BYTES | 601, /* Byte string identifying the authorized + * application. */ + KM_TAG_EXPORTABLE = KM_BOOL | 602, /* If true, private/secret key can be exported, but + * only if all access control requirements for use are + * met. (keymaster2) */ + + /* + * Semantically unenforceable tags, either because they have no specific meaning or because + * they're informational only. + */ + KM_TAG_APPLICATION_DATA = KM_BYTES | 700, /* Data provided by authorized application. */ + KM_TAG_CREATION_DATETIME = KM_DATE | 701, /* Key creation time */ + KM_TAG_ORIGIN = KM_ENUM | 702, /* keymaster_key_origin_t. */ + KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703, /* Whether key is rollback-resistant. */ + KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704, /* Root of trust ID. */ + KM_TAG_OS_VERSION = KM_UINT | 705, /* Version of system (keymaster2) */ + KM_TAG_OS_PATCHLEVEL = KM_UINT | 706, /* Patch level of system (keymaster2) */ + KM_TAG_UNIQUE_ID = KM_BYTES | 707, /* Used to provide unique ID in attestation */ + + /* Tags used only to provide data to or receive data from operations */ + KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000, /* Used to provide associated data for AEAD modes. */ + KM_TAG_NONCE = KM_BYTES | 1001, /* Nonce or Initialization Vector */ + KM_TAG_AUTH_TOKEN = KM_BYTES | 1002, /* Authentication token that proves secure user + authentication has been performed. Structure + defined in hw_auth_token_t in hw_auth_token.h. */ + KM_TAG_MAC_LENGTH = KM_UINT | 1003, /* MAC or AEAD authentication tag length in + * bits. */ + + KM_TAG_RESET_SINCE_ID_ROTATION = KM_BOOL | 1004, /* Whether the device has beeen factory reset + since the last unique ID rotation. Used for + key attestation. */ +} keymaster_tag_t; + +/** + * Algorithms that may be provided by keymaster implementations. Those that must be provided by all + * implementations are tagged as "required". + */ +typedef enum { + /* Asymmetric algorithms. */ + KM_ALGORITHM_RSA = 1, + // KM_ALGORITHM_DSA = 2, -- Removed, do not re-use value 2. + KM_ALGORITHM_EC = 3, + + /* Block ciphers algorithms */ + KM_ALGORITHM_AES = 32, + + /* MAC algorithms */ + KM_ALGORITHM_HMAC = 128, +} keymaster_algorithm_t; + +/** + * Symmetric block cipher modes provided by keymaster implementations. + */ +typedef enum { + /* Unauthenticated modes, usable only for encryption/decryption and not generally recommended + * except for compatibility with existing other protocols. */ + KM_MODE_ECB = 1, + KM_MODE_CBC = 2, + KM_MODE_CTR = 3, + + /* Authenticated modes, usable for encryption/decryption and signing/verification. Recommended + * over unauthenticated modes for all purposes. */ + KM_MODE_GCM = 32, +} keymaster_block_mode_t; + +/** + * Padding modes that may be applied to plaintext for encryption operations. This list includes + * padding modes for both symmetric and asymmetric algorithms. Note that implementations should not + * provide all possible combinations of algorithm and padding, only the + * cryptographically-appropriate pairs. + */ +typedef enum { + KM_PAD_NONE = 1, /* deprecated */ + KM_PAD_RSA_OAEP = 2, + KM_PAD_RSA_PSS = 3, + KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4, + KM_PAD_RSA_PKCS1_1_5_SIGN = 5, + KM_PAD_PKCS7 = 64, +} keymaster_padding_t; + +/** + * Digests provided by keymaster implementations. + */ +typedef enum { + KM_DIGEST_NONE = 0, + KM_DIGEST_MD5 = 1, /* Optional, may not be implemented in hardware, will be handled in software + * if needed. */ + KM_DIGEST_SHA1 = 2, + KM_DIGEST_SHA_2_224 = 3, + KM_DIGEST_SHA_2_256 = 4, + KM_DIGEST_SHA_2_384 = 5, + KM_DIGEST_SHA_2_512 = 6, +} keymaster_digest_t; + +/* + * Key derivation functions, mostly used in ECIES. + */ +typedef enum { + /* Do not apply a key derivation function; use the raw agreed key */ + KM_KDF_NONE = 0, + /* HKDF defined in RFC 5869 with SHA256 */ + KM_KDF_RFC5869_SHA256 = 1, + /* KDF1 defined in ISO 18033-2 with SHA1 */ + KM_KDF_ISO18033_2_KDF1_SHA1 = 2, + /* KDF1 defined in ISO 18033-2 with SHA256 */ + KM_KDF_ISO18033_2_KDF1_SHA256 = 3, + /* KDF2 defined in ISO 18033-2 with SHA1 */ + KM_KDF_ISO18033_2_KDF2_SHA1 = 4, + /* KDF2 defined in ISO 18033-2 with SHA256 */ + KM_KDF_ISO18033_2_KDF2_SHA256 = 5, +} keymaster_kdf_t; + +/** + * Supported EC curves, used in ECDSA/ECIES. + */ +typedef enum { + KM_EC_CURVE_P_224 = 0, + KM_EC_CURVE_P_256 = 1, + KM_EC_CURVE_P_384 = 2, + KM_EC_CURVE_P_521 = 3, +} keymaster_ec_curve_t; + +/** + * The origin of a key (or pair), i.e. where it was generated. Note that KM_TAG_ORIGIN can be found + * in either the hardware-enforced or software-enforced list for a key, indicating whether the key + * is hardware or software-based. Specifically, a key with KM_ORIGIN_GENERATED in the + * hardware-enforced list is guaranteed never to have existed outide the secure hardware. + */ +typedef enum { + KM_ORIGIN_GENERATED = 0, /* Generated in keymaster. Should not exist outside the TEE. */ + KM_ORIGIN_DERIVED = 1, /* Derived inside keymaster. Likely exists off-device. */ + KM_ORIGIN_IMPORTED = 2, /* Imported into keymaster. Existed as cleartext in Android. */ + KM_ORIGIN_UNKNOWN = 3, /* Keymaster did not record origin. This value can only be seen on + * keys in a keymaster0 implementation. The keymaster0 adapter uses + * this value to document the fact that it is unkown whether the key + * was generated inside or imported into keymaster. */ +} keymaster_key_origin_t; + +/** + * Usability requirements of key blobs. This defines what system functionality must be available + * for the key to function. For example, key "blobs" which are actually handles referencing + * encrypted key material stored in the file system cannot be used until the file system is + * available, and should have BLOB_REQUIRES_FILE_SYSTEM. Other requirements entries will be added + * as needed for implementations. + */ +typedef enum { + KM_BLOB_STANDALONE = 0, + KM_BLOB_REQUIRES_FILE_SYSTEM = 1, +} keymaster_key_blob_usage_requirements_t; + +/** + * Possible purposes of a key (or pair). + */ +typedef enum { + KM_PURPOSE_ENCRYPT = 0, /* Usable with RSA, EC and AES keys. */ + KM_PURPOSE_DECRYPT = 1, /* Usable with RSA, EC and AES keys. */ + KM_PURPOSE_SIGN = 2, /* Usable with RSA, EC and HMAC keys. */ + KM_PURPOSE_VERIFY = 3, /* Usable with RSA, EC and HMAC keys. */ + KM_PURPOSE_DERIVE_KEY = 4, /* Usable with EC keys. */ +} keymaster_purpose_t; + +typedef struct { + const uint8_t* data; + size_t data_length; +} keymaster_blob_t; + +typedef struct { + keymaster_tag_t tag; + union { + uint32_t enumerated; /* KM_ENUM and KM_ENUM_REP */ + bool boolean; /* KM_BOOL */ + uint32_t integer; /* KM_INT and KM_INT_REP */ + uint64_t long_integer; /* KM_LONG */ + uint64_t date_time; /* KM_DATE */ + keymaster_blob_t blob; /* KM_BIGNUM and KM_BYTES*/ + }; +} keymaster_key_param_t; + +typedef struct { + keymaster_key_param_t* params; /* may be NULL if length == 0 */ + size_t length; +} keymaster_key_param_set_t; + +/** + * Parameters that define a key's characteristics, including authorized modes of usage and access + * control restrictions. The parameters are divided into two categories, those that are enforced by + * secure hardware, and those that are not. For a software-only keymaster implementation the + * enforced array must NULL. Hardware implementations must enforce everything in the enforced + * array. + */ +typedef struct { + keymaster_key_param_set_t hw_enforced; + keymaster_key_param_set_t sw_enforced; +} keymaster_key_characteristics_t; + +typedef struct { + const uint8_t* key_material; + size_t key_material_size; +} keymaster_key_blob_t; + +typedef struct { + keymaster_blob_t* entries; + size_t entry_count; +} keymaster_cert_chain_t; + +/** + * Formats for key import and export. + */ +typedef enum { + KM_KEY_FORMAT_X509 = 0, /* for public key export */ + KM_KEY_FORMAT_PKCS8 = 1, /* for asymmetric key pair import */ + KM_KEY_FORMAT_RAW = 3, /* for symmetric key import and export*/ +} keymaster_key_format_t; + +/** + * The keymaster operation API consists of begin, update, finish and abort. This is the type of the + * handle used to tie the sequence of calls together. A 64-bit value is used because it's important + * that handles not be predictable. Implementations must use strong random numbers for handle + * values. + */ +typedef uint64_t keymaster_operation_handle_t; + +typedef enum { + KM_ERROR_OK = 0, + KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1, + KM_ERROR_UNSUPPORTED_PURPOSE = -2, + KM_ERROR_INCOMPATIBLE_PURPOSE = -3, + KM_ERROR_UNSUPPORTED_ALGORITHM = -4, + KM_ERROR_INCOMPATIBLE_ALGORITHM = -5, + KM_ERROR_UNSUPPORTED_KEY_SIZE = -6, + KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7, + KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8, + KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9, + KM_ERROR_UNSUPPORTED_PADDING_MODE = -10, + KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11, + KM_ERROR_UNSUPPORTED_DIGEST = -12, + KM_ERROR_INCOMPATIBLE_DIGEST = -13, + KM_ERROR_INVALID_EXPIRATION_TIME = -14, + KM_ERROR_INVALID_USER_ID = -15, + KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT = -16, + KM_ERROR_UNSUPPORTED_KEY_FORMAT = -17, + KM_ERROR_INCOMPATIBLE_KEY_FORMAT = -18, + KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19, /* For PKCS8 & PKCS12 */ + KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20, /* For PKCS8 & PKCS12 */ + KM_ERROR_INVALID_INPUT_LENGTH = -21, + KM_ERROR_KEY_EXPORT_OPTIONS_INVALID = -22, + KM_ERROR_DELEGATION_NOT_ALLOWED = -23, + KM_ERROR_KEY_NOT_YET_VALID = -24, + KM_ERROR_KEY_EXPIRED = -25, + KM_ERROR_KEY_USER_NOT_AUTHENTICATED = -26, + KM_ERROR_OUTPUT_PARAMETER_NULL = -27, + KM_ERROR_INVALID_OPERATION_HANDLE = -28, + KM_ERROR_INSUFFICIENT_BUFFER_SPACE = -29, + KM_ERROR_VERIFICATION_FAILED = -30, + KM_ERROR_TOO_MANY_OPERATIONS = -31, + KM_ERROR_UNEXPECTED_NULL_POINTER = -32, + KM_ERROR_INVALID_KEY_BLOB = -33, + KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED = -34, + KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED = -35, + KM_ERROR_IMPORTED_KEY_NOT_SIGNED = -36, + KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED = -37, + KM_ERROR_INVALID_ARGUMENT = -38, + KM_ERROR_UNSUPPORTED_TAG = -39, + KM_ERROR_INVALID_TAG = -40, + KM_ERROR_MEMORY_ALLOCATION_FAILED = -41, + KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44, + KM_ERROR_SECURE_HW_ACCESS_DENIED = -45, + KM_ERROR_OPERATION_CANCELLED = -46, + KM_ERROR_CONCURRENT_ACCESS_CONFLICT = -47, + KM_ERROR_SECURE_HW_BUSY = -48, + KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49, + KM_ERROR_UNSUPPORTED_EC_FIELD = -50, + KM_ERROR_MISSING_NONCE = -51, + KM_ERROR_INVALID_NONCE = -52, + KM_ERROR_MISSING_MAC_LENGTH = -53, + KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54, + KM_ERROR_CALLER_NONCE_PROHIBITED = -55, + KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56, + KM_ERROR_INVALID_MAC_LENGTH = -57, + KM_ERROR_MISSING_MIN_MAC_LENGTH = -58, + KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59, + KM_ERROR_UNSUPPORTED_KDF = -60, + KM_ERROR_UNSUPPORTED_EC_CURVE = -61, + KM_ERROR_KEY_REQUIRES_UPGRADE = -62, + + KM_ERROR_UNIMPLEMENTED = -100, + KM_ERROR_VERSION_MISMATCH = -101, + + KM_ERROR_UNKNOWN_ERROR = -1000, +} keymaster_error_t; + +/* Convenience functions for manipulating keymaster tag types */ + +static inline keymaster_tag_type_t keymaster_tag_get_type(keymaster_tag_t tag) { + return (keymaster_tag_type_t)(tag & (0xF << 28)); +} + +static inline uint32_t keymaster_tag_mask_type(keymaster_tag_t tag) { + return tag & 0x0FFFFFFF; +} + +static inline bool keymaster_tag_type_repeatable(keymaster_tag_type_t type) { + switch (type) { + case KM_UINT_REP: + case KM_ENUM_REP: + return true; + default: + return false; + } +} + +static inline bool keymaster_tag_repeatable(keymaster_tag_t tag) { + return keymaster_tag_type_repeatable(keymaster_tag_get_type(tag)); +} + +/* Convenience functions for manipulating keymaster_key_param_t structs */ + +inline keymaster_key_param_t keymaster_param_enum(keymaster_tag_t tag, uint32_t value) { + // assert(keymaster_tag_get_type(tag) == KM_ENUM || keymaster_tag_get_type(tag) == KM_ENUM_REP); + keymaster_key_param_t param; + memset(¶m, 0, sizeof(param)); + param.tag = tag; + param.enumerated = value; + return param; +} + +inline keymaster_key_param_t keymaster_param_int(keymaster_tag_t tag, uint32_t value) { + // assert(keymaster_tag_get_type(tag) == KM_INT || keymaster_tag_get_type(tag) == KM_INT_REP); + keymaster_key_param_t param; + memset(¶m, 0, sizeof(param)); + param.tag = tag; + param.integer = value; + return param; +} + +inline keymaster_key_param_t keymaster_param_long(keymaster_tag_t tag, uint64_t value) { + // assert(keymaster_tag_get_type(tag) == KM_LONG); + keymaster_key_param_t param; + memset(¶m, 0, sizeof(param)); + param.tag = tag; + param.long_integer = value; + return param; +} + +inline keymaster_key_param_t keymaster_param_blob(keymaster_tag_t tag, const uint8_t* bytes, + size_t bytes_len) { + // assert(keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM); + keymaster_key_param_t param; + memset(¶m, 0, sizeof(param)); + param.tag = tag; + param.blob.data = (uint8_t*)bytes; + param.blob.data_length = bytes_len; + return param; +} + +inline keymaster_key_param_t keymaster_param_bool(keymaster_tag_t tag) { + // assert(keymaster_tag_get_type(tag) == KM_BOOL); + keymaster_key_param_t param; + memset(¶m, 0, sizeof(param)); + param.tag = tag; + param.boolean = true; + return param; +} + +inline keymaster_key_param_t keymaster_param_date(keymaster_tag_t tag, uint64_t value) { + // assert(keymaster_tag_get_type(tag) == KM_DATE); + keymaster_key_param_t param; + memset(¶m, 0, sizeof(param)); + param.tag = tag; + param.date_time = value; + return param; +} + +#define KEYMASTER_SIMPLE_COMPARE(a, b) (a < b) ? -1 : ((a > b) ? 1 : 0) +inline int keymaster_param_compare(const keymaster_key_param_t* a, const keymaster_key_param_t* b) { + int retval = KEYMASTER_SIMPLE_COMPARE(a->tag, b->tag); + if (retval != 0) + return retval; + + switch (keymaster_tag_get_type(a->tag)) { + case KM_INVALID: + case KM_BOOL: + return 0; + case KM_ENUM: + case KM_ENUM_REP: + return KEYMASTER_SIMPLE_COMPARE(a->enumerated, b->enumerated); + case KM_UINT: + case KM_UINT_REP: + return KEYMASTER_SIMPLE_COMPARE(a->integer, b->integer); + case KM_ULONG: + case KM_ULONG_REP: + return KEYMASTER_SIMPLE_COMPARE(a->long_integer, b->long_integer); + case KM_DATE: + return KEYMASTER_SIMPLE_COMPARE(a->date_time, b->date_time); + case KM_BIGNUM: + case KM_BYTES: + // Handle the empty cases. + if (a->blob.data_length != 0 && b->blob.data_length == 0) + return -1; + if (a->blob.data_length == 0 && b->blob.data_length == 0) + return 0; + if (a->blob.data_length == 0 && b->blob.data_length > 0) + return 1; + + retval = memcmp(a->blob.data, b->blob.data, a->blob.data_length < b->blob.data_length + ? a->blob.data_length + : b->blob.data_length); + if (retval != 0) + return retval; + else if (a->blob.data_length != b->blob.data_length) { + // Equal up to the common length; longer one is larger. + if (a->blob.data_length < b->blob.data_length) + return -1; + if (a->blob.data_length > b->blob.data_length) + return 1; + }; + } + + return 0; +} +#undef KEYMASTER_SIMPLE_COMPARE + +inline void keymaster_free_param_values(keymaster_key_param_t* param, size_t param_count) { + while (param_count-- > 0) { + switch (keymaster_tag_get_type(param->tag)) { + case KM_BIGNUM: + case KM_BYTES: + free((void*)param->blob.data); + param->blob.data = NULL; + break; + default: + // NOP + break; + } + ++param; + } +} + +inline void keymaster_free_param_set(keymaster_key_param_set_t* set) { + if (set) { + keymaster_free_param_values(set->params, set->length); + free(set->params); + set->params = NULL; + } +} + +inline void keymaster_free_characteristics(keymaster_key_characteristics_t* characteristics) { + if (characteristics) { + keymaster_free_param_set(&characteristics->hw_enforced); + keymaster_free_param_set(&characteristics->sw_enforced); + } +} + +inline void keymaster_free_cert_chain(keymaster_cert_chain_t* chain) { + if (chain) { + for (size_t i = 0; i < chain->entry_count; ++i) { + free((uint8_t*)chain->entries[i].data); + chain->entries[i].data = NULL; + chain->entries[i].data_length = 0; + } + free(chain->entries); + chain->entries = NULL; + chain->entry_count = 0; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // ANDROID_HARDWARE_KEYMASTER_DEFS_H
diff --git a/libhardware/include/hardware/lights.h b/libhardware/include/hardware/lights.h new file mode 100644 index 0000000..2cf5519 --- /dev/null +++ b/libhardware/include/hardware/lights.h
@@ -0,0 +1,137 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_LIGHTS_INTERFACE_H +#define ANDROID_LIGHTS_INTERFACE_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define LIGHTS_HARDWARE_MODULE_ID "lights" + +/* + * These light IDs correspond to logical lights, not physical. + * So for example, if your INDICATOR light is in line with your + * BUTTONS, it might make sense to also light the INDICATOR + * light to a reasonable color when the BUTTONS are lit. + */ +#define LIGHT_ID_BACKLIGHT "backlight" +#define LIGHT_ID_KEYBOARD "keyboard" +#define LIGHT_ID_BUTTONS "buttons" +#define LIGHT_ID_BATTERY "battery" +#define LIGHT_ID_NOTIFICATIONS "notifications" +#define LIGHT_ID_ATTENTION "attention" + +/* + * These lights aren't currently supported by the higher + * layers, but could be someday, so we have the constants + * here now. + */ +#define LIGHT_ID_BLUETOOTH "bluetooth" +#define LIGHT_ID_WIFI "wifi" + +/* ************************************************************************ + * Flash modes for the flashMode field of light_state_t. + */ + +#define LIGHT_FLASH_NONE 0 + +/** + * To flash the light at a given rate, set flashMode to LIGHT_FLASH_TIMED, + * and then flashOnMS should be set to the number of milliseconds to turn + * the light on, followed by the number of milliseconds to turn the light + * off. + */ +#define LIGHT_FLASH_TIMED 1 + +/** + * To flash the light using hardware assist, set flashMode to + * the hardware mode. + */ +#define LIGHT_FLASH_HARDWARE 2 + +/** + * Light brightness is managed by a user setting. + */ +#define BRIGHTNESS_MODE_USER 0 + +/** + * Light brightness is managed by a light sensor. + */ +#define BRIGHTNESS_MODE_SENSOR 1 + +/** + * The parameters that can be set for a given light. + * + * Not all lights must support all parameters. If you + * can do something backward-compatible, you should. + */ +struct light_state_t { + /** + * The color of the LED in ARGB. + * + * Do your best here. + * - If your light can only do red or green, if they ask for blue, + * you should do green. + * - If you can only do a brightness ramp, then use this formula: + * unsigned char brightness = ((77*((color>>16)&0x00ff)) + * + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; + * - If you can only do on or off, 0 is off, anything else is on. + * + * The high byte should be ignored. Callers will set it to 0xff (which + * would correspond to 255 alpha). + */ + unsigned int color; + + /** + * See the LIGHT_FLASH_* constants + */ + int flashMode; + int flashOnMS; + int flashOffMS; + + /** + * Policy used by the framework to manage the light's brightness. + * Currently the values are BRIGHTNESS_MODE_USER and BRIGHTNESS_MODE_SENSOR. + */ + int brightnessMode; +}; + +struct light_device_t { + struct hw_device_t common; + + /** + * Set the provided lights to the provided values. + * + * Returns: 0 on succes, error code on failure. + */ + int (*set_light)(struct light_device_t* dev, + struct light_state_t const* state); +}; + + +__END_DECLS + +#endif // ANDROID_LIGHTS_INTERFACE_H +
diff --git a/libhardware/include/hardware/local_time_hal.h b/libhardware/include/hardware/local_time_hal.h new file mode 100644 index 0000000..946e799 --- /dev/null +++ b/libhardware/include/hardware/local_time_hal.h
@@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef ANDROID_LOCAL_TIME_HAL_INTERFACE_H +#define ANDROID_LOCAL_TIME_HAL_INTERFACE_H + +#include <stdint.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define LOCAL_TIME_HARDWARE_MODULE_ID "local_time" + +/** + * Name of the local time devices to open + */ +#define LOCAL_TIME_HARDWARE_INTERFACE "local_time_hw_if" + +/**********************************************************************/ + +/** + * A structure used to collect low level sync data in a lab environment. Most + * HAL implementations will never need this structure. + */ +struct local_time_debug_event { + int64_t local_timesync_event_id; + int64_t local_time; +}; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct local_time_module { + struct hw_module_t common; +}; + +struct local_time_hw_device { + /** + * Common methods of the local time hardware device. This *must* be the first member of + * local_time_hw_device as users of this structure will cast a hw_device_t to + * local_time_hw_device pointer in contexts where it's known the hw_device_t references a + * local_time_hw_device. + */ + struct hw_device_t common; + + /** + * + * Returns the current value of the system wide local time counter + */ + int64_t (*get_local_time)(struct local_time_hw_device* dev); + + /** + * + * Returns the nominal frequency (in hertz) of the system wide local time + * counter + */ + uint64_t (*get_local_freq)(struct local_time_hw_device* dev); + + /** + * + * Sets the HW slew rate of oscillator which drives the system wide local + * time counter. On success, platforms should return 0. Platforms which + * do not support HW slew should leave this method set to NULL. + * + * Valid values for rate range from MIN_INT16 to MAX_INT16. Platform + * implementations should attempt map this range linearly to the min/max + * slew rate of their hardware. + */ + int (*set_local_slew)(struct local_time_hw_device* dev, int16_t rate); + + /** + * + * A method used to collect low level sync data in a lab environments. + * Most HAL implementations will simply set this member to NULL, or return + * -EINVAL to indicate that this functionality is not supported. + * Production HALs should never support this method. + */ + int (*get_debug_log)(struct local_time_hw_device* dev, + struct local_time_debug_event* records, + int max_records); +}; + +typedef struct local_time_hw_device local_time_hw_device_t; + +/** convenience API for opening and closing a supported device */ + +static inline int local_time_hw_device_open( + const struct hw_module_t* module, + struct local_time_hw_device** device) +{ + return module->methods->open(module, LOCAL_TIME_HARDWARE_INTERFACE, + (struct hw_device_t**)device); +} + +static inline int local_time_hw_device_close(struct local_time_hw_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_LOCAL_TIME_INTERFACE_H
diff --git a/libhardware/include/hardware/memtrack.h b/libhardware/include/hardware/memtrack.h new file mode 100644 index 0000000..57ba4ad --- /dev/null +++ b/libhardware/include/hardware/memtrack.h
@@ -0,0 +1,160 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_MEMTRACK_H +#define ANDROID_INCLUDE_HARDWARE_MEMTRACK_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define MEMTRACK_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +/** + * The id of this module + */ +#define MEMTRACK_HARDWARE_MODULE_ID "memtrack" + +/* + * The Memory Tracker HAL is designed to return information about device-specific + * memory usage. The primary goal is to be able to track memory that is not + * trackable in any other way, for example texture memory that is allocated by + * a process, but not mapped in to that process' address space. + * A secondary goal is to be able to categorize memory used by a process into + * GL, graphics, etc. All memory sizes should be in real memory usage, + * accounting for stride, bit depth, rounding up to page size, etc. + * + * A process collecting memory statistics will call getMemory for each + * combination of pid and memory type. For each memory type that it recognizes + * the HAL should fill out an array of memtrack_record structures breaking + * down the statistics of that memory type as much as possible. For example, + * getMemory(<pid>, MEMTRACK_TYPE_GL) might return: + * { { 4096, ACCOUNTED | PRIVATE | SYSTEM }, + * { 40960, UNACCOUNTED | PRIVATE | SYSTEM }, + * { 8192, ACCOUNTED | PRIVATE | DEDICATED }, + * { 8192, UNACCOUNTED | PRIVATE | DEDICATED } } + * If the HAL could not differentiate between SYSTEM and DEDICATED memory, it + * could return: + * { { 12288, ACCOUNTED | PRIVATE }, + * { 49152, UNACCOUNTED | PRIVATE } } + * + * Memory should not overlap between types. For example, a graphics buffer + * that has been mapped into the GPU as a surface should show up when + * MEMTRACK_TYPE_GRAPHICS is requested, and not when MEMTRACK_TYPE_GL + * is requested. + */ + +enum memtrack_type { + MEMTRACK_TYPE_OTHER = 0, + MEMTRACK_TYPE_GL = 1, + MEMTRACK_TYPE_GRAPHICS = 2, + MEMTRACK_TYPE_MULTIMEDIA = 3, + MEMTRACK_TYPE_CAMERA = 4, + MEMTRACK_NUM_TYPES, +}; + +struct memtrack_record { + size_t size_in_bytes; + unsigned int flags; +}; + +/** + * Flags to differentiate memory that can already be accounted for in + * /proc/<pid>/smaps, + * (Shared_Clean + Shared_Dirty + Private_Clean + Private_Dirty = Size). + * In general, memory mapped in to a userspace process is accounted unless + * it was mapped with remap_pfn_range. + * Exactly one of these should be set. + */ +#define MEMTRACK_FLAG_SMAPS_ACCOUNTED (1 << 1) +#define MEMTRACK_FLAG_SMAPS_UNACCOUNTED (1 << 2) + +/** + * Flags to differentiate memory shared across multiple processes vs. memory + * used by a single process. Only zero or one of these may be set in a record. + * If none are set, record is assumed to count shared + private memory. + */ +#define MEMTRACK_FLAG_SHARED (1 << 3) +#define MEMTRACK_FLAG_SHARED_PSS (1 << 4) /* shared / num_procesess */ +#define MEMTRACK_FLAG_PRIVATE (1 << 5) + +/** + * Flags to differentiate memory taken from the kernel's allocation pool vs. + * memory that is dedicated to non-kernel allocations, for example a carveout + * or separate video memory. Only zero or one of these may be set in a record. + * If none are set, record is assumed to count system + dedicated memory. + */ +#define MEMTRACK_FLAG_SYSTEM (1 << 6) +#define MEMTRACK_FLAG_DEDICATED (1 << 7) + +/** + * Flags to differentiate memory accessible by the CPU in non-secure mode vs. + * memory that is protected. Only zero or one of these may be set in a record. + * If none are set, record is assumed to count secure + nonsecure memory. + */ +#define MEMTRACK_FLAG_NONSECURE (1 << 8) +#define MEMTRACK_FLAG_SECURE (1 << 9) + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct memtrack_module { + struct hw_module_t common; + + /** + * (*init)() performs memtrack management setup actions and is called + * once before any calls to getMemory(). + * Returns 0 on success, -errno on error. + */ + int (*init)(const struct memtrack_module *module); + + /** + * (*getMemory)() expects an array of record objects and populates up to + * *num_record structures with the sizes of memory plus associated flags for + * that memory. It also updates *num_records with the total number of + * records it could return if *num_records was large enough when passed in. + * Returning records with size 0 is expected, the number of records should + * not vary between calls to getMemory for the same memory type, even + * for different pids. + * + * The caller will often call getMemory for a type and pid with + * *num_records == 0 to determine how many records to allocate room for, + * this case should be a fast-path in the HAL, returning a constant and + * not querying any kernel files. If *num_records passed in is 0, + * then records may be NULL. + * + * This function must be thread-safe, it may get called from multiple + * threads at the same time. + * + * Returns 0 on success, -ENODEV if the type is not supported, -errno + * on other errors. + */ + int (*getMemory)(const struct memtrack_module *module, + pid_t pid, + int type, + struct memtrack_record *records, + size_t *num_records); +} memtrack_module_t; + +__END_DECLS + +#endif // ANDROID_INCLUDE_HARDWARE_MEMTRACK_H
diff --git a/libhardware/include/hardware/nfc.h b/libhardware/include/hardware/nfc.h new file mode 100644 index 0000000..58d33d9 --- /dev/null +++ b/libhardware/include/hardware/nfc.h
@@ -0,0 +1,301 @@ +/* + * Copyright (C) 2011, 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_NFC_HAL_INTERFACE_H +#define ANDROID_NFC_HAL_INTERFACE_H + +#include <stdint.h> +#include <strings.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + + +/* NFC device HAL for NCI-based NFC controllers. + * + * This HAL allows NCI silicon vendors to make use + * of the core NCI stack in Android for their own silicon. + * + * The responibilities of the NCI HAL implementation + * are as follows: + * + * - Implement the transport to the NFC controller + * - Implement each of the HAL methods specified below as applicable to their silicon + * - Pass up received NCI messages from the controller to the stack + * + * A simplified timeline of NCI HAL method calls: + * 1) Core NCI stack calls open() + * 2) Core NCI stack executes CORE_RESET and CORE_INIT through calls to write() + * 3) Core NCI stack calls core_initialized() to allow HAL to do post-init configuration + * 4) Core NCI stack calls pre_discover() to allow HAL to prepare for RF discovery + * 5) Core NCI stack starts discovery through calls to write() + * 6) Core NCI stack stops discovery through calls to write() (e.g. screen turns off) + * 7) Core NCI stack calls pre_discover() to prepare for RF discovery (e.g. screen turned back on) + * 8) Core NCI stack starts discovery through calls to write() + * ... + * ... + * 9) Core NCI stack calls close() + */ +#define NFC_NCI_HARDWARE_MODULE_ID "nfc_nci" +#define NFC_NCI_BCM2079X_HARDWARE_MODULE_ID "nfc_nci.bcm2079x" +#define NFC_NCI_CONTROLLER "nci" + +/* + * nfc_nci_module_t should contain module-specific parameters + */ +typedef struct nfc_nci_module_t { + /** + * Common methods of the NFC NCI module. This *must* be the first member of + * nfc_nci_module_t as users of this structure will cast a hw_module_t to + * nfc_nci_module_t pointer in contexts where it's known the hw_module_t references a + * nfc_nci_module_t. + */ + struct hw_module_t common; +} nfc_nci_module_t; + +/* + * HAL events that can be passed back to the stack + */ +typedef uint8_t nfc_event_t; + +enum { + HAL_NFC_OPEN_CPLT_EVT = 0x00, + HAL_NFC_CLOSE_CPLT_EVT = 0x01, + HAL_NFC_POST_INIT_CPLT_EVT = 0x02, + HAL_NFC_PRE_DISCOVER_CPLT_EVT = 0x03, + HAL_NFC_REQUEST_CONTROL_EVT = 0x04, + HAL_NFC_RELEASE_CONTROL_EVT = 0x05, + HAL_NFC_ERROR_EVT = 0x06 +}; + +/* + * Allowed status return values for each of the HAL methods + */ +typedef uint8_t nfc_status_t; + +enum { + HAL_NFC_STATUS_OK = 0x00, + HAL_NFC_STATUS_FAILED = 0x01, + HAL_NFC_STATUS_ERR_TRANSPORT = 0x02, + HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 0x03, + HAL_NFC_STATUS_REFUSED = 0x04 +}; + +/* + * The callback passed in from the NFC stack that the HAL + * can use to pass events back to the stack. + */ +typedef void (nfc_stack_callback_t) (nfc_event_t event, nfc_status_t event_status); + +/* + * The callback passed in from the NFC stack that the HAL + * can use to pass incomming data to the stack. + */ +typedef void (nfc_stack_data_callback_t) (uint16_t data_len, uint8_t* p_data); + +/* nfc_nci_device_t starts with a hw_device_t struct, + * followed by device-specific methods and members. + * + * All methods in the NCI HAL are asynchronous. + */ +typedef struct nfc_nci_device { + /** + * Common methods of the NFC NCI device. This *must* be the first member of + * nfc_nci_device_t as users of this structure will cast a hw_device_t to + * nfc_nci_device_t pointer in contexts where it's known the hw_device_t references a + * nfc_nci_device_t. + */ + struct hw_device_t common; + /* + * (*open)() Opens the NFC controller device and performs initialization. + * This may include patch download and other vendor-specific initialization. + * + * If open completes successfully, the controller should be ready to perform + * NCI initialization - ie accept CORE_RESET and subsequent commands through + * the write() call. + * + * If open() returns 0, the NCI stack will wait for a HAL_NFC_OPEN_CPLT_EVT + * before continuing. + * + * If open() returns any other value, the NCI stack will stop. + * + */ + int (*open)(const struct nfc_nci_device *p_dev, nfc_stack_callback_t *p_cback, + nfc_stack_data_callback_t *p_data_cback); + + /* + * (*write)() Performs an NCI write. + * + * This method may queue writes and return immediately. The only + * requirement is that the writes are executed in order. + */ + int (*write)(const struct nfc_nci_device *p_dev, uint16_t data_len, const uint8_t *p_data); + + /* + * (*core_initialized)() is called after the CORE_INIT_RSP is received from the NFCC. + * At this time, the HAL can do any chip-specific configuration. + * + * If core_initialized() returns 0, the NCI stack will wait for a HAL_NFC_POST_INIT_CPLT_EVT + * before continuing. + * + * If core_initialized() returns any other value, the NCI stack will continue + * immediately. + */ + int (*core_initialized)(const struct nfc_nci_device *p_dev, uint8_t* p_core_init_rsp_params); + + /* + * (*pre_discover)() Is called every time before starting RF discovery. + * It is a good place to do vendor-specific configuration that must be + * performed every time RF discovery is about to be started. + * + * If pre_discover() returns 0, the NCI stack will wait for a HAL_NFC_PRE_DISCOVER_CPLT_EVT + * before continuing. + * + * If pre_discover() returns any other value, the NCI stack will start + * RF discovery immediately. + */ + int (*pre_discover)(const struct nfc_nci_device *p_dev); + + /* + * (*close)() Closed the NFC controller. Should free all resources. + */ + int (*close)(const struct nfc_nci_device *p_dev); + + /* + * (*control_granted)() Grant HAL the exclusive control to send NCI commands. + * Called in response to HAL_REQUEST_CONTROL_EVT. + * Must only be called when there are no NCI commands pending. + * HAL_RELEASE_CONTROL_EVT will notify when HAL no longer needs exclusive control. + */ + int (*control_granted)(const struct nfc_nci_device *p_dev); + + /* + * (*power_cycle)() Restart controller by power cyle; + * HAL_OPEN_CPLT_EVT will notify when operation is complete. + */ + int (*power_cycle)(const struct nfc_nci_device *p_dev); +} nfc_nci_device_t; + +/* + * Convenience methods that the NFC stack can use to open + * and close an NCI device + */ +static inline int nfc_nci_open(const struct hw_module_t* module, + nfc_nci_device_t** dev) { + return module->methods->open(module, NFC_NCI_CONTROLLER, + (struct hw_device_t**) dev); +} + +static inline int nfc_nci_close(nfc_nci_device_t* dev) { + return dev->common.close(&dev->common); +} +/* + * End NFC NCI HAL + */ + +/* + * This is a limited NFC HAL for NXP PN544-based devices. + * This HAL as Android is moving to + * an NCI-based NFC stack. + * + * All NCI-based NFC controllers should use the NFC-NCI + * HAL instead. + * Begin PN544 specific HAL + */ +#define NFC_HARDWARE_MODULE_ID "nfc" + +#define NFC_PN544_CONTROLLER "pn544" + +typedef struct nfc_module_t { + /** + * Common methods of the NFC NXP PN544 module. This *must* be the first member of + * nfc_module_t as users of this structure will cast a hw_module_t to + * nfc_module_t pointer in contexts where it's known the hw_module_t references a + * nfc_module_t. + */ + struct hw_module_t common; +} nfc_module_t; + +/* + * PN544 linktypes. + * UART + * I2C + * USB (uses UART DAL) + */ +typedef enum { + PN544_LINK_TYPE_UART, + PN544_LINK_TYPE_I2C, + PN544_LINK_TYPE_USB, + PN544_LINK_TYPE_INVALID, +} nfc_pn544_linktype; + +typedef struct { + /** + * Common methods of the NFC NXP PN544 device. This *must* be the first member of + * nfc_pn544_device_t as users of this structure will cast a hw_device_t to + * nfc_pn544_device_t pointer in contexts where it's known the hw_device_t references a + * nfc_pn544_device_t. + */ + struct hw_device_t common; + + /* The number of EEPROM registers to write */ + uint32_t num_eeprom_settings; + + /* The actual EEPROM settings + * For PN544, each EEPROM setting is a 4-byte entry, + * of the format [0x00, addr_msb, addr_lsb, value]. + */ + uint8_t* eeprom_settings; + + /* The link type to which the PN544 is connected */ + nfc_pn544_linktype linktype; + + /* The device node to which the PN544 is connected */ + const char* device_node; + + /* On Crespo we had an I2C issue that would cause us to sometimes read + * the I2C slave address (0x57) over the bus. libnfc contains + * a hack to ignore this byte and try to read the length byte + * again. + * Set to 0 to disable the workaround, 1 to enable it. + */ + uint8_t enable_i2c_workaround; + /* I2C slave address. Multiple I2C addresses are + * possible for PN544 module. Configure address according to + * board design. + */ + uint8_t i2c_device_address; +} nfc_pn544_device_t; + +static inline int nfc_pn544_open(const struct hw_module_t* module, + nfc_pn544_device_t** dev) { + return module->methods->open(module, NFC_PN544_CONTROLLER, + (struct hw_device_t**) dev); +} + +static inline int nfc_pn544_close(nfc_pn544_device_t* dev) { + return dev->common.close(&dev->common); +} +/* + * End PN544 specific HAL + */ + +__END_DECLS + +#endif // ANDROID_NFC_HAL_INTERFACE_H
diff --git a/libhardware/include/hardware/nfc_tag.h b/libhardware/include/hardware/nfc_tag.h new file mode 100644 index 0000000..040a07d --- /dev/null +++ b/libhardware/include/hardware/nfc_tag.h
@@ -0,0 +1,95 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_NFC_TAG_HAL_INTERFACE_H +#define ANDROID_NFC_TAG_HAL_INTERFACE_H + +#include <stdint.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +/* + * HAL for programmable NFC tags. + * + */ + +#define NFC_TAG_HARDWARE_MODULE_ID "nfc_tag" +#define NFC_TAG_ID "tag" + +typedef struct nfc_tag_module_t { + /** + * Common methods of the NFC tag module. This *must* be the first member of + * nfc_tag_module_t as users of this structure will cast a hw_module_t to + * nfc_tag_module_t pointer in contexts where it's known the hw_module_t references a + * nfc_tag_module_t. + */ + struct hw_module_t common; +} nfc_tag_module_t; + +typedef struct nfc_tag_device { + /** + * Common methods of the NFC tag device. This *must* be the first member of + * nfc_tag_device_t as users of this structure will cast a hw_device_t to + * nfc_tag_device_t pointer in contexts where it's known the hw_device_t references a + * nfc_tag_device_t. + */ + struct hw_device_t common; + + /** + * Initialize the NFC tag. + * + * The driver must: + * * Set the static lock bytes to read only + * * Configure the Capability Container to disable write acess + * eg: 0xE1 0x10 <size> 0x0F + * + * This function is called once before any calls to setContent(). + * + * Return 0 on success or -errno on error. + */ + int (*init)(const struct nfc_tag_device *dev); + + /** + * Set the NFC tag content. + * + * The driver must write <data> in the data area of the tag starting at + * byte 0 of block 4 and zero the rest of the data area. + * + * Returns 0 on success or -errno on error. + */ + int (*setContent)(const struct nfc_tag_device *dev, const uint8_t *data, size_t len); + + /** + * Returns the memory size of the data area. + */ + int (*getMemorySize)(const struct nfc_tag_device *dev); +} nfc_tag_device_t; + +static inline int nfc_tag_open(const struct hw_module_t* module, + nfc_tag_device_t** dev) { + return module->methods->open(module, NFC_TAG_ID, + (struct hw_device_t**)dev); +} + +static inline int nfc_tag_close(nfc_tag_device_t* dev) { + return dev->common.close(&dev->common); +} + +__END_DECLS + +#endif // ANDROID_NFC_TAG_HAL_INTERFACE_H
diff --git a/libhardware/include/hardware/nvram.h b/libhardware/include/hardware/nvram.h new file mode 100644 index 0000000..859ea47 --- /dev/null +++ b/libhardware/include/hardware/nvram.h
@@ -0,0 +1,338 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_NVRAM_H +#define ANDROID_HARDWARE_NVRAM_H + +#include <stdint.h> +#include <sys/cdefs.h> + +#include <hardware/hardware.h> +#include <hardware/nvram_defs.h> + +__BEGIN_DECLS + +/* The id of this module. */ +#define NVRAM_HARDWARE_MODULE_ID "nvram" +#define NVRAM_HARDWARE_DEVICE_ID "nvram-dev" + +/* The version of this module. */ +#define NVRAM_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define NVRAM_DEVICE_API_VERSION_1_1 HARDWARE_DEVICE_API_VERSION(1, 1) + +struct nvram_module { + /** + * Common methods of the nvram_module. This *must* be the first member of + * nvram_module as users of this structure will cast a hw_module_t to + * nvram_module pointer in contexts where it's known the hw_module_t + * references a nvram_module. + */ + hw_module_t common; + + /* There are no module methods other than the common ones. */ +}; + +struct nvram_device { + /** + * Common methods of the nvram_device. This *must* be the first member of + * nvram_device as users of this structure will cast a hw_device_t to + * nvram_device pointer in contexts where it's known the hw_device_t + * references a nvram_device. + */ + struct hw_device_t common; + + /** + * Outputs the total number of bytes available in NVRAM. This will + * always be at least 2048. If an implementation does not know the + * total size it may provide an estimate or 2048. + * + * device - The nvram_device instance. + * total_size - Receives the output. Cannot be NULL. + */ + nvram_result_t (*get_total_size_in_bytes)(const struct nvram_device* device, + uint64_t* total_size); + + /** + * Outputs the unallocated number of bytes available in NVRAM. If an + * implementation does not know the available size it may provide an + * estimate or the total size. + * + * device - The nvram_device instance. + * available_size - Receives the output. Cannot be NULL. + */ + nvram_result_t (*get_available_size_in_bytes)( + const struct nvram_device* device, uint64_t* available_size); + + /** + * Outputs the maximum number of bytes that can be allocated for a single + * space. This will always be at least 32. If an implementation does not + * limit the maximum size it may provide the total size. + * + * device - The nvram_device instance. + * max_space_size - Receives the output. Cannot be NULL. + */ + nvram_result_t (*get_max_space_size_in_bytes)( + const struct nvram_device* device, uint64_t* max_space_size); + + /** + * Outputs the maximum total number of spaces that may be allocated. + * This will always be at least 8. Outputs NV_UNLIMITED_SPACES if any + * number of spaces are supported (limited only to available NVRAM + * bytes). + * + * device - The nvram_device instance. + * num_spaces - Receives the output. Cannot be NULL. + */ + nvram_result_t (*get_max_spaces)(const struct nvram_device* device, + uint32_t* num_spaces); + + /** + * Outputs a list of created space indices. If |max_list_size| is + * 0, only |list_size| is populated. + * + * device - The nvram_device instance. + * max_list_size - The number of items in the |space_index_list| + * array. + * space_index_list - Receives the list of created spaces up to the + * given |max_list_size|. May be NULL if + * |max_list_size| is 0. + * list_size - Receives the number of items populated in + * |space_index_list|, or the number of items available + * if |space_index_list| is NULL. + */ + nvram_result_t (*get_space_list)(const struct nvram_device* device, + uint32_t max_list_size, + uint32_t* space_index_list, + uint32_t* list_size); + + /** + * Outputs the size, in bytes, of a given space. + * + * device - The nvram_device instance. + * index - The space index. + * size - Receives the output. Cannot be NULL. + */ + nvram_result_t (*get_space_size)(const struct nvram_device* device, + uint32_t index, uint64_t* size); + + /** + * Outputs the list of controls associated with a given space. + * + * device - The nvram_device instance. + * index - The space index. + * max_list_size - The number of items in the |control_list| array. + * control_list - Receives the list of controls up to the given + * |max_list_size|. May be NULL if |max_list_size| + * is 0. + * list_size - Receives the number of items populated in + * |control_list|, or the number of items available if + * |control_list| is NULL. + */ + nvram_result_t (*get_space_controls)(const struct nvram_device* device, + uint32_t index, uint32_t max_list_size, + nvram_control_t* control_list, + uint32_t* list_size); + + /** + * Outputs whether locks are enabled for the given space. When a lock + * is enabled, the operation is disabled and any attempt to perform that + * operation will result in NV_RESULT_OPERATION_DISABLED. + * + * device - The nvram_device instance. + * index - The space index. + * write_lock_enabled - Will be set to non-zero iff write + * operations are currently disabled. + * read_lock_enabled - Will be set to non-zero iff read operations + * are currently disabled. + */ + nvram_result_t (*is_space_locked)(const struct nvram_device* device, + uint32_t index, int* write_lock_enabled, + int* read_lock_enabled); + + /** + * Creates a new space with the given index, size, controls, and + * authorization value. + * + * device - The nvram_device instance. + * index - An index for the new space. The index can be any 32-bit + * value but must not already be assigned to an existing + * space. + * size_in_bytes - The number of bytes to allocate for the space. + * control_list - An array of controls to enforce for the space. + * list_size - The number of items in |control_list|. + * authorization_value - If |control_list| contains + * NV_CONTROL_READ_AUTHORIZATION and / or + * NV_CONTROL_WRITE_AUTHORIZATION, then this + * parameter provides the authorization value + * for these policies (if both controls are + * set then this value applies to both). + * Otherwise, this value is ignored and may + * be NULL. + * authorization_value_size - The number of bytes in + * |authorization_value|. + */ + nvram_result_t (*create_space)(const struct nvram_device* device, + uint32_t index, uint64_t size_in_bytes, + const nvram_control_t* control_list, + uint32_t list_size, + const uint8_t* authorization_value, + uint32_t authorization_value_size); + + /** + * Deletes a space. + * + * device - The nvram_device instance. + * index - The space index. + * authorization_value - If the space has the + * NV_CONTROL_WRITE_AUTHORIZATION policy, + * then this parameter provides the + * authorization value. Otherwise, this value + * is ignored and may be NULL. + * authorization_value_size - The number of bytes in + * |authorization_value|. + */ + nvram_result_t (*delete_space)(const struct nvram_device* device, + uint32_t index, + const uint8_t* authorization_value, + uint32_t authorization_value_size); + + /** + * Disables any further creation of spaces until the next full device + * reset (as in factory reset, not reboot). Subsequent calls to + * NV_CreateSpace should return NV_RESULT_OPERATION_DISABLED. + * + * device - The nvram_device instance. + */ + nvram_result_t (*disable_create)(const struct nvram_device* device); + + /** + * Writes the contents of a space. If the space is configured with + * NV_CONTROL_WRITE_EXTEND then the input data is used to extend the + * current data. + * + * device - The nvram_device instance. + * index - The space index. + * buffer - The data to write. + * buffer_size - The number of bytes in |buffer|. If this is less + * than the size of the space, the remaining bytes + * will be set to 0x00. If this is more than the size + * of the space, returns NV_RESULT_INVALID_PARAMETER. + * authorization_value - If the space has the + * NV_CONTROL_WRITE_AUTHORIZATION policy, + * then this parameter provides the + * authorization value. Otherwise, this value + * is ignored and may be NULL. + * authorization_value_size - The number of bytes in + * |authorization_value|. + */ + nvram_result_t (*write_space)(const struct nvram_device* device, + uint32_t index, const uint8_t* buffer, + uint64_t buffer_size, + const uint8_t* authorization_value, + uint32_t authorization_value_size); + + /** + * Reads the contents of a space. If the space has never been + * written, all bytes read will be 0x00. + * + * device - The nvram_device instance. + * index - The space index. + * num_bytes_to_read - The number of bytes to read; |buffer| must + * be large enough to hold this many bytes. If + * this is more than the size of the space, the + * entire space is read. If this is less than + * the size of the space, the first bytes in + * the space are read. + * authorization_value - If the space has the + * NV_CONTROL_READ_AUTHORIZATION policy, then + * this parameter provides the authorization + * value. Otherwise, this value is ignored + * and may be NULL. + * authorization_value_size - The number of bytes in + * |authorization_value|. + * buffer - Receives the data read from the space. Must be at least + * |num_bytes_to_read| bytes in size. + * bytes_read - The number of bytes read. If NV_RESULT_SUCCESS is + * returned this will be set to the smaller of + * |num_bytes_to_read| or the size of the space. + */ + nvram_result_t (*read_space)(const struct nvram_device* device, + uint32_t index, uint64_t num_bytes_to_read, + const uint8_t* authorization_value, + uint32_t authorization_value_size, + uint8_t* buffer, uint64_t* bytes_read); + + /** + * Enables a write lock for the given space according to its policy. + * If the space does not have NV_CONTROL_PERSISTENT_WRITE_LOCK or + * NV_CONTROL_BOOT_WRITE_LOCK set then this function has no effect + * and may return an error. + * + * device - The nvram_device instance. + * index - The space index. + * authorization_value - If the space has the + * NV_CONTROL_WRITE_AUTHORIZATION policy, + * then this parameter provides the + * authorization value. Otherwise, this value + * is ignored and may be NULL. + * authorization_value_size - The number of bytes in + * |authorization_value|. + */ + nvram_result_t (*enable_write_lock)(const struct nvram_device* device, + uint32_t index, + const uint8_t* authorization_value, + uint32_t authorization_value_size); + + /** + * Enables a read lock for the given space according to its policy. + * If the space does not have NV_CONTROL_BOOT_READ_LOCK set then this + * function has no effect and may return an error. + * + * device - The nvram_device instance. + * index - The space index. + * authorization_value - If the space has the + * NV_CONTROL_READ_AUTHORIZATION policy, then + * this parameter provides the authorization + * value. (Note that there is no requirement + * for write access in order to lock for + * reading. A read lock is always volatile.) + * Otherwise, this value is ignored and may + * be NULL. + * authorization_value_size - The number of bytes in + * |authorization_value|. + */ + nvram_result_t (*enable_read_lock)(const struct nvram_device* device, + uint32_t index, + const uint8_t* authorization_value, + uint32_t authorization_value_size); +}; + +typedef struct nvram_device nvram_device_t; + +/* Convenience API for opening and closing nvram devices. */ +static inline int nvram_open(const struct hw_module_t* module, + nvram_device_t** device) { + return module->methods->open(module, NVRAM_HARDWARE_DEVICE_ID, + (struct hw_device_t**)device); +} + +static inline int nvram_close(nvram_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_HARDWARE_NVRAM_H
diff --git a/libhardware/include/hardware/nvram_defs.h b/libhardware/include/hardware/nvram_defs.h new file mode 100644 index 0000000..0256a3c --- /dev/null +++ b/libhardware/include/hardware/nvram_defs.h
@@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file contains data type definitions and constants that are useful to + * code interacting with and implementing the NVRAM HAL, even though it doesn't + * use the actual NVRAM HAL module interface. Keeping this in a separate file + * simplifies inclusion in low-level code which can't easily include the heavier + * hardware.h due to lacking standard headers. + */ + +#ifndef ANDROID_HARDWARE_NVRAM_DEFS_H +#define ANDROID_HARDWARE_NVRAM_DEFS_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/* Values returned by nvram_device methods. */ +typedef uint32_t nvram_result_t; + +const nvram_result_t NV_RESULT_SUCCESS = 0; +const nvram_result_t NV_RESULT_INTERNAL_ERROR = 1; +const nvram_result_t NV_RESULT_ACCESS_DENIED = 2; +const nvram_result_t NV_RESULT_INVALID_PARAMETER = 3; +const nvram_result_t NV_RESULT_SPACE_DOES_NOT_EXIST = 4; +const nvram_result_t NV_RESULT_SPACE_ALREADY_EXISTS = 5; +const nvram_result_t NV_RESULT_OPERATION_DISABLED = 6; + +/* Values describing available access controls. */ +typedef uint32_t nvram_control_t; + +const nvram_control_t NV_CONTROL_PERSISTENT_WRITE_LOCK = 1; +const nvram_control_t NV_CONTROL_BOOT_WRITE_LOCK = 2; +const nvram_control_t NV_CONTROL_BOOT_READ_LOCK = 3; +const nvram_control_t NV_CONTROL_WRITE_AUTHORIZATION = 4; +const nvram_control_t NV_CONTROL_READ_AUTHORIZATION = 5; +const nvram_control_t NV_CONTROL_WRITE_EXTEND = 6; + +const uint32_t NV_UNLIMITED_SPACES = 0xFFFFFFFF; + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // ANDROID_HARDWARE_NVRAM_DEFS_H
diff --git a/libhardware/include/hardware/power.h b/libhardware/include/hardware/power.h new file mode 100644 index 0000000..10612f3 --- /dev/null +++ b/libhardware/include/hardware/power.h
@@ -0,0 +1,156 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INCLUDE_HARDWARE_POWER_H +#define ANDROID_INCLUDE_HARDWARE_POWER_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define POWER_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define POWER_MODULE_API_VERSION_0_2 HARDWARE_MODULE_API_VERSION(0, 2) +#define POWER_MODULE_API_VERSION_0_3 HARDWARE_MODULE_API_VERSION(0, 3) + +/** + * The id of this module + */ +#define POWER_HARDWARE_MODULE_ID "power" + +/* + * Power hint identifiers passed to (*powerHint) + */ + +typedef enum { + POWER_HINT_VSYNC = 0x00000001, + POWER_HINT_INTERACTION = 0x00000002, + /* DO NOT USE POWER_HINT_VIDEO_ENCODE/_DECODE! They will be removed in + * KLP. + */ + POWER_HINT_VIDEO_ENCODE = 0x00000003, + POWER_HINT_VIDEO_DECODE = 0x00000004, + POWER_HINT_LOW_POWER = 0x00000005 +} power_hint_t; + +typedef enum { + POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 0x00000001 +} feature_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct power_module { + struct hw_module_t common; + + /* + * (*init)() performs power management setup actions at runtime + * startup, such as to set default cpufreq parameters. This is + * called only by the Power HAL instance loaded by + * PowerManagerService. + */ + void (*init)(struct power_module *module); + + /* + * (*setInteractive)() performs power management actions upon the + * system entering interactive state (that is, the system is awake + * and ready for interaction, often with UI devices such as + * display and touchscreen enabled) or non-interactive state (the + * system appears asleep, display usually turned off). The + * non-interactive state is usually entered after a period of + * inactivity, in order to conserve battery power during + * such inactive periods. + * + * Typical actions are to turn on or off devices and adjust + * cpufreq parameters. This function may also call the + * appropriate interfaces to allow the kernel to suspend the + * system to low-power sleep state when entering non-interactive + * state, and to disallow low-power suspend when the system is in + * interactive state. When low-power suspend state is allowed, the + * kernel may suspend the system whenever no wakelocks are held. + * + * on is non-zero when the system is transitioning to an + * interactive / awake state, and zero when transitioning to a + * non-interactive / asleep state. + * + * This function is called to enter non-interactive state after + * turning off the screen (if present), and called to enter + * interactive state prior to turning on the screen. + */ + void (*setInteractive)(struct power_module *module, int on); + + /* + * (*powerHint) is called to pass hints on power requirements, which + * may result in adjustment of power/performance parameters of the + * cpufreq governor and other controls. The possible hints are: + * + * POWER_HINT_VSYNC + * + * Foreground app has started or stopped requesting a VSYNC pulse + * from SurfaceFlinger. If the app has started requesting VSYNC + * then CPU and GPU load is expected soon, and it may be appropriate + * to raise speeds of CPU, memory bus, etc. The data parameter is + * non-zero to indicate VSYNC pulse is now requested, or zero for + * VSYNC pulse no longer requested. + * + * POWER_HINT_INTERACTION + * + * User is interacting with the device, for example, touchscreen + * events are incoming. CPU and GPU load may be expected soon, + * and it may be appropriate to raise speeds of CPU, memory bus, + * etc. The data parameter is the estimated length of the interaction + * in milliseconds, or 0 if unknown. + * + * POWER_HINT_LOW_POWER + * + * Low power mode is activated or deactivated. Low power mode + * is intended to save battery at the cost of performance. The data + * parameter is non-zero when low power mode is activated, and zero + * when deactivated. + * + * A particular platform may choose to ignore any hint. + * + * availability: version 0.2 + * + */ + void (*powerHint)(struct power_module *module, power_hint_t hint, + void *data); + + /* + * (*setFeature) is called to turn on or off a particular feature + * depending on the state parameter. The possible features are: + * + * FEATURE_DOUBLE_TAP_TO_WAKE + * + * Enabling/Disabling this feature will allow/disallow the system + * to wake up by tapping the screen twice. + * + * availability: version 0.3 + * + */ + void (*setFeature)(struct power_module *module, feature_t feature, int state); + +} power_module_t; + + +__END_DECLS + +#endif // ANDROID_INCLUDE_HARDWARE_POWER_H
diff --git a/libhardware/include/hardware/radio.h b/libhardware/include/hardware/radio.h new file mode 100644 index 0000000..145deb5 --- /dev/null +++ b/libhardware/include/hardware/radio.h
@@ -0,0 +1,298 @@ +/* + * 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 <system/radio.h> +#include <hardware/hardware.h> + +#ifndef ANDROID_RADIO_HAL_H +#define ANDROID_RADIO_HAL_H + + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define RADIO_HARDWARE_MODULE_ID "radio" + +/** + * Name of the audio devices to open + */ +#define RADIO_HARDWARE_DEVICE "radio_hw_device" + +#define RADIO_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define RADIO_MODULE_API_VERSION_CURRENT RADIO_MODULE_API_VERSION_1_0 + + +#define RADIO_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define RADIO_DEVICE_API_VERSION_CURRENT RADIO_DEVICE_API_VERSION_1_0 + +/** + * List of known radio HAL modules. This is the base name of the radio HAL + * library composed of the "radio." prefix, one of the base names below and + * a suffix specific to the device. + * E.g: radio.fm.default.so + */ + +#define RADIO_HARDWARE_MODULE_ID_FM "fm" /* corresponds to RADIO_CLASS_AM_FM */ +#define RADIO_HARDWARE_MODULE_ID_SAT "sat" /* corresponds to RADIO_CLASS_SAT */ +#define RADIO_HARDWARE_MODULE_ID_DT "dt" /* corresponds to RADIO_CLASS_DT */ + + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct radio_module { + struct hw_module_t common; +}; + +/* + * Callback function called by the HAL when one of the following occurs: + * - event RADIO_EVENT_HW_FAILURE: radio chip of driver failure requiring + * closing and reopening of the tuner interface. + * - event RADIO_EVENT_CONFIG: new configuration applied in response to open_tuner(), + * or set_configuration(). The event status is 0 (no error) if the configuration has been applied, + * -EINVAL is not or -ETIMEDOUT in case of time out. + * - event RADIO_EVENT_TUNED: tune locked on new station/frequency following scan(), + * step(), tune() or auto AF switching. The event status is 0 (no error) if in tune, + * -EINVAL is not tuned and data in radio_program_info is not valid or -ETIMEDOUT if scan() + * timed out. + * - event RADIO_EVENT_TA: at the beginning and end of traffic announcement if current + * configuration enables TA. + * - event RADIO_EVENT_AF: after automatic switching to alternate frequency if current + * configuration enables AF switching. + * - event RADIO_EVENT_ANTENNA: when the antenna is connected or disconnected. + * - event RADIO_EVENT_METADATA: when new meta data are received from the tuned station. + * The callback MUST NOT be called synchronously while executing a HAL function but from + * a separate thread. + */ +typedef void (*radio_callback_t)(radio_hal_event_t *event, void *cookie); + +/* control interface for a radio tuner */ +struct radio_tuner { + /* + * Apply current radio band configuration (band, range, channel spacing ...). + * + * arguments: + * - config: the band configuration to apply + * + * returns: + * 0 if configuration could be applied + * -EINVAL if configuration requested is invalid + * + * Automatically cancels pending scan, step or tune. + * + * Callback function with event RADIO_EVENT_CONFIG MUST be called once the + * configuration is applied or a failure occurs or after a time out. + */ + int (*set_configuration)(const struct radio_tuner *tuner, + const radio_hal_band_config_t *config); + + /* + * Retrieve current radio band configuration. + * + * arguments: + * - config: where to return the band configuration + * + * returns: + * 0 if valid configuration is returned + * -EINVAL if invalid arguments are passed + */ + int (*get_configuration)(const struct radio_tuner *tuner, + radio_hal_band_config_t *config); + + /* + * Start scanning up to next valid station. + * Must be called when a valid configuration has been applied. + * + * arguments: + * - direction: RADIO_DIRECTION_UP or RADIO_DIRECTION_DOWN + * - skip_sub_channel: valid for HD radio or digital radios only: ignore sub channels + * (e.g SPS for HD radio). + * + * returns: + * 0 if scan successfully started + * -ENOSYS if called out of sequence + * -ENODEV if another error occurs + * + * Automatically cancels pending scan, step or tune. + * + * Callback function with event RADIO_EVENT_TUNED MUST be called once + * locked on a station or after a time out or full frequency scan if + * no station found. The event status should indicate if a valid station + * is tuned or not. + */ + int (*scan)(const struct radio_tuner *tuner, + radio_direction_t direction, bool skip_sub_channel); + + /* + * Move one channel spacing up or down. + * Must be called when a valid configuration has been applied. + * + * arguments: + * - direction: RADIO_DIRECTION_UP or RADIO_DIRECTION_DOWN + * - skip_sub_channel: valid for HD radio or digital radios only: ignore sub channels + * (e.g SPS for HD radio). + * + * returns: + * 0 if step successfully started + * -ENOSYS if called out of sequence + * -ENODEV if another error occurs + * + * Automatically cancels pending scan, step or tune. + * + * Callback function with event RADIO_EVENT_TUNED MUST be called once + * step completed or after a time out. The event status should indicate + * if a valid station is tuned or not. + */ + int (*step)(const struct radio_tuner *tuner, + radio_direction_t direction, bool skip_sub_channel); + + /* + * Tune to specified frequency. + * Must be called when a valid configuration has been applied. + * + * arguments: + * - channel: channel to tune to. A frequency in kHz for AM/FM/HD Radio bands. + * - sub_channel: valid for HD radio or digital radios only: (e.g SPS number for HD radio). + * + * returns: + * 0 if tune successfully started + * -ENOSYS if called out of sequence + * -EINVAL if invalid arguments are passed + * -ENODEV if another error occurs + * + * Automatically cancels pending scan, step or tune. + * + * Callback function with event RADIO_EVENT_TUNED MUST be called once + * tuned or after a time out. The event status should indicate + * if a valid station is tuned or not. + */ + int (*tune)(const struct radio_tuner *tuner, + unsigned int channel, unsigned int sub_channel); + + /* + * Cancel a scan, step or tune operation. + * Must be called while a scan, step or tune operation is pending + * (callback not yet sent). + * + * returns: + * 0 if successful + * -ENOSYS if called out of sequence + * -ENODEV if another error occurs + * + * The callback is not sent. + */ + int (*cancel)(const struct radio_tuner *tuner); + + /* + * Retrieve current station information. + * + * arguments: + * - info: where to return the program info. + * If info->metadata is NULL. no meta data should be returned. + * If meta data must be returned, they should be added to or cloned to + * info->metadata, not passed from a newly created meta data buffer. + * + * returns: + * 0 if tuned and information available + * -EINVAL if invalid arguments are passed + * -ENODEV if another error occurs + */ + int (*get_program_information)(const struct radio_tuner *tuner, + radio_program_info_t *info); +}; + +struct radio_hw_device { + struct hw_device_t common; + + /* + * Retrieve implementation properties. + * + * arguments: + * - properties: where to return the module properties + * + * returns: + * 0 if no error + * -EINVAL if invalid arguments are passed + */ + int (*get_properties)(const struct radio_hw_device *dev, + radio_hal_properties_t *properties); + + /* + * Open a tuner interface for the requested configuration. + * If no other tuner is opened, this will activate the radio module. + * + * arguments: + * - config: the band configuration to apply + * - audio: this tuner will be used for live radio listening and should be connected to + * the radio audio source. + * - callback: the event callback + * - cookie: the cookie to pass when calling the callback + * - tuner: where to return the tuner interface + * + * returns: + * 0 if HW was powered up and configuration could be applied + * -EINVAL if configuration requested is invalid + * -ENOSYS if called out of sequence + * + * Callback function with event RADIO_EVENT_CONFIG MUST be called once the + * configuration is applied or a failure occurs or after a time out. + */ + int (*open_tuner)(const struct radio_hw_device *dev, + const radio_hal_band_config_t *config, + bool audio, + radio_callback_t callback, + void *cookie, + const struct radio_tuner **tuner); + + /* + * Close a tuner interface. + * If the last tuner is closed, the radio module is deactivated. + * + * arguments: + * - tuner: the tuner interface to close + * + * returns: + * 0 if powered down successfully. + * -EINVAL if an invalid argument is passed + * -ENOSYS if called out of sequence + */ + int (*close_tuner)(const struct radio_hw_device *dev, const struct radio_tuner *tuner); + +}; + +typedef struct radio_hw_device radio_hw_device_t; + +/** convenience API for opening and closing a supported device */ + +static inline int radio_hw_device_open(const struct hw_module_t* module, + struct radio_hw_device** device) +{ + return module->methods->open(module, RADIO_HARDWARE_DEVICE, + (struct hw_device_t**)device); +} + +static inline int radio_hw_device_close(const struct radio_hw_device* device) +{ + return device->common.close((struct hw_device_t *)&device->common); +} + +__END_DECLS + +#endif // ANDROID_RADIO_HAL_H
diff --git a/libhardware/include/hardware/sensors.h b/libhardware/include/hardware/sensors.h new file mode 100644 index 0000000..51bffe1 --- /dev/null +++ b/libhardware/include/hardware/sensors.h
@@ -0,0 +1,1096 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SENSORS_INTERFACE_H +#define ANDROID_SENSORS_INTERFACE_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> +#include <cutils/native_handle.h> + +__BEGIN_DECLS + +/*****************************************************************************/ + +#define SENSORS_HEADER_VERSION 1 +#define SENSORS_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define SENSORS_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION_2(0, 1, SENSORS_HEADER_VERSION) +#define SENSORS_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION_2(1, 0, SENSORS_HEADER_VERSION) +#define SENSORS_DEVICE_API_VERSION_1_1 HARDWARE_DEVICE_API_VERSION_2(1, 1, SENSORS_HEADER_VERSION) +#define SENSORS_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION_2(1, 2, SENSORS_HEADER_VERSION) +#define SENSORS_DEVICE_API_VERSION_1_3 HARDWARE_DEVICE_API_VERSION_2(1, 3, SENSORS_HEADER_VERSION) +#define SENSORS_DEVICE_API_VERSION_1_4 HARDWARE_DEVICE_API_VERSION_2(1, 4, SENSORS_HEADER_VERSION) + +/** + * Please see the Sensors section of source.android.com for an + * introduction to and detailed descriptions of Android sensor types: + * http://source.android.com/devices/sensors/index.html + */ + +/** + * The id of this module + */ +#define SENSORS_HARDWARE_MODULE_ID "sensors" + +/** + * Name of the sensors device to open + */ +#define SENSORS_HARDWARE_POLL "poll" + +/** + * Handles must be higher than SENSORS_HANDLE_BASE and must be unique. + * A Handle identifies a given sensors. The handle is used to activate + * and/or deactivate sensors. + * In this version of the API there can only be 256 handles. + */ +#define SENSORS_HANDLE_BASE 0 +#define SENSORS_HANDLE_BITS 8 +#define SENSORS_HANDLE_COUNT (1<<SENSORS_HANDLE_BITS) + + +/* + * **** Deprecated ***** + * flags for (*batch)() + * Availability: SENSORS_DEVICE_API_VERSION_1_0 + * see (*batch)() documentation for details. + * Deprecated as of SENSORS_DEVICE_API_VERSION_1_3. + * WAKE_UP_* sensors replace WAKE_UPON_FIFO_FULL concept. + */ +enum { + SENSORS_BATCH_DRY_RUN = 0x00000001, + SENSORS_BATCH_WAKE_UPON_FIFO_FULL = 0x00000002 +}; + +/* + * what field for meta_data_event_t + */ +enum { + /* a previous flush operation has completed */ + META_DATA_FLUSH_COMPLETE = 1, + META_DATA_VERSION /* always last, leave auto-assigned */ +}; + +/* + * The permission to use for body sensors (like heart rate monitors). + * See sensor types for more details on what sensors should require this + * permission. + */ +#define SENSOR_PERMISSION_BODY_SENSORS "android.permission.BODY_SENSORS" + +/* + * Availability: SENSORS_DEVICE_API_VERSION_1_4 + * Sensor HAL modes used in set_operation_mode method + */ +enum { + /* + * Operating modes for the HAL. + */ + + /* + * Normal mode operation. This is the default state of operation. + * The HAL shall initialize into this mode on device startup. + */ + SENSOR_HAL_NORMAL_MODE = 0, + + /* + * Data Injection mode. In this mode, the device shall not source data from the + * physical sensors as it would in normal mode. Instead sensor data is + * injected by the sensor service. + */ + SENSOR_HAL_DATA_INJECTION_MODE = 0x1 +}; + +/* + * Availability: SENSORS_DEVICE_API_VERSION_1_3 + * Sensor flags used in sensor_t.flags. + */ +enum { + /* + * Whether this sensor wakes up the AP from suspend mode when data is available. Whenever + * sensor events are delivered from a wake_up sensor, the driver needs to hold a wake_lock till + * the events are read by the SensorService i.e till sensors_poll_device_t.poll() is called the + * next time. Once poll is called again it means events have been read by the SensorService, the + * driver can safely release the wake_lock. SensorService will continue to hold a wake_lock till + * the app actually reads the events. + */ + SENSOR_FLAG_WAKE_UP = 1U << 0, + /* + * Reporting modes for various sensors. Each sensor will have exactly one of these modes set. + * The least significant 2nd, 3rd and 4th bits are used to represent four possible reporting + * modes. + */ + SENSOR_FLAG_CONTINUOUS_MODE = 0, // 0000 + SENSOR_FLAG_ON_CHANGE_MODE = 0x2, // 0010 + SENSOR_FLAG_ONE_SHOT_MODE = 0x4, // 0100 + SENSOR_FLAG_SPECIAL_REPORTING_MODE = 0x6, // 0110 + + /* + * Set this flag if the sensor supports data_injection mode and allows data to be injected + * from the SensorService. When in data_injection ONLY sensors with this flag set are injected + * sensor data and only sensors with this flag set are activated. Eg: Accelerometer and Step + * Counter sensors can be set with this flag and SensorService will inject accelerometer data + * and read the corresponding step counts. + */ + SENSOR_FLAG_SUPPORTS_DATA_INJECTION = 0x10 // 1 0000 +}; + +/* + * Mask and shift for reporting mode sensor flags defined above. + */ +#define REPORTING_MODE_MASK (0xE) +#define REPORTING_MODE_SHIFT (1) + +/* + * Mask and shift for data_injection mode sensor flags defined above. + */ +#define DATA_INJECTION_MASK (0x10) +#define DATA_INJECTION_SHIFT (4) + +/* + * Sensor type + * + * Each sensor has a type which defines what this sensor measures and how + * measures are reported. See the Base sensors and Composite sensors lists + * for complete descriptions: + * http://source.android.com/devices/sensors/base_triggers.html + * http://source.android.com/devices/sensors/composite_sensors.html + * + * Device manufacturers (OEMs) can define their own sensor types, for + * their private use by applications or services provided by them. Such + * sensor types are specific to an OEM and can't be exposed in the SDK. + * These types must start at SENSOR_TYPE_DEVICE_PRIVATE_BASE. + * + * All sensors defined outside of the device private range must correspond to + * a type defined in this file, and must satisfy the characteristics listed in + * the description of the sensor type. + * + * Starting with version SENSORS_DEVICE_API_VERSION_1_2, each sensor also + * has a stringType. + * - StringType of sensors inside of the device private range MUST be prefixed + * by the sensor provider's or OEM reverse domain name. In particular, they + * cannot use the "android.sensor" prefix. + * - StringType of sensors outside of the device private range MUST correspond + * to the one defined in this file (starting with "android.sensor"). + * For example, accelerometers must have + * type=SENSOR_TYPE_ACCELEROMETER and + * stringType=SENSOR_STRING_TYPE_ACCELEROMETER + * + * When android introduces a new sensor type that can replace an OEM-defined + * sensor type, the OEM must use the official sensor type and stringType on + * versions of the HAL that support this new official sensor type. + * + * Example (made up): Suppose Google's Glass team wants to surface a sensor + * detecting that Glass is on a head. + * - Such a sensor is not officially supported in android KitKat + * - Glass devices launching on KitKat can implement a sensor with + * type = 0x10001 and stringType = "com.google.glass.onheaddetector" + * - In L android release, if android decides to define + * SENSOR_TYPE_ON_HEAD_DETECTOR and STRING_SENSOR_TYPE_ON_HEAD_DETECTOR, + * those types should replace the Glass-team-specific types in all future + * launches. + * - When launching Glass on the L release, Google should now use the official + * type (SENSOR_TYPE_ON_HEAD_DETECTOR) and stringType. + * - This way, all applications can now use this sensor. + */ + +/* + * Base for device manufacturers private sensor types. + * These sensor types can't be exposed in the SDK. + */ +#define SENSOR_TYPE_DEVICE_PRIVATE_BASE 0x10000 + +/* + * SENSOR_TYPE_META_DATA + * reporting-mode: n/a + * wake-up sensor: n/a + * + * NO SENSOR OF THAT TYPE MUST BE RETURNED (*get_sensors_list)() + * + * SENSOR_TYPE_META_DATA is a special token used to populate the + * sensors_meta_data_event structure. It doesn't correspond to a physical + * sensor. sensors_meta_data_event are special, they exist only inside + * the HAL and are generated spontaneously, as opposed to be related to + * a physical sensor. + * + * sensors_meta_data_event_t.version must be META_DATA_VERSION + * sensors_meta_data_event_t.sensor must be 0 + * sensors_meta_data_event_t.type must be SENSOR_TYPE_META_DATA + * sensors_meta_data_event_t.reserved must be 0 + * sensors_meta_data_event_t.timestamp must be 0 + * + * The payload is a meta_data_event_t, where: + * meta_data_event_t.what can take the following values: + * + * META_DATA_FLUSH_COMPLETE + * This event indicates that a previous (*flush)() call has completed for the sensor + * handle specified in meta_data_event_t.sensor. + * see (*flush)() for more details + * + * All other values for meta_data_event_t.what are reserved and + * must not be used. + * + */ +#define SENSOR_TYPE_META_DATA (0) + +/* + * Wake up sensors. + * Each sensor may have either or both a wake-up and a non-wake variant. + * When registered in batch mode, wake-up sensors will wake up the AP when + * their FIFOs are full or when the batch timeout expires. A separate FIFO has + * to be maintained for wake up sensors and non wake up sensors. The non wake-up + * sensors need to overwrite their FIFOs when they are full till the AP wakes up + * and the wake-up sensors will wake-up the AP when their FIFOs are full or when + * the batch timeout expires without losing events. Wake-up and non wake-up variants + * of each sensor can be activated at different rates independently of each other. + * + * Note: Proximity sensor and significant motion sensor which were defined in previous + * releases are also wake-up sensors and should be treated as such. Wake-up one-shot + * sensors like SIGNIFICANT_MOTION cannot be batched, hence the text about batch above + * doesn't apply to them. See the definitions of SENSOR_TYPE_PROXIMITY and + * SENSOR_TYPE_SIGNIFICANT_MOTION for more info. + * + * Set SENSOR_FLAG_WAKE_UP flag for all wake-up sensors. + * + * For example, A device can have two sensors both of SENSOR_TYPE_ACCELEROMETER and + * one of them can be a wake_up sensor (with SENSOR_FLAG_WAKE_UP flag set) and the other + * can be a regular non wake_up sensor. Both of these sensors must be activated/deactivated + * independently of the other. + */ + +/* + * SENSOR_TYPE_ACCELEROMETER + * reporting-mode: continuous + * + * All values are in SI units (m/s^2) and measure the acceleration of the + * device minus the force of gravity. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_ACCELEROMETER (1) +#define SENSOR_STRING_TYPE_ACCELEROMETER "android.sensor.accelerometer" + +/* + * SENSOR_TYPE_GEOMAGNETIC_FIELD + * reporting-mode: continuous + * + * All values are in micro-Tesla (uT) and measure the geomagnetic + * field in the X, Y and Z axis. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_GEOMAGNETIC_FIELD (2) +#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD +#define SENSOR_STRING_TYPE_MAGNETIC_FIELD "android.sensor.magnetic_field" + +/* + * SENSOR_TYPE_ORIENTATION + * reporting-mode: continuous + * + * All values are angles in degrees. + * + * Orientation sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_ORIENTATION (3) +#define SENSOR_STRING_TYPE_ORIENTATION "android.sensor.orientation" + +/* + * SENSOR_TYPE_GYROSCOPE + * reporting-mode: continuous + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_GYROSCOPE (4) +#define SENSOR_STRING_TYPE_GYROSCOPE "android.sensor.gyroscope" + +/* + * SENSOR_TYPE_LIGHT + * reporting-mode: on-change + * + * The light sensor value is returned in SI lux units. + * + * Both wake-up and non wake-up versions are useful. + */ +#define SENSOR_TYPE_LIGHT (5) +#define SENSOR_STRING_TYPE_LIGHT "android.sensor.light" + +/* + * SENSOR_TYPE_PRESSURE + * reporting-mode: continuous + * + * The pressure sensor return the athmospheric pressure in hectopascal (hPa) + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_PRESSURE (6) +#define SENSOR_STRING_TYPE_PRESSURE "android.sensor.pressure" + +/* SENSOR_TYPE_TEMPERATURE is deprecated in the HAL */ +#define SENSOR_TYPE_TEMPERATURE (7) +#define SENSOR_STRING_TYPE_TEMPERATURE "android.sensor.temperature" + +/* + * SENSOR_TYPE_PROXIMITY + * reporting-mode: on-change + * + * The proximity sensor which turns the screen off and back on during calls is the + * wake-up proximity sensor. Implement wake-up proximity sensor before implementing + * a non wake-up proximity sensor. For the wake-up proximity sensor set the flag + * SENSOR_FLAG_WAKE_UP. + * The value corresponds to the distance to the nearest object in centimeters. + */ +#define SENSOR_TYPE_PROXIMITY (8) +#define SENSOR_STRING_TYPE_PROXIMITY "android.sensor.proximity" + +/* + * SENSOR_TYPE_GRAVITY + * reporting-mode: continuous + * + * A gravity output indicates the direction of and magnitude of gravity in + * the devices's coordinates. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_GRAVITY (9) +#define SENSOR_STRING_TYPE_GRAVITY "android.sensor.gravity" + +/* + * SENSOR_TYPE_LINEAR_ACCELERATION + * reporting-mode: continuous + * + * Indicates the linear acceleration of the device in device coordinates, + * not including gravity. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_LINEAR_ACCELERATION (10) +#define SENSOR_STRING_TYPE_LINEAR_ACCELERATION "android.sensor.linear_acceleration" + + +/* + * SENSOR_TYPE_ROTATION_VECTOR + * reporting-mode: continuous + * + * The rotation vector symbolizes the orientation of the device relative to the + * East-North-Up coordinates frame. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_ROTATION_VECTOR (11) +#define SENSOR_STRING_TYPE_ROTATION_VECTOR "android.sensor.rotation_vector" + +/* + * SENSOR_TYPE_RELATIVE_HUMIDITY + * reporting-mode: on-change + * + * A relative humidity sensor measures relative ambient air humidity and + * returns a value in percent. + * + * Both wake-up and non wake-up versions are useful. + */ +#define SENSOR_TYPE_RELATIVE_HUMIDITY (12) +#define SENSOR_STRING_TYPE_RELATIVE_HUMIDITY "android.sensor.relative_humidity" + +/* + * SENSOR_TYPE_AMBIENT_TEMPERATURE + * reporting-mode: on-change + * + * The ambient (room) temperature in degree Celsius. + * + * Both wake-up and non wake-up versions are useful. + */ +#define SENSOR_TYPE_AMBIENT_TEMPERATURE (13) +#define SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE "android.sensor.ambient_temperature" + +/* + * SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED + * reporting-mode: continuous + * + * Similar to SENSOR_TYPE_MAGNETIC_FIELD, but the hard iron calibration is + * reported separately instead of being included in the measurement. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED (14) +#define SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED "android.sensor.magnetic_field_uncalibrated" + +/* + * SENSOR_TYPE_GAME_ROTATION_VECTOR + * reporting-mode: continuous + * + * Similar to SENSOR_TYPE_ROTATION_VECTOR, but not using the geomagnetic + * field. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_GAME_ROTATION_VECTOR (15) +#define SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR "android.sensor.game_rotation_vector" + +/* + * SENSOR_TYPE_GYROSCOPE_UNCALIBRATED + * reporting-mode: continuous + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED (16) +#define SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED "android.sensor.gyroscope_uncalibrated" + +/* + * SENSOR_TYPE_SIGNIFICANT_MOTION + * reporting-mode: one-shot + * + * A sensor of this type triggers an event each time significant motion + * is detected and automatically disables itself. + * For Significant Motion sensor to be useful, it must be defined as a + * wake-up sensor. (set SENSOR_FLAG_WAKE_UP). Implement the wake-up significant motion + * sensor. A non wake-up version is not useful. + * The only allowed value to return is 1.0. + */ + +#define SENSOR_TYPE_SIGNIFICANT_MOTION (17) +#define SENSOR_STRING_TYPE_SIGNIFICANT_MOTION "android.sensor.significant_motion" + +/* + * SENSOR_TYPE_STEP_DETECTOR + * reporting-mode: special + * + * A sensor of this type triggers an event each time a step is taken + * by the user. The only allowed value to return is 1.0 and an event + * is generated for each step. + * + * Both wake-up and non wake-up versions are useful. + */ + +#define SENSOR_TYPE_STEP_DETECTOR (18) +#define SENSOR_STRING_TYPE_STEP_DETECTOR "android.sensor.step_detector" + + +/* + * SENSOR_TYPE_STEP_COUNTER + * reporting-mode: on-change + * + * A sensor of this type returns the number of steps taken by the user since + * the last reboot while activated. The value is returned as a uint64_t and is + * reset to zero only on a system / android reboot. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ + +#define SENSOR_TYPE_STEP_COUNTER (19) +#define SENSOR_STRING_TYPE_STEP_COUNTER "android.sensor.step_counter" + +/* + * SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR + * reporting-mode: continuous + * + * Similar to SENSOR_TYPE_ROTATION_VECTOR, but using a magnetometer instead + * of using a gyroscope. + * + * Implement the non-wake-up version of this sensor and implement the wake-up + * version if the system possesses a wake up fifo. + */ +#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR (20) +#define SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR "android.sensor.geomagnetic_rotation_vector" + +/* + * SENSOR_TYPE_HEART_RATE + * reporting-mode: on-change + * + * A sensor of this type returns the current heart rate. + * The events contain the current heart rate in beats per minute (BPM) and the + * status of the sensor during the measurement. See heart_rate_event_t for more + * details. + * + * Because this sensor is on-change, events must be generated when and only + * when heart_rate.bpm or heart_rate.status have changed since the last + * event. In particular, upon the first activation, unless the device is known + * to not be on the body, the status field of the first event must be set to + * SENSOR_STATUS_UNRELIABLE. The event should be generated no faster than every + * period_ns passed to setDelay() or to batch(). + * See the definition of the on-change reporting mode for more information. + * + * sensor_t.requiredPermission must be set to SENSOR_PERMISSION_BODY_SENSORS. + * + * Both wake-up and non wake-up versions are useful. + */ +#define SENSOR_TYPE_HEART_RATE (21) +#define SENSOR_STRING_TYPE_HEART_RATE "android.sensor.heart_rate" + +/* + * SENSOR_TYPE_WAKE_UP_TILT_DETECTOR + * reporting-mode: special (setDelay has no impact) + * + * A sensor of this type generates an event each time a tilt event is detected. A tilt event + * should be generated if the direction of the 2-seconds window average gravity changed by at least + * 35 degrees since the activation or the last trigger of the sensor. + * reference_estimated_gravity = average of accelerometer measurements over the first + * 1 second after activation or the estimated gravity at the last + * trigger. + * current_estimated_gravity = average of accelerometer measurements over the last 2 seconds. + * trigger when angle (reference_estimated_gravity, current_estimated_gravity) > 35 degrees + * + * Large accelerations without a change in phone orientation should not trigger a tilt event. + * For example, a sharp turn or strong acceleration while driving a car should not trigger a tilt + * event, even though the angle of the average acceleration might vary by more than 35 degrees. + * + * Typically, this sensor is implemented with the help of only an accelerometer. Other sensors can + * be used as well if they do not increase the power consumption significantly. This is a low power + * sensor that should allow the AP to go into suspend mode. Do not emulate this sensor in the HAL. + * Like other wake up sensors, the driver is expected to a hold a wake_lock with a timeout of 200 ms + * while reporting this event. The only allowed return value is 1.0. + * + * Implement only the wake-up version of this sensor. + */ +#define SENSOR_TYPE_TILT_DETECTOR (22) +#define SENSOR_STRING_TYPE_TILT_DETECTOR "android.sensor.tilt_detector" + +/* + * SENSOR_TYPE_WAKE_GESTURE + * reporting-mode: one-shot + * + * A sensor enabling waking up the device based on a device specific motion. + * + * When this sensor triggers, the device behaves as if the power button was + * pressed, turning the screen on. This behavior (turning on the screen when + * this sensor triggers) might be deactivated by the user in the device + * settings. Changes in settings do not impact the behavior of the sensor: + * only whether the framework turns the screen on when it triggers. + * + * The actual gesture to be detected is not specified, and can be chosen by + * the manufacturer of the device. + * This sensor must be low power, as it is likely to be activated 24/7. + * The only allowed value to return is 1.0. + * + * Implement only the wake-up version of this sensor. + */ +#define SENSOR_TYPE_WAKE_GESTURE (23) +#define SENSOR_STRING_TYPE_WAKE_GESTURE "android.sensor.wake_gesture" + +/* + * SENSOR_TYPE_GLANCE_GESTURE + * reporting-mode: one-shot + * + * A sensor enabling briefly turning the screen on to enable the user to + * glance content on screen based on a specific motion. The device should + * turn the screen off after a few moments. + * + * When this sensor triggers, the device turns the screen on momentarily + * to allow the user to glance notifications or other content while the + * device remains locked in a non-interactive state (dozing). This behavior + * (briefly turning on the screen when this sensor triggers) might be deactivated + * by the user in the device settings. Changes in settings do not impact the + * behavior of the sensor: only whether the framework briefly turns the screen on + * when it triggers. + * + * The actual gesture to be detected is not specified, and can be chosen by + * the manufacturer of the device. + * This sensor must be low power, as it is likely to be activated 24/7. + * The only allowed value to return is 1.0. + * + * Implement only the wake-up version of this sensor. + */ +#define SENSOR_TYPE_GLANCE_GESTURE (24) +#define SENSOR_STRING_TYPE_GLANCE_GESTURE "android.sensor.glance_gesture" + +/** + * SENSOR_TYPE_PICK_UP_GESTURE + * reporting-mode: one-shot + * + * A sensor of this type triggers when the device is picked up regardless of wherever is was + * before (desk, pocket, bag). The only allowed return value is 1.0. + * This sensor de-activates itself immediately after it triggers. + * + * Implement only the wake-up version of this sensor. + */ +#define SENSOR_TYPE_PICK_UP_GESTURE (25) +#define SENSOR_STRING_TYPE_PICK_UP_GESTURE "android.sensor.pick_up_gesture" + +/* + * SENSOR_TYPE_WRIST_TILT_GESTURE + * trigger-mode: special + * wake-up sensor: yes + * + * A sensor of this type triggers an event each time a tilt of the wrist-worn + * device is detected. + * + * This sensor must be low power, as it is likely to be activated 24/7. + * The only allowed value to return is 1.0. + * + * Implement only the wake-up version of this sensor. + */ +#define SENSOR_TYPE_WRIST_TILT_GESTURE (26) +#define SENSOR_STRING_TYPE_WRIST_TILT_GESTURE "android.sensor.wrist_tilt_gesture" + +/** + * Values returned by the accelerometer in various locations in the universe. + * all values are in SI units (m/s^2) + */ +#define GRAVITY_SUN (275.0f) +#define GRAVITY_EARTH (9.80665f) + +/** Maximum magnetic field on Earth's surface */ +#define MAGNETIC_FIELD_EARTH_MAX (60.0f) + +/** Minimum magnetic field on Earth's surface */ +#define MAGNETIC_FIELD_EARTH_MIN (30.0f) + +/** + * Possible values of the status field of sensor events. + */ +#define SENSOR_STATUS_NO_CONTACT -1 +#define SENSOR_STATUS_UNRELIABLE 0 +#define SENSOR_STATUS_ACCURACY_LOW 1 +#define SENSOR_STATUS_ACCURACY_MEDIUM 2 +#define SENSOR_STATUS_ACCURACY_HIGH 3 + +/** + * sensor event data + */ +typedef struct { + union { + float v[3]; + struct { + float x; + float y; + float z; + }; + struct { + float azimuth; + float pitch; + float roll; + }; + }; + int8_t status; + uint8_t reserved[3]; +} sensors_vec_t; + +/** + * uncalibrated gyroscope and magnetometer event data + */ +typedef struct { + union { + float uncalib[3]; + struct { + float x_uncalib; + float y_uncalib; + float z_uncalib; + }; + }; + union { + float bias[3]; + struct { + float x_bias; + float y_bias; + float z_bias; + }; + }; +} uncalibrated_event_t; + +/** + * Meta data event data + */ +typedef struct meta_data_event { + int32_t what; + int32_t sensor; +} meta_data_event_t; + +/** + * Heart rate event data + */ +typedef struct { + // Heart rate in beats per minute. + // Set to 0 when status is SENSOR_STATUS_UNRELIABLE or ..._NO_CONTACT + float bpm; + // Status of the sensor for this reading. Set to one SENSOR_STATUS_... + // Note that this value should only be set for sensors that explicitly define + // the meaning of this field. This field is not piped through the framework + // for other sensors. + int8_t status; +} heart_rate_event_t; + +/** + * Union of the various types of sensor data + * that can be returned. + */ +typedef struct sensors_event_t { + /* must be sizeof(struct sensors_event_t) */ + int32_t version; + + /* sensor identifier */ + int32_t sensor; + + /* sensor type */ + int32_t type; + + /* reserved */ + int32_t reserved0; + + /* time is in nanosecond */ + int64_t timestamp; + + union { + union { + float data[16]; + + /* acceleration values are in meter per second per second (m/s^2) */ + sensors_vec_t acceleration; + + /* magnetic vector values are in micro-Tesla (uT) */ + sensors_vec_t magnetic; + + /* orientation values are in degrees */ + sensors_vec_t orientation; + + /* gyroscope values are in rad/s */ + sensors_vec_t gyro; + + /* temperature is in degrees centigrade (Celsius) */ + float temperature; + + /* distance in centimeters */ + float distance; + + /* light in SI lux units */ + float light; + + /* pressure in hectopascal (hPa) */ + float pressure; + + /* relative humidity in percent */ + float relative_humidity; + + /* uncalibrated gyroscope values are in rad/s */ + uncalibrated_event_t uncalibrated_gyro; + + /* uncalibrated magnetometer values are in micro-Teslas */ + uncalibrated_event_t uncalibrated_magnetic; + + /* heart rate data containing value in bpm and status */ + heart_rate_event_t heart_rate; + + /* this is a special event. see SENSOR_TYPE_META_DATA above. + * sensors_meta_data_event_t events are all reported with a type of + * SENSOR_TYPE_META_DATA. The handle is ignored and must be zero. + */ + meta_data_event_t meta_data; + }; + + union { + uint64_t data[8]; + + /* step-counter */ + uint64_t step_counter; + } u64; + }; + + /* Reserved flags for internal use. Set to zero. */ + uint32_t flags; + + uint32_t reserved1[3]; +} sensors_event_t; + + +/* see SENSOR_TYPE_META_DATA */ +typedef sensors_event_t sensors_meta_data_event_t; + + +struct sensor_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct sensors_module_t { + struct hw_module_t common; + + /** + * Enumerate all available sensors. The list is returned in "list". + * @return number of sensors in the list + */ + int (*get_sensors_list)(struct sensors_module_t* module, + struct sensor_t const** list); + + /** + * Place the module in a specific mode. The following modes are defined + * + * 0 - Normal operation. Default state of the module. + * 1 - Loopback mode. Data is injected for the the supported + * sensors by the sensor service in this mode. + * @return 0 on success + * -EINVAL if requested mode is not supported + * -EPERM if operation is not allowed + */ + int (*set_operation_mode)(unsigned int mode); +}; + +struct sensor_t { + + /* Name of this sensor. + * All sensors of the same "type" must have a different "name". + */ + const char* name; + + /* vendor of the hardware part */ + const char* vendor; + + /* version of the hardware part + driver. The value of this field + * must increase when the driver is updated in a way that changes the + * output of this sensor. This is important for fused sensors when the + * fusion algorithm is updated. + */ + int version; + + /* handle that identifies this sensors. This handle is used to reference + * this sensor throughout the HAL API. + */ + int handle; + + /* this sensor's type. */ + int type; + + /* maximum range of this sensor's value in SI units */ + float maxRange; + + /* smallest difference between two values reported by this sensor */ + float resolution; + + /* rough estimate of this sensor's power consumption in mA */ + float power; + + /* this value depends on the reporting mode: + * + * continuous: minimum sample period allowed in microseconds + * on-change : 0 + * one-shot :-1 + * special : 0, unless otherwise noted + */ + int32_t minDelay; + + /* number of events reserved for this sensor in the batch mode FIFO. + * If there is a dedicated FIFO for this sensor, then this is the + * size of this FIFO. If the FIFO is shared with other sensors, + * this is the size reserved for that sensor and it can be zero. + */ + uint32_t fifoReservedEventCount; + + /* maximum number of events of this sensor that could be batched. + * This is especially relevant when the FIFO is shared between + * several sensors; this value is then set to the size of that FIFO. + */ + uint32_t fifoMaxEventCount; + + /* type of this sensor as a string. Set to corresponding + * SENSOR_STRING_TYPE_*. + * When defining an OEM specific sensor or sensor manufacturer specific + * sensor, use your reserve domain name as a prefix. + * ex: com.google.glass.onheaddetector + * For sensors of known type, the android framework might overwrite this + * string automatically. + */ + const char* stringType; + + /* permission required to see this sensor, register to it and receive data. + * Set to "" if no permission is required. Some sensor types like the + * heart rate monitor have a mandatory require_permission. + * For sensors that always require a specific permission, like the heart + * rate monitor, the android framework might overwrite this string + * automatically. + */ + const char* requiredPermission; + + /* This value is defined only for continuous mode and on-change sensors. It is the delay between + * two sensor events corresponding to the lowest frequency that this sensor supports. When lower + * frequencies are requested through batch()/setDelay() the events will be generated at this + * frequency instead. It can be used by the framework or applications to estimate when the batch + * FIFO may be full. + * + * NOTE: 1) period_ns is in nanoseconds where as maxDelay/minDelay are in microseconds. + * continuous, on-change: maximum sampling period allowed in microseconds. + * one-shot, special : 0 + * 2) maxDelay should always fit within a 32 bit signed integer. It is declared as 64 bit + * on 64 bit architectures only for binary compatibility reasons. + * Availability: SENSORS_DEVICE_API_VERSION_1_3 + */ + #ifdef __LP64__ + int64_t maxDelay; + #else + int32_t maxDelay; + #endif + + /* Flags for sensor. See SENSOR_FLAG_* above. Only the least significant 32 bits are used here. + * It is declared as 64 bit on 64 bit architectures only for binary compatibility reasons. + * Availability: SENSORS_DEVICE_API_VERSION_1_3 + */ + #ifdef __LP64__ + uint64_t flags; + #else + uint32_t flags; + #endif + + /* reserved fields, must be zero */ + void* reserved[2]; +}; + + +/* + * sensors_poll_device_t is used with SENSORS_DEVICE_API_VERSION_0_1 + * and is present for backward binary and source compatibility. + * See the Sensors HAL interface section for complete descriptions of the + * following functions: + * http://source.android.com/devices/sensors/index.html#hal + */ +struct sensors_poll_device_t { + struct hw_device_t common; + int (*activate)(struct sensors_poll_device_t *dev, + int sensor_handle, int enabled); + int (*setDelay)(struct sensors_poll_device_t *dev, + int sensor_handle, int64_t sampling_period_ns); + int (*poll)(struct sensors_poll_device_t *dev, + sensors_event_t* data, int count); +}; + +/* + * struct sensors_poll_device_1 is used in HAL versions >= SENSORS_DEVICE_API_VERSION_1_0 + */ +typedef struct sensors_poll_device_1 { + union { + /* sensors_poll_device_1 is compatible with sensors_poll_device_t, + * and can be down-cast to it + */ + struct sensors_poll_device_t v0; + + struct { + struct hw_device_t common; + + /* Activate/de-activate one sensor. Return 0 on success, negative + * + * sensor_handle is the handle of the sensor to change. + * enabled set to 1 to enable, or 0 to disable the sensor. + * + * Return 0 on success, negative errno code otherwise. + */ + int (*activate)(struct sensors_poll_device_t *dev, + int sensor_handle, int enabled); + + /** + * Set the events's period in nanoseconds for a given sensor. + * If sampling_period_ns > max_delay it will be truncated to + * max_delay and if sampling_period_ns < min_delay it will be + * replaced by min_delay. + */ + int (*setDelay)(struct sensors_poll_device_t *dev, + int sensor_handle, int64_t sampling_period_ns); + + /** + * Returns an array of sensor data. + */ + int (*poll)(struct sensors_poll_device_t *dev, + sensors_event_t* data, int count); + }; + }; + + + /* + * Sets a sensor’s parameters, including sampling frequency and maximum + * report latency. This function can be called while the sensor is + * activated, in which case it must not cause any sensor measurements to + * be lost: transitioning from one sampling rate to the other cannot cause + * lost events, nor can transitioning from a high maximum report latency to + * a low maximum report latency. + * See the Batching sensor results page for details: + * http://source.android.com/devices/sensors/batching.html + */ + int (*batch)(struct sensors_poll_device_1* dev, + int sensor_handle, int flags, int64_t sampling_period_ns, + int64_t max_report_latency_ns); + + /* + * Flush adds a META_DATA_FLUSH_COMPLETE event (sensors_event_meta_data_t) + * to the end of the "batch mode" FIFO for the specified sensor and flushes + * the FIFO. + * If the FIFO is empty or if the sensor doesn't support batching (FIFO size zero), + * it should return SUCCESS along with a trivial META_DATA_FLUSH_COMPLETE event added to the + * event stream. This applies to all sensors other than one-shot sensors. + * If the sensor is a one-shot sensor, flush must return -EINVAL and not generate + * any flush complete metadata. + * If the sensor is not active at the time flush() is called, flush() should return + * -EINVAL. + */ + int (*flush)(struct sensors_poll_device_1* dev, int sensor_handle); + + /* + * Inject a single sensor sample to be to this device. + * data points to the sensor event to be injected + * @return 0 on success + * -EPERM if operation is not allowed + * -EINVAL if sensor event cannot be injected + */ + int (*inject_sensor_data)(struct sensors_poll_device_1 *dev, const sensors_event_t *data); + + void (*reserved_procs[7])(void); + +} sensors_poll_device_1_t; + + +/** convenience API for opening and closing a device */ + +static inline int sensors_open(const struct hw_module_t* module, + struct sensors_poll_device_t** device) { + return module->methods->open(module, + SENSORS_HARDWARE_POLL, (struct hw_device_t**)device); +} + +static inline int sensors_close(struct sensors_poll_device_t* device) { + return device->common.close(&device->common); +} + +static inline int sensors_open_1(const struct hw_module_t* module, + sensors_poll_device_1_t** device) { + return module->methods->open(module, + SENSORS_HARDWARE_POLL, (struct hw_device_t**)device); +} + +static inline int sensors_close_1(sensors_poll_device_1_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_SENSORS_INTERFACE_H
diff --git a/libhardware/include/hardware/sound_trigger.h b/libhardware/include/hardware/sound_trigger.h new file mode 100644 index 0000000..3d2bba2 --- /dev/null +++ b/libhardware/include/hardware/sound_trigger.h
@@ -0,0 +1,138 @@ +/* + * Copyright (C) 2014 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 <system/audio.h> +#include <system/sound_trigger.h> +#include <hardware/hardware.h> + +#ifndef ANDROID_SOUND_TRIGGER_HAL_H +#define ANDROID_SOUND_TRIGGER_HAL_H + + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define SOUND_TRIGGER_HARDWARE_MODULE_ID "sound_trigger" + +/** + * Name of the audio devices to open + */ +#define SOUND_TRIGGER_HARDWARE_INTERFACE "sound_trigger_hw_if" + +#define SOUND_TRIGGER_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define SOUND_TRIGGER_MODULE_API_VERSION_CURRENT SOUND_TRIGGER_MODULE_API_VERSION_1_0 + + +#define SOUND_TRIGGER_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT SOUND_TRIGGER_DEVICE_API_VERSION_1_0 + +/** + * List of known sound trigger HAL modules. This is the base name of the sound_trigger HAL + * library composed of the "sound_trigger." prefix, one of the base names below and + * a suffix specific to the device. + * e.g: sondtrigger.primary.goldfish.so or sound_trigger.primary.default.so + */ + +#define SOUND_TRIGGER_HARDWARE_MODULE_ID_PRIMARY "primary" + + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct sound_trigger_module { + struct hw_module_t common; +}; + +typedef void (*recognition_callback_t)(struct sound_trigger_recognition_event *event, void *cookie); +typedef void (*sound_model_callback_t)(struct sound_trigger_model_event *event, void *cookie); + +struct sound_trigger_hw_device { + struct hw_device_t common; + + /* + * Retrieve implementation properties. + */ + int (*get_properties)(const struct sound_trigger_hw_device *dev, + struct sound_trigger_properties *properties); + + /* + * Load a sound model. Once loaded, recognition of this model can be started and stopped. + * Only one active recognition per model at a time. The SoundTrigger service will handle + * concurrent recognition requests by different users/applications on the same model. + * The implementation returns a unique handle used by other functions (unload_sound_model(), + * start_recognition(), etc... + */ + int (*load_sound_model)(const struct sound_trigger_hw_device *dev, + struct sound_trigger_sound_model *sound_model, + sound_model_callback_t callback, + void *cookie, + sound_model_handle_t *handle); + + /* + * Unload a sound model. A sound model can be unloaded to make room for a new one to overcome + * implementation limitations. + */ + int (*unload_sound_model)(const struct sound_trigger_hw_device *dev, + sound_model_handle_t handle); + + /* Start recognition on a given model. Only one recognition active at a time per model. + * Once recognition succeeds of fails, the callback is called. + * TODO: group recognition configuration parameters into one struct and add key phrase options. + */ + int (*start_recognition)(const struct sound_trigger_hw_device *dev, + sound_model_handle_t sound_model_handle, + const struct sound_trigger_recognition_config *config, + recognition_callback_t callback, + void *cookie); + + /* Stop recognition on a given model. + * The implementation does not have to call the callback when stopped via this method. + */ + int (*stop_recognition)(const struct sound_trigger_hw_device *dev, + sound_model_handle_t sound_model_handle); + + /* set parameters on a given model. + * The function accepts a list of + * parameter key value pairs in the form: key1=value1;key2=value2;... + */ + int (*set_parameters)(const struct sound_trigger_hw_device *dev, + sound_model_handle_t sound_model_handle, + const char *kv_pairs); +}; + +typedef struct sound_trigger_hw_device sound_trigger_hw_device_t; + +/** convenience API for opening and closing a supported device */ + +static inline int sound_trigger_hw_device_open(const struct hw_module_t* module, + struct sound_trigger_hw_device** device) +{ + return module->methods->open(module, SOUND_TRIGGER_HARDWARE_INTERFACE, + (struct hw_device_t**)device); +} + +static inline int sound_trigger_hw_device_close(struct sound_trigger_hw_device* device) +{ + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_SOUND_TRIGGER_HAL_H
diff --git a/libhardware/include/hardware/tv_input.h b/libhardware/include/hardware/tv_input.h new file mode 100644 index 0000000..ed3fafb --- /dev/null +++ b/libhardware/include/hardware/tv_input.h
@@ -0,0 +1,405 @@ +/* + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_TV_INPUT_INTERFACE_H +#define ANDROID_TV_INPUT_INTERFACE_H + +#include <stdint.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <hardware/hardware.h> +#include <system/audio.h> +#include <system/window.h> + +__BEGIN_DECLS + +/* + * Module versioning information for the TV input hardware module, based on + * tv_input_module_t.common.module_api_version. + * + * Version History: + * + * TV_INPUT_MODULE_API_VERSION_0_1: + * Initial TV input hardware module API. + * + */ + +#define TV_INPUT_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +#define TV_INPUT_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION(0, 1) + +/* + * The id of this module + */ +#define TV_INPUT_HARDWARE_MODULE_ID "tv_input" + +#define TV_INPUT_DEFAULT_DEVICE "default" + +/*****************************************************************************/ + +/* + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct tv_input_module { + struct hw_module_t common; +} tv_input_module_t; + +/*****************************************************************************/ + +enum { + /* Generic hardware. */ + TV_INPUT_TYPE_OTHER_HARDWARE = 1, + /* Tuner. (e.g. built-in terrestrial tuner) */ + TV_INPUT_TYPE_TUNER = 2, + TV_INPUT_TYPE_COMPOSITE = 3, + TV_INPUT_TYPE_SVIDEO = 4, + TV_INPUT_TYPE_SCART = 5, + TV_INPUT_TYPE_COMPONENT = 6, + TV_INPUT_TYPE_VGA = 7, + TV_INPUT_TYPE_DVI = 8, + /* Physical HDMI port. (e.g. HDMI 1) */ + TV_INPUT_TYPE_HDMI = 9, + TV_INPUT_TYPE_DISPLAY_PORT = 10, +}; +typedef uint32_t tv_input_type_t; + +typedef struct tv_input_device_info { + /* Device ID */ + int device_id; + + /* Type of physical TV input. */ + tv_input_type_t type; + + union { + struct { + /* HDMI port ID number */ + uint32_t port_id; + } hdmi; + + /* TODO: add other type specific information. */ + + int32_t type_info_reserved[16]; + }; + + /* TODO: Add capability if necessary. */ + + /* + * Audio info + * + * audio_type == AUDIO_DEVICE_NONE if this input has no audio. + */ + audio_devices_t audio_type; + const char* audio_address; + + int32_t reserved[16]; +} tv_input_device_info_t; + +/* See tv_input_event_t for more details. */ +enum { + /* + * Hardware notifies the framework that a device is available. + * + * Note that DEVICE_AVAILABLE and DEVICE_UNAVAILABLE events do not represent + * hotplug events (i.e. plugging cable into or out of the physical port). + * These events notify the framework whether the port is available or not. + * For a concrete example, when a user plugs in or pulls out the HDMI cable + * from a HDMI port, it does not generate DEVICE_AVAILABLE and/or + * DEVICE_UNAVAILABLE events. However, if a user inserts a pluggable USB + * tuner into the Android device, it will generate a DEVICE_AVAILABLE event + * and when the port is removed, it should generate a DEVICE_UNAVAILABLE + * event. + * + * For hotplug events, please see STREAM_CONFIGURATION_CHANGED for more + * details. + * + * HAL implementation should register devices by using this event when the + * device boots up. The framework will recognize device reported via this + * event only. In addition, the implementation could use this event to + * notify the framework that a removable TV input device (such as USB tuner + * as stated in the example above) is attached. + */ + TV_INPUT_EVENT_DEVICE_AVAILABLE = 1, + /* + * Hardware notifies the framework that a device is unavailable. + * + * HAL implementation should generate this event when a device registered + * by TV_INPUT_EVENT_DEVICE_AVAILABLE is no longer available. For example, + * the event can indicate that a USB tuner is plugged out from the Android + * device. + * + * Note that this event is not for indicating cable plugged out of the port; + * for that purpose, the implementation should use + * STREAM_CONFIGURATION_CHANGED event. This event represents the port itself + * being no longer available. + */ + TV_INPUT_EVENT_DEVICE_UNAVAILABLE = 2, + /* + * Stream configurations are changed. Client should regard all open streams + * at the specific device are closed, and should call + * get_stream_configurations() again, opening some of them if necessary. + * + * HAL implementation should generate this event when the available stream + * configurations change for any reason. A typical use case of this event + * would be to notify the framework that the input signal has changed + * resolution, or that the cable is plugged out so that the number of + * available streams is 0. + * + * The implementation may use this event to indicate hotplug status of the + * port. the framework regards input devices with no available streams as + * disconnected, so the implementation can generate this event with no + * available streams to indicate that this device is disconnected, and vice + * versa. + */ + TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED = 3, + /* + * Hardware is done with capture request with the buffer. Client can assume + * ownership of the buffer again. + * + * HAL implementation should generate this event after request_capture() if + * it succeeded. The event shall have the buffer with the captured image. + */ + TV_INPUT_EVENT_CAPTURE_SUCCEEDED = 4, + /* + * Hardware met a failure while processing a capture request or client + * canceled the request. Client can assume ownership of the buffer again. + * + * The event is similar to TV_INPUT_EVENT_CAPTURE_SUCCEEDED, but HAL + * implementation generates this event upon a failure to process + * request_capture(), or a request cancellation. + */ + TV_INPUT_EVENT_CAPTURE_FAILED = 5, +}; +typedef uint32_t tv_input_event_type_t; + +typedef struct tv_input_capture_result { + /* Device ID */ + int device_id; + + /* Stream ID */ + int stream_id; + + /* Sequence number of the request */ + uint32_t seq; + + /* + * The buffer passed to hardware in request_capture(). The content of + * buffer is undefined (although buffer itself is valid) for + * TV_INPUT_CAPTURE_FAILED event. + */ + buffer_handle_t buffer; + + /* + * Error code for the request. -ECANCELED if request is cancelled; other + * error codes are unknown errors. + */ + int error_code; +} tv_input_capture_result_t; + +typedef struct tv_input_event { + tv_input_event_type_t type; + + union { + /* + * TV_INPUT_EVENT_DEVICE_AVAILABLE: all fields are relevant + * TV_INPUT_EVENT_DEVICE_UNAVAILABLE: only device_id is relevant + * TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: only device_id is + * relevant + */ + tv_input_device_info_t device_info; + /* + * TV_INPUT_EVENT_CAPTURE_SUCCEEDED: error_code is not relevant + * TV_INPUT_EVENT_CAPTURE_FAILED: all fields are relevant + */ + tv_input_capture_result_t capture_result; + }; +} tv_input_event_t; + +typedef struct tv_input_callback_ops { + /* + * event contains the type of the event and additional data if necessary. + * The event object is guaranteed to be valid only for the duration of the + * call. + * + * data is an object supplied at device initialization, opaque to the + * hardware. + */ + void (*notify)(struct tv_input_device* dev, + tv_input_event_t* event, void* data); +} tv_input_callback_ops_t; + +enum { + TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE = 1, + TV_STREAM_TYPE_BUFFER_PRODUCER = 2, +}; +typedef uint32_t tv_stream_type_t; + +typedef struct tv_stream_config { + /* + * ID number of the stream. This value is used to identify the whole stream + * configuration. + */ + int stream_id; + + /* Type of the stream */ + tv_stream_type_t type; + + /* Max width/height of the stream. */ + uint32_t max_video_width; + uint32_t max_video_height; +} tv_stream_config_t; + +typedef struct buffer_producer_stream { + /* + * IN/OUT: Width / height of the stream. Client may request for specific + * size but hardware may change it. Client must allocate buffers with + * specified width and height. + */ + uint32_t width; + uint32_t height; + + /* OUT: Client must set this usage when allocating buffer. */ + uint32_t usage; + + /* OUT: Client must allocate a buffer with this format. */ + uint32_t format; +} buffer_producer_stream_t; + +typedef struct tv_stream { + /* IN: ID in the stream configuration */ + int stream_id; + + /* OUT: Type of the stream (for convenience) */ + tv_stream_type_t type; + + /* Data associated with the stream for client's use */ + union { + /* OUT: A native handle describing the sideband stream source */ + native_handle_t* sideband_stream_source_handle; + + /* IN/OUT: Details are in buffer_producer_stream_t */ + buffer_producer_stream_t buffer_producer; + }; +} tv_stream_t; + +/* + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ +typedef struct tv_input_device { + struct hw_device_t common; + + /* + * initialize: + * + * Provide callbacks to the device and start operation. At first, no device + * is available and after initialize() completes, currently available + * devices including static devices should notify via callback. + * + * Framework owns callbacks object. + * + * data is a framework-owned object which would be sent back to the + * framework for each callback notifications. + * + * Return 0 on success. + */ + int (*initialize)(struct tv_input_device* dev, + const tv_input_callback_ops_t* callback, void* data); + + /* + * get_stream_configurations: + * + * Get stream configurations for a specific device. An input device may have + * multiple configurations. + * + * The configs object is guaranteed to be valid only until the next call to + * get_stream_configurations() or STREAM_CONFIGURATIONS_CHANGED event. + * + * Return 0 on success. + */ + int (*get_stream_configurations)(const struct tv_input_device* dev, + int device_id, int* num_configurations, + const tv_stream_config_t** configs); + + /* + * open_stream: + * + * Open a stream with given stream ID. Caller owns stream object, and the + * populated data is only valid until the stream is closed. + * + * Return 0 on success; -EBUSY if the client should close other streams to + * open the stream; -EEXIST if the stream with the given ID is already open; + * -EINVAL if device_id and/or stream_id are invalid; other non-zero value + * denotes unknown error. + */ + int (*open_stream)(struct tv_input_device* dev, int device_id, + tv_stream_t* stream); + + /* + * close_stream: + * + * Close a stream to a device. data in tv_stream_t* object associated with + * the stream_id is obsolete once this call finishes. + * + * Return 0 on success; -ENOENT if the stream is not open; -EINVAL if + * device_id and/or stream_id are invalid. + */ + int (*close_stream)(struct tv_input_device* dev, int device_id, + int stream_id); + + /* + * request_capture: + * + * Request buffer capture for a stream. This is only valid for buffer + * producer streams. The buffer should be created with size, format and + * usage specified in the stream. Framework provides seq in an + * increasing sequence per each stream. Hardware should provide the picture + * in a chronological order according to seq. For example, if two + * requests are being processed at the same time, the request with the + * smaller seq should get an earlier frame. + * + * The framework releases the ownership of the buffer upon calling this + * function. When the buffer is filled, hardware notifies the framework + * via TV_INPUT_EVENT_CAPTURE_FINISHED callback, and the ownership is + * transferred back to framework at that time. + * + * Return 0 on success; -ENOENT if the stream is not open; -EINVAL if + * device_id and/or stream_id are invalid; -EWOULDBLOCK if HAL cannot take + * additional requests until it releases a buffer. + */ + int (*request_capture)(struct tv_input_device* dev, int device_id, + int stream_id, buffer_handle_t buffer, uint32_t seq); + + /* + * cancel_capture: + * + * Cancel an ongoing capture. Hardware should release the buffer as soon as + * possible via TV_INPUT_EVENT_CAPTURE_FAILED callback. + * + * Return 0 on success; -ENOENT if the stream is not open; -EINVAL if + * device_id, stream_id, and/or seq are invalid. + */ + int (*cancel_capture)(struct tv_input_device* dev, int device_id, + int stream_id, uint32_t seq); + + void* reserved[16]; +} tv_input_device_t; + +__END_DECLS + +#endif // ANDROID_TV_INPUT_INTERFACE_H
diff --git a/libhardware/include/hardware/vibrator.h b/libhardware/include/hardware/vibrator.h new file mode 100644 index 0000000..200adf0 --- /dev/null +++ b/libhardware/include/hardware/vibrator.h
@@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 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 _HARDWARE_VIBRATOR_H +#define _HARDWARE_VIBRATOR_H + +#include <hardware/hardware.h> + +__BEGIN_DECLS + +#define VIBRATOR_API_VERSION HARDWARE_MODULE_API_VERSION(1,0) + +/** + * The id of this module + */ +#define VIBRATOR_HARDWARE_MODULE_ID "vibrator" + +/** + * The id of the main vibrator device + */ +#define VIBRATOR_DEVICE_ID_MAIN "main_vibrator" + +struct vibrator_device; +typedef struct vibrator_device { + /** + * Common methods of the vibrator device. This *must* be the first member of + * vibrator_device as users of this structure will cast a hw_device_t to + * vibrator_device pointer in contexts where it's known the hw_device_t references a + * vibrator_device. + */ + struct hw_device_t common; + + /** Turn on vibrator + * + * This function must only be called after the previous timeout has expired or + * was canceled (through vibrator_off()). + * + * @param timeout_ms number of milliseconds to vibrate + * + * @return 0 in case of success, negative errno code else + */ + int (*vibrator_on)(struct vibrator_device* vibradev, unsigned int timeout_ms); + + /** Turn off vibrator + * + * Cancel a previously-started vibration, if any. + * + * @return 0 in case of success, negative errno code else + */ + int (*vibrator_off)(struct vibrator_device* vibradev); +} vibrator_device_t; + +static inline int vibrator_open(const struct hw_module_t* module, vibrator_device_t** device) +{ + return module->methods->open(module, VIBRATOR_DEVICE_ID_MAIN, (struct hw_device_t**)device); +} + +__END_DECLS + +#endif // _HARDWARE_VIBRATOR_H
diff --git a/libhardware/modules/Android.mk b/libhardware/modules/Android.mk new file mode 100644 index 0000000..c62b2db --- /dev/null +++ b/libhardware/modules/Android.mk
@@ -0,0 +1,3 @@ +hardware_modules := gralloc hwcomposer \ + usbaudio audio_remote_submix camera usbcamera sensors input +include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/libhardware/modules/README.android b/libhardware/modules/README.android new file mode 100644 index 0000000..57abb72 --- /dev/null +++ b/libhardware/modules/README.android
@@ -0,0 +1,23 @@ +Default (and possibly architecture dependents) HAL modules go here. + + +libhardware.so eventually should contain *just* the HAL hub +(hardware.c), everything in it should be rewritten as modules. + +Modules are .so in /system/libs/hw/ and have a well defined naming +convention: + + /system/libs/hw/<*_HARDWARE_MODULE_ID>.<ro.product.board>.so + /system/libs/hw/<*_HARDWARE_MODULE_ID>.<ro.board.platform>.so + /system/libs/hw/<*_HARDWARE_MODULE_ID>.<ro.arch>.so + /system/libs/hw/<*_HARDWARE_MODULE_ID>.default.so + +They also have a well defined interface which lives in include/hardware/. + +A module can have several variants: "default", "arch" and "board", and they're +loaded in the "board", "arch" and "default" order. +The source code for the "board" variant, usually lives under partners/... + +The source code for "default" and "arch" would usually +live under hardware/modules/. +
diff --git a/libhardware/modules/audio/Android.bp b/libhardware/modules/audio/Android.bp new file mode 100644 index 0000000..02da2b3 --- /dev/null +++ b/libhardware/modules/audio/Android.bp
@@ -0,0 +1,60 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The default audio HAL module, which is a stub, that is loaded if no other +// device specific modules are present. The exact load order can be seen in +// libhardware/hardware.c +// +// The format of the name is audio.<type>.<hardware/etc>.so where the only +// required type is 'primary'. Other possibilites are 'a2dp', 'usb', etc. +cc_library_shared { + name: "audio.primary.default", + relative_install_path: "hw", + srcs: ["audio_hw.c"], + shared_libs: [ + "liblog", + "libcutils", + ], + cflags: ["-Wno-unused-parameter"], +} + +// The stub audio HAL module, identical to the default audio hal, but with +// different name to be loaded concurrently with other audio HALs if necessary. +// This can also be used as skeleton for new implementations +// +// The format of the name is audio.<type>.<hardware/etc>.so where the only +// required type is 'primary'. Other possibilites are 'a2dp', 'usb', etc. +cc_library_shared { + name: "audio.stub.default", + relative_install_path: "hw", + srcs: ["audio_hw.c"], + shared_libs: [ + "liblog", + "libcutils", + ], + cflags: ["-Wno-unused-parameter"], +} + +// The stub audio policy HAL module that can be used as a skeleton for +// new implementations. +cc_library_shared { + name: "audio_policy.stub", + relative_install_path: "hw", + srcs: ["audio_policy.c"], + shared_libs: [ + "liblog", + "libcutils", + ], + cflags: ["-Wno-unused-parameter"], +}
diff --git a/libhardware/modules/audio/audio_hw.c b/libhardware/modules/audio/audio_hw.c new file mode 100644 index 0000000..a1a322f --- /dev/null +++ b/libhardware/modules/audio/audio_hw.c
@@ -0,0 +1,489 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "audio_hw_default" +//#define LOG_NDEBUG 0 + +#include <errno.h> +#include <malloc.h> +#include <pthread.h> +#include <stdint.h> +#include <sys/time.h> + +#include <cutils/log.h> + +#include <hardware/hardware.h> +#include <system/audio.h> +#include <hardware/audio.h> + +struct stub_audio_device { + struct audio_hw_device device; +}; + +struct stub_stream_out { + struct audio_stream_out stream; +}; + +struct stub_stream_in { + struct audio_stream_in stream; +}; + +static uint32_t out_get_sample_rate(const struct audio_stream *stream) +{ + return 44100; +} + +static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + ALOGV("out_set_sample_rate: %d", 0); + return -ENOSYS; +} + +static size_t out_get_buffer_size(const struct audio_stream *stream) +{ + ALOGV("out_get_buffer_size: %d", 4096); + return 4096; +} + +static audio_channel_mask_t out_get_channels(const struct audio_stream *stream) +{ + ALOGV("out_get_channels"); + return AUDIO_CHANNEL_OUT_STEREO; +} + +static audio_format_t out_get_format(const struct audio_stream *stream) +{ + ALOGV("out_get_format"); + return AUDIO_FORMAT_PCM_16_BIT; +} + +static int out_set_format(struct audio_stream *stream, audio_format_t format) +{ + ALOGV("out_set_format: %d",format); + return -ENOSYS; +} + +static int out_standby(struct audio_stream *stream) +{ + ALOGV("out_standby"); + + return 0; +} + +static int out_dump(const struct audio_stream *stream, int fd) +{ + ALOGV("out_dump"); + return 0; +} + +static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + ALOGV("out_set_parameters"); + return 0; +} + +static char * out_get_parameters(const struct audio_stream *stream, const char *keys) +{ + ALOGV("out_get_parameters"); + return strdup(""); +} + +static uint32_t out_get_latency(const struct audio_stream_out *stream) +{ + ALOGV("out_get_latency"); + return 0; +} + +static int out_set_volume(struct audio_stream_out *stream, float left, + float right) +{ + ALOGV("out_set_volume: Left:%f Right:%f", left, right); + return 0; +} + +static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, + size_t bytes) +{ + ALOGV("out_write: bytes: %d", bytes); + /* XXX: fake timing for audio output */ + usleep((int64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) / + out_get_sample_rate(&stream->common)); + return bytes; +} + +static int out_get_render_position(const struct audio_stream_out *stream, + uint32_t *dsp_frames) +{ + *dsp_frames = 0; + ALOGV("out_get_render_position: dsp_frames: %p", dsp_frames); + return -EINVAL; +} + +static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + ALOGV("out_add_audio_effect: %p", effect); + return 0; +} + +static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + ALOGV("out_remove_audio_effect: %p", effect); + return 0; +} + +static int out_get_next_write_timestamp(const struct audio_stream_out *stream, + int64_t *timestamp) +{ + *timestamp = 0; + ALOGV("out_get_next_write_timestamp: %ld", (long int)(*timestamp)); + return -EINVAL; +} + +/** audio_stream_in implementation **/ +static uint32_t in_get_sample_rate(const struct audio_stream *stream) +{ + ALOGV("in_get_sample_rate"); + return 8000; +} + +static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + ALOGV("in_set_sample_rate: %d", rate); + return -ENOSYS; +} + +static size_t in_get_buffer_size(const struct audio_stream *stream) +{ + ALOGV("in_get_buffer_size: %d", 320); + return 320; +} + +static audio_channel_mask_t in_get_channels(const struct audio_stream *stream) +{ + ALOGV("in_get_channels: %d", AUDIO_CHANNEL_IN_MONO); + return AUDIO_CHANNEL_IN_MONO; +} + +static audio_format_t in_get_format(const struct audio_stream *stream) +{ + return AUDIO_FORMAT_PCM_16_BIT; +} + +static int in_set_format(struct audio_stream *stream, audio_format_t format) +{ + return -ENOSYS; +} + +static int in_standby(struct audio_stream *stream) +{ + return 0; +} + +static int in_dump(const struct audio_stream *stream, int fd) +{ + return 0; +} + +static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + return 0; +} + +static char * in_get_parameters(const struct audio_stream *stream, + const char *keys) +{ + return strdup(""); +} + +static int in_set_gain(struct audio_stream_in *stream, float gain) +{ + return 0; +} + +static ssize_t in_read(struct audio_stream_in *stream, void* buffer, + size_t bytes) +{ + ALOGV("in_read: bytes %d", bytes); + /* XXX: fake timing for audio input */ + usleep((int64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) / + in_get_sample_rate(&stream->common)); + memset(buffer, 0, bytes); + return bytes; +} + +static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) +{ + return 0; +} + +static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + return 0; +} + +static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + return 0; +} + +static int adev_open_output_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out, + const char *address __unused) +{ + ALOGV("adev_open_output_stream..."); + + struct stub_audio_device *ladev = (struct stub_audio_device *)dev; + struct stub_stream_out *out; + int ret; + + out = (struct stub_stream_out *)calloc(1, sizeof(struct stub_stream_out)); + if (!out) + return -ENOMEM; + + out->stream.common.get_sample_rate = out_get_sample_rate; + out->stream.common.set_sample_rate = out_set_sample_rate; + out->stream.common.get_buffer_size = out_get_buffer_size; + out->stream.common.get_channels = out_get_channels; + out->stream.common.get_format = out_get_format; + out->stream.common.set_format = out_set_format; + out->stream.common.standby = out_standby; + out->stream.common.dump = out_dump; + out->stream.common.set_parameters = out_set_parameters; + out->stream.common.get_parameters = out_get_parameters; + out->stream.common.add_audio_effect = out_add_audio_effect; + out->stream.common.remove_audio_effect = out_remove_audio_effect; + out->stream.get_latency = out_get_latency; + out->stream.set_volume = out_set_volume; + out->stream.write = out_write; + out->stream.get_render_position = out_get_render_position; + out->stream.get_next_write_timestamp = out_get_next_write_timestamp; + + *stream_out = &out->stream; + return 0; + +err_open: + free(out); + *stream_out = NULL; + return ret; +} + +static void adev_close_output_stream(struct audio_hw_device *dev, + struct audio_stream_out *stream) +{ + ALOGV("adev_close_output_stream..."); + free(stream); +} + +static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) +{ + ALOGV("adev_set_parameters"); + return -ENOSYS; +} + +static char * adev_get_parameters(const struct audio_hw_device *dev, + const char *keys) +{ + ALOGV("adev_get_parameters"); + return strdup(""); +} + +static int adev_init_check(const struct audio_hw_device *dev) +{ + ALOGV("adev_init_check"); + return 0; +} + +static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) +{ + ALOGV("adev_set_voice_volume: %f", volume); + return -ENOSYS; +} + +static int adev_set_master_volume(struct audio_hw_device *dev, float volume) +{ + ALOGV("adev_set_master_volume: %f", volume); + return -ENOSYS; +} + +static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) +{ + ALOGV("adev_get_master_volume: %f", *volume); + return -ENOSYS; +} + +static int adev_set_master_mute(struct audio_hw_device *dev, bool muted) +{ + ALOGV("adev_set_master_mute: %d", muted); + return -ENOSYS; +} + +static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted) +{ + ALOGV("adev_get_master_mute: %d", *muted); + return -ENOSYS; +} + +static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) +{ + ALOGV("adev_set_mode: %d", mode); + return 0; +} + +static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) +{ + ALOGV("adev_set_mic_mute: %d",state); + return -ENOSYS; +} + +static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) +{ + ALOGV("adev_get_mic_mute"); + return -ENOSYS; +} + +static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, + const struct audio_config *config) +{ + ALOGV("adev_get_input_buffer_size: %d", 320); + return 320; +} + +static int adev_open_input_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in, + audio_input_flags_t flags __unused, + const char *address __unused, + audio_source_t source __unused) +{ + ALOGV("adev_open_input_stream..."); + + struct stub_audio_device *ladev = (struct stub_audio_device *)dev; + struct stub_stream_in *in; + int ret; + + in = (struct stub_stream_in *)calloc(1, sizeof(struct stub_stream_in)); + if (!in) + return -ENOMEM; + + in->stream.common.get_sample_rate = in_get_sample_rate; + in->stream.common.set_sample_rate = in_set_sample_rate; + in->stream.common.get_buffer_size = in_get_buffer_size; + in->stream.common.get_channels = in_get_channels; + in->stream.common.get_format = in_get_format; + in->stream.common.set_format = in_set_format; + in->stream.common.standby = in_standby; + in->stream.common.dump = in_dump; + in->stream.common.set_parameters = in_set_parameters; + in->stream.common.get_parameters = in_get_parameters; + in->stream.common.add_audio_effect = in_add_audio_effect; + in->stream.common.remove_audio_effect = in_remove_audio_effect; + in->stream.set_gain = in_set_gain; + in->stream.read = in_read; + in->stream.get_input_frames_lost = in_get_input_frames_lost; + + *stream_in = &in->stream; + return 0; + +err_open: + free(in); + *stream_in = NULL; + return ret; +} + +static void adev_close_input_stream(struct audio_hw_device *dev, + struct audio_stream_in *in) +{ + ALOGV("adev_close_input_stream..."); + return; +} + +static int adev_dump(const audio_hw_device_t *device, int fd) +{ + ALOGV("adev_dump"); + return 0; +} + +static int adev_close(hw_device_t *device) +{ + ALOGV("adev_close"); + free(device); + return 0; +} + +static int adev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + ALOGV("adev_open: %s", name); + + struct stub_audio_device *adev; + int ret; + + if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) + return -EINVAL; + + adev = calloc(1, sizeof(struct stub_audio_device)); + if (!adev) + return -ENOMEM; + + adev->device.common.tag = HARDWARE_DEVICE_TAG; + adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0; + adev->device.common.module = (struct hw_module_t *) module; + adev->device.common.close = adev_close; + + adev->device.init_check = adev_init_check; + adev->device.set_voice_volume = adev_set_voice_volume; + adev->device.set_master_volume = adev_set_master_volume; + adev->device.get_master_volume = adev_get_master_volume; + adev->device.set_master_mute = adev_set_master_mute; + adev->device.get_master_mute = adev_get_master_mute; + adev->device.set_mode = adev_set_mode; + adev->device.set_mic_mute = adev_set_mic_mute; + adev->device.get_mic_mute = adev_get_mic_mute; + adev->device.set_parameters = adev_set_parameters; + adev->device.get_parameters = adev_get_parameters; + adev->device.get_input_buffer_size = adev_get_input_buffer_size; + adev->device.open_output_stream = adev_open_output_stream; + adev->device.close_output_stream = adev_close_output_stream; + adev->device.open_input_stream = adev_open_input_stream; + adev->device.close_input_stream = adev_close_input_stream; + adev->device.dump = adev_dump; + + *device = &adev->device.common; + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + .open = adev_open, +}; + +struct audio_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = AUDIO_MODULE_API_VERSION_0_1, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = AUDIO_HARDWARE_MODULE_ID, + .name = "Default audio HW HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +};
diff --git a/libhardware/modules/audio/audio_policy.c b/libhardware/modules/audio/audio_policy.c new file mode 100644 index 0000000..9335654 --- /dev/null +++ b/libhardware/modules/audio/audio_policy.c
@@ -0,0 +1,352 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "audio_policy_default" +//#define LOG_NDEBUG 0 + +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <hardware/hardware.h> +#include <system/audio.h> +#include <system/audio_policy.h> +#include <hardware/audio_policy.h> + +struct default_ap_module { + struct audio_policy_module module; +}; + +struct default_ap_device { + struct audio_policy_device device; +}; + +struct default_audio_policy { + struct audio_policy policy; + + struct audio_policy_service_ops *aps_ops; + void *service; +}; + +static int ap_set_device_connection_state(struct audio_policy *pol, + audio_devices_t device, + audio_policy_dev_state_t state, + const char *device_address) +{ + return -ENOSYS; +} + +static audio_policy_dev_state_t ap_get_device_connection_state( + const struct audio_policy *pol, + audio_devices_t device, + const char *device_address) +{ + return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; +} + +static void ap_set_phone_state(struct audio_policy *pol, audio_mode_t state) +{ +} + +// deprecated, never called +static void ap_set_ringer_mode(struct audio_policy *pol, uint32_t mode, + uint32_t mask) +{ +} + +static void ap_set_force_use(struct audio_policy *pol, + audio_policy_force_use_t usage, + audio_policy_forced_cfg_t config) +{ +} + + /* retreive current device category forced for a given usage */ +static audio_policy_forced_cfg_t ap_get_force_use( + const struct audio_policy *pol, + audio_policy_force_use_t usage) +{ + return AUDIO_POLICY_FORCE_NONE; +} + +/* if can_mute is true, then audio streams that are marked ENFORCED_AUDIBLE + * can still be muted. */ +static void ap_set_can_mute_enforced_audible(struct audio_policy *pol, + bool can_mute) +{ +} + +static int ap_init_check(const struct audio_policy *pol) +{ + return 0; +} + +static audio_io_handle_t ap_get_output(struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t sampling_rate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *info) +{ + return 0; +} + +static int ap_start_output(struct audio_policy *pol, audio_io_handle_t output, + audio_stream_type_t stream, int session) +{ + return -ENOSYS; +} + +static int ap_stop_output(struct audio_policy *pol, audio_io_handle_t output, + audio_stream_type_t stream, int session) +{ + return -ENOSYS; +} + +static void ap_release_output(struct audio_policy *pol, + audio_io_handle_t output) +{ +} + +static audio_io_handle_t ap_get_input(struct audio_policy *pol, audio_source_t inputSource, + uint32_t sampling_rate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_in_acoustics_t acoustics) +{ + return 0; +} + +static int ap_start_input(struct audio_policy *pol, audio_io_handle_t input) +{ + return -ENOSYS; +} + +static int ap_stop_input(struct audio_policy *pol, audio_io_handle_t input) +{ + return -ENOSYS; +} + +static void ap_release_input(struct audio_policy *pol, audio_io_handle_t input) +{ +} + +static void ap_init_stream_volume(struct audio_policy *pol, + audio_stream_type_t stream, int index_min, + int index_max) +{ +} + +static int ap_set_stream_volume_index(struct audio_policy *pol, + audio_stream_type_t stream, + int index) +{ + return -ENOSYS; +} + +static int ap_get_stream_volume_index(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index) +{ + return -ENOSYS; +} + +static int ap_set_stream_volume_index_for_device(struct audio_policy *pol, + audio_stream_type_t stream, + int index, + audio_devices_t device) +{ + return -ENOSYS; +} + +static int ap_get_stream_volume_index_for_device(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index, + audio_devices_t device) +{ + return -ENOSYS; +} + +static uint32_t ap_get_strategy_for_stream(const struct audio_policy *pol, + audio_stream_type_t stream) +{ + return 0; +} + +static audio_devices_t ap_get_devices_for_stream(const struct audio_policy *pol, + audio_stream_type_t stream) +{ + return 0; +} + +static audio_io_handle_t ap_get_output_for_effect(struct audio_policy *pol, + const struct effect_descriptor_s *desc) +{ + return 0; +} + +static int ap_register_effect(struct audio_policy *pol, + const struct effect_descriptor_s *desc, + audio_io_handle_t output, + uint32_t strategy, + int session, + int id) +{ + return -ENOSYS; +} + +static int ap_unregister_effect(struct audio_policy *pol, int id) +{ + return -ENOSYS; +} + +static int ap_set_effect_enabled(struct audio_policy *pol, int id, bool enabled) +{ + return -ENOSYS; +} + +static bool ap_is_stream_active(const struct audio_policy *pol, audio_stream_type_t stream, + uint32_t in_past_ms) +{ + return false; +} + +static int ap_dump(const struct audio_policy *pol, int fd) +{ + return -ENOSYS; +} + +static bool ap_is_offload_supported(const struct audio_policy *pol, + const audio_offload_info_t *info) +{ + return false; +} + +static int create_default_ap(const struct audio_policy_device *device, + struct audio_policy_service_ops *aps_ops, + void *service, + struct audio_policy **ap) +{ + struct default_ap_device *dev; + struct default_audio_policy *dap; + int ret; + + *ap = NULL; + + if (!service || !aps_ops) + return -EINVAL; + + dap = (struct default_audio_policy *)calloc(1, sizeof(*dap)); + if (!dap) + return -ENOMEM; + + dap->policy.set_device_connection_state = ap_set_device_connection_state; + dap->policy.get_device_connection_state = ap_get_device_connection_state; + dap->policy.set_phone_state = ap_set_phone_state; + dap->policy.set_ringer_mode = ap_set_ringer_mode; + dap->policy.set_force_use = ap_set_force_use; + dap->policy.get_force_use = ap_get_force_use; + dap->policy.set_can_mute_enforced_audible = + ap_set_can_mute_enforced_audible; + dap->policy.init_check = ap_init_check; + dap->policy.get_output = ap_get_output; + dap->policy.start_output = ap_start_output; + dap->policy.stop_output = ap_stop_output; + dap->policy.release_output = ap_release_output; + dap->policy.get_input = ap_get_input; + dap->policy.start_input = ap_start_input; + dap->policy.stop_input = ap_stop_input; + dap->policy.release_input = ap_release_input; + dap->policy.init_stream_volume = ap_init_stream_volume; + dap->policy.set_stream_volume_index = ap_set_stream_volume_index; + dap->policy.get_stream_volume_index = ap_get_stream_volume_index; + dap->policy.set_stream_volume_index_for_device = ap_set_stream_volume_index_for_device; + dap->policy.get_stream_volume_index_for_device = ap_get_stream_volume_index_for_device; + dap->policy.get_strategy_for_stream = ap_get_strategy_for_stream; + dap->policy.get_devices_for_stream = ap_get_devices_for_stream; + dap->policy.get_output_for_effect = ap_get_output_for_effect; + dap->policy.register_effect = ap_register_effect; + dap->policy.unregister_effect = ap_unregister_effect; + dap->policy.set_effect_enabled = ap_set_effect_enabled; + dap->policy.is_stream_active = ap_is_stream_active; + dap->policy.dump = ap_dump; + + dap->policy.is_offload_supported = ap_is_offload_supported; + + dap->service = service; + dap->aps_ops = aps_ops; + + *ap = &dap->policy; + return 0; +} + +static int destroy_default_ap(const struct audio_policy_device *ap_dev, + struct audio_policy *ap) +{ + free(ap); + return 0; +} + +static int default_ap_dev_close(hw_device_t* device) +{ + free(device); + return 0; +} + +static int default_ap_dev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + struct default_ap_device *dev; + + *device = NULL; + + if (strcmp(name, AUDIO_POLICY_INTERFACE) != 0) + return -EINVAL; + + dev = (struct default_ap_device *)calloc(1, sizeof(*dev)); + if (!dev) + return -ENOMEM; + + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = (hw_module_t *)module; + dev->device.common.close = default_ap_dev_close; + dev->device.create_audio_policy = create_default_ap; + dev->device.destroy_audio_policy = destroy_default_ap; + + *device = &dev->device.common; + + return 0; +} + +static struct hw_module_methods_t default_ap_module_methods = { + .open = default_ap_dev_open, +}; + +struct default_ap_module HAL_MODULE_INFO_SYM = { + .module = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = AUDIO_POLICY_HARDWARE_MODULE_ID, + .name = "Default audio policy HAL", + .author = "The Android Open Source Project", + .methods = &default_ap_module_methods, + }, + }, +};
diff --git a/libhardware/modules/audio_remote_submix/Android.mk b/libhardware/modules/audio_remote_submix/Android.mk new file mode 100644 index 0000000..90da396 --- /dev/null +++ b/libhardware/modules/audio_remote_submix/Android.mk
@@ -0,0 +1,32 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := audio.r_submix.default +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + audio_hw.cpp +LOCAL_C_INCLUDES += \ + frameworks/av/include/ \ + frameworks/native/include/ +LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libnbaio +LOCAL_STATIC_LIBRARIES := libmedia_helper +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -Wno-unused-parameter + +include $(BUILD_SHARED_LIBRARY) +
diff --git a/libhardware/modules/audio_remote_submix/audio_hw.cpp b/libhardware/modules/audio_remote_submix/audio_hw.cpp new file mode 100644 index 0000000..ed3d311 --- /dev/null +++ b/libhardware/modules/audio_remote_submix/audio_hw.cpp
@@ -0,0 +1,1782 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "r_submix" +//#define LOG_NDEBUG 0 + +#include <errno.h> +#include <pthread.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/limits.h> + +#include <cutils/compiler.h> +#include <cutils/log.h> +#include <cutils/properties.h> +#include <cutils/str_parms.h> + +#include <hardware/audio.h> +#include <hardware/hardware.h> +#include <system/audio.h> + +#include <media/AudioParameter.h> +#include <media/AudioBufferProvider.h> +#include <media/nbaio/MonoPipe.h> +#include <media/nbaio/MonoPipeReader.h> + +#include <utils/String8.h> + +#define LOG_STREAMS_TO_FILES 0 +#if LOG_STREAMS_TO_FILES +#include <fcntl.h> +#include <stdio.h> +#include <sys/stat.h> +#endif // LOG_STREAMS_TO_FILES + +extern "C" { + +namespace android { + +// Set to 1 to enable extremely verbose logging in this module. +#define SUBMIX_VERBOSE_LOGGING 0 +#if SUBMIX_VERBOSE_LOGGING +#define SUBMIX_ALOGV(...) ALOGV(__VA_ARGS__) +#define SUBMIX_ALOGE(...) ALOGE(__VA_ARGS__) +#else +#define SUBMIX_ALOGV(...) +#define SUBMIX_ALOGE(...) +#endif // SUBMIX_VERBOSE_LOGGING + +// NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe(). +#define DEFAULT_PIPE_SIZE_IN_FRAMES (1024*4) +// Value used to divide the MonoPipe() buffer into segments that are written to the source and +// read from the sink. The maximum latency of the device is the size of the MonoPipe's buffer +// the minimum latency is the MonoPipe buffer size divided by this value. +#define DEFAULT_PIPE_PERIOD_COUNT 4 +// The duration of MAX_READ_ATTEMPTS * READ_ATTEMPT_SLEEP_MS must be stricly inferior to +// the duration of a record buffer at the current record sample rate (of the device, not of +// the recording itself). Here we have: +// 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms +#define MAX_READ_ATTEMPTS 3 +#define READ_ATTEMPT_SLEEP_MS 5 // 5ms between two read attempts when pipe is empty +#define DEFAULT_SAMPLE_RATE_HZ 48000 // default sample rate +// See NBAIO_Format frameworks/av/include/media/nbaio/NBAIO.h. +#define DEFAULT_FORMAT AUDIO_FORMAT_PCM_16_BIT +// A legacy user of this device does not close the input stream when it shuts down, which +// results in the application opening a new input stream before closing the old input stream +// handle it was previously using. Setting this value to 1 allows multiple clients to open +// multiple input streams from this device. If this option is enabled, each input stream returned +// is *the same stream* which means that readers will race to read data from these streams. +#define ENABLE_LEGACY_INPUT_OPEN 1 +// Whether channel conversion (16-bit signed PCM mono->stereo, stereo->mono) is enabled. +#define ENABLE_CHANNEL_CONVERSION 1 +// Whether resampling is enabled. +#define ENABLE_RESAMPLING 1 +#if LOG_STREAMS_TO_FILES +// Folder to save stream log files to. +#define LOG_STREAM_FOLDER "/data/misc/media" +// Log filenames for input and output streams. +#define LOG_STREAM_OUT_FILENAME LOG_STREAM_FOLDER "/r_submix_out.raw" +#define LOG_STREAM_IN_FILENAME LOG_STREAM_FOLDER "/r_submix_in.raw" +// File permissions for stream log files. +#define LOG_STREAM_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) +#endif // LOG_STREAMS_TO_FILES +// limit for number of read error log entries to avoid spamming the logs +#define MAX_READ_ERROR_LOGS 5 + +// Common limits macros. +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif // min +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif // max + +// Set *result_variable_ptr to true if value_to_find is present in the array array_to_search, +// otherwise set *result_variable_ptr to false. +#define SUBMIX_VALUE_IN_SET(value_to_find, array_to_search, result_variable_ptr) \ + { \ + size_t i; \ + *(result_variable_ptr) = false; \ + for (i = 0; i < sizeof(array_to_search) / sizeof((array_to_search)[0]); i++) { \ + if ((value_to_find) == (array_to_search)[i]) { \ + *(result_variable_ptr) = true; \ + break; \ + } \ + } \ + } + +// Configuration of the submix pipe. +struct submix_config { + // Channel mask field in this data structure is set to either input_channel_mask or + // output_channel_mask depending upon the last stream to be opened on this device. + struct audio_config common; + // Input stream and output stream channel masks. This is required since input and output + // channel bitfields are not equivalent. + audio_channel_mask_t input_channel_mask; + audio_channel_mask_t output_channel_mask; +#if ENABLE_RESAMPLING + // Input stream and output stream sample rates. + uint32_t input_sample_rate; + uint32_t output_sample_rate; +#endif // ENABLE_RESAMPLING + size_t pipe_frame_size; // Number of bytes in each audio frame in the pipe. + size_t buffer_size_frames; // Size of the audio pipe in frames. + // Maximum number of frames buffered by the input and output streams. + size_t buffer_period_size_frames; +}; + +#define MAX_ROUTES 10 +typedef struct route_config { + struct submix_config config; + char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; + // Pipe variables: they handle the ring buffer that "pipes" audio: + // - from the submix virtual audio output == what needs to be played + // remotely, seen as an output for AudioFlinger + // - to the virtual audio source == what is captured by the component + // which "records" the submix / virtual audio source, and handles it as needed. + // A usecase example is one where the component capturing the audio is then sending it over + // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a + // TV with Wifi Display capabilities), or to a wireless audio player. + sp<MonoPipe> rsxSink; + sp<MonoPipeReader> rsxSource; + // Pointers to the current input and output stream instances. rsxSink and rsxSource are + // destroyed if both and input and output streams are destroyed. + struct submix_stream_out *output; + struct submix_stream_in *input; +#if ENABLE_RESAMPLING + // Buffer used as temporary storage for resampled data prior to returning data to the output + // stream. + int16_t resampler_buffer[DEFAULT_PIPE_SIZE_IN_FRAMES]; +#endif // ENABLE_RESAMPLING +} route_config_t; + +struct submix_audio_device { + struct audio_hw_device device; + route_config_t routes[MAX_ROUTES]; + // Device lock, also used to protect access to submix_audio_device from the input and output + // streams. + pthread_mutex_t lock; +}; + +struct submix_stream_out { + struct audio_stream_out stream; + struct submix_audio_device *dev; + int route_handle; + bool output_standby; + uint64_t frames_written; + uint64_t frames_written_since_standby; +#if LOG_STREAMS_TO_FILES + int log_fd; +#endif // LOG_STREAMS_TO_FILES +}; + +struct submix_stream_in { + struct audio_stream_in stream; + struct submix_audio_device *dev; + int route_handle; + bool input_standby; + bool output_standby_rec_thr; // output standby state as seen from record thread + // wall clock when recording starts + struct timespec record_start_time; + // how many frames have been requested to be read + uint64_t read_counter_frames; + +#if ENABLE_LEGACY_INPUT_OPEN + // Number of references to this input stream. + volatile int32_t ref_count; +#endif // ENABLE_LEGACY_INPUT_OPEN +#if LOG_STREAMS_TO_FILES + int log_fd; +#endif // LOG_STREAMS_TO_FILES + + volatile int16_t read_error_count; +}; + +// Determine whether the specified sample rate is supported by the submix module. +static bool sample_rate_supported(const uint32_t sample_rate) +{ + // Set of sample rates supported by Format_from_SR_C() frameworks/av/media/libnbaio/NAIO.cpp. + static const unsigned int supported_sample_rates[] = { + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, + }; + bool return_value; + SUBMIX_VALUE_IN_SET(sample_rate, supported_sample_rates, &return_value); + return return_value; +} + +// Determine whether the specified sample rate is supported, if it is return the specified sample +// rate, otherwise return the default sample rate for the submix module. +static uint32_t get_supported_sample_rate(uint32_t sample_rate) +{ + return sample_rate_supported(sample_rate) ? sample_rate : DEFAULT_SAMPLE_RATE_HZ; +} + +// Determine whether the specified channel in mask is supported by the submix module. +static bool channel_in_mask_supported(const audio_channel_mask_t channel_in_mask) +{ + // Set of channel in masks supported by Format_from_SR_C() + // frameworks/av/media/libnbaio/NAIO.cpp. + static const audio_channel_mask_t supported_channel_in_masks[] = { + AUDIO_CHANNEL_IN_MONO, AUDIO_CHANNEL_IN_STEREO, + }; + bool return_value; + SUBMIX_VALUE_IN_SET(channel_in_mask, supported_channel_in_masks, &return_value); + return return_value; +} + +// Determine whether the specified channel in mask is supported, if it is return the specified +// channel in mask, otherwise return the default channel in mask for the submix module. +static audio_channel_mask_t get_supported_channel_in_mask( + const audio_channel_mask_t channel_in_mask) +{ + return channel_in_mask_supported(channel_in_mask) ? channel_in_mask : + static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_IN_STEREO); +} + +// Determine whether the specified channel out mask is supported by the submix module. +static bool channel_out_mask_supported(const audio_channel_mask_t channel_out_mask) +{ + // Set of channel out masks supported by Format_from_SR_C() + // frameworks/av/media/libnbaio/NAIO.cpp. + static const audio_channel_mask_t supported_channel_out_masks[] = { + AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO, + }; + bool return_value; + SUBMIX_VALUE_IN_SET(channel_out_mask, supported_channel_out_masks, &return_value); + return return_value; +} + +// Determine whether the specified channel out mask is supported, if it is return the specified +// channel out mask, otherwise return the default channel out mask for the submix module. +static audio_channel_mask_t get_supported_channel_out_mask( + const audio_channel_mask_t channel_out_mask) +{ + return channel_out_mask_supported(channel_out_mask) ? channel_out_mask : + static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_OUT_STEREO); +} + +// Get a pointer to submix_stream_out given an audio_stream_out that is embedded within the +// structure. +static struct submix_stream_out * audio_stream_out_get_submix_stream_out( + struct audio_stream_out * const stream) +{ + ALOG_ASSERT(stream); + return reinterpret_cast<struct submix_stream_out *>(reinterpret_cast<uint8_t *>(stream) - + offsetof(struct submix_stream_out, stream)); +} + +// Get a pointer to submix_stream_out given an audio_stream that is embedded within the structure. +static struct submix_stream_out * audio_stream_get_submix_stream_out( + struct audio_stream * const stream) +{ + ALOG_ASSERT(stream); + return audio_stream_out_get_submix_stream_out( + reinterpret_cast<struct audio_stream_out *>(stream)); +} + +// Get a pointer to submix_stream_in given an audio_stream_in that is embedded within the +// structure. +static struct submix_stream_in * audio_stream_in_get_submix_stream_in( + struct audio_stream_in * const stream) +{ + ALOG_ASSERT(stream); + return reinterpret_cast<struct submix_stream_in *>(reinterpret_cast<uint8_t *>(stream) - + offsetof(struct submix_stream_in, stream)); +} + +// Get a pointer to submix_stream_in given an audio_stream that is embedded within the structure. +static struct submix_stream_in * audio_stream_get_submix_stream_in( + struct audio_stream * const stream) +{ + ALOG_ASSERT(stream); + return audio_stream_in_get_submix_stream_in( + reinterpret_cast<struct audio_stream_in *>(stream)); +} + +// Get a pointer to submix_audio_device given a pointer to an audio_device that is embedded within +// the structure. +static struct submix_audio_device * audio_hw_device_get_submix_audio_device( + struct audio_hw_device *device) +{ + ALOG_ASSERT(device); + return reinterpret_cast<struct submix_audio_device *>(reinterpret_cast<uint8_t *>(device) - + offsetof(struct submix_audio_device, device)); +} + +// Compare an audio_config with input channel mask and an audio_config with output channel mask +// returning false if they do *not* match, true otherwise. +static bool audio_config_compare(const audio_config * const input_config, + const audio_config * const output_config) +{ +#if !ENABLE_CHANNEL_CONVERSION + const uint32_t input_channels = audio_channel_count_from_in_mask(input_config->channel_mask); + const uint32_t output_channels = audio_channel_count_from_out_mask(output_config->channel_mask); + if (input_channels != output_channels) { + ALOGE("audio_config_compare() channel count mismatch input=%d vs. output=%d", + input_channels, output_channels); + return false; + } +#endif // !ENABLE_CHANNEL_CONVERSION +#if ENABLE_RESAMPLING + if (input_config->sample_rate != output_config->sample_rate && + audio_channel_count_from_in_mask(input_config->channel_mask) != 1) { +#else + if (input_config->sample_rate != output_config->sample_rate) { +#endif // ENABLE_RESAMPLING + ALOGE("audio_config_compare() sample rate mismatch %ul vs. %ul", + input_config->sample_rate, output_config->sample_rate); + return false; + } + if (input_config->format != output_config->format) { + ALOGE("audio_config_compare() format mismatch %x vs. %x", + input_config->format, output_config->format); + return false; + } + // This purposely ignores offload_info as it's not required for the submix device. + return true; +} + +// If one doesn't exist, create a pipe for the submix audio device rsxadev of size +// buffer_size_frames and optionally associate "in" or "out" with the submix audio device. +// Must be called with lock held on the submix_audio_device +static void submix_audio_device_create_pipe_l(struct submix_audio_device * const rsxadev, + const struct audio_config * const config, + const size_t buffer_size_frames, + const uint32_t buffer_period_count, + struct submix_stream_in * const in, + struct submix_stream_out * const out, + const char *address, + int route_idx) +{ + ALOG_ASSERT(in || out); + ALOG_ASSERT(route_idx > -1); + ALOG_ASSERT(route_idx < MAX_ROUTES); + ALOGD("submix_audio_device_create_pipe_l(addr=%s, idx=%d)", address, route_idx); + + // Save a reference to the specified input or output stream and the associated channel + // mask. + if (in) { + in->route_handle = route_idx; + rsxadev->routes[route_idx].input = in; + rsxadev->routes[route_idx].config.input_channel_mask = config->channel_mask; +#if ENABLE_RESAMPLING + rsxadev->routes[route_idx].config.input_sample_rate = config->sample_rate; + // If the output isn't configured yet, set the output sample rate to the maximum supported + // sample rate such that the smallest possible input buffer is created, and put a default + // value for channel count + if (!rsxadev->routes[route_idx].output) { + rsxadev->routes[route_idx].config.output_sample_rate = 48000; + rsxadev->routes[route_idx].config.output_channel_mask = AUDIO_CHANNEL_OUT_STEREO; + } +#endif // ENABLE_RESAMPLING + } + if (out) { + out->route_handle = route_idx; + rsxadev->routes[route_idx].output = out; + rsxadev->routes[route_idx].config.output_channel_mask = config->channel_mask; +#if ENABLE_RESAMPLING + rsxadev->routes[route_idx].config.output_sample_rate = config->sample_rate; +#endif // ENABLE_RESAMPLING + } + // Save the address + strncpy(rsxadev->routes[route_idx].address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN); + ALOGD(" now using address %s for route %d", rsxadev->routes[route_idx].address, route_idx); + // If a pipe isn't associated with the device, create one. + if (rsxadev->routes[route_idx].rsxSink == NULL || rsxadev->routes[route_idx].rsxSource == NULL) + { + struct submix_config * const device_config = &rsxadev->routes[route_idx].config; + uint32_t channel_count; + if (out) + channel_count = audio_channel_count_from_out_mask(config->channel_mask); + else + channel_count = audio_channel_count_from_in_mask(config->channel_mask); +#if ENABLE_CHANNEL_CONVERSION + // If channel conversion is enabled, allocate enough space for the maximum number of + // possible channels stored in the pipe for the situation when the number of channels in + // the output stream don't match the number in the input stream. + const uint32_t pipe_channel_count = max(channel_count, 2); +#else + const uint32_t pipe_channel_count = channel_count; +#endif // ENABLE_CHANNEL_CONVERSION + const NBAIO_Format format = Format_from_SR_C(config->sample_rate, pipe_channel_count, + config->format); + const NBAIO_Format offers[1] = {format}; + size_t numCounterOffers = 0; + // Create a MonoPipe with optional blocking set to true. + MonoPipe* sink = new MonoPipe(buffer_size_frames, format, true /*writeCanBlock*/); + // Negotiation between the source and sink cannot fail as the device open operation + // creates both ends of the pipe using the same audio format. + ssize_t index = sink->negotiate(offers, 1, NULL, numCounterOffers); + ALOG_ASSERT(index == 0); + MonoPipeReader* source = new MonoPipeReader(sink); + numCounterOffers = 0; + index = source->negotiate(offers, 1, NULL, numCounterOffers); + ALOG_ASSERT(index == 0); + ALOGV("submix_audio_device_create_pipe_l(): created pipe"); + + // Save references to the source and sink. + ALOG_ASSERT(rsxadev->routes[route_idx].rsxSink == NULL); + ALOG_ASSERT(rsxadev->routes[route_idx].rsxSource == NULL); + rsxadev->routes[route_idx].rsxSink = sink; + rsxadev->routes[route_idx].rsxSource = source; + // Store the sanitized audio format in the device so that it's possible to determine + // the format of the pipe source when opening the input device. + memcpy(&device_config->common, config, sizeof(device_config->common)); + device_config->buffer_size_frames = sink->maxFrames(); + device_config->buffer_period_size_frames = device_config->buffer_size_frames / + buffer_period_count; + if (in) device_config->pipe_frame_size = audio_stream_in_frame_size(&in->stream); + if (out) device_config->pipe_frame_size = audio_stream_out_frame_size(&out->stream); +#if ENABLE_CHANNEL_CONVERSION + // Calculate the pipe frame size based upon the number of channels. + device_config->pipe_frame_size = (device_config->pipe_frame_size * pipe_channel_count) / + channel_count; +#endif // ENABLE_CHANNEL_CONVERSION + SUBMIX_ALOGV("submix_audio_device_create_pipe_l(): pipe frame size %zd, pipe size %zd, " + "period size %zd", device_config->pipe_frame_size, + device_config->buffer_size_frames, device_config->buffer_period_size_frames); + } +} + +// Release references to the sink and source. Input and output threads may maintain references +// to these objects via StrongPointer (sp<MonoPipe> and sp<MonoPipeReader>) which they can use +// before they shutdown. +// Must be called with lock held on the submix_audio_device +static void submix_audio_device_release_pipe_l(struct submix_audio_device * const rsxadev, + int route_idx) +{ + ALOG_ASSERT(route_idx > -1); + ALOG_ASSERT(route_idx < MAX_ROUTES); + ALOGD("submix_audio_device_release_pipe_l(idx=%d) addr=%s", route_idx, + rsxadev->routes[route_idx].address); + if (rsxadev->routes[route_idx].rsxSink != 0) { + rsxadev->routes[route_idx].rsxSink.clear(); + rsxadev->routes[route_idx].rsxSink = 0; + } + if (rsxadev->routes[route_idx].rsxSource != 0) { + rsxadev->routes[route_idx].rsxSource.clear(); + rsxadev->routes[route_idx].rsxSource = 0; + } + memset(rsxadev->routes[route_idx].address, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN); +#ifdef ENABLE_RESAMPLING + memset(rsxadev->routes[route_idx].resampler_buffer, 0, + sizeof(int16_t) * DEFAULT_PIPE_SIZE_IN_FRAMES); +#endif +} + +// Remove references to the specified input and output streams. When the device no longer +// references input and output streams destroy the associated pipe. +// Must be called with lock held on the submix_audio_device +static void submix_audio_device_destroy_pipe_l(struct submix_audio_device * const rsxadev, + const struct submix_stream_in * const in, + const struct submix_stream_out * const out) +{ + MonoPipe* sink; + ALOGV("submix_audio_device_destroy_pipe_l()"); + int route_idx = -1; + if (in != NULL) { +#if ENABLE_LEGACY_INPUT_OPEN + const_cast<struct submix_stream_in*>(in)->ref_count--; + route_idx = in->route_handle; + ALOG_ASSERT(rsxadev->routes[route_idx].input == in); + if (in->ref_count == 0) { + rsxadev->routes[route_idx].input = NULL; + } + ALOGV("submix_audio_device_destroy_pipe_l(): input ref_count %d", in->ref_count); +#else + rsxadev->input = NULL; +#endif // ENABLE_LEGACY_INPUT_OPEN + } + if (out != NULL) { + route_idx = out->route_handle; + ALOG_ASSERT(rsxadev->routes[route_idx].output == out); + rsxadev->routes[route_idx].output = NULL; + } + if (route_idx != -1 && + rsxadev->routes[route_idx].input == NULL && rsxadev->routes[route_idx].output == NULL) { + submix_audio_device_release_pipe_l(rsxadev, route_idx); + ALOGD("submix_audio_device_destroy_pipe_l(): pipe destroyed"); + } +} + +// Sanitize the user specified audio config for a submix input / output stream. +static void submix_sanitize_config(struct audio_config * const config, const bool is_input_format) +{ + config->channel_mask = is_input_format ? get_supported_channel_in_mask(config->channel_mask) : + get_supported_channel_out_mask(config->channel_mask); + config->sample_rate = get_supported_sample_rate(config->sample_rate); + config->format = DEFAULT_FORMAT; +} + +// Verify a submix input or output stream can be opened. +// Must be called with lock held on the submix_audio_device +static bool submix_open_validate_l(const struct submix_audio_device * const rsxadev, + int route_idx, + const struct audio_config * const config, + const bool opening_input) +{ + bool input_open; + bool output_open; + audio_config pipe_config; + + // Query the device for the current audio config and whether input and output streams are open. + output_open = rsxadev->routes[route_idx].output != NULL; + input_open = rsxadev->routes[route_idx].input != NULL; + memcpy(&pipe_config, &rsxadev->routes[route_idx].config.common, sizeof(pipe_config)); + + // If the stream is already open, don't open it again. + if (opening_input ? !ENABLE_LEGACY_INPUT_OPEN && input_open : output_open) { + ALOGE("submix_open_validate_l(): %s stream already open.", opening_input ? "Input" : + "Output"); + return false; + } + + SUBMIX_ALOGV("submix_open_validate_l(): sample rate=%d format=%x " + "%s_channel_mask=%x", config->sample_rate, config->format, + opening_input ? "in" : "out", config->channel_mask); + + // If either stream is open, verify the existing audio config the pipe matches the user + // specified config. + if (input_open || output_open) { + const audio_config * const input_config = opening_input ? config : &pipe_config; + const audio_config * const output_config = opening_input ? &pipe_config : config; + // Get the channel mask of the open device. + pipe_config.channel_mask = + opening_input ? rsxadev->routes[route_idx].config.output_channel_mask : + rsxadev->routes[route_idx].config.input_channel_mask; + if (!audio_config_compare(input_config, output_config)) { + ALOGE("submix_open_validate_l(): Unsupported format."); + return false; + } + } + return true; +} + +// Must be called with lock held on the submix_audio_device +static status_t submix_get_route_idx_for_address_l(const struct submix_audio_device * const rsxadev, + const char* address, /*in*/ + int *idx /*out*/) +{ + // Do we already have a route for this address + int route_idx = -1; + int route_empty_idx = -1; // index of an empty route slot that can be used if needed + for (int i=0 ; i < MAX_ROUTES ; i++) { + if (strcmp(rsxadev->routes[i].address, "") == 0) { + route_empty_idx = i; + } + if (strncmp(rsxadev->routes[i].address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) { + route_idx = i; + break; + } + } + + if ((route_idx == -1) && (route_empty_idx == -1)) { + ALOGE("Cannot create new route for address %s, max number of routes reached", address); + return -ENOMEM; + } + if (route_idx == -1) { + route_idx = route_empty_idx; + } + *idx = route_idx; + return OK; +} + + +// Calculate the maximum size of the pipe buffer in frames for the specified stream. +static size_t calculate_stream_pipe_size_in_frames(const struct audio_stream *stream, + const struct submix_config *config, + const size_t pipe_frames, + const size_t stream_frame_size) +{ + const size_t pipe_frame_size = config->pipe_frame_size; + const size_t max_frame_size = max(stream_frame_size, pipe_frame_size); + return (pipe_frames * config->pipe_frame_size) / max_frame_size; +} + +/* audio HAL functions */ + +static uint32_t out_get_sample_rate(const struct audio_stream *stream) +{ + const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( + const_cast<struct audio_stream *>(stream)); +#if ENABLE_RESAMPLING + const uint32_t out_rate = out->dev->routes[out->route_handle].config.output_sample_rate; +#else + const uint32_t out_rate = out->dev->routes[out->route_handle].config.common.sample_rate; +#endif // ENABLE_RESAMPLING + SUBMIX_ALOGV("out_get_sample_rate() returns %u for addr %s", + out_rate, out->dev->routes[out->route_handle].address); + return out_rate; +} + +static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream); +#if ENABLE_RESAMPLING + // The sample rate of the stream can't be changed once it's set since this would change the + // output buffer size and hence break playback to the shared pipe. + if (rate != out->dev->routes[out->route_handle].config.output_sample_rate) { + ALOGE("out_set_sample_rate() resampling enabled can't change sample rate from " + "%u to %u for addr %s", + out->dev->routes[out->route_handle].config.output_sample_rate, rate, + out->dev->routes[out->route_handle].address); + return -ENOSYS; + } +#endif // ENABLE_RESAMPLING + if (!sample_rate_supported(rate)) { + ALOGE("out_set_sample_rate(rate=%u) rate unsupported", rate); + return -ENOSYS; + } + SUBMIX_ALOGV("out_set_sample_rate(rate=%u)", rate); + out->dev->routes[out->route_handle].config.common.sample_rate = rate; + return 0; +} + +static size_t out_get_buffer_size(const struct audio_stream *stream) +{ + const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( + const_cast<struct audio_stream *>(stream)); + const struct submix_config * const config = &out->dev->routes[out->route_handle].config; + const size_t stream_frame_size = + audio_stream_out_frame_size((const struct audio_stream_out *)stream); + const size_t buffer_size_frames = calculate_stream_pipe_size_in_frames( + stream, config, config->buffer_period_size_frames, stream_frame_size); + const size_t buffer_size_bytes = buffer_size_frames * stream_frame_size; + SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames", + buffer_size_bytes, buffer_size_frames); + return buffer_size_bytes; +} + +static audio_channel_mask_t out_get_channels(const struct audio_stream *stream) +{ + const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( + const_cast<struct audio_stream *>(stream)); + uint32_t channel_mask = out->dev->routes[out->route_handle].config.output_channel_mask; + SUBMIX_ALOGV("out_get_channels() returns %08x", channel_mask); + return channel_mask; +} + +static audio_format_t out_get_format(const struct audio_stream *stream) +{ + const struct submix_stream_out * const out = audio_stream_get_submix_stream_out( + const_cast<struct audio_stream *>(stream)); + const audio_format_t format = out->dev->routes[out->route_handle].config.common.format; + SUBMIX_ALOGV("out_get_format() returns %x", format); + return format; +} + +static int out_set_format(struct audio_stream *stream, audio_format_t format) +{ + const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream); + if (format != out->dev->routes[out->route_handle].config.common.format) { + ALOGE("out_set_format(format=%x) format unsupported", format); + return -ENOSYS; + } + SUBMIX_ALOGV("out_set_format(format=%x)", format); + return 0; +} + +static int out_standby(struct audio_stream *stream) +{ + ALOGI("out_standby()"); + struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream); + struct submix_audio_device * const rsxadev = out->dev; + + pthread_mutex_lock(&rsxadev->lock); + + out->output_standby = true; + out->frames_written_since_standby = 0; + + pthread_mutex_unlock(&rsxadev->lock); + + return 0; +} + +static int out_dump(const struct audio_stream *stream, int fd) +{ + (void)stream; + (void)fd; + return 0; +} + +static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + int exiting = -1; + AudioParameter parms = AudioParameter(String8(kvpairs)); + SUBMIX_ALOGV("out_set_parameters() kvpairs='%s'", kvpairs); + + // FIXME this is using hard-coded strings but in the future, this functionality will be + // converted to use audio HAL extensions required to support tunneling + if ((parms.getInt(String8("exiting"), exiting) == NO_ERROR) && (exiting > 0)) { + struct submix_audio_device * const rsxadev = + audio_stream_get_submix_stream_out(stream)->dev; + pthread_mutex_lock(&rsxadev->lock); + { // using the sink + sp<MonoPipe> sink = + rsxadev->routes[audio_stream_get_submix_stream_out(stream)->route_handle] + .rsxSink; + if (sink == NULL) { + pthread_mutex_unlock(&rsxadev->lock); + return 0; + } + + ALOGD("out_set_parameters(): shutting down MonoPipe sink"); + sink->shutdown(true); + } // done using the sink + pthread_mutex_unlock(&rsxadev->lock); + } + return 0; +} + +static char * out_get_parameters(const struct audio_stream *stream, const char *keys) +{ + (void)stream; + (void)keys; + return strdup(""); +} + +static uint32_t out_get_latency(const struct audio_stream_out *stream) +{ + const struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out( + const_cast<struct audio_stream_out *>(stream)); + const struct submix_config * const config = &out->dev->routes[out->route_handle].config; + const size_t stream_frame_size = + audio_stream_out_frame_size(stream); + const size_t buffer_size_frames = calculate_stream_pipe_size_in_frames( + &stream->common, config, config->buffer_size_frames, stream_frame_size); + const uint32_t sample_rate = out_get_sample_rate(&stream->common); + const uint32_t latency_ms = (buffer_size_frames * 1000) / sample_rate; + SUBMIX_ALOGV("out_get_latency() returns %u ms, size in frames %zu, sample rate %u", + latency_ms, buffer_size_frames, sample_rate); + return latency_ms; +} + +static int out_set_volume(struct audio_stream_out *stream, float left, + float right) +{ + (void)stream; + (void)left; + (void)right; + return -ENOSYS; +} + +static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, + size_t bytes) +{ + SUBMIX_ALOGV("out_write(bytes=%zd)", bytes); + ssize_t written_frames = 0; + const size_t frame_size = audio_stream_out_frame_size(stream); + struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream); + struct submix_audio_device * const rsxadev = out->dev; + const size_t frames = bytes / frame_size; + + pthread_mutex_lock(&rsxadev->lock); + + out->output_standby = false; + + sp<MonoPipe> sink = rsxadev->routes[out->route_handle].rsxSink; + if (sink != NULL) { + if (sink->isShutdown()) { + sink.clear(); + pthread_mutex_unlock(&rsxadev->lock); + SUBMIX_ALOGV("out_write(): pipe shutdown, ignoring the write."); + // the pipe has already been shutdown, this buffer will be lost but we must + // simulate timing so we don't drain the output faster than realtime + usleep(frames * 1000000 / out_get_sample_rate(&stream->common)); + return bytes; + } + } else { + pthread_mutex_unlock(&rsxadev->lock); + ALOGE("out_write without a pipe!"); + ALOG_ASSERT("out_write without a pipe!"); + return 0; + } + + // If the write to the sink would block when no input stream is present, flush enough frames + // from the pipe to make space to write the most recent data. + { + const size_t availableToWrite = sink->availableToWrite(); + sp<MonoPipeReader> source = rsxadev->routes[out->route_handle].rsxSource; + if (rsxadev->routes[out->route_handle].input == NULL && availableToWrite < frames) { + static uint8_t flush_buffer[64]; + const size_t flushBufferSizeFrames = sizeof(flush_buffer) / frame_size; + size_t frames_to_flush_from_source = frames - availableToWrite; + SUBMIX_ALOGV("out_write(): flushing %d frames from the pipe to avoid blocking", + frames_to_flush_from_source); + while (frames_to_flush_from_source) { + const size_t flush_size = min(frames_to_flush_from_source, flushBufferSizeFrames); + frames_to_flush_from_source -= flush_size; + // read does not block + source->read(flush_buffer, flush_size, AudioBufferProvider::kInvalidPTS); + } + } + } + + pthread_mutex_unlock(&rsxadev->lock); + + written_frames = sink->write(buffer, frames); + +#if LOG_STREAMS_TO_FILES + if (out->log_fd >= 0) write(out->log_fd, buffer, written_frames * frame_size); +#endif // LOG_STREAMS_TO_FILES + + if (written_frames < 0) { + if (written_frames == (ssize_t)NEGOTIATE) { + ALOGE("out_write() write to pipe returned NEGOTIATE"); + + pthread_mutex_lock(&rsxadev->lock); + sink.clear(); + pthread_mutex_unlock(&rsxadev->lock); + + written_frames = 0; + return 0; + } else { + // write() returned UNDERRUN or WOULD_BLOCK, retry + ALOGE("out_write() write to pipe returned unexpected %zd", written_frames); + written_frames = sink->write(buffer, frames); + } + } + + pthread_mutex_lock(&rsxadev->lock); + sink.clear(); + if (written_frames > 0) { + out->frames_written_since_standby += written_frames; + out->frames_written += written_frames; + } + pthread_mutex_unlock(&rsxadev->lock); + + if (written_frames < 0) { + ALOGE("out_write() failed writing to pipe with %zd", written_frames); + return 0; + } + const ssize_t written_bytes = written_frames * frame_size; + SUBMIX_ALOGV("out_write() wrote %zd bytes %zd frames", written_bytes, written_frames); + return written_bytes; +} + +static int out_get_presentation_position(const struct audio_stream_out *stream, + uint64_t *frames, struct timespec *timestamp) +{ + if (stream == NULL || frames == NULL || timestamp == NULL) { + return -EINVAL; + } + + const submix_stream_out *out = audio_stream_out_get_submix_stream_out( + const_cast<struct audio_stream_out *>(stream)); + struct submix_audio_device * const rsxadev = out->dev; + + int ret = -EWOULDBLOCK; + pthread_mutex_lock(&rsxadev->lock); + const ssize_t frames_in_pipe = + rsxadev->routes[out->route_handle].rsxSource->availableToRead(); + if (CC_UNLIKELY(frames_in_pipe < 0)) { + *frames = out->frames_written; + ret = 0; + } else if (out->frames_written >= (uint64_t)frames_in_pipe) { + *frames = out->frames_written - frames_in_pipe; + ret = 0; + } + pthread_mutex_unlock(&rsxadev->lock); + + if (ret == 0) { + clock_gettime(CLOCK_MONOTONIC, timestamp); + } + + SUBMIX_ALOGV("out_get_presentation_position() got frames=%llu timestamp sec=%llu", + frames ? *frames : -1, timestamp ? timestamp->tv_sec : -1); + + return ret; +} + +static int out_get_render_position(const struct audio_stream_out *stream, + uint32_t *dsp_frames) +{ + if (stream == NULL || dsp_frames == NULL) { + return -EINVAL; + } + + const submix_stream_out *out = audio_stream_out_get_submix_stream_out( + const_cast<struct audio_stream_out *>(stream)); + struct submix_audio_device * const rsxadev = out->dev; + + pthread_mutex_lock(&rsxadev->lock); + const ssize_t frames_in_pipe = + rsxadev->routes[out->route_handle].rsxSource->availableToRead(); + if (CC_UNLIKELY(frames_in_pipe < 0)) { + *dsp_frames = (uint32_t)out->frames_written_since_standby; + } else { + *dsp_frames = out->frames_written_since_standby > (uint64_t) frames_in_pipe ? + (uint32_t)(out->frames_written_since_standby - frames_in_pipe) : 0; + } + pthread_mutex_unlock(&rsxadev->lock); + + return 0; +} + +static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + (void)stream; + (void)effect; + return 0; +} + +static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + (void)stream; + (void)effect; + return 0; +} + +static int out_get_next_write_timestamp(const struct audio_stream_out *stream, + int64_t *timestamp) +{ + (void)stream; + (void)timestamp; + return -EINVAL; +} + +/** audio_stream_in implementation **/ +static uint32_t in_get_sample_rate(const struct audio_stream *stream) +{ + const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( + const_cast<struct audio_stream*>(stream)); +#if ENABLE_RESAMPLING + const uint32_t rate = in->dev->routes[in->route_handle].config.input_sample_rate; +#else + const uint32_t rate = in->dev->routes[in->route_handle].config.common.sample_rate; +#endif // ENABLE_RESAMPLING + SUBMIX_ALOGV("in_get_sample_rate() returns %u", rate); + return rate; +} + +static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream); +#if ENABLE_RESAMPLING + // The sample rate of the stream can't be changed once it's set since this would change the + // input buffer size and hence break recording from the shared pipe. + if (rate != in->dev->routes[in->route_handle].config.input_sample_rate) { + ALOGE("in_set_sample_rate() resampling enabled can't change sample rate from " + "%u to %u", in->dev->routes[in->route_handle].config.input_sample_rate, rate); + return -ENOSYS; + } +#endif // ENABLE_RESAMPLING + if (!sample_rate_supported(rate)) { + ALOGE("in_set_sample_rate(rate=%u) rate unsupported", rate); + return -ENOSYS; + } + in->dev->routes[in->route_handle].config.common.sample_rate = rate; + SUBMIX_ALOGV("in_set_sample_rate() set %u", rate); + return 0; +} + +static size_t in_get_buffer_size(const struct audio_stream *stream) +{ + const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( + const_cast<struct audio_stream*>(stream)); + const struct submix_config * const config = &in->dev->routes[in->route_handle].config; + const size_t stream_frame_size = + audio_stream_in_frame_size((const struct audio_stream_in *)stream); + size_t buffer_size_frames = calculate_stream_pipe_size_in_frames( + stream, config, config->buffer_period_size_frames, stream_frame_size); +#if ENABLE_RESAMPLING + // Scale the size of the buffer based upon the maximum number of frames that could be returned + // given the ratio of output to input sample rate. + buffer_size_frames = (size_t)(((float)buffer_size_frames * + (float)config->input_sample_rate) / + (float)config->output_sample_rate); +#endif // ENABLE_RESAMPLING + const size_t buffer_size_bytes = buffer_size_frames * stream_frame_size; + SUBMIX_ALOGV("in_get_buffer_size() returns %zu bytes, %zu frames", buffer_size_bytes, + buffer_size_frames); + return buffer_size_bytes; +} + +static audio_channel_mask_t in_get_channels(const struct audio_stream *stream) +{ + const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( + const_cast<struct audio_stream*>(stream)); + const audio_channel_mask_t channel_mask = + in->dev->routes[in->route_handle].config.input_channel_mask; + SUBMIX_ALOGV("in_get_channels() returns %x", channel_mask); + return channel_mask; +} + +static audio_format_t in_get_format(const struct audio_stream *stream) +{ + const struct submix_stream_in * const in = audio_stream_get_submix_stream_in( + const_cast<struct audio_stream*>(stream)); + const audio_format_t format = in->dev->routes[in->route_handle].config.common.format; + SUBMIX_ALOGV("in_get_format() returns %x", format); + return format; +} + +static int in_set_format(struct audio_stream *stream, audio_format_t format) +{ + const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream); + if (format != in->dev->routes[in->route_handle].config.common.format) { + ALOGE("in_set_format(format=%x) format unsupported", format); + return -ENOSYS; + } + SUBMIX_ALOGV("in_set_format(format=%x)", format); + return 0; +} + +static int in_standby(struct audio_stream *stream) +{ + ALOGI("in_standby()"); + struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream); + struct submix_audio_device * const rsxadev = in->dev; + + pthread_mutex_lock(&rsxadev->lock); + + in->input_standby = true; + + pthread_mutex_unlock(&rsxadev->lock); + + return 0; +} + +static int in_dump(const struct audio_stream *stream, int fd) +{ + (void)stream; + (void)fd; + return 0; +} + +static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + (void)stream; + (void)kvpairs; + return 0; +} + +static char * in_get_parameters(const struct audio_stream *stream, + const char *keys) +{ + (void)stream; + (void)keys; + return strdup(""); +} + +static int in_set_gain(struct audio_stream_in *stream, float gain) +{ + (void)stream; + (void)gain; + return 0; +} + +static ssize_t in_read(struct audio_stream_in *stream, void* buffer, + size_t bytes) +{ + struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream); + struct submix_audio_device * const rsxadev = in->dev; + struct audio_config *format; + const size_t frame_size = audio_stream_in_frame_size(stream); + const size_t frames_to_read = bytes / frame_size; + + SUBMIX_ALOGV("in_read bytes=%zu", bytes); + pthread_mutex_lock(&rsxadev->lock); + + const bool output_standby = rsxadev->routes[in->route_handle].output == NULL + ? true : rsxadev->routes[in->route_handle].output->output_standby; + const bool output_standby_transition = (in->output_standby_rec_thr != output_standby); + in->output_standby_rec_thr = output_standby; + + if (in->input_standby || output_standby_transition) { + in->input_standby = false; + // keep track of when we exit input standby (== first read == start "real recording") + // or when we start recording silence, and reset projected time + int rc = clock_gettime(CLOCK_MONOTONIC, &in->record_start_time); + if (rc == 0) { + in->read_counter_frames = 0; + } + } + + in->read_counter_frames += frames_to_read; + size_t remaining_frames = frames_to_read; + + { + // about to read from audio source + sp<MonoPipeReader> source = rsxadev->routes[in->route_handle].rsxSource; + if (source == NULL) { + in->read_error_count++;// ok if it rolls over + ALOGE_IF(in->read_error_count < MAX_READ_ERROR_LOGS, + "no audio pipe yet we're trying to read! (not all errors will be logged)"); + pthread_mutex_unlock(&rsxadev->lock); + usleep(frames_to_read * 1000000 / in_get_sample_rate(&stream->common)); + memset(buffer, 0, bytes); + return bytes; + } + + pthread_mutex_unlock(&rsxadev->lock); + + // read the data from the pipe (it's non blocking) + int attempts = 0; + char* buff = (char*)buffer; +#if ENABLE_CHANNEL_CONVERSION + // Determine whether channel conversion is required. + const uint32_t input_channels = audio_channel_count_from_in_mask( + rsxadev->routes[in->route_handle].config.input_channel_mask); + const uint32_t output_channels = audio_channel_count_from_out_mask( + rsxadev->routes[in->route_handle].config.output_channel_mask); + if (input_channels != output_channels) { + SUBMIX_ALOGV("in_read(): %d output channels will be converted to %d " + "input channels", output_channels, input_channels); + // Only support 16-bit PCM channel conversion from mono to stereo or stereo to mono. + ALOG_ASSERT(rsxadev->routes[in->route_handle].config.common.format == + AUDIO_FORMAT_PCM_16_BIT); + ALOG_ASSERT((input_channels == 1 && output_channels == 2) || + (input_channels == 2 && output_channels == 1)); + } +#endif // ENABLE_CHANNEL_CONVERSION + +#if ENABLE_RESAMPLING + const uint32_t input_sample_rate = in_get_sample_rate(&stream->common); + const uint32_t output_sample_rate = + rsxadev->routes[in->route_handle].config.output_sample_rate; + const size_t resampler_buffer_size_frames = + sizeof(rsxadev->routes[in->route_handle].resampler_buffer) / + sizeof(rsxadev->routes[in->route_handle].resampler_buffer[0]); + float resampler_ratio = 1.0f; + // Determine whether resampling is required. + if (input_sample_rate != output_sample_rate) { + resampler_ratio = (float)output_sample_rate / (float)input_sample_rate; + // Only support 16-bit PCM mono resampling. + // NOTE: Resampling is performed after the channel conversion step. + ALOG_ASSERT(rsxadev->routes[in->route_handle].config.common.format == + AUDIO_FORMAT_PCM_16_BIT); + ALOG_ASSERT(audio_channel_count_from_in_mask( + rsxadev->routes[in->route_handle].config.input_channel_mask) == 1); + } +#endif // ENABLE_RESAMPLING + + while ((remaining_frames > 0) && (attempts < MAX_READ_ATTEMPTS)) { + ssize_t frames_read = -1977; + size_t read_frames = remaining_frames; +#if ENABLE_RESAMPLING + char* const saved_buff = buff; + if (resampler_ratio != 1.0f) { + // Calculate the number of frames from the pipe that need to be read to generate + // the data for the input stream read. + const size_t frames_required_for_resampler = (size_t)( + (float)read_frames * (float)resampler_ratio); + read_frames = min(frames_required_for_resampler, resampler_buffer_size_frames); + // Read into the resampler buffer. + buff = (char*)rsxadev->routes[in->route_handle].resampler_buffer; + } +#endif // ENABLE_RESAMPLING +#if ENABLE_CHANNEL_CONVERSION + if (output_channels == 1 && input_channels == 2) { + // Need to read half the requested frames since the converted output + // data will take twice the space (mono->stereo). + read_frames /= 2; + } +#endif // ENABLE_CHANNEL_CONVERSION + + SUBMIX_ALOGV("in_read(): frames available to read %zd", source->availableToRead()); + + frames_read = source->read(buff, read_frames, AudioBufferProvider::kInvalidPTS); + + SUBMIX_ALOGV("in_read(): frames read %zd", frames_read); + +#if ENABLE_CHANNEL_CONVERSION + // Perform in-place channel conversion. + // NOTE: In the following "input stream" refers to the data returned by this function + // and "output stream" refers to the data read from the pipe. + if (input_channels != output_channels && frames_read > 0) { + int16_t *data = (int16_t*)buff; + if (output_channels == 2 && input_channels == 1) { + // Offset into the output stream data in samples. + ssize_t output_stream_offset = 0; + for (ssize_t input_stream_frame = 0; input_stream_frame < frames_read; + input_stream_frame++, output_stream_offset += 2) { + // Average the content from both channels. + data[input_stream_frame] = ((int32_t)data[output_stream_offset] + + (int32_t)data[output_stream_offset + 1]) / 2; + } + } else if (output_channels == 1 && input_channels == 2) { + // Offset into the input stream data in samples. + ssize_t input_stream_offset = (frames_read - 1) * 2; + for (ssize_t output_stream_frame = frames_read - 1; output_stream_frame >= 0; + output_stream_frame--, input_stream_offset -= 2) { + const short sample = data[output_stream_frame]; + data[input_stream_offset] = sample; + data[input_stream_offset + 1] = sample; + } + } + } +#endif // ENABLE_CHANNEL_CONVERSION + +#if ENABLE_RESAMPLING + if (resampler_ratio != 1.0f) { + SUBMIX_ALOGV("in_read(): resampling %zd frames", frames_read); + const int16_t * const data = (int16_t*)buff; + int16_t * const resampled_buffer = (int16_t*)saved_buff; + // Resample with *no* filtering - if the data from the ouptut stream was really + // sampled at a different rate this will result in very nasty aliasing. + const float output_stream_frames = (float)frames_read; + size_t input_stream_frame = 0; + for (float output_stream_frame = 0.0f; + output_stream_frame < output_stream_frames && + input_stream_frame < remaining_frames; + output_stream_frame += resampler_ratio, input_stream_frame++) { + resampled_buffer[input_stream_frame] = data[(size_t)output_stream_frame]; + } + ALOG_ASSERT(input_stream_frame <= (ssize_t)resampler_buffer_size_frames); + SUBMIX_ALOGV("in_read(): resampler produced %zd frames", input_stream_frame); + frames_read = input_stream_frame; + buff = saved_buff; + } +#endif // ENABLE_RESAMPLING + + if (frames_read > 0) { +#if LOG_STREAMS_TO_FILES + if (in->log_fd >= 0) write(in->log_fd, buff, frames_read * frame_size); +#endif // LOG_STREAMS_TO_FILES + + remaining_frames -= frames_read; + buff += frames_read * frame_size; + SUBMIX_ALOGV(" in_read (att=%d) got %zd frames, remaining=%zu", + attempts, frames_read, remaining_frames); + } else { + attempts++; + SUBMIX_ALOGE(" in_read read returned %zd", frames_read); + usleep(READ_ATTEMPT_SLEEP_MS * 1000); + } + } + // done using the source + pthread_mutex_lock(&rsxadev->lock); + source.clear(); + pthread_mutex_unlock(&rsxadev->lock); + } + + if (remaining_frames > 0) { + const size_t remaining_bytes = remaining_frames * frame_size; + SUBMIX_ALOGV(" clearing remaining_frames = %zu", remaining_frames); + memset(((char*)buffer)+ bytes - remaining_bytes, 0, remaining_bytes); + } + + // compute how much we need to sleep after reading the data by comparing the wall clock with + // the projected time at which we should return. + struct timespec time_after_read;// wall clock after reading from the pipe + struct timespec record_duration;// observed record duration + int rc = clock_gettime(CLOCK_MONOTONIC, &time_after_read); + const uint32_t sample_rate = in_get_sample_rate(&stream->common); + if (rc == 0) { + // for how long have we been recording? + record_duration.tv_sec = time_after_read.tv_sec - in->record_start_time.tv_sec; + record_duration.tv_nsec = time_after_read.tv_nsec - in->record_start_time.tv_nsec; + if (record_duration.tv_nsec < 0) { + record_duration.tv_sec--; + record_duration.tv_nsec += 1000000000; + } + + // read_counter_frames contains the number of frames that have been read since the + // beginning of recording (including this call): it's converted to usec and compared to + // how long we've been recording for, which gives us how long we must wait to sync the + // projected recording time, and the observed recording time. + long projected_vs_observed_offset_us = + ((int64_t)(in->read_counter_frames + - (record_duration.tv_sec*sample_rate))) + * 1000000 / sample_rate + - (record_duration.tv_nsec / 1000); + + SUBMIX_ALOGV(" record duration %5lds %3ldms, will wait: %7ldus", + record_duration.tv_sec, record_duration.tv_nsec/1000000, + projected_vs_observed_offset_us); + if (projected_vs_observed_offset_us > 0) { + usleep(projected_vs_observed_offset_us); + } + } + + SUBMIX_ALOGV("in_read returns %zu", bytes); + return bytes; + +} + +static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) +{ + (void)stream; + return 0; +} + +static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + (void)stream; + (void)effect; + return 0; +} + +static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + (void)stream; + (void)effect; + return 0; +} + +static int adev_open_output_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out, + const char *address) +{ + struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev); + ALOGD("adev_open_output_stream(address=%s)", address); + struct submix_stream_out *out; + bool force_pipe_creation = false; + (void)handle; + (void)devices; + (void)flags; + + *stream_out = NULL; + + // Make sure it's possible to open the device given the current audio config. + submix_sanitize_config(config, false); + + int route_idx = -1; + + pthread_mutex_lock(&rsxadev->lock); + + status_t res = submix_get_route_idx_for_address_l(rsxadev, address, &route_idx); + if (res != OK) { + ALOGE("Error %d looking for address=%s in adev_open_output_stream", res, address); + pthread_mutex_unlock(&rsxadev->lock); + return res; + } + + if (!submix_open_validate_l(rsxadev, route_idx, config, false)) { + ALOGE("adev_open_output_stream(): Unable to open output stream for address %s", address); + pthread_mutex_unlock(&rsxadev->lock); + return -EINVAL; + } + + out = (struct submix_stream_out *)calloc(1, sizeof(struct submix_stream_out)); + if (!out) { + pthread_mutex_unlock(&rsxadev->lock); + return -ENOMEM; + } + + // Initialize the function pointer tables (v-tables). + out->stream.common.get_sample_rate = out_get_sample_rate; + out->stream.common.set_sample_rate = out_set_sample_rate; + out->stream.common.get_buffer_size = out_get_buffer_size; + out->stream.common.get_channels = out_get_channels; + out->stream.common.get_format = out_get_format; + out->stream.common.set_format = out_set_format; + out->stream.common.standby = out_standby; + out->stream.common.dump = out_dump; + out->stream.common.set_parameters = out_set_parameters; + out->stream.common.get_parameters = out_get_parameters; + out->stream.common.add_audio_effect = out_add_audio_effect; + out->stream.common.remove_audio_effect = out_remove_audio_effect; + out->stream.get_latency = out_get_latency; + out->stream.set_volume = out_set_volume; + out->stream.write = out_write; + out->stream.get_render_position = out_get_render_position; + out->stream.get_next_write_timestamp = out_get_next_write_timestamp; + out->stream.get_presentation_position = out_get_presentation_position; + +#if ENABLE_RESAMPLING + // Recreate the pipe with the correct sample rate so that MonoPipe.write() rate limits + // writes correctly. + force_pipe_creation = rsxadev->routes[route_idx].config.common.sample_rate + != config->sample_rate; +#endif // ENABLE_RESAMPLING + + // If the sink has been shutdown or pipe recreation is forced (see above), delete the pipe so + // that it's recreated. + if ((rsxadev->routes[route_idx].rsxSink != NULL + && rsxadev->routes[route_idx].rsxSink->isShutdown()) || force_pipe_creation) { + submix_audio_device_release_pipe_l(rsxadev, route_idx); + } + + // Store a pointer to the device from the output stream. + out->dev = rsxadev; + // Initialize the pipe. + ALOGV("adev_open_output_stream(): about to create pipe at index %d", route_idx); + submix_audio_device_create_pipe_l(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES, + DEFAULT_PIPE_PERIOD_COUNT, NULL, out, address, route_idx); +#if LOG_STREAMS_TO_FILES + out->log_fd = open(LOG_STREAM_OUT_FILENAME, O_CREAT | O_TRUNC | O_WRONLY, + LOG_STREAM_FILE_PERMISSIONS); + ALOGE_IF(out->log_fd < 0, "adev_open_output_stream(): log file open failed %s", + strerror(errno)); + ALOGV("adev_open_output_stream(): log_fd = %d", out->log_fd); +#endif // LOG_STREAMS_TO_FILES + // Return the output stream. + *stream_out = &out->stream; + + pthread_mutex_unlock(&rsxadev->lock); + return 0; +} + +static void adev_close_output_stream(struct audio_hw_device *dev, + struct audio_stream_out *stream) +{ + struct submix_audio_device * rsxadev = audio_hw_device_get_submix_audio_device( + const_cast<struct audio_hw_device*>(dev)); + struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream); + + pthread_mutex_lock(&rsxadev->lock); + ALOGD("adev_close_output_stream() addr = %s", rsxadev->routes[out->route_handle].address); + submix_audio_device_destroy_pipe_l(audio_hw_device_get_submix_audio_device(dev), NULL, out); +#if LOG_STREAMS_TO_FILES + if (out->log_fd >= 0) close(out->log_fd); +#endif // LOG_STREAMS_TO_FILES + + pthread_mutex_unlock(&rsxadev->lock); + free(out); +} + +static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) +{ + (void)dev; + (void)kvpairs; + return -ENOSYS; +} + +static char * adev_get_parameters(const struct audio_hw_device *dev, + const char *keys) +{ + (void)dev; + (void)keys; + return strdup("");; +} + +static int adev_init_check(const struct audio_hw_device *dev) +{ + ALOGI("adev_init_check()"); + (void)dev; + return 0; +} + +static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) +{ + (void)dev; + (void)volume; + return -ENOSYS; +} + +static int adev_set_master_volume(struct audio_hw_device *dev, float volume) +{ + (void)dev; + (void)volume; + return -ENOSYS; +} + +static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) +{ + (void)dev; + (void)volume; + return -ENOSYS; +} + +static int adev_set_master_mute(struct audio_hw_device *dev, bool muted) +{ + (void)dev; + (void)muted; + return -ENOSYS; +} + +static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted) +{ + (void)dev; + (void)muted; + return -ENOSYS; +} + +static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) +{ + (void)dev; + (void)mode; + return 0; +} + +static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) +{ + (void)dev; + (void)state; + return -ENOSYS; +} + +static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) +{ + (void)dev; + (void)state; + return -ENOSYS; +} + +static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, + const struct audio_config *config) +{ + if (audio_is_linear_pcm(config->format)) { + size_t max_buffer_period_size_frames = 0; + struct submix_audio_device * rsxadev = audio_hw_device_get_submix_audio_device( + const_cast<struct audio_hw_device*>(dev)); + // look for the largest buffer period size + for (int i = 0 ; i < MAX_ROUTES ; i++) { + if (rsxadev->routes[i].config.buffer_period_size_frames > max_buffer_period_size_frames) + { + max_buffer_period_size_frames = rsxadev->routes[i].config.buffer_period_size_frames; + } + } + const size_t frame_size_in_bytes = audio_channel_count_from_in_mask(config->channel_mask) * + audio_bytes_per_sample(config->format); + const size_t buffer_size = max_buffer_period_size_frames * frame_size_in_bytes; + SUBMIX_ALOGV("adev_get_input_buffer_size() returns %zu bytes, %zu frames", + buffer_size, buffer_period_size_frames); + return buffer_size; + } + return 0; +} + +static int adev_open_input_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in, + audio_input_flags_t flags __unused, + const char *address, + audio_source_t source __unused) +{ + struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev); + struct submix_stream_in *in; + ALOGD("adev_open_input_stream(addr=%s)", address); + (void)handle; + (void)devices; + + *stream_in = NULL; + + // Do we already have a route for this address + int route_idx = -1; + + pthread_mutex_lock(&rsxadev->lock); + + status_t res = submix_get_route_idx_for_address_l(rsxadev, address, &route_idx); + if (res != OK) { + ALOGE("Error %d looking for address=%s in adev_open_output_stream", res, address); + pthread_mutex_unlock(&rsxadev->lock); + return res; + } + + // Make sure it's possible to open the device given the current audio config. + submix_sanitize_config(config, true); + if (!submix_open_validate_l(rsxadev, route_idx, config, true)) { + ALOGE("adev_open_input_stream(): Unable to open input stream."); + pthread_mutex_unlock(&rsxadev->lock); + return -EINVAL; + } + +#if ENABLE_LEGACY_INPUT_OPEN + in = rsxadev->routes[route_idx].input; + if (in) { + in->ref_count++; + sp<MonoPipe> sink = rsxadev->routes[route_idx].rsxSink; + ALOG_ASSERT(sink != NULL); + // If the sink has been shutdown, delete the pipe. + if (sink != NULL) { + if (sink->isShutdown()) { + ALOGD(" Non-NULL shut down sink when opening input stream, releasing, refcount=%d", + in->ref_count); + submix_audio_device_release_pipe_l(rsxadev, in->route_handle); + } else { + ALOGD(" Non-NULL sink when opening input stream, refcount=%d", in->ref_count); + } + } else { + ALOGE("NULL sink when opening input stream, refcount=%d", in->ref_count); + } + } +#else + in = NULL; +#endif // ENABLE_LEGACY_INPUT_OPEN + + if (!in) { + in = (struct submix_stream_in *)calloc(1, sizeof(struct submix_stream_in)); + if (!in) return -ENOMEM; + in->ref_count = 1; + + // Initialize the function pointer tables (v-tables). + in->stream.common.get_sample_rate = in_get_sample_rate; + in->stream.common.set_sample_rate = in_set_sample_rate; + in->stream.common.get_buffer_size = in_get_buffer_size; + in->stream.common.get_channels = in_get_channels; + in->stream.common.get_format = in_get_format; + in->stream.common.set_format = in_set_format; + in->stream.common.standby = in_standby; + in->stream.common.dump = in_dump; + in->stream.common.set_parameters = in_set_parameters; + in->stream.common.get_parameters = in_get_parameters; + in->stream.common.add_audio_effect = in_add_audio_effect; + in->stream.common.remove_audio_effect = in_remove_audio_effect; + in->stream.set_gain = in_set_gain; + in->stream.read = in_read; + in->stream.get_input_frames_lost = in_get_input_frames_lost; + + in->dev = rsxadev; +#if LOG_STREAMS_TO_FILES + in->log_fd = -1; +#endif + } + + // Initialize the input stream. + in->read_counter_frames = 0; + in->input_standby = true; + if (rsxadev->routes[route_idx].output != NULL) { + in->output_standby_rec_thr = rsxadev->routes[route_idx].output->output_standby; + } else { + in->output_standby_rec_thr = true; + } + + in->read_error_count = 0; + // Initialize the pipe. + ALOGV("adev_open_input_stream(): about to create pipe"); + submix_audio_device_create_pipe_l(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES, + DEFAULT_PIPE_PERIOD_COUNT, in, NULL, address, route_idx); +#if LOG_STREAMS_TO_FILES + if (in->log_fd >= 0) close(in->log_fd); + in->log_fd = open(LOG_STREAM_IN_FILENAME, O_CREAT | O_TRUNC | O_WRONLY, + LOG_STREAM_FILE_PERMISSIONS); + ALOGE_IF(in->log_fd < 0, "adev_open_input_stream(): log file open failed %s", + strerror(errno)); + ALOGV("adev_open_input_stream(): log_fd = %d", in->log_fd); +#endif // LOG_STREAMS_TO_FILES + // Return the input stream. + *stream_in = &in->stream; + + pthread_mutex_unlock(&rsxadev->lock); + return 0; +} + +static void adev_close_input_stream(struct audio_hw_device *dev, + struct audio_stream_in *stream) +{ + struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev); + + struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream); + ALOGD("adev_close_input_stream()"); + pthread_mutex_lock(&rsxadev->lock); + submix_audio_device_destroy_pipe_l(rsxadev, in, NULL); +#if LOG_STREAMS_TO_FILES + if (in->log_fd >= 0) close(in->log_fd); +#endif // LOG_STREAMS_TO_FILES +#if ENABLE_LEGACY_INPUT_OPEN + if (in->ref_count == 0) free(in); +#else + free(in); +#endif // ENABLE_LEGACY_INPUT_OPEN + + pthread_mutex_unlock(&rsxadev->lock); +} + +static int adev_dump(const audio_hw_device_t *device, int fd) +{ + const struct submix_audio_device * rsxadev = //audio_hw_device_get_submix_audio_device(device); + reinterpret_cast<const struct submix_audio_device *>( + reinterpret_cast<const uint8_t *>(device) - + offsetof(struct submix_audio_device, device)); + char msg[100]; + int n = sprintf(msg, "\nReroute submix audio module:\n"); + write(fd, &msg, n); + for (int i=0 ; i < MAX_ROUTES ; i++) { + n = sprintf(msg, " route[%d] rate in=%d out=%d, addr=[%s]\n", i, + rsxadev->routes[i].config.input_sample_rate, + rsxadev->routes[i].config.output_sample_rate, + rsxadev->routes[i].address); + write(fd, &msg, n); + } + return 0; +} + +static int adev_close(hw_device_t *device) +{ + ALOGI("adev_close()"); + free(device); + return 0; +} + +static int adev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + ALOGI("adev_open(name=%s)", name); + struct submix_audio_device *rsxadev; + + if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) + return -EINVAL; + + rsxadev = (submix_audio_device*) calloc(1, sizeof(struct submix_audio_device)); + if (!rsxadev) + return -ENOMEM; + + rsxadev->device.common.tag = HARDWARE_DEVICE_TAG; + rsxadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0; + rsxadev->device.common.module = (struct hw_module_t *) module; + rsxadev->device.common.close = adev_close; + + rsxadev->device.init_check = adev_init_check; + rsxadev->device.set_voice_volume = adev_set_voice_volume; + rsxadev->device.set_master_volume = adev_set_master_volume; + rsxadev->device.get_master_volume = adev_get_master_volume; + rsxadev->device.set_master_mute = adev_set_master_mute; + rsxadev->device.get_master_mute = adev_get_master_mute; + rsxadev->device.set_mode = adev_set_mode; + rsxadev->device.set_mic_mute = adev_set_mic_mute; + rsxadev->device.get_mic_mute = adev_get_mic_mute; + rsxadev->device.set_parameters = adev_set_parameters; + rsxadev->device.get_parameters = adev_get_parameters; + rsxadev->device.get_input_buffer_size = adev_get_input_buffer_size; + rsxadev->device.open_output_stream = adev_open_output_stream; + rsxadev->device.close_output_stream = adev_close_output_stream; + rsxadev->device.open_input_stream = adev_open_input_stream; + rsxadev->device.close_input_stream = adev_close_input_stream; + rsxadev->device.dump = adev_dump; + + for (int i=0 ; i < MAX_ROUTES ; i++) { + memset(&rsxadev->routes[i], 0, sizeof(route_config)); + strcpy(rsxadev->routes[i].address, ""); + } + + *device = &rsxadev->device.common; + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + /* open */ adev_open, +}; + +struct audio_module HAL_MODULE_INFO_SYM = { + /* common */ { + /* tag */ HARDWARE_MODULE_TAG, + /* module_api_version */ AUDIO_MODULE_API_VERSION_0_1, + /* hal_api_version */ HARDWARE_HAL_API_VERSION, + /* id */ AUDIO_HARDWARE_MODULE_ID, + /* name */ "Wifi Display audio HAL", + /* author */ "The Android Open Source Project", + /* methods */ &hal_module_methods, + /* dso */ NULL, + /* reserved */ { 0 }, + }, +}; + +} //namespace android + +} //extern "C"
diff --git a/libhardware/modules/camera/Android.mk b/libhardware/modules/camera/Android.mk new file mode 100644 index 0000000..ae68ed5 --- /dev/null +++ b/libhardware/modules/camera/Android.mk
@@ -0,0 +1,45 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := camera.default +LOCAL_MODULE_RELATIVE_PATH := hw + +LOCAL_C_INCLUDES += \ + system/core/include \ + system/media/camera/include \ + +LOCAL_SRC_FILES := \ + CameraHAL.cpp \ + Camera.cpp \ + ExampleCamera.cpp \ + Metadata.cpp \ + Stream.cpp \ + VendorTags.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libcamera_metadata \ + libcutils \ + liblog \ + libsync \ + libutils \ + +LOCAL_CFLAGS += -Wall -Wextra -fvisibility=hidden + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/camera/Camera.cpp b/libhardware/modules/camera/Camera.cpp new file mode 100644 index 0000000..de3ae78 --- /dev/null +++ b/libhardware/modules/camera/Camera.cpp
@@ -0,0 +1,594 @@ +/* + * Copyright (C) 2012 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 <cstdlib> +#include <stdio.h> +#include <hardware/camera3.h> +#include <sync/sync.h> +#include <system/camera_metadata.h> +#include <system/graphics.h> +#include <utils/Mutex.h> +#include "CameraHAL.h" +#include "Metadata.h" +#include "Stream.h" + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Camera" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Camera.h" + +#define CAMERA_SYNC_TIMEOUT 5000 // in msecs + +namespace default_camera_hal { + +extern "C" { +// Shim passed to the framework to close an opened device. +static int close_device(hw_device_t* dev) +{ + camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(dev); + Camera* cam = static_cast<Camera*>(cam_dev->priv); + return cam->close(); +} +} // extern "C" + +Camera::Camera(int id) + : mId(id), + mStaticInfo(NULL), + mBusy(false), + mCallbackOps(NULL), + mStreams(NULL), + mNumStreams(0), + mSettings(NULL) +{ + memset(&mTemplates, 0, sizeof(mTemplates)); + memset(&mDevice, 0, sizeof(mDevice)); + mDevice.common.tag = HARDWARE_DEVICE_TAG; + mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0; + mDevice.common.close = close_device; + mDevice.ops = const_cast<camera3_device_ops_t*>(&sOps); + mDevice.priv = this; +} + +Camera::~Camera() +{ + if (mStaticInfo != NULL) { + free_camera_metadata(mStaticInfo); + } +} + +int Camera::open(const hw_module_t *module, hw_device_t **device) +{ + ALOGI("%s:%d: Opening camera device", __func__, mId); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + if (mBusy) { + ALOGE("%s:%d: Error! Camera device already opened", __func__, mId); + return -EBUSY; + } + + // TODO: open camera dev nodes, etc + mBusy = true; + mDevice.common.module = const_cast<hw_module_t*>(module); + *device = &mDevice.common; + return 0; +} + +int Camera::getInfo(struct camera_info *info) +{ + android::Mutex::Autolock al(mStaticInfoLock); + + info->facing = CAMERA_FACING_FRONT; + info->orientation = 0; + info->device_version = mDevice.common.version; + if (mStaticInfo == NULL) { + mStaticInfo = initStaticInfo(); + } + info->static_camera_characteristics = mStaticInfo; + return 0; +} + +int Camera::close() +{ + ALOGI("%s:%d: Closing camera device", __func__, mId); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + if (!mBusy) { + ALOGE("%s:%d: Error! Camera device not open", __func__, mId); + return -EINVAL; + } + + // TODO: close camera dev nodes, etc + mBusy = false; + return 0; +} + +int Camera::initialize(const camera3_callback_ops_t *callback_ops) +{ + int res; + + ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops); + mCallbackOps = callback_ops; + // per-device specific initialization + res = initDevice(); + if (res != 0) { + ALOGE("%s:%d: Failed to initialize device!", __func__, mId); + return res; + } + return 0; +} + +int Camera::configureStreams(camera3_stream_configuration_t *stream_config) +{ + camera3_stream_t *astream; + Stream **newStreams = NULL; + + ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + if (stream_config == NULL) { + ALOGE("%s:%d: NULL stream configuration array", __func__, mId); + return -EINVAL; + } + if (stream_config->num_streams == 0) { + ALOGE("%s:%d: Empty stream configuration array", __func__, mId); + return -EINVAL; + } + + // Create new stream array + newStreams = new Stream*[stream_config->num_streams]; + ALOGV("%s:%d: Number of Streams: %d", __func__, mId, + stream_config->num_streams); + + // Mark all current streams unused for now + for (int i = 0; i < mNumStreams; i++) + mStreams[i]->mReuse = false; + // Fill new stream array with reused streams and new streams + for (unsigned int i = 0; i < stream_config->num_streams; i++) { + astream = stream_config->streams[i]; + if (astream->max_buffers > 0) { + ALOGV("%s:%d: Reusing stream %d", __func__, mId, i); + newStreams[i] = reuseStream(astream); + } else { + ALOGV("%s:%d: Creating new stream %d", __func__, mId, i); + newStreams[i] = new Stream(mId, astream); + } + + if (newStreams[i] == NULL) { + ALOGE("%s:%d: Error processing stream %d", __func__, mId, i); + goto err_out; + } + astream->priv = newStreams[i]; + } + + // Verify the set of streams in aggregate + if (!isValidStreamSet(newStreams, stream_config->num_streams)) { + ALOGE("%s:%d: Invalid stream set", __func__, mId); + goto err_out; + } + + // Set up all streams (calculate usage/max_buffers for each) + setupStreams(newStreams, stream_config->num_streams); + + // Destroy all old streams and replace stream array with new one + destroyStreams(mStreams, mNumStreams); + mStreams = newStreams; + mNumStreams = stream_config->num_streams; + + // Clear out last seen settings metadata + setSettings(NULL); + return 0; + +err_out: + // Clean up temporary streams, preserve existing mStreams/mNumStreams + destroyStreams(newStreams, stream_config->num_streams); + return -EINVAL; +} + +void Camera::destroyStreams(Stream **streams, int count) +{ + if (streams == NULL) + return; + for (int i = 0; i < count; i++) { + // Only destroy streams that weren't reused + if (streams[i] != NULL && !streams[i]->mReuse) + delete streams[i]; + } + delete [] streams; +} + +Stream *Camera::reuseStream(camera3_stream_t *astream) +{ + Stream *priv = reinterpret_cast<Stream*>(astream->priv); + // Verify the re-used stream's parameters match + if (!priv->isValidReuseStream(mId, astream)) { + ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId); + return NULL; + } + // Mark stream to be reused + priv->mReuse = true; + return priv; +} + +bool Camera::isValidStreamSet(Stream **streams, int count) +{ + int inputs = 0; + int outputs = 0; + + if (streams == NULL) { + ALOGE("%s:%d: NULL stream configuration streams", __func__, mId); + return false; + } + if (count == 0) { + ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId); + return false; + } + // Validate there is at most one input stream and at least one output stream + for (int i = 0; i < count; i++) { + // A stream may be both input and output (bidirectional) + if (streams[i]->isInputType()) + inputs++; + if (streams[i]->isOutputType()) + outputs++; + } + ALOGV("%s:%d: Configuring %d output streams and %d input streams", + __func__, mId, outputs, inputs); + if (outputs < 1) { + ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId); + return false; + } + if (inputs > 1) { + ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId); + return false; + } + // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams + return true; +} + +void Camera::setupStreams(Stream **streams, int count) +{ + /* + * This is where the HAL has to decide internally how to handle all of the + * streams, and then produce usage and max_buffer values for each stream. + * Note, the stream array has been checked before this point for ALL invalid + * conditions, so it must find a successful configuration for this stream + * array. The HAL may not return an error from this point. + * + * In this demo HAL, we just set all streams to be the same dummy values; + * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN. + */ + for (int i = 0; i < count; i++) { + uint32_t usage = 0; + + if (streams[i]->isOutputType()) + usage |= GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_CAMERA_WRITE; + if (streams[i]->isInputType()) + usage |= GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_HW_CAMERA_READ; + + streams[i]->setUsage(usage); + streams[i]->setMaxBuffers(1); + } +} + +int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set) +{ + ALOGV("%s:%d: buffer_set=%p", __func__, mId, buf_set); + if (buf_set == NULL) { + ALOGE("%s:%d: NULL buffer set", __func__, mId); + return -EINVAL; + } + if (buf_set->stream == NULL) { + ALOGE("%s:%d: NULL stream handle", __func__, mId); + return -EINVAL; + } + Stream *stream = reinterpret_cast<Stream*>(buf_set->stream->priv); + return stream->registerBuffers(buf_set); +} + +bool Camera::isValidTemplateType(int type) +{ + return type < 1 || type >= CAMERA3_TEMPLATE_COUNT; +} + +const camera_metadata_t* Camera::constructDefaultRequestSettings(int type) +{ + ALOGV("%s:%d: type=%d", __func__, mId, type); + + if (!isValidTemplateType(type)) { + ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type); + return NULL; + } + return mTemplates[type]; +} + +int Camera::processCaptureRequest(camera3_capture_request_t *request) +{ + camera3_capture_result result; + + ALOGV("%s:%d: request=%p", __func__, mId, request); + ATRACE_CALL(); + + if (request == NULL) { + ALOGE("%s:%d: NULL request recieved", __func__, mId); + return -EINVAL; + } + + ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId, + request->frame_number, request->settings); + + // NULL indicates use last settings + if (request->settings == NULL) { + if (mSettings == NULL) { + ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p", + __func__, mId, request->frame_number, request); + return -EINVAL; + } + } else { + setSettings(request->settings); + } + + if (request->input_buffer != NULL) { + ALOGV("%s:%d: Reprocessing input buffer %p", __func__, mId, + request->input_buffer); + + if (!isValidReprocessSettings(request->settings)) { + ALOGE("%s:%d: Invalid settings for reprocess request: %p", + __func__, mId, request->settings); + return -EINVAL; + } + } else { + ALOGV("%s:%d: Capturing new frame.", __func__, mId); + + if (!isValidCaptureSettings(request->settings)) { + ALOGE("%s:%d: Invalid settings for capture request: %p", + __func__, mId, request->settings); + return -EINVAL; + } + } + + if (request->num_output_buffers <= 0) { + ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId, + request->num_output_buffers); + return -EINVAL; + } + result.num_output_buffers = request->num_output_buffers; + result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers]; + for (unsigned int i = 0; i < request->num_output_buffers; i++) { + int res = processCaptureBuffer(&request->output_buffers[i], + const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i])); + if (res) + goto err_out; + } + + result.frame_number = request->frame_number; + // TODO: return actual captured/reprocessed settings + result.result = request->settings; + // TODO: asynchronously return results + notifyShutter(request->frame_number, 0); + mCallbackOps->process_capture_result(mCallbackOps, &result); + + return 0; + +err_out: + delete [] result.output_buffers; + // TODO: this should probably be a total device failure; transient for now + return -EINVAL; +} + +void Camera::setSettings(const camera_metadata_t *new_settings) +{ + if (mSettings != NULL) { + free_camera_metadata(mSettings); + mSettings = NULL; + } + + if (new_settings != NULL) + mSettings = clone_camera_metadata(new_settings); +} + +bool Camera::isValidReprocessSettings(const camera_metadata_t* /*settings*/) +{ + // TODO: reject settings that cannot be reprocessed + // input buffers unimplemented, use this to reject reprocessing requests + ALOGE("%s:%d: Input buffer reprocessing not implemented", __func__, mId); + return false; +} + +int Camera::processCaptureBuffer(const camera3_stream_buffer_t *in, + camera3_stream_buffer_t *out) +{ + if (in->acquire_fence != -1) { + int res = sync_wait(in->acquire_fence, CAMERA_SYNC_TIMEOUT); + if (res == -ETIME) { + ALOGE("%s:%d: Timeout waiting on buffer acquire fence", + __func__, mId); + return res; + } else if (res) { + ALOGE("%s:%d: Error waiting on buffer acquire fence: %s(%d)", + __func__, mId, strerror(-res), res); + return res; + } + } + + out->stream = in->stream; + out->buffer = in->buffer; + out->status = CAMERA3_BUFFER_STATUS_OK; + // TODO: use driver-backed release fences + out->acquire_fence = -1; + out->release_fence = -1; + + // TODO: lock and software-paint buffer + return 0; +} + +void Camera::notifyShutter(uint32_t frame_number, uint64_t timestamp) +{ + int res; + struct timespec ts; + + // If timestamp is 0, get timestamp from right now instead + if (timestamp == 0) { + ALOGW("%s:%d: No timestamp provided, using CLOCK_BOOTTIME", + __func__, mId); + res = clock_gettime(CLOCK_BOOTTIME, &ts); + if (res == 0) { + timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + } else { + ALOGE("%s:%d: No timestamp and failed to get CLOCK_BOOTTIME %s(%d)", + __func__, mId, strerror(errno), errno); + } + } + camera3_notify_msg_t m; + memset(&m, 0, sizeof(m)); + m.type = CAMERA3_MSG_SHUTTER; + m.message.shutter.frame_number = frame_number; + m.message.shutter.timestamp = timestamp; + mCallbackOps->notify(mCallbackOps, &m); +} + +void Camera::dump(int fd) +{ + ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + dprintf(fd, "Camera ID: %d (Busy: %d)\n", mId, mBusy); + + // TODO: dump all settings + dprintf(fd, "Most Recent Settings: (%p)\n", mSettings); + + dprintf(fd, "Number of streams: %d\n", mNumStreams); + for (int i = 0; i < mNumStreams; i++) { + dprintf(fd, "Stream %d/%d:\n", i, mNumStreams); + mStreams[i]->dump(fd); + } +} + +const char* Camera::templateToString(int type) +{ + switch (type) { + case CAMERA3_TEMPLATE_PREVIEW: + return "CAMERA3_TEMPLATE_PREVIEW"; + case CAMERA3_TEMPLATE_STILL_CAPTURE: + return "CAMERA3_TEMPLATE_STILL_CAPTURE"; + case CAMERA3_TEMPLATE_VIDEO_RECORD: + return "CAMERA3_TEMPLATE_VIDEO_RECORD"; + case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT: + return "CAMERA3_TEMPLATE_VIDEO_SNAPSHOT"; + case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG: + return "CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG"; + } + // TODO: support vendor templates + return "Invalid template type!"; +} + +int Camera::setTemplate(int type, camera_metadata_t *settings) +{ + android::Mutex::Autolock al(mDeviceLock); + + if (!isValidTemplateType(type)) { + ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type); + return -EINVAL; + } + + if (mTemplates[type] != NULL) { + ALOGE("%s:%d: Setting already constructed template type %s(%d)", + __func__, mId, templateToString(type), type); + return -EINVAL; + } + + // Make a durable copy of the underlying metadata + mTemplates[type] = clone_camera_metadata(settings); + if (mTemplates[type] == NULL) { + ALOGE("%s:%d: Failed to clone metadata %p for template type %s(%d)", + __func__, mId, settings, templateToString(type), type); + return -EINVAL; + } + return 0; +} + +extern "C" { +// Get handle to camera from device priv data +static Camera *camdev_to_camera(const camera3_device_t *dev) +{ + return reinterpret_cast<Camera*>(dev->priv); +} + +static int initialize(const camera3_device_t *dev, + const camera3_callback_ops_t *callback_ops) +{ + return camdev_to_camera(dev)->initialize(callback_ops); +} + +static int configure_streams(const camera3_device_t *dev, + camera3_stream_configuration_t *stream_list) +{ + return camdev_to_camera(dev)->configureStreams(stream_list); +} + +static int register_stream_buffers(const camera3_device_t *dev, + const camera3_stream_buffer_set_t *buffer_set) +{ + return camdev_to_camera(dev)->registerStreamBuffers(buffer_set); +} + +static const camera_metadata_t *construct_default_request_settings( + const camera3_device_t *dev, int type) +{ + return camdev_to_camera(dev)->constructDefaultRequestSettings(type); +} + +static int process_capture_request(const camera3_device_t *dev, + camera3_capture_request_t *request) +{ + return camdev_to_camera(dev)->processCaptureRequest(request); +} + +static void dump(const camera3_device_t *dev, int fd) +{ + camdev_to_camera(dev)->dump(fd); +} + +static int flush(const camera3_device_t*) +{ + ALOGE("%s: unimplemented.", __func__); + return -1; +} + +} // extern "C" + +const camera3_device_ops_t Camera::sOps = { + .initialize = default_camera_hal::initialize, + .configure_streams = default_camera_hal::configure_streams, + .register_stream_buffers = default_camera_hal::register_stream_buffers, + .construct_default_request_settings + = default_camera_hal::construct_default_request_settings, + .process_capture_request = default_camera_hal::process_capture_request, + .get_metadata_vendor_tag_ops = NULL, + .dump = default_camera_hal::dump, + .flush = default_camera_hal::flush, + .reserved = {0}, +}; + +} // namespace default_camera_hal
diff --git a/libhardware/modules/camera/Camera.h b/libhardware/modules/camera/Camera.h new file mode 100644 index 0000000..072de35 --- /dev/null +++ b/libhardware/modules/camera/Camera.h
@@ -0,0 +1,117 @@ +/* + * Copyright (C) 2012 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_H_ +#define CAMERA_H_ + +#include <hardware/hardware.h> +#include <hardware/camera3.h> +#include <utils/Mutex.h> +#include "Metadata.h" +#include "Stream.h" + +namespace default_camera_hal { +// Camera represents a physical camera on a device. +// This is constructed when the HAL module is loaded, one per physical camera. +// It is opened by the framework, and must be closed before it can be opened +// again. +// This is an abstract class, containing all logic and data shared between all +// camera devices (front, back, etc) and common to the ISP. +class Camera { + public: + // id is used to distinguish cameras. 0 <= id < NUM_CAMERAS. + // module is a handle to the HAL module, used when the device is opened. + explicit Camera(int id); + virtual ~Camera(); + + // Common Camera Device Operations (see <hardware/camera_common.h>) + int open(const hw_module_t *module, hw_device_t **device); + int getInfo(struct camera_info *info); + int close(); + + // Camera v3 Device Operations (see <hardware/camera3.h>) + int initialize(const camera3_callback_ops_t *callback_ops); + int configureStreams(camera3_stream_configuration_t *stream_list); + int registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set); + const camera_metadata_t *constructDefaultRequestSettings(int type); + int processCaptureRequest(camera3_capture_request_t *request); + void dump(int fd); + + + protected: + // Initialize static camera characteristics for individual device + virtual camera_metadata_t *initStaticInfo() = 0; + // Verify settings are valid for a capture + virtual bool isValidCaptureSettings(const camera_metadata_t *) = 0; + // Separate initialization method for individual devices when opened + virtual int initDevice() = 0; + // Accessor used by initDevice() to set the templates' metadata + int setTemplate(int type, camera_metadata_t *static_info); + // Prettyprint template names + const char* templateToString(int type); + + private: + // Camera device handle returned to framework for use + camera3_device_t mDevice; + // Reuse a stream already created by this device + Stream *reuseStream(camera3_stream_t *astream); + // Destroy all streams in a stream array, and the array itself + void destroyStreams(Stream **array, int count); + // Verify a set of streams is valid in aggregate + bool isValidStreamSet(Stream **array, int count); + // Calculate usage and max_bufs of each stream + void setupStreams(Stream **array, int count); + // Copy new settings for re-use and clean up old settings. + void setSettings(const camera_metadata_t *new_settings); + // Verify settings are valid for reprocessing an input buffer + bool isValidReprocessSettings(const camera_metadata_t *settings); + // Process an output buffer + int processCaptureBuffer(const camera3_stream_buffer_t *in, + camera3_stream_buffer_t *out); + // Send a shutter notify message with start of exposure time + void notifyShutter(uint32_t frame_number, uint64_t timestamp); + // Is type a valid template type (and valid index into mTemplates) + bool isValidTemplateType(int type); + + // Identifier used by framework to distinguish cameras + const int mId; + // Metadata containing persistent camera characteristics + Metadata mMetadata; + // camera_metadata structure containing static characteristics + camera_metadata_t *mStaticInfo; + // Busy flag indicates camera is in use + bool mBusy; + // Camera device operations handle shared by all devices + const static camera3_device_ops_t sOps; + // Methods used to call back into the framework + const camera3_callback_ops_t *mCallbackOps; + // Lock protecting the Camera object for modifications + android::Mutex mDeviceLock; + // Lock protecting only static camera characteristics, which may + // be accessed without the camera device open + android::Mutex mStaticInfoLock; + // Array of handles to streams currently in use by the device + Stream **mStreams; + // Number of streams in mStreams + int mNumStreams; + // Static array of standard camera settings templates + camera_metadata_t *mTemplates[CAMERA3_TEMPLATE_COUNT]; + // Most recent request settings seen, memoized to be reused + camera_metadata_t *mSettings; +}; +} // namespace default_camera_hal + +#endif // CAMERA_H_
diff --git a/libhardware/modules/camera/CameraHAL.cpp b/libhardware/modules/camera/CameraHAL.cpp new file mode 100644 index 0000000..62ee6d4 --- /dev/null +++ b/libhardware/modules/camera/CameraHAL.cpp
@@ -0,0 +1,194 @@ +/* + * Copyright (C) 2012 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 <cstdlib> +#include <hardware/camera_common.h> +#include <hardware/hardware.h> +#include "ExampleCamera.h" +#include "VendorTags.h" + +//#define LOG_NDEBUG 0 +#define LOG_TAG "DefaultCameraHAL" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <cutils/trace.h> + +#include "CameraHAL.h" + +/* + * This file serves as the entry point to the HAL. It contains the module + * structure and functions used by the framework to load and interface to this + * HAL, as well as the handles to the individual camera devices. + */ + +namespace default_camera_hal { + +// Default Camera HAL has 2 cameras, front and rear. +static CameraHAL gCameraHAL(2); +// Handle containing vendor tag functionality +static VendorTags gVendorTags; + +CameraHAL::CameraHAL(int num_cameras) + : mNumberOfCameras(num_cameras), + mCallbacks(NULL) +{ + // Allocate camera array and instantiate camera devices + mCameras = new Camera*[mNumberOfCameras]; + // Rear camera + mCameras[0] = new ExampleCamera(0); + // Front camera + mCameras[1] = new ExampleCamera(1); +} + +CameraHAL::~CameraHAL() +{ + for (int i = 0; i < mNumberOfCameras; i++) { + delete mCameras[i]; + } + delete [] mCameras; +} + +int CameraHAL::getNumberOfCameras() +{ + ALOGV("%s: %d", __func__, mNumberOfCameras); + return mNumberOfCameras; +} + +int CameraHAL::getCameraInfo(int id, struct camera_info* info) +{ + ALOGV("%s: camera id %d: info=%p", __func__, id, info); + if (id < 0 || id >= mNumberOfCameras) { + ALOGE("%s: Invalid camera id %d", __func__, id); + return -ENODEV; + } + // TODO: return device-specific static metadata + return mCameras[id]->getInfo(info); +} + +int CameraHAL::setCallbacks(const camera_module_callbacks_t *callbacks) +{ + ALOGV("%s : callbacks=%p", __func__, callbacks); + mCallbacks = callbacks; + return 0; +} + +int CameraHAL::open(const hw_module_t* mod, const char* name, hw_device_t** dev) +{ + int id; + char *nameEnd; + + ALOGV("%s: module=%p, name=%s, device=%p", __func__, mod, name, dev); + if (*name == '\0') { + ALOGE("%s: Invalid camera id name is NULL", __func__); + return -EINVAL; + } + id = strtol(name, &nameEnd, 10); + if (*nameEnd != '\0') { + ALOGE("%s: Invalid camera id name %s", __func__, name); + return -EINVAL; + } else if (id < 0 || id >= mNumberOfCameras) { + ALOGE("%s: Invalid camera id %d", __func__, id); + return -ENODEV; + } + return mCameras[id]->open(mod, dev); +} + +extern "C" { + +static int get_number_of_cameras() +{ + return gCameraHAL.getNumberOfCameras(); +} + +static int get_camera_info(int id, struct camera_info* info) +{ + return gCameraHAL.getCameraInfo(id, info); +} + +static int set_callbacks(const camera_module_callbacks_t *callbacks) +{ + return gCameraHAL.setCallbacks(callbacks); +} + +static int get_tag_count(const vendor_tag_ops_t* ops) +{ + return gVendorTags.getTagCount(ops); +} + +static void get_all_tags(const vendor_tag_ops_t* ops, uint32_t* tag_array) +{ + gVendorTags.getAllTags(ops, tag_array); +} + +static const char* get_section_name(const vendor_tag_ops_t* ops, uint32_t tag) +{ + return gVendorTags.getSectionName(ops, tag); +} + +static const char* get_tag_name(const vendor_tag_ops_t* ops, uint32_t tag) +{ + return gVendorTags.getTagName(ops, tag); +} + +static int get_tag_type(const vendor_tag_ops_t* ops, uint32_t tag) +{ + return gVendorTags.getTagType(ops, tag); +} + +static void get_vendor_tag_ops(vendor_tag_ops_t* ops) +{ + ALOGV("%s : ops=%p", __func__, ops); + ops->get_tag_count = get_tag_count; + ops->get_all_tags = get_all_tags; + ops->get_section_name = get_section_name; + ops->get_tag_name = get_tag_name; + ops->get_tag_type = get_tag_type; +} + +static int open_dev(const hw_module_t* mod, const char* name, hw_device_t** dev) +{ + return gCameraHAL.open(mod, name, dev); +} + +static hw_module_methods_t gCameraModuleMethods = { + open : open_dev +}; + +camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = { + common : { + tag : HARDWARE_MODULE_TAG, + module_api_version : CAMERA_MODULE_API_VERSION_2_2, + hal_api_version : HARDWARE_HAL_API_VERSION, + id : CAMERA_HARDWARE_MODULE_ID, + name : "Default Camera HAL", + author : "The Android Open Source Project", + methods : &gCameraModuleMethods, + dso : NULL, + reserved : {0}, + }, + get_number_of_cameras : get_number_of_cameras, + get_camera_info : get_camera_info, + set_callbacks : set_callbacks, + get_vendor_tag_ops : get_vendor_tag_ops, + open_legacy : NULL, + set_torch_mode : NULL, + init : NULL, + reserved : {0}, +}; +} // extern "C" + +} // namespace default_camera_hal
diff --git a/libhardware/modules/camera/CameraHAL.h b/libhardware/modules/camera/CameraHAL.h new file mode 100644 index 0000000..74a70a6 --- /dev/null +++ b/libhardware/modules/camera/CameraHAL.h
@@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 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_HAL_H_ +#define CAMERA_HAL_H_ + +#include <cutils/bitops.h> +#include <hardware/hardware.h> +#include <hardware/camera_common.h> +#include <system/camera_vendor_tags.h> +#include "Camera.h" +#include "VendorTags.h" + +namespace default_camera_hal { +// CameraHAL contains all module state that isn't specific to an individual +// camera device. +class CameraHAL { + public: + explicit CameraHAL(int num_cameras); + ~CameraHAL(); + + // Camera Module Interface (see <hardware/camera_common.h>) + int getNumberOfCameras(); + int getCameraInfo(int camera_id, struct camera_info *info); + int setCallbacks(const camera_module_callbacks_t *callbacks); + void getVendorTagOps(vendor_tag_ops_t* ops); + + // Hardware Module Interface (see <hardware/hardware.h>) + int open(const hw_module_t* mod, const char* name, hw_device_t** dev); + + private: + // Number of cameras + const int mNumberOfCameras; + // Callback handle + const camera_module_callbacks_t *mCallbacks; + // Array of camera devices, contains mNumberOfCameras device pointers + Camera **mCameras; +}; +} // namespace default_camera_hal + +#endif // CAMERA_HAL_H_
diff --git a/libhardware/modules/camera/ExampleCamera.cpp b/libhardware/modules/camera/ExampleCamera.cpp new file mode 100644 index 0000000..2b1f185 --- /dev/null +++ b/libhardware/modules/camera/ExampleCamera.cpp
@@ -0,0 +1,273 @@ +/* + * Copyright (C) 2013 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 <system/camera_metadata.h> +#include "Camera.h" + +//#define LOG_NDEBUG 0 +#define LOG_TAG "ExampleCamera" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "ExampleCamera.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +namespace default_camera_hal { + +ExampleCamera::ExampleCamera(int id) : Camera(id) +{ +} + +ExampleCamera::~ExampleCamera() +{ +} + +camera_metadata_t *ExampleCamera::initStaticInfo() +{ + /* + * Setup static camera info. This will have to customized per camera + * device. + */ + Metadata m; + + /* android.control */ + int32_t android_control_ae_available_target_fps_ranges[] = {30, 30}; + m.addInt32(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + ARRAY_SIZE(android_control_ae_available_target_fps_ranges), + android_control_ae_available_target_fps_ranges); + + int32_t android_control_ae_compensation_range[] = {-4, 4}; + m.addInt32(ANDROID_CONTROL_AE_COMPENSATION_RANGE, + ARRAY_SIZE(android_control_ae_compensation_range), + android_control_ae_compensation_range); + + camera_metadata_rational_t android_control_ae_compensation_step[] = {{2,1}}; + m.addRational(ANDROID_CONTROL_AE_COMPENSATION_STEP, + ARRAY_SIZE(android_control_ae_compensation_step), + android_control_ae_compensation_step); + + int32_t android_control_max_regions[] = {/*AE*/ 1,/*AWB*/ 1,/*AF*/ 1}; + m.addInt32(ANDROID_CONTROL_MAX_REGIONS, + ARRAY_SIZE(android_control_max_regions), + android_control_max_regions); + + /* android.jpeg */ + int32_t android_jpeg_available_thumbnail_sizes[] = {0, 0, 128, 96}; + m.addInt32(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, + ARRAY_SIZE(android_jpeg_available_thumbnail_sizes), + android_jpeg_available_thumbnail_sizes); + + int32_t android_jpeg_max_size[] = {13 * 1024 * 1024}; // 13MB + m.addInt32(ANDROID_JPEG_MAX_SIZE, + ARRAY_SIZE(android_jpeg_max_size), + android_jpeg_max_size); + + /* android.lens */ + float android_lens_info_available_focal_lengths[] = {1.0}; + m.addFloat(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, + ARRAY_SIZE(android_lens_info_available_focal_lengths), + android_lens_info_available_focal_lengths); + + /* android.request */ + int32_t android_request_max_num_output_streams[] = {0, 3, 1}; + m.addInt32(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, + ARRAY_SIZE(android_request_max_num_output_streams), + android_request_max_num_output_streams); + + /* android.scaler */ + int32_t android_scaler_available_formats[] = { + HAL_PIXEL_FORMAT_RAW16, + HAL_PIXEL_FORMAT_BLOB, + HAL_PIXEL_FORMAT_RGBA_8888, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + // These are handled by YCbCr_420_888 + // HAL_PIXEL_FORMAT_YV12, + // HAL_PIXEL_FORMAT_YCrCb_420_SP, + HAL_PIXEL_FORMAT_YCbCr_420_888}; + m.addInt32(ANDROID_SCALER_AVAILABLE_FORMATS, + ARRAY_SIZE(android_scaler_available_formats), + android_scaler_available_formats); + + int64_t android_scaler_available_jpeg_min_durations[] = {1}; + m.addInt64(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_jpeg_min_durations), + android_scaler_available_jpeg_min_durations); + + int32_t android_scaler_available_jpeg_sizes[] = {640, 480}; + m.addInt32(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, + ARRAY_SIZE(android_scaler_available_jpeg_sizes), + android_scaler_available_jpeg_sizes); + + float android_scaler_available_max_digital_zoom[] = {1}; + m.addFloat(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, + ARRAY_SIZE(android_scaler_available_max_digital_zoom), + android_scaler_available_max_digital_zoom); + + int64_t android_scaler_available_processed_min_durations[] = {1}; + m.addInt64(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_processed_min_durations), + android_scaler_available_processed_min_durations); + + int32_t android_scaler_available_processed_sizes[] = {640, 480}; + m.addInt32(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, + ARRAY_SIZE(android_scaler_available_processed_sizes), + android_scaler_available_processed_sizes); + + int64_t android_scaler_available_raw_min_durations[] = {1}; + m.addInt64(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_raw_min_durations), + android_scaler_available_raw_min_durations); + + int32_t android_scaler_available_raw_sizes[] = {640, 480}; + m.addInt32(ANDROID_SCALER_AVAILABLE_RAW_SIZES, + ARRAY_SIZE(android_scaler_available_raw_sizes), + android_scaler_available_raw_sizes); + + /* android.sensor */ + + int32_t android_sensor_info_active_array_size[] = {0, 0, 640, 480}; + m.addInt32(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, + ARRAY_SIZE(android_sensor_info_active_array_size), + android_sensor_info_active_array_size); + + int32_t android_sensor_info_sensitivity_range[] = + {100, 1600}; + m.addInt32(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE, + ARRAY_SIZE(android_sensor_info_sensitivity_range), + android_sensor_info_sensitivity_range); + + int64_t android_sensor_info_max_frame_duration[] = {30000000000}; + m.addInt64(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, + ARRAY_SIZE(android_sensor_info_max_frame_duration), + android_sensor_info_max_frame_duration); + + float android_sensor_info_physical_size[] = {3.2, 2.4}; + m.addFloat(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, + ARRAY_SIZE(android_sensor_info_physical_size), + android_sensor_info_physical_size); + + int32_t android_sensor_info_pixel_array_size[] = {640, 480}; + m.addInt32(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, + ARRAY_SIZE(android_sensor_info_pixel_array_size), + android_sensor_info_pixel_array_size); + + int32_t android_sensor_orientation[] = {0}; + m.addInt32(ANDROID_SENSOR_ORIENTATION, + ARRAY_SIZE(android_sensor_orientation), + android_sensor_orientation); + + /* End of static camera characteristics */ + + return clone_camera_metadata(m.get()); +} + +int ExampleCamera::initDevice() +{ + int res; + Metadata base; + + // Create standard settings templates from copies of base metadata + // TODO: use vendor tags in base metadata + res = base.add1UInt8(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_OFF); + if (res) + return res; + + // Use base settings to create all other templates and set them + res = setPreviewTemplate(base); + if (res) + return res; + res = setStillTemplate(base); + if (res) + return res; + res = setRecordTemplate(base); + if (res) + return res; + res = setSnapshotTemplate(base); + if (res) + return res; + res = setZslTemplate(base); + if (res) + return res; + + return 0; +} + +int ExampleCamera::setPreviewTemplate(Metadata m) +{ + // Setup default preview controls + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW); + + if (res) + return res; + // TODO: set fast auto-focus, auto-whitebalance, auto-exposure, auto flash + return setTemplate(CAMERA3_TEMPLATE_PREVIEW, m.get()); +} + +int ExampleCamera::setStillTemplate(Metadata m) +{ + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE); + // Setup default still capture controls + if (res) + return res; + // TODO: set fast auto-focus, auto-whitebalance, auto-exposure, auto flash + return setTemplate(CAMERA3_TEMPLATE_STILL_CAPTURE, m.get()); +} + +int ExampleCamera::setRecordTemplate(Metadata m) +{ + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + // Setup default video record controls + if (res) + return res; + // TODO: set slow auto-focus, auto-whitebalance, auto-exposure, flash off + return setTemplate(CAMERA3_TEMPLATE_VIDEO_RECORD, m.get()); +} + +int ExampleCamera::setSnapshotTemplate(Metadata m) +{ + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT); + // Setup default video snapshot controls + if (res) + return res; + // TODO: set slow auto-focus, auto-whitebalance, auto-exposure, flash off + return setTemplate(CAMERA3_TEMPLATE_VIDEO_SNAPSHOT, m.get()); +} + +int ExampleCamera::setZslTemplate(Metadata m) +{ + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG); + // Setup default zero shutter lag controls + if (res) + return res; + // TODO: set reprocessing parameters for zsl input queue + return setTemplate(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG, m.get()); +} + +bool ExampleCamera::isValidCaptureSettings(const camera_metadata_t* settings) +{ + // TODO: reject settings that cannot be captured + return true; +} + +} // namespace default_camera_hal
diff --git a/libhardware/modules/camera/ExampleCamera.h b/libhardware/modules/camera/ExampleCamera.h new file mode 100644 index 0000000..44eac76 --- /dev/null +++ b/libhardware/modules/camera/ExampleCamera.h
@@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 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 EXAMPLE_CAMERA_H_ +#define EXAMPLE_CAMERA_H_ + +#include <system/camera_metadata.h> +#include "Camera.h" + +namespace default_camera_hal { +// ExampleCamera is an example for a specific camera device. The Camera object +// contains all logic common between all cameras (e.g. front and back cameras), +// while a specific camera device (e.g. ExampleCamera) holds all specific +// metadata and logic about that device. +class ExampleCamera : public Camera { + public: + explicit ExampleCamera(int id); + ~ExampleCamera(); + + private: + // Initialize static camera characteristics for individual device + camera_metadata_t *initStaticInfo(); + // Initialize whole device (templates/etc) when opened + int initDevice(); + // Initialize each template metadata controls + int setPreviewTemplate(Metadata m); + int setStillTemplate(Metadata m); + int setRecordTemplate(Metadata m); + int setSnapshotTemplate(Metadata m); + int setZslTemplate(Metadata m); + // Verify settings are valid for a capture with this device + bool isValidCaptureSettings(const camera_metadata_t* settings); +}; +} // namespace default_camera_hal + +#endif // CAMERA_H_
diff --git a/libhardware/modules/camera/Metadata.cpp b/libhardware/modules/camera/Metadata.cpp new file mode 100644 index 0000000..18e5239 --- /dev/null +++ b/libhardware/modules/camera/Metadata.cpp
@@ -0,0 +1,183 @@ +/* + * Copyright (C) 2013 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 <system/camera_metadata.h> + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Metadata" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Metadata.h" + +namespace default_camera_hal { + +Metadata::Metadata(): + mData(NULL) +{ +} + +Metadata::~Metadata() +{ + replace(NULL); +} + +void Metadata::replace(camera_metadata_t *m) +{ + if (m == mData) { + ALOGE("%s: Replacing metadata with itself?!", __func__); + return; + } + if (mData) + free_camera_metadata(mData); + mData = m; +} + +int Metadata::init(const camera_metadata_t *metadata) +{ + camera_metadata_t* tmp; + + if (validate_camera_metadata_structure(metadata, NULL)) + return -EINVAL; + + tmp = clone_camera_metadata(metadata); + if (tmp == NULL) + return -EINVAL; + + replace(tmp); + return 0; +} + +int Metadata::addUInt8(uint32_t tag, int count, const uint8_t *data) +{ + if (!validate(tag, TYPE_BYTE, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::add1UInt8(uint32_t tag, const uint8_t data) +{ + return addUInt8(tag, 1, &data); +} + +int Metadata::addInt32(uint32_t tag, int count, const int32_t *data) +{ + if (!validate(tag, TYPE_INT32, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addFloat(uint32_t tag, int count, const float *data) +{ + if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addInt64(uint32_t tag, int count, const int64_t *data) +{ + if (!validate(tag, TYPE_INT64, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addDouble(uint32_t tag, int count, const double *data) +{ + if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addRational(uint32_t tag, int count, + const camera_metadata_rational_t *data) +{ + if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL; + return add(tag, count, data); +} + +bool Metadata::validate(uint32_t tag, int tag_type, int count) +{ + if (get_camera_metadata_tag_type(tag) < 0) { + ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag); + return false; + } + if (tag_type < 0 || tag_type >= NUM_TYPES) { + ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type); + return false; + } + if (tag_type != get_camera_metadata_tag_type(tag)) { + ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag, + camera_metadata_type_names[tag_type], tag_type); + return false; + } + if (count < 1) { + ALOGE("%s: Invalid metadata entry count: %d", __func__, count); + return false; + } + return true; +} + +int Metadata::add(uint32_t tag, int count, const void *tag_data) +{ + int res; + size_t entry_capacity = 0; + size_t data_capacity = 0; + camera_metadata_t* tmp; + int tag_type = get_camera_metadata_tag_type(tag); + size_t size = calculate_camera_metadata_entry_data_size(tag_type, count); + + if (NULL == mData) { + entry_capacity = 1; + data_capacity = size; + } else { + entry_capacity = get_camera_metadata_entry_count(mData) + 1; + data_capacity = get_camera_metadata_data_count(mData) + size; + } + + // Opportunistically attempt to add if metadata exists and has room for it + if (mData && !add_camera_metadata_entry(mData, tag, tag_data, count)) + return 0; + // Double new dimensions to minimize future reallocations + tmp = allocate_camera_metadata(entry_capacity * 2, data_capacity * 2); + if (tmp == NULL) { + ALOGE("%s: Failed to allocate new metadata with %zu entries, %zu data", + __func__, entry_capacity, data_capacity); + return -ENOMEM; + } + // Append the current metadata to the new (empty) metadata, if any + if (NULL != mData) { + res = append_camera_metadata(tmp, mData); + if (res) { + ALOGE("%s: Failed to append old metadata %p to new %p", + __func__, mData, tmp); + return res; + } + } + // Add the remaining new item to tmp and replace mData + res = add_camera_metadata_entry(tmp, tag, tag_data, count); + if (res) { + ALOGE("%s: Failed to add new entry (%d, %p, %d) to metadata %p", + __func__, tag, tag_data, count, tmp); + return res; + } + replace(tmp); + + return 0; +} + +camera_metadata_t* Metadata::get() +{ + return mData; +} + +} // namespace default_camera_hal
diff --git a/libhardware/modules/camera/Metadata.h b/libhardware/modules/camera/Metadata.h new file mode 100644 index 0000000..f432d04 --- /dev/null +++ b/libhardware/modules/camera/Metadata.h
@@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 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 METADATA_H_ +#define METADATA_H_ + +#include <stdint.h> +#include <hardware/camera3.h> +#include <system/camera_metadata.h> + +namespace default_camera_hal { +// Metadata is a convenience class for dealing with libcamera_metadata +class Metadata { + public: + Metadata(); + ~Metadata(); + // Initialize with framework metadata + int init(const camera_metadata_t *metadata); + + // Parse and add an entry. Allocates and copies new storage for *data. + int addUInt8(uint32_t tag, int count, const uint8_t *data); + int add1UInt8(uint32_t tag, const uint8_t data); + int addInt32(uint32_t tag, int count, const int32_t *data); + int addFloat(uint32_t tag, int count, const float *data); + int addInt64(uint32_t tag, int count, const int64_t *data); + int addDouble(uint32_t tag, int count, const double *data); + int addRational(uint32_t tag, int count, + const camera_metadata_rational_t *data); + + // Get a handle to the current metadata + // This is not a durable handle, and may be destroyed by add*/init + camera_metadata_t* get(); + + private: + // Actual internal storage + camera_metadata_t* mData; + // Destroy old metadata and replace with new + void replace(camera_metadata_t *m); + // Validate the tag, type and count for a metadata entry + bool validate(uint32_t tag, int tag_type, int count); + // Add a verified tag with data + int add(uint32_t tag, int count, const void *tag_data); +}; +} // namespace default_camera_hal + +#endif // METADATA_H_
diff --git a/libhardware/modules/camera/Stream.cpp b/libhardware/modules/camera/Stream.cpp new file mode 100644 index 0000000..e0099b6 --- /dev/null +++ b/libhardware/modules/camera/Stream.cpp
@@ -0,0 +1,241 @@ +/* + * Copyright (C) 2013 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 <stdio.h> +#include <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/graphics.h> +#include <utils/Mutex.h> + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Stream" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Stream.h" + +namespace default_camera_hal { + +Stream::Stream(int id, camera3_stream_t *s) + : mReuse(false), + mId(id), + mStream(s), + mType(s->stream_type), + mWidth(s->width), + mHeight(s->height), + mFormat(s->format), + mUsage(0), + mMaxBuffers(0), + mRegistered(false), + mBuffers(0), + mNumBuffers(0) +{ +} + +Stream::~Stream() +{ + android::Mutex::Autolock al(mLock); + unregisterBuffers_L(); +} + +void Stream::setUsage(uint32_t usage) +{ + android::Mutex::Autolock al(mLock); + if (usage != mUsage) { + mUsage = usage; + mStream->usage = usage; + unregisterBuffers_L(); + } +} + +void Stream::setMaxBuffers(uint32_t max_buffers) +{ + android::Mutex::Autolock al(mLock); + if (max_buffers != mMaxBuffers) { + mMaxBuffers = max_buffers; + mStream->max_buffers = max_buffers; + unregisterBuffers_L(); + } +} + +int Stream::getType() +{ + return mType; +} + +bool Stream::isInputType() +{ + return mType == CAMERA3_STREAM_INPUT || + mType == CAMERA3_STREAM_BIDIRECTIONAL; +} + +bool Stream::isOutputType() +{ + return mType == CAMERA3_STREAM_OUTPUT || + mType == CAMERA3_STREAM_BIDIRECTIONAL; +} + +const char* Stream::typeToString(int type) +{ + switch (type) { + case CAMERA3_STREAM_INPUT: + return "CAMERA3_STREAM_INPUT"; + case CAMERA3_STREAM_OUTPUT: + return "CAMERA3_STREAM_OUTPUT"; + case CAMERA3_STREAM_BIDIRECTIONAL: + return "CAMERA3_STREAM_BIDIRECTIONAL"; + } + return "Invalid stream type!"; +} + +const char* Stream::formatToString(int format) +{ + // See <system/graphics.h> for full list + switch (format) { + case HAL_PIXEL_FORMAT_BGRA_8888: + return "BGRA 8888"; + case HAL_PIXEL_FORMAT_RGBA_8888: + return "RGBA 8888"; + case HAL_PIXEL_FORMAT_RGBX_8888: + return "RGBX 8888"; + case HAL_PIXEL_FORMAT_RGB_888: + return "RGB 888"; + case HAL_PIXEL_FORMAT_RGB_565: + return "RGB 565"; + case HAL_PIXEL_FORMAT_Y8: + return "Y8"; + case HAL_PIXEL_FORMAT_Y16: + return "Y16"; + case HAL_PIXEL_FORMAT_YV12: + return "YV12"; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + return "NV16"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return "NV21"; + case HAL_PIXEL_FORMAT_YCbCr_422_I: + return "YUY2"; + case HAL_PIXEL_FORMAT_RAW10: + return "RAW10"; + case HAL_PIXEL_FORMAT_RAW16: + return "RAW16"; + case HAL_PIXEL_FORMAT_BLOB: + return "BLOB"; + case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: + return "IMPLEMENTATION DEFINED"; + case HAL_PIXEL_FORMAT_YCbCr_420_888: + return "FLEXIBLE YCbCr 420 888"; + } + return "Invalid stream format!"; +} + +bool Stream::isRegistered() +{ + return mRegistered; +} + +bool Stream::isValidReuseStream(int id, camera3_stream_t *s) +{ + if (id != mId) { + ALOGE("%s:%d: Invalid camera id for reuse. Got %d expect %d", + __func__, mId, id, mId); + return false; + } + if (s != mStream) { + ALOGE("%s:%d: Invalid stream handle for reuse. Got %p expect %p", + __func__, mId, s, mStream); + return false; + } + if (s->stream_type != mType) { + ALOGE("%s:%d: Mismatched type in reused stream. Got %s(%d) " + "expect %s(%d)", __func__, mId, typeToString(s->stream_type), + s->stream_type, typeToString(mType), mType); + return false; + } + if (s->format != mFormat) { + ALOGE("%s:%d: Mismatched format in reused stream. Got %s(%d) " + "expect %s(%d)", __func__, mId, formatToString(s->format), + s->format, formatToString(mFormat), mFormat); + return false; + } + if (s->width != mWidth) { + ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d", + __func__, mId, s->width, mWidth); + return false; + } + if (s->height != mHeight) { + ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d", + __func__, mId, s->height, mHeight); + return false; + } + return true; +} + +int Stream::registerBuffers(const camera3_stream_buffer_set_t *buf_set) +{ + ATRACE_CALL(); + android::Mutex::Autolock al(mLock); + + if (buf_set->stream != mStream) { + ALOGE("%s:%d: Buffer set for invalid stream. Got %p expect %p", + __func__, mId, buf_set->stream, mStream); + return -EINVAL; + } + + mNumBuffers = buf_set->num_buffers; + mBuffers = new buffer_handle_t*[mNumBuffers]; + + for (unsigned int i = 0; i < mNumBuffers; i++) { + ALOGV("%s:%d: Registering buffer %p", __func__, mId, + buf_set->buffers[i]); + mBuffers[i] = buf_set->buffers[i]; + // TODO: register buffers with hw, handle error cases + } + mRegistered = true; + + return 0; +} + +// This must only be called with mLock held +void Stream::unregisterBuffers_L() +{ + mRegistered = false; + mNumBuffers = 0; + delete [] mBuffers; + // TODO: unregister buffers from hw +} + +void Stream::dump(int fd) +{ + android::Mutex::Autolock al(mLock); + + dprintf(fd, "Stream ID: %d (%p)\n", mId, mStream); + dprintf(fd, "Stream Type: %s (%d)\n", typeToString(mType), mType); + dprintf(fd, "Width: %" PRIu32 " Height: %" PRIu32 "\n", mWidth, mHeight); + dprintf(fd, "Stream Format: %s (%d)", formatToString(mFormat), mFormat); + // ToDo: prettyprint usage mask flags + dprintf(fd, "Gralloc Usage Mask: %#" PRIx32 "\n", mUsage); + dprintf(fd, "Max Buffer Count: %" PRIu32 "\n", mMaxBuffers); + dprintf(fd, "Buffers Registered: %s\n", mRegistered ? "true" : "false"); + dprintf(fd, "Number of Buffers: %" PRIu32 "\n", mNumBuffers); + for (uint32_t i = 0; i < mNumBuffers; i++) { + dprintf(fd, "Buffer %" PRIu32 "/%" PRIu32 ": %p\n", i, mNumBuffers, + mBuffers[i]); + } +} + +} // namespace default_camera_hal
diff --git a/libhardware/modules/camera/Stream.h b/libhardware/modules/camera/Stream.h new file mode 100644 index 0000000..5efbc52 --- /dev/null +++ b/libhardware/modules/camera/Stream.h
@@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 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 STREAM_H_ +#define STREAM_H_ + +#include <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/graphics.h> +#include <utils/Mutex.h> + +namespace default_camera_hal { +// Stream represents a single input or output stream for a camera device. +class Stream { + public: + Stream(int id, camera3_stream_t *s); + ~Stream(); + + // validate that astream's parameters match this stream's parameters + bool isValidReuseStream(int id, camera3_stream_t *s); + + // Register buffers with hardware + int registerBuffers(const camera3_stream_buffer_set_t *buf_set); + + void setUsage(uint32_t usage); + void setMaxBuffers(uint32_t max_buffers); + + int getType(); + bool isInputType(); + bool isOutputType(); + bool isRegistered(); + const char* typeToString(int type); + const char* formatToString(int format); + void dump(int fd); + + // This stream is being reused. Used in stream configuration passes + bool mReuse; + + private: + // Clean up buffer state. must be called with mLock held. + void unregisterBuffers_L(); + + // The camera device id this stream belongs to + const int mId; + // Handle to framework's stream, used as a cookie for buffers + camera3_stream_t *mStream; + // Stream type: CAMERA3_STREAM_* (see <hardware/camera3.h>) + const int mType; + // Width in pixels of the buffers in this stream + const uint32_t mWidth; + // Height in pixels of the buffers in this stream + const uint32_t mHeight; + // Gralloc format: HAL_PIXEL_FORMAT_* (see <system/graphics.h>) + const int mFormat; + // Gralloc usage mask : GRALLOC_USAGE_* (see <hardware/gralloc.h>) + uint32_t mUsage; + // Max simultaneous in-flight buffers for this stream + uint32_t mMaxBuffers; + // Buffers have been registered for this stream and are ready + bool mRegistered; + // Array of handles to buffers currently in use by the stream + buffer_handle_t **mBuffers; + // Number of buffers in mBuffers + unsigned int mNumBuffers; + // Lock protecting the Stream object for modifications + android::Mutex mLock; +}; +} // namespace default_camera_hal + +#endif // STREAM_H_
diff --git a/libhardware/modules/camera/VendorTags.cpp b/libhardware/modules/camera/VendorTags.cpp new file mode 100644 index 0000000..2c54648 --- /dev/null +++ b/libhardware/modules/camera/VendorTags.cpp
@@ -0,0 +1,188 @@ +/* + * Copyright (C) 2013 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 <system/camera_metadata.h> +#include "Metadata.h" + +//#define LOG_NDEBUG 0 +#define LOG_TAG "VendorTags" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "VendorTags.h" + +namespace default_camera_hal { + +// Internal representations of vendor tags for convenience. +// Other classes must access this data via public interfaces. +// Structured to be easy to extend and contain complexity. +namespace { +// Describes a single vendor tag entry +struct Entry { + const char* name; + uint8_t type; +}; +// Describes a vendor tag section +struct Section { + const char* name; + uint32_t start; + uint32_t end; + const Entry* tags; +}; + +// Entry arrays for each section +const Entry DemoWizardry[demo_wizardry_end - demo_wizardry_start] = { + [demo_wizardry_dimension_size - demo_wizardry_start] = + {"dimensionSize", TYPE_INT32}, + [demo_wizardry_dimensions - demo_wizardry_start] = + {"dimensions", TYPE_INT32}, + [demo_wizardry_familiar - demo_wizardry_start] = + {"familiar", TYPE_BYTE}, + [demo_wizardry_fire - demo_wizardry_start] = + {"fire", TYPE_RATIONAL} +}; + +const Entry DemoSorcery[demo_sorcery_end - demo_sorcery_start] = { + [demo_sorcery_difficulty - demo_sorcery_start] = + {"difficulty", TYPE_INT64}, + [demo_sorcery_light - demo_sorcery_start] = + {"light", TYPE_BYTE} +}; + +const Entry DemoMagic[demo_magic_end - demo_magic_start] = { + [demo_magic_card_trick - demo_magic_start] = + {"cardTrick", TYPE_DOUBLE}, + [demo_magic_levitation - demo_magic_start] = + {"levitation", TYPE_FLOAT} +}; + +// Array of all sections +const Section DemoSections[DEMO_SECTION_COUNT] = { + [DEMO_WIZARDRY] = { "demo.wizardry", + demo_wizardry_start, + demo_wizardry_end, + DemoWizardry }, + [DEMO_SORCERY] = { "demo.sorcery", + demo_sorcery_start, + demo_sorcery_end, + DemoSorcery }, + [DEMO_MAGIC] = { "demo.magic", + demo_magic_start, + demo_magic_end, + DemoMagic } +}; + +// Get a static handle to a specific vendor tag section +const Section* getSection(uint32_t tag) +{ + uint32_t section = (tag - vendor_section_start) >> 16; + + if (tag < vendor_section_start) { + ALOGE("%s: Tag 0x%x before vendor section", __func__, tag); + return NULL; + } + + if (section >= DEMO_SECTION_COUNT) { + ALOGE("%s: Tag 0x%x after vendor section", __func__, tag); + return NULL; + } + + return &DemoSections[section]; +} + +// Get a static handle to a specific vendor tag entry +const Entry* getEntry(uint32_t tag) +{ + const Section* section = getSection(tag); + int index; + + if (section == NULL) + return NULL; + + if (tag >= section->end) { + ALOGE("%s: Tag 0x%x outside section", __func__, tag); + return NULL; + } + + index = tag - section->start; + return §ion->tags[index]; +} +} // namespace + +VendorTags::VendorTags() + : mTagCount(0) +{ + for (int i = 0; i < DEMO_SECTION_COUNT; i++) { + mTagCount += DemoSections[i].end - DemoSections[i].start; + } +} + +VendorTags::~VendorTags() +{ +} + +int VendorTags::getTagCount(const vendor_tag_ops_t* ops) +{ + return mTagCount; +} + +void VendorTags::getAllTags(const vendor_tag_ops_t* ops, uint32_t* tag_array) +{ + if (tag_array == NULL) { + ALOGE("%s: NULL tag_array", __func__); + return; + } + + for (int i = 0; i < DEMO_SECTION_COUNT; i++) { + for (uint32_t tag = DemoSections[i].start; + tag < DemoSections[i].end; tag++) { + *tag_array++ = tag; + } + } +} + +const char* VendorTags::getSectionName(const vendor_tag_ops_t* ops, uint32_t tag) +{ + const Section* section = getSection(tag); + + if (section == NULL) + return NULL; + + return section->name; +} + +const char* VendorTags::getTagName(const vendor_tag_ops_t* ops, uint32_t tag) +{ + const Entry* entry = getEntry(tag); + + if (entry == NULL) + return NULL; + + return entry->name; +} + +int VendorTags::getTagType(const vendor_tag_ops_t* ops, uint32_t tag) +{ + const Entry* entry = getEntry(tag); + + if (entry == NULL) + return -1; + + return entry->type; +} +} // namespace default_camera_hal
diff --git a/libhardware/modules/camera/VendorTags.h b/libhardware/modules/camera/VendorTags.h new file mode 100644 index 0000000..ecf777e --- /dev/null +++ b/libhardware/modules/camera/VendorTags.h
@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 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 VENDOR_TAGS_H_ +#define VENDOR_TAGS_H_ + +#include <hardware/camera_common.h> +#include <system/camera_metadata.h> + +namespace default_camera_hal { + +// VendorTags contains all vendor-specific metadata tag functionality +class VendorTags { + public: + VendorTags(); + ~VendorTags(); + + // Vendor Tags Operations (see <hardware/camera_common.h>) + int getTagCount(const vendor_tag_ops_t* ops); + void getAllTags(const vendor_tag_ops_t* ops, uint32_t* tag_array); + const char* getSectionName(const vendor_tag_ops_t* ops, uint32_t tag); + const char* getTagName(const vendor_tag_ops_t* ops, uint32_t tag); + int getTagType(const vendor_tag_ops_t* ops, uint32_t tag); + + private: + // Total number of vendor tags + int mTagCount; +}; + +// Tag sections start at the beginning of vendor tags (0x8000_0000) +// See <system/camera_metadata.h> +enum { + DEMO_WIZARDRY, + DEMO_SORCERY, + DEMO_MAGIC, + DEMO_SECTION_COUNT +}; + +const uint32_t vendor_section_start = VENDOR_SECTION_START; + +// Each section starts at increments of 0x1_0000 +const uint32_t demo_wizardry_start = (DEMO_WIZARDRY + VENDOR_SECTION) << 16; +const uint32_t demo_sorcery_start = (DEMO_SORCERY + VENDOR_SECTION) << 16; +const uint32_t demo_magic_start = (DEMO_MAGIC + VENDOR_SECTION) << 16; + +// Vendor Tag values, start value begins each section +const uint32_t demo_wizardry_dimension_size = demo_wizardry_start; +const uint32_t demo_wizardry_dimensions = demo_wizardry_start + 1; +const uint32_t demo_wizardry_familiar = demo_wizardry_start + 2; +const uint32_t demo_wizardry_fire = demo_wizardry_start + 3; +const uint32_t demo_wizardry_end = demo_wizardry_start + 4; + +const uint32_t demo_sorcery_difficulty = demo_sorcery_start; +const uint32_t demo_sorcery_light = demo_sorcery_start + 1; +const uint32_t demo_sorcery_end = demo_sorcery_start + 2; + +const uint32_t demo_magic_card_trick = demo_magic_start; +const uint32_t demo_magic_levitation = demo_magic_start + 1; +const uint32_t demo_magic_end = demo_magic_start + 2; + +} // namespace default_camera_hal + +#endif // VENDOR_TAGS_H_
diff --git a/libhardware/modules/consumerir/Android.bp b/libhardware/modules/consumerir/Android.bp new file mode 100644 index 0000000..bbce6b1 --- /dev/null +++ b/libhardware/modules/consumerir/Android.bp
@@ -0,0 +1,23 @@ +// Copyright (C) 2013 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. + +cc_library_shared { + name: "consumerir.default", + relative_install_path: "hw", + srcs: ["consumerir.c"], + shared_libs: [ + "liblog", + "libcutils", + ], +}
diff --git a/libhardware/modules/consumerir/consumerir.c b/libhardware/modules/consumerir/consumerir.c new file mode 100644 index 0000000..b0ff940 --- /dev/null +++ b/libhardware/modules/consumerir/consumerir.c
@@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "ConsumerIrHal" + +#include <errno.h> +#include <malloc.h> +#include <string.h> +#include <cutils/log.h> +#include <hardware/hardware.h> +#include <hardware/consumerir.h> + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static const consumerir_freq_range_t consumerir_freqs[] = { + {.min = 30000, .max = 30000}, + {.min = 33000, .max = 33000}, + {.min = 36000, .max = 36000}, + {.min = 38000, .max = 38000}, + {.min = 40000, .max = 40000}, + {.min = 56000, .max = 56000}, +}; + +static int consumerir_transmit(struct consumerir_device *dev __unused, + int carrier_freq, const int pattern[], int pattern_len) +{ + int total_time = 0; + long i; + + for (i = 0; i < pattern_len; i++) + total_time += pattern[i]; + + /* simulate the time spent transmitting by sleeping */ + ALOGD("transmit for %d uS at %d Hz", total_time, carrier_freq); + usleep(total_time); + + return 0; +} + +static int consumerir_get_num_carrier_freqs(struct consumerir_device *dev __unused) +{ + return ARRAY_SIZE(consumerir_freqs); +} + +static int consumerir_get_carrier_freqs(struct consumerir_device *dev __unused, + size_t len, consumerir_freq_range_t *ranges) +{ + size_t to_copy = ARRAY_SIZE(consumerir_freqs); + + to_copy = len < to_copy ? len : to_copy; + memcpy(ranges, consumerir_freqs, to_copy * sizeof(consumerir_freq_range_t)); + return to_copy; +} + +static int consumerir_close(hw_device_t *dev) +{ + free(dev); + return 0; +} + +/* + * Generic device handling + */ +static int consumerir_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + if (strcmp(name, CONSUMERIR_TRANSMITTER) != 0) { + return -EINVAL; + } + if (device == NULL) { + ALOGE("NULL device on open"); + return -EINVAL; + } + + consumerir_device_t *dev = malloc(sizeof(consumerir_device_t)); + memset(dev, 0, sizeof(consumerir_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*) module; + dev->common.close = consumerir_close; + + dev->transmit = consumerir_transmit; + dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs; + dev->get_carrier_freqs = consumerir_get_carrier_freqs; + + *device = (hw_device_t*) dev; + return 0; +} + +static struct hw_module_methods_t consumerir_module_methods = { + .open = consumerir_open, +}; + +consumerir_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = CONSUMERIR_MODULE_API_VERSION_1_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = CONSUMERIR_HARDWARE_MODULE_ID, + .name = "Demo IR HAL", + .author = "The Android Open Source Project", + .methods = &consumerir_module_methods, + }, +};
diff --git a/libhardware/modules/fingerprint/Android.bp b/libhardware/modules/fingerprint/Android.bp new file mode 100644 index 0000000..a66f9f9 --- /dev/null +++ b/libhardware/modules/fingerprint/Android.bp
@@ -0,0 +1,20 @@ +// Copyright (C) 2013 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. + +cc_library_shared { + name: "fingerprint.default", + relative_install_path: "hw", + srcs: ["fingerprint.c"], + shared_libs: ["liblog"], +}
diff --git a/libhardware/modules/fingerprint/fingerprint.c b/libhardware/modules/fingerprint/fingerprint.c new file mode 100644 index 0000000..08b112b --- /dev/null +++ b/libhardware/modules/fingerprint/fingerprint.c
@@ -0,0 +1,121 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "FingerprintHal" + +#include <errno.h> +#include <malloc.h> +#include <string.h> +#include <cutils/log.h> +#include <hardware/hardware.h> +#include <hardware/fingerprint.h> + +static int fingerprint_close(hw_device_t *dev) +{ + if (dev) { + free(dev); + return 0; + } else { + return -1; + } +} + + +static uint64_t fingerprint_pre_enroll(struct fingerprint_device __unused *dev) { + return FINGERPRINT_ERROR; +} + +static int fingerprint_enroll(struct fingerprint_device __unused *dev, + const hw_auth_token_t __unused *hat, + uint32_t __unused gid, + uint32_t __unused timeout_sec) { + return FINGERPRINT_ERROR; +} + +static uint64_t fingerprint_get_auth_id(struct fingerprint_device __unused *dev) { + return FINGERPRINT_ERROR; +} + +static int fingerprint_cancel(struct fingerprint_device __unused *dev) { + return FINGERPRINT_ERROR; +} + +static int fingerprint_remove(struct fingerprint_device __unused *dev, + uint32_t __unused gid, uint32_t __unused fid) { + return FINGERPRINT_ERROR; +} + +static int fingerprint_set_active_group(struct fingerprint_device __unused *dev, + uint32_t __unused gid, const char __unused *store_path) { + return FINGERPRINT_ERROR; +} + +static int fingerprint_authenticate(struct fingerprint_device __unused *dev, + uint64_t __unused operation_id, __unused uint32_t gid) { + return FINGERPRINT_ERROR; +} + +static int set_notify_callback(struct fingerprint_device *dev, + fingerprint_notify_t notify) { + /* Decorate with locks */ + dev->notify = notify; + return FINGERPRINT_ERROR; +} + +static int fingerprint_open(const hw_module_t* module, const char __unused *id, + hw_device_t** device) +{ + if (device == NULL) { + ALOGE("NULL device on open"); + return -EINVAL; + } + + fingerprint_device_t *dev = malloc(sizeof(fingerprint_device_t)); + memset(dev, 0, sizeof(fingerprint_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0; + dev->common.module = (struct hw_module_t*) module; + dev->common.close = fingerprint_close; + + dev->pre_enroll = fingerprint_pre_enroll; + dev->enroll = fingerprint_enroll; + dev->get_authenticator_id = fingerprint_get_auth_id; + dev->cancel = fingerprint_cancel; + dev->remove = fingerprint_remove; + dev->set_active_group = fingerprint_set_active_group; + dev->authenticate = fingerprint_authenticate; + dev->set_notify = set_notify_callback; + dev->notify = NULL; + + *device = (hw_device_t*) dev; + return 0; +} + +static struct hw_module_methods_t fingerprint_module_methods = { + .open = fingerprint_open, +}; + +fingerprint_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = FINGERPRINT_HARDWARE_MODULE_ID, + .name = "Demo Fingerprint HAL", + .author = "The Android Open Source Project", + .methods = &fingerprint_module_methods, + }, +};
diff --git a/libhardware/modules/gralloc/Android.mk b/libhardware/modules/gralloc/Android.mk new file mode 100644 index 0000000..092e851 --- /dev/null +++ b/libhardware/modules/gralloc/Android.mk
@@ -0,0 +1,36 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH := $(call my-dir) + +# HAL module implemenation stored in +# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so +include $(CLEAR_VARS) + +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SHARED_LIBRARIES := liblog libcutils + +LOCAL_SRC_FILES := \ + gralloc.cpp \ + framebuffer.cpp \ + mapper.cpp + +LOCAL_MODULE := gralloc.default +LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" -Wno-missing-field-initializers +ifeq ($(TARGET_USE_PAN_DISPLAY),true) +LOCAL_CFLAGS += -DUSE_PAN_DISPLAY=1 +endif + +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/gralloc/framebuffer.cpp b/libhardware/modules/gralloc/framebuffer.cpp new file mode 100644 index 0000000..eadcdaa --- /dev/null +++ b/libhardware/modules/gralloc/framebuffer.cpp
@@ -0,0 +1,361 @@ +/* + * Copyright (C) 2008 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 <sys/mman.h> + +#include <dlfcn.h> + +#include <cutils/ashmem.h> +#include <cutils/log.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <fcntl.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <string.h> +#include <stdlib.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> + +#ifdef __ANDROID__ +#include <linux/fb.h> +#endif + +#include "gralloc_priv.h" +#include "gr.h" + +/*****************************************************************************/ + +// Set TARGET_USE_PAN_DISPLAY to true at compile time if the +// board uses FBIOPAN_DISPLAY to setup page flipping, otherwise +// default ioctl to do page-flipping is FBIOPUT_VSCREENINFO. +#ifndef USE_PAN_DISPLAY +#define USE_PAN_DISPLAY 0 +#endif + +// numbers of buffers for page flipping +#define NUM_BUFFERS 2 + + +enum { + PAGE_FLIP = 0x00000001, + LOCKED = 0x00000002 +}; + +struct fb_context_t { + framebuffer_device_t device; +}; + +/*****************************************************************************/ + +static int fb_setSwapInterval(struct framebuffer_device_t* dev, + int interval) +{ + fb_context_t* ctx = (fb_context_t*)dev; + if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) + return -EINVAL; + // FIXME: implement fb_setSwapInterval + return 0; +} + +static int fb_setUpdateRect(struct framebuffer_device_t* dev, + int l, int t, int w, int h) +{ + if (((w|h) <= 0) || ((l|t)<0)) + return -EINVAL; + + fb_context_t* ctx = (fb_context_t*)dev; + private_module_t* m = reinterpret_cast<private_module_t*>( + dev->common.module); + m->info.reserved[0] = 0x54445055; // "UPDT"; + m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); + m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); + return 0; +} + +static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) +{ + if (private_handle_t::validate(buffer) < 0) + return -EINVAL; + + fb_context_t* ctx = (fb_context_t*)dev; + + private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); + private_module_t* m = reinterpret_cast<private_module_t*>( + dev->common.module); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + ALOGE("FBIOPUT_VSCREENINFO failed"); + m->base.unlock(&m->base, buffer); + return -errno; + } + m->currentBuffer = buffer; + + } else { + // If we can't do the page_flip, just copy the buffer to the front + // FIXME: use copybit HAL instead of memcpy + + void* fb_vaddr; + void* buffer_vaddr; + + m->base.lock(&m->base, m->framebuffer, + GRALLOC_USAGE_SW_WRITE_RARELY, + 0, 0, m->info.xres, m->info.yres, + &fb_vaddr); + + m->base.lock(&m->base, buffer, + GRALLOC_USAGE_SW_READ_RARELY, + 0, 0, m->info.xres, m->info.yres, + &buffer_vaddr); + + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); + } + + return 0; +} + +/*****************************************************************************/ + +int mapFrameBufferLocked(struct private_module_t* module) +{ + // already initialized... + if (module->framebuffer) { + return 0; + } + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd < 0) + return -errno; + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + + uint32_t flags = PAGE_FLIP; +#if USE_PAN_DISPLAY + if (ioctl(fd, FBIOPAN_DISPLAY, &info) == -1) { + ALOGW("FBIOPAN_DISPLAY failed, page flipping not supported"); +#else + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); +#endif + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + } + + if (info.yres_virtual < info.yres * 2) { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres*2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + uint64_t refreshQuotient = + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + /* Beware, info.pixclock might be 0 under emulation, so avoid a + * division-by-0 here (SIGFPE on ARM) */ + int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0; + + if (refreshRate == 0) { + // bleagh, bad info from the driver + refreshRate = 60*1000; // 60 Hz + } + + if (int(info.width) <= 0 || int(info.height) <= 0) { + // the driver doesn't return that information + // default to 160 dpi + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + ALOGI( "using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length + ); + + ALOGI( "width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps + ); + + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + if (finfo.smem_len <= 0) + return -errno; + + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + /* + * map the framebuffer + */ + + int err; + size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); + module->framebuffer = new private_handle_t(dup(fd), fbSize, 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + ALOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + module->framebuffer->base = intptr_t(vaddr); + memset(vaddr, 0, fbSize); + return 0; +} + +static int mapFrameBuffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = mapFrameBufferLocked(module); + pthread_mutex_unlock(&module->lock); + return err; +} + +/*****************************************************************************/ + +static int fb_close(struct hw_device_t *dev) +{ + fb_context_t* ctx = (fb_context_t*)dev; + if (ctx) { + free(ctx); + } + return 0; +} + +int fb_device_open(hw_module_t const* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { + /* initialize our state here */ + fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast<hw_module_t*>(module); + dev->device.common.close = fb_close; + dev->device.setSwapInterval = fb_setSwapInterval; + dev->device.post = fb_post; + dev->device.setUpdateRect = 0; + + private_module_t* m = (private_module_t*)module; + status = mapFrameBuffer(m); + if (status >= 0) { + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + int format = (m->info.bits_per_pixel == 32) + ? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : HAL_PIXEL_FORMAT_RGBX_8888) + : HAL_PIXEL_FORMAT_RGB_565; + const_cast<uint32_t&>(dev->device.flags) = 0; + const_cast<uint32_t&>(dev->device.width) = m->info.xres; + const_cast<uint32_t&>(dev->device.height) = m->info.yres; + const_cast<int&>(dev->device.stride) = stride; + const_cast<int&>(dev->device.format) = format; + const_cast<float&>(dev->device.xdpi) = m->xdpi; + const_cast<float&>(dev->device.ydpi) = m->ydpi; + const_cast<float&>(dev->device.fps) = m->fps; + const_cast<int&>(dev->device.minSwapInterval) = 1; + const_cast<int&>(dev->device.maxSwapInterval) = 1; + *device = &dev->device.common; + } + } + return status; +}
diff --git a/libhardware/modules/gralloc/gr.h b/libhardware/modules/gralloc/gr.h new file mode 100644 index 0000000..ac7e967 --- /dev/null +++ b/libhardware/modules/gralloc/gr.h
@@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 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 GR_H_ +#define GR_H_ + +#include <stdint.h> +#include <sys/user.h> +#include <limits.h> +#include <sys/cdefs.h> +#include <hardware/gralloc.h> +#include <pthread.h> +#include <errno.h> + +#include <cutils/native_handle.h> + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); +int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd); + +/*****************************************************************************/ + +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline explicit Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; + +#endif /* GR_H_ */
diff --git a/libhardware/modules/gralloc/gralloc.cpp b/libhardware/modules/gralloc/gralloc.cpp new file mode 100644 index 0000000..a9fbc80 --- /dev/null +++ b/libhardware/modules/gralloc/gralloc.cpp
@@ -0,0 +1,310 @@ +/* + * Copyright (C) 2008 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 <limits.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <cutils/ashmem.h> +#include <cutils/log.h> +#include <cutils/atomic.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include "gralloc_priv.h" +#include "gr.h" + +/*****************************************************************************/ + +struct gralloc_context_t { + alloc_device_t device; + /* our private data here */ +}; + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle); + +/*****************************************************************************/ + +int fb_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); + +static int gralloc_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); + +extern int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr); + +extern int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle); + +/*****************************************************************************/ + +static struct hw_module_methods_t gralloc_module_methods = { + .open = gralloc_device_open +}; + +struct private_module_t HAL_MODULE_INFO_SYM = { + .base = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = GRALLOC_HARDWARE_MODULE_ID, + .name = "Graphics Memory Allocator Module", + .author = "The Android Open Source Project", + .methods = &gralloc_module_methods + }, + .registerBuffer = gralloc_register_buffer, + .unregisterBuffer = gralloc_unregister_buffer, + .lock = gralloc_lock, + .unlock = gralloc_unlock, + }, + .framebuffer = 0, + .flags = 0, + .numBuffers = 0, + .bufferMask = 0, + .lock = PTHREAD_MUTEX_INITIALIZER, + .currentBuffer = 0, +}; + +/*****************************************************************************/ + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast<private_module_t*>( + dev->common.module); + + // allocate the framebuffer + if (m->framebuffer == NULL) { + // initialize the framebuffer, the framebuffer is mapped once + // and forever. + int err = mapFrameBufferLocked(m); + if (err < 0) { + return err; + } + } + + const uint32_t bufferMask = m->bufferMask; + const uint32_t numBuffers = m->numBuffers; + const size_t bufferSize = m->finfo.line_length * m->info.yres; + if (numBuffers == 1) { + // If we have only one buffer, we never use page-flipping. Instead, + // we return a regular buffer which will be memcpy'ed to the main + // screen when post is called. + int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; + return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle); + } + + if (bufferMask >= ((1LU<<numBuffers)-1)) { + // We ran out of buffers. + return -ENOMEM; + } + + // create a "fake" handles for it + intptr_t vaddr = intptr_t(m->framebuffer->base); + private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, + private_handle_t::PRIV_FLAGS_FRAMEBUFFER); + + // find a free slot + for (uint32_t i=0 ; i<numBuffers ; i++) { + if ((bufferMask & (1LU<<i)) == 0) { + m->bufferMask |= (1LU<<i); + break; + } + vaddr += bufferSize; + } + + hnd->base = vaddr; + hnd->offset = vaddr - intptr_t(m->framebuffer->base); + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast<private_module_t*>( + dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); + pthread_mutex_unlock(&m->lock); + return err; +} + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int /*usage*/, buffer_handle_t* pHandle) +{ + int err = 0; + int fd = -1; + + size = roundUpToPageSize(size); + + fd = ashmem_create_region("gralloc-buffer", size); + if (fd < 0) { + ALOGE("couldn't create ashmem (%s)", strerror(-errno)); + err = -errno; + } + + if (err == 0) { + private_handle_t* hnd = new private_handle_t(fd, size, 0); + gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( + dev->common.module); + err = mapBuffer(module, hnd); + if (err == 0) { + *pHandle = hnd; + } + } + + ALOGE_IF(err, "gralloc failed err=%s", strerror(-err)); + + return err; +} + +/*****************************************************************************/ + +static int gralloc_alloc(alloc_device_t* dev, + int w, int h, int format, int usage, + buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) + return -EINVAL; + + size_t size, stride; + + int align = 4; + int bpp = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RAW16: + bpp = 2; + break; + default: + return -EINVAL; + } + size_t bpr = (w*bpp + (align-1)) & ~(align-1); + size = bpr * h; + stride = bpr / bpp; + + int err; + if (usage & GRALLOC_USAGE_HW_FB) { + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); + } else { + err = gralloc_alloc_buffer(dev, size, usage, pHandle); + } + + if (err < 0) { + return err; + } + + *pStride = stride; + return 0; +} + +static int gralloc_free(alloc_device_t* dev, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + // free this buffer + private_module_t* m = reinterpret_cast<private_module_t*>( + dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<<index); + } else { + gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( + dev->common.module); + terminateBuffer(module, const_cast<private_handle_t*>(hnd)); + } + + close(hnd->fd); + delete hnd; + return 0; +} + +/*****************************************************************************/ + +static int gralloc_close(struct hw_device_t *dev) +{ + gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev); + if (ctx) { + /* TODO: keep a list of all buffer_handle_t created, and free them + * all here. + */ + free(ctx); + } + return 0; +} + +int gralloc_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { + gralloc_context_t *dev; + dev = (gralloc_context_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast<hw_module_t*>(module); + dev->device.common.close = gralloc_close; + + dev->device.alloc = gralloc_alloc; + dev->device.free = gralloc_free; + + *device = &dev->device.common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +}
diff --git a/libhardware/modules/gralloc/gralloc_priv.h b/libhardware/modules/gralloc/gralloc_priv.h new file mode 100644 index 0000000..2cd1007 --- /dev/null +++ b/libhardware/modules/gralloc/gralloc_priv.h
@@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008 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 GRALLOC_PRIV_H_ +#define GRALLOC_PRIV_H_ + +#include <stdint.h> +#include <limits.h> +#include <sys/cdefs.h> +#include <hardware/gralloc.h> +#include <pthread.h> +#include <errno.h> +#include <unistd.h> + +#include <cutils/native_handle.h> + +#include <linux/fb.h> + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +struct private_module_t { + gralloc_module_t base; + + private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int pmem_master; + void* pmem_master_base; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +struct private_handle_t : public native_handle { +#else +struct private_handle_t { + struct native_handle nativeHandle; +#endif + + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001 + }; + + // file-descriptors + int fd; + // ints + int magic; + int flags; + int size; + int offset; + + // FIXME: the attributes below should be out-of-line + uint64_t base __attribute__((aligned(8))); + int pid; + +#ifdef __cplusplus + static inline int sNumInts() { + return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds); + } + static const int sNumFds = 1; + static const int sMagic = 0x3141592; + + private_handle_t(int fd, int size, int flags) : + fd(fd), magic(sMagic), flags(flags), size(size), offset(0), + base(0), pid(getpid()) + { + version = sizeof(native_handle); + numInts = sNumInts(); + numFds = sNumFds; + } + ~private_handle_t() { + magic = 0; + } + + static int validate(const native_handle* h) { + const private_handle_t* hnd = (const private_handle_t*)h; + if (!h || h->version != sizeof(native_handle) || + h->numInts != sNumInts() || h->numFds != sNumFds || + hnd->magic != sMagic) + { + ALOGE("invalid gralloc handle (at %p)", h); + return -EINVAL; + } + return 0; + } +#endif +}; + +#endif /* GRALLOC_PRIV_H_ */
diff --git a/libhardware/modules/gralloc/mapper.cpp b/libhardware/modules/gralloc/mapper.cpp new file mode 100644 index 0000000..20d9841 --- /dev/null +++ b/libhardware/modules/gralloc/mapper.cpp
@@ -0,0 +1,188 @@ +/* + * Copyright (C) 2008 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 <limits.h> +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#include <string.h> + +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include "gralloc_priv.h" + + +/*****************************************************************************/ + +static int gralloc_map(gralloc_module_t const* /*module*/, + buffer_handle_t handle, + void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + size_t size = hnd->size; + void* mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + ALOGE("Could not mmap %s", strerror(errno)); + return -errno; + } + hnd->base = uintptr_t(mappedAddress) + hnd->offset; + //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + // hnd->fd, hnd->offset, hnd->size, mappedAddress); + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* /*module*/, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + void* base = (void*)hnd->base; + size_t size = hnd->size; + //ALOGD("unmapping from %p, size=%d", base, size); + if (munmap(base, size) < 0) { + ALOGE("Could not unmap %s", strerror(errno)); + } + } + hnd->base = 0; + return 0; +} + +/*****************************************************************************/ + +int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + // *** WARNING WARNING WARNING *** + // + // If a buffer handle is passed from the process that allocated it to a + // different process, and then back to the allocator process, we will + // create a second mapping of the buffer. If the process reads and writes + // through both mappings, normal memory ordering guarantees may be + // violated, depending on the processor cache implementation*. + // + // If you are deriving a new gralloc implementation from this code, don't + // do this. A "real" gralloc should provide a single reference-counted + // mapping for each buffer in a process. + // + // In the current system, there is one case that needs a buffer to be + // registered in the same process that allocated it. The SurfaceFlinger + // process acts as the IGraphicBufferAlloc Binder provider, so all gralloc + // allocations happen in its process. After returning the buffer handle to + // the IGraphicBufferAlloc client, SurfaceFlinger free's its handle to the + // buffer (unmapping it from the SurfaceFlinger process). If + // SurfaceFlinger later acts as the producer end of the buffer queue the + // buffer belongs to, it will get a new handle to the buffer in response + // to IGraphicBufferProducer::requestBuffer(). Like any buffer handle + // received through Binder, the SurfaceFlinger process will register it. + // Since it already freed its original handle, it will only end up with + // one mapping to the buffer and there will be no problem. + // + // Currently SurfaceFlinger only acts as a buffer producer for a remote + // consumer when taking screenshots and when using virtual displays. + // + // Eventually, each application should be allowed to make its own gralloc + // allocations, solving the problem. Also, this ashmem-based gralloc + // should go away, replaced with a real ion-based gralloc. + // + // * Specifically, associative virtually-indexed caches are likely to have + // problems. Most modern L1 caches fit that description. + + private_handle_t* hnd = (private_handle_t*)handle; + ALOGD_IF(hnd->pid == getpid(), + "Registering a buffer in the process that created it. " + "This may cause memory ordering problems."); + + void *vaddr; + return gralloc_map(module, handle, &vaddr); +} + +int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + if (hnd->base) + gralloc_unmap(module, handle); + + return 0; +} + +int mapBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + void* vaddr; + return gralloc_map(module, hnd, &vaddr); +} + +int terminateBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + if (hnd->base) { + // this buffer was mapped, unmap it now + gralloc_unmap(module, hnd); + } + + return 0; +} + +int gralloc_lock(gralloc_module_t const* /*module*/, + buffer_handle_t handle, int /*usage*/, + int /*l*/, int /*t*/, int /*w*/, int /*h*/, + void** vaddr) +{ + // this is called when a buffer is being locked for software + // access. in thin implementation we have nothing to do since + // not synchronization with the h/w is needed. + // typically this is used to wait for the h/w to finish with + // this buffer if relevant. the data cache may need to be + // flushed or invalidated depending on the usage bits and the + // hardware. + + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + *vaddr = (void*)hnd->base; + return 0; +} + +int gralloc_unlock(gralloc_module_t const* /*module*/, + buffer_handle_t handle) +{ + // we're done with a software buffer. nothing to do in this + // implementation. typically this is used to flush the data cache. + + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + return 0; +}
diff --git a/libhardware/modules/hwcomposer/Android.mk b/libhardware/modules/hwcomposer/Android.mk new file mode 100644 index 0000000..35c0fae --- /dev/null +++ b/libhardware/modules/hwcomposer/Android.mk
@@ -0,0 +1,28 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LOCAL_PATH := $(call my-dir) + +# HAL module implemenation stored in +# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so +include $(CLEAR_VARS) + +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SHARED_LIBRARIES := liblog libEGL +LOCAL_SRC_FILES := hwcomposer.cpp +LOCAL_MODULE := hwcomposer.default +LOCAL_CFLAGS:= -DLOG_TAG=\"hwcomposer\" +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/hwcomposer/README.android b/libhardware/modules/hwcomposer/README.android new file mode 100644 index 0000000..4aa7203 --- /dev/null +++ b/libhardware/modules/hwcomposer/README.android
@@ -0,0 +1,3 @@ + +Skeleton for the "hwcomposer" HAL module. +
diff --git a/libhardware/modules/hwcomposer/hwcomposer.cpp b/libhardware/modules/hwcomposer/hwcomposer.cpp new file mode 100644 index 0000000..9d1aa34 --- /dev/null +++ b/libhardware/modules/hwcomposer/hwcomposer.cpp
@@ -0,0 +1,132 @@ +/* + * 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 <hardware/hardware.h> + +#include <errno.h> +#include <fcntl.h> +#include <malloc.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> + +#include <hardware/hwcomposer.h> + +#include <EGL/egl.h> + +/*****************************************************************************/ + +struct hwc_context_t { + hwc_composer_device_1_t device; + /* our private state goes below here */ +}; + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device); + +static struct hw_module_methods_t hwc_module_methods = { + open: hwc_device_open +}; + +hwc_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: HWC_HARDWARE_MODULE_ID, + name: "Sample hwcomposer module", + author: "The Android Open Source Project", + methods: &hwc_module_methods, + } +}; + +/*****************************************************************************/ + +static void dump_layer(hwc_layer_1_t const* l) { + ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", + l->compositionType, l->flags, l->handle, l->transform, l->blending, + l->sourceCrop.left, + l->sourceCrop.top, + l->sourceCrop.right, + l->sourceCrop.bottom, + l->displayFrame.left, + l->displayFrame.top, + l->displayFrame.right, + l->displayFrame.bottom); +} + +static int hwc_prepare(hwc_composer_device_1_t *dev, + size_t numDisplays, hwc_display_contents_1_t** displays) { + if (displays && (displays[0]->flags & HWC_GEOMETRY_CHANGED)) { + for (size_t i=0 ; i<displays[0]->numHwLayers ; i++) { + //dump_layer(&list->hwLayers[i]); + displays[0]->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + } + } + return 0; +} + +static int hwc_set(hwc_composer_device_1_t *dev, + size_t numDisplays, hwc_display_contents_1_t** displays) +{ + //for (size_t i=0 ; i<list->numHwLayers ; i++) { + // dump_layer(&list->hwLayers[i]); + //} + + EGLBoolean sucess = eglSwapBuffers((EGLDisplay)displays[0]->dpy, + (EGLSurface)displays[0]->sur); + if (!sucess) { + return HWC_EGL_ERROR; + } + return 0; +} + +static int hwc_device_close(struct hw_device_t *dev) +{ + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; + if (ctx) { + free(ctx); + } + return 0; +} + +/*****************************************************************************/ + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { + struct hwc_context_t *dev; + dev = (hwc_context_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = HWC_DEVICE_API_VERSION_1_0; + dev->device.common.module = const_cast<hw_module_t*>(module); + dev->device.common.close = hwc_device_close; + + dev->device.prepare = hwc_prepare; + dev->device.set = hwc_set; + + *device = &dev->device.common; + status = 0; + } + return status; +}
diff --git a/libhardware/modules/input/Android.mk b/libhardware/modules/input/Android.mk new file mode 100644 index 0000000..3011b2e --- /dev/null +++ b/libhardware/modules/input/Android.mk
@@ -0,0 +1,19 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libhardware/modules/input/evdev/Android.mk b/libhardware/modules/input/evdev/Android.mk new file mode 100644 index 0000000..d3c49e7 --- /dev/null +++ b/libhardware/modules/input/evdev/Android.mk
@@ -0,0 +1,57 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +# Evdev module implementation +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + InputHub.cpp \ + InputDevice.cpp \ + InputDeviceManager.cpp \ + InputHost.cpp + +LOCAL_SHARED_LIBRARIES := \ + libhardware_legacy \ + liblog \ + libutils + +LOCAL_CLANG := true +LOCAL_CPPFLAGS += -std=c++14 -Wno-unused-parameter + +LOCAL_MODULE := libinput_evdev +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) + +# HAL module +include $(CLEAR_VARS) + +LOCAL_MODULE := input.evdev.default +LOCAL_MODULE_RELATIVE_PATH := hw + +LOCAL_SRC_FILES := \ + EvdevModule.cpp + +LOCAL_SHARED_LIBRARIES := \ + libinput_evdev \ + liblog + +LOCAL_CLANG := true +LOCAL_CPPFLAGS += -std=c++14 -Wno-unused-parameter + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/input/evdev/EvdevModule.cpp b/libhardware/modules/input/evdev/EvdevModule.cpp new file mode 100644 index 0000000..e9c8222 --- /dev/null +++ b/libhardware/modules/input/evdev/EvdevModule.cpp
@@ -0,0 +1,134 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "EvdevModule" + +#include <memory> +#include <string> +#include <thread> + +#include <assert.h> +#include <hardware/hardware.h> +#include <hardware/input.h> + +#include <utils/Log.h> + +#include "InputHub.h" +#include "InputDeviceManager.h" +#include "InputHost.h" + +namespace android { + +static const char kDevInput[] = "/dev/input"; + +class EvdevModule { +public: + explicit EvdevModule(InputHost inputHost); + + void init(); + void notifyReport(input_report_t* r); + +private: + void loop(); + + InputHost mInputHost; + std::shared_ptr<InputDeviceManager> mDeviceManager; + std::shared_ptr<InputHub> mInputHub; + std::thread mPollThread; +}; + +static std::shared_ptr<EvdevModule> gEvdevModule; + +EvdevModule::EvdevModule(InputHost inputHost) : + mInputHost(inputHost), + mDeviceManager(std::make_shared<InputDeviceManager>()), + mInputHub(std::make_shared<InputHub>(mDeviceManager)) {} + +void EvdevModule::init() { + ALOGV("%s", __func__); + + mInputHub->registerDevicePath(kDevInput); + mPollThread = std::thread(&EvdevModule::loop, this); +} + +void EvdevModule::notifyReport(input_report_t* r) { + ALOGV("%s", __func__); + + // notifyReport() will be called from an arbitrary thread within the input + // host. Since InputHub is not threadsafe, this is how I expect this to + // work: + // * notifyReport() will queue up the output report in the EvdevModule and + // call wake() on the InputHub. + // * In the main loop thread, after returning from poll(), the queue will + // be processed with any pending work. +} + +void EvdevModule::loop() { + ALOGV("%s", __func__); + for (;;) { + mInputHub->poll(); + + // TODO: process any pending work, like notify reports + } +} + +extern "C" { + +static int dummy_open(const hw_module_t __unused *module, const char __unused *id, + hw_device_t __unused **device) { + ALOGW("open not implemented in the input HAL!"); + return 0; +} + +static void input_init(const input_module_t* module, + input_host_t* host, input_host_callbacks_t cb) { + LOG_ALWAYS_FATAL_IF(strcmp(module->common.id, INPUT_HARDWARE_MODULE_ID) != 0); + InputHost inputHost = {host, cb}; + gEvdevModule = std::make_shared<EvdevModule>(inputHost); + gEvdevModule->init(); +} + +static void input_notify_report(const input_module_t* module, input_report_t* r) { + LOG_ALWAYS_FATAL_IF(strcmp(module->common.id, INPUT_HARDWARE_MODULE_ID) != 0); + LOG_ALWAYS_FATAL_IF(gEvdevModule == nullptr); + gEvdevModule->notifyReport(r); +} + +static struct hw_module_methods_t input_module_methods = { + .open = dummy_open, +}; + +input_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = INPUT_MODULE_API_VERSION_1_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = INPUT_HARDWARE_MODULE_ID, + .name = "Input evdev HAL", + .author = "The Android Open Source Project", + .methods = &input_module_methods, + .dso = NULL, + .reserved = {0}, + }, + + .init = input_init, + .notify_report = input_notify_report, +}; + +} // extern "C" + +} // namespace input
diff --git a/libhardware/modules/input/evdev/InputDevice.cpp b/libhardware/modules/input/evdev/InputDevice.cpp new file mode 100644 index 0000000..c0b59d7 --- /dev/null +++ b/libhardware/modules/input/evdev/InputDevice.cpp
@@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "InputDevice" +#define LOG_NDEBUG 0 + +#include <linux/input.h> + +#define __STDC_FORMAT_MACROS +#include <cinttypes> +#include <string> + +#include <utils/Log.h> +#include <utils/Timers.h> + +#include "InputHub.h" +#include "InputDevice.h" + +#define MSC_ANDROID_TIME_SEC 0x6 +#define MSC_ANDROID_TIME_USEC 0x7 + +namespace android { + +EvdevDevice::EvdevDevice(std::shared_ptr<InputDeviceNode> node) : + mDeviceNode(node) {} + +void EvdevDevice::processInput(InputEvent& event, nsecs_t currentTime) { + std::string log; + log.append("---InputEvent for device %s---\n"); + log.append(" when: %" PRId64 "\n"); + log.append(" type: %d\n"); + log.append(" code: %d\n"); + log.append(" value: %d\n"); + ALOGV(log.c_str(), mDeviceNode->getPath().c_str(), event.when, event.type, event.code, + event.value); + + if (event.type == EV_MSC) { + if (event.code == MSC_ANDROID_TIME_SEC) { + mOverrideSec = event.value; + } else if (event.code == MSC_ANDROID_TIME_USEC) { + mOverrideUsec = event.value; + } + return; + } + + if (mOverrideSec || mOverrideUsec) { + event.when = s2ns(mOverrideSec) + us2ns(mOverrideUsec); + ALOGV("applied override time %d.%06d", mOverrideSec, mOverrideUsec); + + if (event.type == EV_SYN && event.code == SYN_REPORT) { + mOverrideSec = 0; + mOverrideUsec = 0; + } + } + + // Bug 7291243: Add a guard in case the kernel generates timestamps + // that appear to be far into the future because they were generated + // using the wrong clock source. + // + // This can happen because when the input device is initially opened + // it has a default clock source of CLOCK_REALTIME. Any input events + // enqueued right after the device is opened will have timestamps + // generated using CLOCK_REALTIME. We later set the clock source + // to CLOCK_MONOTONIC but it is already too late. + // + // Invalid input event timestamps can result in ANRs, crashes and + // and other issues that are hard to track down. We must not let them + // propagate through the system. + // + // Log a warning so that we notice the problem and recover gracefully. + if (event.when >= currentTime + s2ns(10)) { + // Double-check. Time may have moved on. + auto time = systemTime(SYSTEM_TIME_MONOTONIC); + if (event.when > time) { + ALOGW("An input event from %s has a timestamp that appears to have " + "been generated using the wrong clock source (expected " + "CLOCK_MONOTONIC): event time %" PRId64 ", current time %" PRId64 + ", call time %" PRId64 ". Using current time instead.", + mDeviceNode->getPath().c_str(), event.when, time, currentTime); + event.when = time; + } else { + ALOGV("Event time is ok but failed the fast path and required an extra " + "call to systemTime: event time %" PRId64 ", current time %" PRId64 + ", call time %" PRId64 ".", event.when, time, currentTime); + } + } +} + +} // namespace android
diff --git a/libhardware/modules/input/evdev/InputDevice.h b/libhardware/modules/input/evdev/InputDevice.h new file mode 100644 index 0000000..3aa16cc --- /dev/null +++ b/libhardware/modules/input/evdev/InputDevice.h
@@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INPUT_DEVICE_H_ +#define ANDROID_INPUT_DEVICE_H_ + +#include <memory> + +#include <utils/Timers.h> + +#include "InputHub.h" + +namespace android { + +/** + * InputDeviceInterface represents an input device in the HAL. It processes + * input events before passing them to the input host. + */ +class InputDeviceInterface { +public: + virtual void processInput(InputEvent& event, nsecs_t currentTime) = 0; + +protected: + InputDeviceInterface() = default; + virtual ~InputDeviceInterface() = default; +}; + +/** + * EvdevDevice is an input device backed by a Linux evdev node. + */ +class EvdevDevice : public InputDeviceInterface { +public: + explicit EvdevDevice(std::shared_ptr<InputDeviceNode> node); + virtual ~EvdevDevice() override = default; + + virtual void processInput(InputEvent& event, nsecs_t currentTime) override; + +private: + std::shared_ptr<InputDeviceNode> mDeviceNode; + + int32_t mOverrideSec = 0; + int32_t mOverrideUsec = 0; +}; + +} // namespace android + +#endif // ANDROID_INPUT_DEVICE_H_
diff --git a/libhardware/modules/input/evdev/InputDeviceManager.cpp b/libhardware/modules/input/evdev/InputDeviceManager.cpp new file mode 100644 index 0000000..ceddd90 --- /dev/null +++ b/libhardware/modules/input/evdev/InputDeviceManager.cpp
@@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "InputDeviceManager" +//#define LOG_NDEBUG 0 + +#include <utils/Log.h> + +#include "InputDevice.h" +#include "InputDeviceManager.h" + +namespace android { + +void InputDeviceManager::onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event, + nsecs_t event_time) { + if (mDevices[node] == nullptr) { + ALOGE("got input event for unknown node %s", node->getPath().c_str()); + return; + } + mDevices[node]->processInput(event, event_time); +} + +void InputDeviceManager::onDeviceAdded(std::shared_ptr<InputDeviceNode> node) { + mDevices[node] = std::make_shared<EvdevDevice>(node); +} + +void InputDeviceManager::onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) { + if (mDevices[node] == nullptr) { + ALOGE("could not remove unknown node %s", node->getPath().c_str()); + return; + } + // TODO: tell the InputDevice and InputDeviceNode that they are being + // removed so they can run any cleanup. + mDevices.erase(node); +} + +} // namespace android
diff --git a/libhardware/modules/input/evdev/InputDeviceManager.h b/libhardware/modules/input/evdev/InputDeviceManager.h new file mode 100644 index 0000000..b652155 --- /dev/null +++ b/libhardware/modules/input/evdev/InputDeviceManager.h
@@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INPUT_DEVICE_MANAGER_H_ +#define ANDROID_INPUT_DEVICE_MANAGER_H_ + +#include <memory> +#include <unordered_map> + +#include <utils/Timers.h> + +#include "InputDevice.h" +#include "InputHub.h" + +namespace android { + +/** + * InputDeviceManager keeps the mapping of InputDeviceNodes to + * InputDeviceInterfaces and handles the callbacks from the InputHub, delegating + * them to the appropriate InputDeviceInterface. + */ +class InputDeviceManager : public InputCallbackInterface { +public: + virtual ~InputDeviceManager() override = default; + + virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event, + nsecs_t event_time) override; + virtual void onDeviceAdded(std::shared_ptr<InputDeviceNode> node) override; + virtual void onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) override; + +private: + template<class T, class U> + using DeviceMap = std::unordered_map<std::shared_ptr<T>, std::shared_ptr<U>>; + + DeviceMap<InputDeviceNode, InputDeviceInterface> mDevices; +}; + +} // namespace android + +#endif // ANDROID_INPUT_DEVICE_MANAGER_H_
diff --git a/libhardware/modules/input/evdev/InputHost.cpp b/libhardware/modules/input/evdev/InputHost.cpp new file mode 100644 index 0000000..6a65fcd --- /dev/null +++ b/libhardware/modules/input/evdev/InputHost.cpp
@@ -0,0 +1,104 @@ +/* + * 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 "InputHost.h" + +namespace android { + +void InputReport::reportEvent(InputDeviceHandle d) { + mCallbacks.report_event(mHost, d, mReport); +} + +void InputReportDefinition::addCollection(InputCollectionId id, int32_t arity) { + mCallbacks.input_report_definition_add_collection(mHost, mReportDefinition, id, arity); +} + +void InputReportDefinition::declareUsage(InputCollectionId id, InputUsage usage, + int32_t min, int32_t max, float resolution) { + mCallbacks.input_report_definition_declare_usage_int(mHost, mReportDefinition, + id, usage, min, max, resolution); +} + +void InputReportDefinition::declareUsage(InputCollectionId id, InputUsage* usage, + size_t usageCount) { + mCallbacks.input_report_definition_declare_usages_bool(mHost, mReportDefinition, + id, usage, usageCount); +} + +InputReport InputReportDefinition::allocateReport() { + return InputReport(mHost, mCallbacks, + mCallbacks.input_allocate_report(mHost, mReportDefinition)); +} + +void InputDeviceDefinition::addReport(InputReportDefinition r) { + mCallbacks.input_device_definition_add_report(mHost, mDeviceDefinition, r); +} + +InputProperty::~InputProperty() { + mCallbacks.input_free_device_property(mHost, mProperty); +} + +const char* InputProperty::getKey() { + return mCallbacks.input_get_property_key(mHost, mProperty); +} + +const char* InputProperty::getValue() { + return mCallbacks.input_get_property_value(mHost, mProperty); +} + +InputPropertyMap::~InputPropertyMap() { + mCallbacks.input_free_device_property_map(mHost, mMap); +} + +InputProperty InputPropertyMap::getDeviceProperty(const char* key) { + return InputProperty(mHost, mCallbacks, + mCallbacks.input_get_device_property(mHost, mMap, key)); +} + +InputDeviceIdentifier InputHost::createDeviceIdentifier(const char* name, int32_t productId, + int32_t vendorId, InputBus bus, const char* uniqueId) { + return mCallbacks.create_device_identifier(mHost, name, productId, vendorId, bus, uniqueId); +} + +InputDeviceDefinition InputHost::createDeviceDefinition() { + return InputDeviceDefinition(mHost, mCallbacks, mCallbacks.create_device_definition(mHost)); +} + +InputReportDefinition InputHost::createInputReportDefinition() { + return InputReportDefinition(mHost, mCallbacks, + mCallbacks.create_input_report_definition(mHost)); +} + +InputReportDefinition InputHost::createOutputReportDefinition() { + return InputReportDefinition(mHost, mCallbacks, + mCallbacks.create_output_report_definition(mHost)); +} + +InputDeviceHandle InputHost::registerDevice(InputDeviceIdentifier id, + InputDeviceDefinition d) { + return mCallbacks.register_device(mHost, id, d); +} + +void InputHost::unregisterDevice(InputDeviceHandle handle) { + return mCallbacks.unregister_device(mHost, handle); +} + +InputPropertyMap InputHost::getDevicePropertyMap(InputDeviceIdentifier id) { + return InputPropertyMap(mHost, mCallbacks, + mCallbacks.input_get_device_property_map(mHost, id)); +} + +} // namespace android
diff --git a/libhardware/modules/input/evdev/InputHost.h b/libhardware/modules/input/evdev/InputHost.h new file mode 100644 index 0000000..98ce26f --- /dev/null +++ b/libhardware/modules/input/evdev/InputHost.h
@@ -0,0 +1,192 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INPUT_HOST_H_ +#define ANDROID_INPUT_HOST_H_ + +#include <memory> + +#include <hardware/input.h> + +namespace android { + +/** + * Classes in this file wrap the corresponding interfaces in the Input HAL. They + * are intended to be lightweight and passed by value. It is still important not + * to use an object after a HAL-specific method has freed the underlying + * representation. + * + * See hardware/input.h for details about each of these methods. + */ + +using InputBus = input_bus_t; +using InputCollectionId = input_collection_id_t; +using InputDeviceHandle = input_device_handle_t*; +using InputDeviceIdentifier = input_device_identifier_t*; +using InputUsage = input_usage_t; + +class InputHostBase { +protected: + InputHostBase(input_host_t* host, input_host_callbacks_t cb) : mHost(host), mCallbacks(cb) {} + virtual ~InputHostBase() = default; + + input_host_t* mHost; + input_host_callbacks_t mCallbacks; +}; + +class InputReport : private InputHostBase { +public: + virtual ~InputReport() = default; + + InputReport(const InputReport& rhs) = default; + InputReport& operator=(const InputReport& rhs) = default; + operator input_report_t*() const { return mReport; } + + void reportEvent(InputDeviceHandle d); + +private: + friend class InputReportDefinition; + + InputReport(input_host_t* host, input_host_callbacks_t cb, input_report_t* r) : + InputHostBase(host, cb), mReport(r) {} + + input_report_t* mReport; +}; + +class InputReportDefinition : private InputHostBase { +public: + virtual ~InputReportDefinition() = default; + + InputReportDefinition(const InputReportDefinition& rhs) = default; + InputReportDefinition& operator=(const InputReportDefinition& rhs) = default; + operator input_report_definition_t*() { return mReportDefinition; } + + void addCollection(InputCollectionId id, int32_t arity); + void declareUsage(InputCollectionId id, InputUsage usage, int32_t min, int32_t max, + float resolution); + void declareUsage(InputCollectionId id, InputUsage* usage, size_t usageCount); + + InputReport allocateReport(); + +private: + friend class InputHost; + + InputReportDefinition( + input_host_t* host, input_host_callbacks_t cb, input_report_definition_t* r) : + InputHostBase(host, cb), mReportDefinition(r) {} + + input_report_definition_t* mReportDefinition; +}; + +class InputDeviceDefinition : private InputHostBase { +public: + virtual ~InputDeviceDefinition() = default; + + InputDeviceDefinition(const InputDeviceDefinition& rhs) = default; + InputDeviceDefinition& operator=(const InputDeviceDefinition& rhs) = default; + operator input_device_definition_t*() { return mDeviceDefinition; } + + void addReport(InputReportDefinition r); + +private: + friend class InputHost; + + InputDeviceDefinition( + input_host_t* host, input_host_callbacks_t cb, input_device_definition_t* d) : + InputHostBase(host, cb), mDeviceDefinition(d) {} + + input_device_definition_t* mDeviceDefinition; +}; + +class InputProperty : private InputHostBase { +public: + virtual ~InputProperty(); + + operator input_property_t*() { return mProperty; } + + const char* getKey(); + const char* getValue(); + + // Default move constructor transfers ownership of the input_property_t + // pointer. + InputProperty(InputProperty&& rhs) = default; + + // Prevent copy/assign because of the ownership of the underlying + // input_property_t pointer. + InputProperty(const InputProperty& rhs) = delete; + InputProperty& operator=(const InputProperty& rhs) = delete; + +private: + friend class InputPropertyMap; + + InputProperty( + input_host_t* host, input_host_callbacks_t cb, input_property_t* p) : + InputHostBase(host, cb), mProperty(p) {} + + input_property_t* mProperty; +}; + +class InputPropertyMap : private InputHostBase { +public: + virtual ~InputPropertyMap(); + + operator input_property_map_t*() { return mMap; } + + InputProperty getDeviceProperty(const char* key); + + // Default move constructor transfers ownership of the input_property_map_t + // pointer. + InputPropertyMap(InputPropertyMap&& rhs) = default; + + // Prevent copy/assign because of the ownership of the underlying + // input_property_map_t pointer. + InputPropertyMap(const InputPropertyMap& rhs) = delete; + InputPropertyMap& operator=(const InputPropertyMap& rhs) = delete; + +private: + friend class InputHost; + + InputPropertyMap( + input_host_t* host, input_host_callbacks_t cb, input_property_map_t* m) : + InputHostBase(host, cb), mMap(m) {} + + input_property_map_t* mMap; +}; + +class InputHost : private InputHostBase { +public: + InputHost(input_host_t* host, input_host_callbacks_t cb) : InputHostBase(host, cb) {} + virtual ~InputHost() = default; + + InputHost(const InputHost& rhs) = default; + InputHost& operator=(const InputHost& rhs) = default; + + InputDeviceIdentifier createDeviceIdentifier(const char* name, int32_t productId, + int32_t vendorId, InputBus bus, const char* uniqueId); + + InputDeviceDefinition createDeviceDefinition(); + InputReportDefinition createInputReportDefinition(); + InputReportDefinition createOutputReportDefinition(); + + InputDeviceHandle registerDevice(InputDeviceIdentifier id, InputDeviceDefinition d); + void unregisterDevice(InputDeviceHandle handle); + + InputPropertyMap getDevicePropertyMap(InputDeviceIdentifier id); +}; + +} // namespace android + +#endif // ANDROID_INPUT_HOST_H_
diff --git a/libhardware/modules/input/evdev/InputHub.cpp b/libhardware/modules/input/evdev/InputHub.cpp new file mode 100644 index 0000000..e72ac2e --- /dev/null +++ b/libhardware/modules/input/evdev/InputHub.cpp
@@ -0,0 +1,802 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "InputHub" +#define LOG_NDEBUG 0 + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/capability.h> +#include <sys/epoll.h> +#include <sys/eventfd.h> +#include <sys/inotify.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <unistd.h> + +#include <vector> + +#include "InputHub.h" + +#include <android/input.h> +#include <hardware_legacy/power.h> +#include <linux/input.h> + +#include <utils/Log.h> + +namespace android { + +static const char WAKE_LOCK_ID[] = "KeyEvents"; +static const int NO_TIMEOUT = -1; +static const int EPOLL_MAX_EVENTS = 16; +static const int INPUT_MAX_EVENTS = 128; + +static constexpr bool testBit(int bit, const uint8_t arr[]) { + return arr[bit / 8] & (1 << (bit % 8)); +} + +static constexpr size_t sizeofBitArray(size_t bits) { + return (bits + 7) / 8; +} + +static void getLinuxRelease(int* major, int* minor) { + struct utsname info; + if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) { + *major = 0, *minor = 0; + ALOGE("Could not get linux version: %s", strerror(errno)); + } +} + +static bool processHasCapability(int capability) { + LOG_ALWAYS_FATAL_IF(!cap_valid(capability), "invalid linux capability: %d", capability); + struct __user_cap_header_struct cap_header_data; + struct __user_cap_data_struct cap_data_data[2]; + cap_user_header_t caphdr = &cap_header_data; + cap_user_data_t capdata = cap_data_data; + caphdr->pid = 0; + caphdr->version = _LINUX_CAPABILITY_VERSION_3; + LOG_ALWAYS_FATAL_IF(capget(caphdr, capdata) != 0, + "Could not get process capabilities. errno=%d", errno); + ALOGV("effective capabilities: %08x %08x", capdata[0].effective, capdata[1].effective); + int idx = CAP_TO_INDEX(capability); + return capdata[idx].effective & CAP_TO_MASK(capability); +} + +class EvdevDeviceNode : public InputDeviceNode { +public: + static EvdevDeviceNode* openDeviceNode(const std::string& path); + + virtual ~EvdevDeviceNode() { + ALOGV("closing %s (fd=%d)", mPath.c_str(), mFd); + if (mFd >= 0) { + ::close(mFd); + } + } + + virtual int getFd() const { return mFd; } + virtual const std::string& getPath() const override { return mPath; } + virtual const std::string& getName() const override { return mName; } + virtual const std::string& getLocation() const override { return mLocation; } + virtual const std::string& getUniqueId() const override { return mUniqueId; } + + virtual uint16_t getBusType() const override { return mBusType; } + virtual uint16_t getVendorId() const override { return mVendorId; } + virtual uint16_t getProductId() const override { return mProductId; } + virtual uint16_t getVersion() const override { return mVersion; } + + virtual bool hasKey(int32_t key) const override; + virtual bool hasRelativeAxis(int axis) const override; + virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override; + virtual bool hasInputProperty(int property) const override; + + virtual int32_t getKeyState(int32_t key) const override; + virtual int32_t getSwitchState(int32_t sw) const override; + virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override; + + virtual void vibrate(nsecs_t duration) override; + virtual void cancelVibrate(int32_t deviceId) override; + + virtual void disableDriverKeyRepeat() override; + +private: + EvdevDeviceNode(const std::string& path, int fd) : + mFd(fd), mPath(path) {} + + status_t queryProperties(); + void queryAxisInfo(); + + int mFd; + std::string mPath; + + std::string mName; + std::string mLocation; + std::string mUniqueId; + + uint16_t mBusType; + uint16_t mVendorId; + uint16_t mProductId; + uint16_t mVersion; + + uint8_t mKeyBitmask[KEY_CNT / 8]; + uint8_t mAbsBitmask[ABS_CNT / 8]; + uint8_t mRelBitmask[REL_CNT / 8]; + uint8_t mSwBitmask[SW_CNT / 8]; + uint8_t mLedBitmask[LED_CNT / 8]; + uint8_t mFfBitmask[FF_CNT / 8]; + uint8_t mPropBitmask[INPUT_PROP_CNT / 8]; + + std::unordered_map<uint32_t, std::unique_ptr<AbsoluteAxisInfo>> mAbsInfo; + + bool mFfEffectPlaying = false; + int16_t mFfEffectId = -1; +}; + +EvdevDeviceNode* EvdevDeviceNode::openDeviceNode(const std::string& path) { + auto fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)); + if (fd < 0) { + ALOGE("could not open evdev device %s. err=%d", path.c_str(), errno); + return nullptr; + } + + // Tell the kernel that we want to use the monotonic clock for reporting + // timestamps associated with input events. This is important because the + // input system uses the timestamps extensively and assumes they were + // recorded using the monotonic clock. + // + // The EVIOCSCLOCKID ioctl was introduced in Linux 3.4. + int clockId = CLOCK_MONOTONIC; + if (TEMP_FAILURE_RETRY(ioctl(fd, EVIOCSCLOCKID, &clockId)) < 0) { + ALOGW("Could not set input clock id to CLOCK_MONOTONIC. errno=%d", errno); + } + + auto node = new EvdevDeviceNode(path, fd); + status_t ret = node->queryProperties(); + if (ret != OK) { + ALOGE("could not open evdev device %s: failed to read properties. errno=%d", + path.c_str(), ret); + delete node; + return nullptr; + } + return node; +} + +status_t EvdevDeviceNode::queryProperties() { + char buffer[80]; + + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGNAME(sizeof(buffer) - 1), buffer)) < 1) { + ALOGV("could not get device name for %s.", mPath.c_str()); + } else { + buffer[sizeof(buffer) - 1] = '\0'; + mName = buffer; + } + + int driverVersion; + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGVERSION, &driverVersion))) { + ALOGE("could not get driver version for %s. err=%d", mPath.c_str(), errno); + return -errno; + } + + struct input_id inputId; + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGID, &inputId))) { + ALOGE("could not get device input id for %s. err=%d", mPath.c_str(), errno); + return -errno; + } + mBusType = inputId.bustype; + mVendorId = inputId.vendor; + mProductId = inputId.product; + mVersion = inputId.version; + + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPHYS(sizeof(buffer) - 1), buffer)) < 1) { + ALOGV("could not get location for %s.", mPath.c_str()); + } else { + buffer[sizeof(buffer) - 1] = '\0'; + mLocation = buffer; + } + + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGUNIQ(sizeof(buffer) - 1), buffer)) < 1) { + ALOGV("could not get unique id for %s.", mPath.c_str()); + } else { + buffer[sizeof(buffer) - 1] = '\0'; + mUniqueId = buffer; + } + + ALOGV("add device %s", mPath.c_str()); + ALOGV(" bus: %04x\n" + " vendor: %04x\n" + " product: %04x\n" + " version: %04x\n", + mBusType, mVendorId, mProductId, mVersion); + ALOGV(" name: \"%s\"\n" + " location: \"%s\"\n" + " unique_id: \"%s\"\n" + " descriptor: (TODO)\n" + " driver: v%d.%d.%d", + mName.c_str(), mLocation.c_str(), mUniqueId.c_str(), + driverVersion >> 16, (driverVersion >> 8) & 0xff, (driverVersion >> 16) & 0xff); + + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_KEY, sizeof(mKeyBitmask)), mKeyBitmask)); + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_ABS, sizeof(mAbsBitmask)), mAbsBitmask)); + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_REL, sizeof(mRelBitmask)), mRelBitmask)); + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_SW, sizeof(mSwBitmask)), mSwBitmask)); + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_LED, sizeof(mLedBitmask)), mLedBitmask)); + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_FF, sizeof(mFfBitmask)), mFfBitmask)); + TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPROP(sizeof(mPropBitmask)), mPropBitmask)); + + queryAxisInfo(); + + return OK; +} + +void EvdevDeviceNode::queryAxisInfo() { + for (int32_t axis = 0; axis < ABS_MAX; ++axis) { + if (testBit(axis, mAbsBitmask)) { + struct input_absinfo info; + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGABS(axis), &info))) { + ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", + axis, mPath.c_str(), mFd, errno); + continue; + } + + mAbsInfo[axis] = std::unique_ptr<AbsoluteAxisInfo>(new AbsoluteAxisInfo{ + .minValue = info.minimum, + .maxValue = info.maximum, + .flat = info.flat, + .fuzz = info.fuzz, + .resolution = info.resolution + }); + } + } +} + +bool EvdevDeviceNode::hasKey(int32_t key) const { + if (key >= 0 && key <= KEY_MAX) { + return testBit(key, mKeyBitmask); + } + return false; +} + +bool EvdevDeviceNode::hasRelativeAxis(int axis) const { + if (axis >= 0 && axis <= REL_MAX) { + return testBit(axis, mRelBitmask); + } + return false; +} + +const AbsoluteAxisInfo* EvdevDeviceNode::getAbsoluteAxisInfo(int32_t axis) const { + if (axis < 0 || axis > ABS_MAX) { + return nullptr; + } + + const auto absInfo = mAbsInfo.find(axis); + if (absInfo != mAbsInfo.end()) { + return absInfo->second.get(); + } + return nullptr; +} + +bool EvdevDeviceNode::hasInputProperty(int property) const { + if (property >= 0 && property <= INPUT_PROP_MAX) { + return testBit(property, mPropBitmask); + } + return false; +} + +int32_t EvdevDeviceNode::getKeyState(int32_t key) const { + if (key >= 0 && key <= KEY_MAX) { + if (testBit(key, mKeyBitmask)) { + uint8_t keyState[sizeofBitArray(KEY_CNT)]; + memset(keyState, 0, sizeof(keyState)); + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGKEY(sizeof(keyState)), keyState)) >= 0) { + return testBit(key, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; + } + } + } + return AKEY_STATE_UNKNOWN; +} + +int32_t EvdevDeviceNode::getSwitchState(int32_t sw) const { + if (sw >= 0 && sw <= SW_MAX) { + if (testBit(sw, mSwBitmask)) { + uint8_t swState[sizeofBitArray(SW_CNT)]; + memset(swState, 0, sizeof(swState)); + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGSW(sizeof(swState)), swState)) >= 0) { + return testBit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; + } + } + } + return AKEY_STATE_UNKNOWN; +} + +status_t EvdevDeviceNode::getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const { + *outValue = 0; + + if (axis >= 0 && axis <= ABS_MAX) { + if (testBit(axis, mAbsBitmask)) { + struct input_absinfo info; + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGABS(axis), &info))) { + ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", + axis, mPath.c_str(), mFd, errno); + return -errno; + } + + *outValue = info.value; + return OK; + } + } + return -1; +} + +void EvdevDeviceNode::vibrate(nsecs_t duration) { + ff_effect effect{}; + effect.type = FF_RUMBLE; + effect.id = mFfEffectId; + effect.u.rumble.strong_magnitude = 0xc000; + effect.u.rumble.weak_magnitude = 0xc000; + effect.replay.length = (duration + 999'999LL) / 1'000'000LL; + effect.replay.delay = 0; + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCSFF, &effect))) { + ALOGW("Could not upload force feedback effect to device %s due to error %d.", + mPath.c_str(), errno); + return; + } + mFfEffectId = effect.id; + + struct input_event ev{}; + ev.type = EV_FF; + ev.code = mFfEffectId; + ev.value = 1; + size_t written = TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(ev))); + if (written != sizeof(ev)) { + ALOGW("Could not start force feedback effect on device %s due to error %d.", + mPath.c_str(), errno); + return; + } + mFfEffectPlaying = true; +} + +void EvdevDeviceNode::cancelVibrate(int32_t deviceId) { + if (mFfEffectPlaying) { + mFfEffectPlaying = false; + + struct input_event ev{}; + ev.type = EV_FF; + ev.code = mFfEffectId; + ev.value = 0; + size_t written = TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(ev))); + if (written != sizeof(ev)) { + ALOGW("Could not stop force feedback effect on device %s due to error %d.", + mPath.c_str(), errno); + return; + } + } +} + +void EvdevDeviceNode::disableDriverKeyRepeat() { + unsigned int repeatRate[] = {0, 0}; + if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCSREP, repeatRate))) { + ALOGW("Unable to disable kernel key repeat for %s due to error %d.", + mPath.c_str(), errno); + } +} + +InputHub::InputHub(std::shared_ptr<InputCallbackInterface> cb) : + mInputCallback(cb) { + // Determine the type of suspend blocking we can do on this device. There + // are 3 options, in decreasing order of preference: + // 1) EPOLLWAKEUP: introduced in Linux kernel 3.5, this flag can be set on + // an epoll event to indicate that a wake lock should be held from the + // time an fd has data until the next epoll_wait (or the epoll fd is + // closed). + // 2) EVIOCSSUSPENDBLOCK: introduced into the Android kernel's evdev + // driver, this ioctl blocks suspend while the event queue for the fd is + // not empty. This was never accepted into the mainline kernel, and it was + // replaced by EPOLLWAKEUP. + // 3) explicit wake locks: use acquire_wake_lock to manage suspend + // blocking explicitly in the InputHub code. + // + // (1) can be checked by simply observing the Linux kernel version. (2) + // requires an fd from an evdev node, which cannot be done in the InputHub + // constructor. So we assume (3) unless (1) is true, and we can verify + // whether (2) is true once we have an evdev fd (and we're not in (1)). + int major, minor; + getLinuxRelease(&major, &minor); + if (major > 3 || (major == 3 && minor >= 5)) { + ALOGI("Using EPOLLWAKEUP to block suspend while processing input events."); + mWakeupMechanism = WakeMechanism::EPOLL_WAKEUP; + mNeedToCheckSuspendBlockIoctl = false; + } + if (manageWakeLocks()) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); + } + + // epoll_create argument is ignored, but it must be > 0. + mEpollFd = epoll_create(1); + LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); + + mINotifyFd = inotify_init(); + LOG_ALWAYS_FATAL_IF(mINotifyFd < 0, "Could not create inotify instance. errno=%d", errno); + + struct epoll_event eventItem; + memset(&eventItem, 0, sizeof(eventItem)); + eventItem.events = EPOLLIN; + if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) { + eventItem.events |= EPOLLWAKEUP; + } + eventItem.data.u32 = mINotifyFd; + int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); + LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno); + + int wakeFds[2]; + result = pipe(wakeFds); + LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); + + mWakeEventFd = eventfd(0, EFD_NONBLOCK); + LOG_ALWAYS_FATAL_IF(mWakeEventFd == -1, "Could not create wake event fd. errno=%d", errno); + + eventItem.data.u32 = mWakeEventFd; + result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem); + LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance. errno=%d", errno); +} + +InputHub::~InputHub() { + ::close(mEpollFd); + ::close(mINotifyFd); + ::close(mWakeEventFd); + + if (manageWakeLocks()) { + release_wake_lock(WAKE_LOCK_ID); + } +} + +status_t InputHub::registerDevicePath(const std::string& path) { + ALOGV("registering device path %s", path.c_str()); + int wd = inotify_add_watch(mINotifyFd, path.c_str(), IN_DELETE | IN_CREATE); + if (wd < 0) { + ALOGE("Could not add %s to INotify watch. errno=%d", path.c_str(), errno); + return -errno; + } + mWatchedPaths[wd] = path; + scanDir(path); + return OK; +} + +status_t InputHub::unregisterDevicePath(const std::string& path) { + int wd = -1; + for (auto pair : mWatchedPaths) { + if (pair.second == path) { + wd = pair.first; + break; + } + } + + if (wd == -1) { + return BAD_VALUE; + } + mWatchedPaths.erase(wd); + if (inotify_rm_watch(mINotifyFd, wd) != 0) { + return -errno; + } + return OK; +} + +status_t InputHub::poll() { + bool deviceChange = false; + + if (manageWakeLocks()) { + // Mind the wake lock dance! + // If we're relying on wake locks, we hold a wake lock at all times + // except during epoll_wait(). This works due to some subtle + // choreography. When a device driver has pending (unread) events, it + // acquires a kernel wake lock. However, once the last pending event + // has been read, the device driver will release the kernel wake lock. + // To prevent the system from going to sleep when this happens, the + // InputHub holds onto its own user wake lock while the client is + // processing events. Thus the system can only sleep if there are no + // events pending or currently being processed. + release_wake_lock(WAKE_LOCK_ID); + } + + struct epoll_event pendingEventItems[EPOLL_MAX_EVENTS]; + int pollResult = epoll_wait(mEpollFd, pendingEventItems, EPOLL_MAX_EVENTS, NO_TIMEOUT); + + if (manageWakeLocks()) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); + } + + if (pollResult == 0) { + ALOGW("epoll_wait should not return 0 with no timeout"); + return UNKNOWN_ERROR; + } + if (pollResult < 0) { + // An error occurred. Return even if it's EINTR, and let the caller + // restart the poll. + ALOGE("epoll_wait returned with errno=%d", errno); + return -errno; + } + + // pollResult > 0: there are events to process + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + std::vector<int> removedDeviceFds; + int inputFd = -1; + std::shared_ptr<InputDeviceNode> deviceNode; + for (int i = 0; i < pollResult; ++i) { + const struct epoll_event& eventItem = pendingEventItems[i]; + + int dataFd = static_cast<int>(eventItem.data.u32); + if (dataFd == mINotifyFd) { + if (eventItem.events & EPOLLIN) { + deviceChange = true; + } else { + ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events); + } + continue; + } + + if (dataFd == mWakeEventFd) { + if (eventItem.events & EPOLLIN) { + ALOGV("awoken after wake()"); + uint64_t u; + ssize_t nRead = TEMP_FAILURE_RETRY(read(mWakeEventFd, &u, sizeof(uint64_t))); + if (nRead != sizeof(uint64_t)) { + ALOGW("Could not read event fd; waking anyway."); + } + } else { + ALOGW("Received unexpected epoll event 0x%08x for wake event.", + eventItem.events); + } + continue; + } + + // Update the fd and device node when the fd changes. When several + // events are read back-to-back with the same fd, this saves many reads + // from the hash table. + if (inputFd != dataFd) { + inputFd = dataFd; + deviceNode = mDeviceNodes[inputFd]; + } + if (deviceNode == nullptr) { + ALOGE("could not find device node for fd %d", inputFd); + continue; + } + if (eventItem.events & EPOLLIN) { + struct input_event ievs[INPUT_MAX_EVENTS]; + for (;;) { + ssize_t readSize = TEMP_FAILURE_RETRY(read(inputFd, ievs, sizeof(ievs))); + if (readSize == 0 || (readSize < 0 && errno == ENODEV)) { + ALOGW("could not get event, removed? (fd: %d, size: %d errno: %d)", + inputFd, readSize, errno); + + removedDeviceFds.push_back(inputFd); + break; + } else if (readSize < 0) { + if (errno != EAGAIN && errno != EINTR) { + ALOGW("could not get event. errno=%d", errno); + } + break; + } else if (readSize % sizeof(input_event) != 0) { + ALOGE("could not get event. wrong size=%d", readSize); + break; + } else { + size_t count = static_cast<size_t>(readSize) / sizeof(struct input_event); + for (size_t i = 0; i < count; ++i) { + auto& iev = ievs[i]; + auto when = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec); + InputEvent inputEvent = { when, iev.type, iev.code, iev.value }; + mInputCallback->onInputEvent(deviceNode, inputEvent, now); + } + } + } + } else if (eventItem.events & EPOLLHUP) { + ALOGI("Removing device fd %d due to epoll hangup event.", inputFd); + removedDeviceFds.push_back(inputFd); + } else { + ALOGW("Received unexpected epoll event 0x%08x for device fd %d", + eventItem.events, inputFd); + } + } + + if (removedDeviceFds.size()) { + for (auto deviceFd : removedDeviceFds) { + auto deviceNode = mDeviceNodes[deviceFd]; + if (deviceNode != nullptr) { + status_t ret = closeNodeByFd(deviceFd); + if (ret != OK) { + ALOGW("Could not close device with fd %d. errno=%d", deviceFd, ret); + } else { + mInputCallback->onDeviceRemoved(deviceNode); + } + } + } + } + + if (deviceChange) { + readNotify(); + } + + return OK; +} + +status_t InputHub::wake() { + ALOGV("wake() called"); + + uint64_t u = 1; + ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &u, sizeof(uint64_t))); + + if (nWrite != sizeof(uint64_t) && errno != EAGAIN) { + ALOGW("Could not write wake signal, errno=%d", errno); + return -errno; + } + return OK; +} + +void InputHub::dump(String8& dump) { + // TODO +} + +status_t InputHub::readNotify() { + char event_buf[512]; + struct inotify_event* event; + + ssize_t res = TEMP_FAILURE_RETRY(read(mINotifyFd, event_buf, sizeof(event_buf))); + if (res < static_cast<int>(sizeof(*event))) { + ALOGW("could not get inotify event, %s\n", strerror(errno)); + return -errno; + } + + size_t event_pos = 0; + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + while (res >= static_cast<int>(sizeof(*event))) { + event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos); + if (event->len) { + std::string path = mWatchedPaths[event->wd]; + path.append("/").append(event->name); + ALOGV("inotify event for path %s", path.c_str()); + + if (event->mask & IN_CREATE) { + std::shared_ptr<InputDeviceNode> deviceNode; + status_t res = openNode(path, &deviceNode); + if (res != OK) { + ALOGE("could not open device node %s. err=%d", path.c_str(), res); + } else { + mInputCallback->onDeviceAdded(deviceNode); + } + } else { + auto deviceNode = findNodeByPath(path); + if (deviceNode != nullptr) { + status_t ret = closeNode(deviceNode); + if (ret != OK) { + ALOGW("Could not close device %s. errno=%d", path.c_str(), ret); + } else { + mInputCallback->onDeviceRemoved(deviceNode); + } + } else { + ALOGW("could not find device node for %s", path.c_str()); + } + } + } + int event_size = sizeof(*event) + event->len; + res -= event_size; + event_pos += event_size; + } + + return OK; +} + +status_t InputHub::scanDir(const std::string& path) { + auto dir = ::opendir(path.c_str()); + if (dir == nullptr) { + ALOGE("could not open device path %s to scan for devices. err=%d", path.c_str(), errno); + return -errno; + } + + while (auto dirent = readdir(dir)) { + if (strcmp(dirent->d_name, ".") == 0 || + strcmp(dirent->d_name, "..") == 0) { + continue; + } + std::string filename = path + "/" + dirent->d_name; + std::shared_ptr<InputDeviceNode> node; + if (openNode(filename, &node) != OK) { + ALOGE("could not open device node %s", filename.c_str()); + } else { + mInputCallback->onDeviceAdded(node); + } + } + ::closedir(dir); + return OK; +} + +status_t InputHub::openNode(const std::string& path, + std::shared_ptr<InputDeviceNode>* outNode) { + ALOGV("opening %s...", path.c_str()); + auto evdevNode = std::shared_ptr<EvdevDeviceNode>(EvdevDeviceNode::openDeviceNode(path)); + if (evdevNode == nullptr) { + return UNKNOWN_ERROR; + } + + auto fd = evdevNode->getFd(); + ALOGV("opened %s with fd %d", path.c_str(), fd); + *outNode = std::static_pointer_cast<InputDeviceNode>(evdevNode); + mDeviceNodes[fd] = *outNode; + struct epoll_event eventItem{}; + eventItem.events = EPOLLIN; + if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) { + eventItem.events |= EPOLLWAKEUP; + } + eventItem.data.u32 = fd; + if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) { + ALOGE("Could not add device fd to epoll instance. errno=%d", errno); + return -errno; + } + + if (mNeedToCheckSuspendBlockIoctl) { +#ifndef EVIOCSSUSPENDBLOCK + // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels + // will use an epoll flag instead, so as long as we want to support this + // feature, we need to be prepared to define the ioctl ourselves. +#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int) +#endif + if (TEMP_FAILURE_RETRY(ioctl(fd, EVIOCSSUSPENDBLOCK, 1))) { + // no wake mechanism, continue using explicit wake locks + ALOGI("Using explicit wakelocks to block suspend while processing input events."); + } else { + mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_SUSPENDBLOCK_IOCTL; + // release any held wakelocks since we won't need them anymore + release_wake_lock(WAKE_LOCK_ID); + ALOGI("Using EVIOCSSUSPENDBLOCK to block suspend while processing input events."); + } + mNeedToCheckSuspendBlockIoctl = false; + } + + return OK; +} + +status_t InputHub::closeNode(const std::shared_ptr<InputDeviceNode>& node) { + for (auto pair : mDeviceNodes) { + if (pair.second.get() == node.get()) { + return closeNodeByFd(pair.first); + } + } + return BAD_VALUE; +} + +status_t InputHub::closeNodeByFd(int fd) { + status_t ret = OK; + if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL)) { + ALOGW("Could not remove device fd from epoll instance. errno=%d", errno); + ret = -errno; + } + mDeviceNodes.erase(fd); + ::close(fd); + return ret; +} + +std::shared_ptr<InputDeviceNode> InputHub::findNodeByPath(const std::string& path) { + for (auto pair : mDeviceNodes) { + if (pair.second->getPath() == path) return pair.second; + } + return nullptr; +} + +bool InputHub::manageWakeLocks() const { + return mWakeupMechanism != WakeMechanism::EPOLL_WAKEUP; +} + +} // namespace android
diff --git a/libhardware/modules/input/evdev/InputHub.h b/libhardware/modules/input/evdev/InputHub.h new file mode 100644 index 0000000..bec327a --- /dev/null +++ b/libhardware/modules/input/evdev/InputHub.h
@@ -0,0 +1,204 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INPUT_HUB_H_ +#define ANDROID_INPUT_HUB_H_ + +#include <memory> +#include <string> +#include <unordered_map> + +#include <utils/String8.h> +#include <utils/Timers.h> + +namespace android { + +/** + * InputEvent represents an event from the kernel. The fields largely mirror + * those found in linux/input.h. + */ +struct InputEvent { + nsecs_t when; + + int32_t type; + int32_t code; + int32_t value; +}; + +/** Describes an absolute axis. */ +struct AbsoluteAxisInfo { + int32_t minValue = 0; // minimum value + int32_t maxValue = 0; // maximum value + int32_t flat = 0; // center flat position, e.g. flat == 8 means center is between -8 and 8 + int32_t fuzz = 0; // error tolerance, e.g. fuzz == 4 means value is +/- 4 due to noise + int32_t resolution = 0; // resolution in units per mm or radians per mm +}; + +/** + * An InputDeviceNode represents a device node in the Linux system. It can be + * used to interact with the device, setting and getting property values. + * + * An InputDeviceNode should only be used on the same thread that is polling for + * input events. + */ +class InputDeviceNode { +public: + virtual const std::string& getPath() const = 0; + + virtual const std::string& getName() const = 0; + virtual const std::string& getLocation() const = 0; + virtual const std::string& getUniqueId() const = 0; + + virtual uint16_t getBusType() const = 0; + virtual uint16_t getVendorId() const = 0; + virtual uint16_t getProductId() const = 0; + virtual uint16_t getVersion() const = 0; + + virtual bool hasKey(int32_t key) const = 0; + virtual bool hasRelativeAxis(int axis) const = 0; + virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0; + virtual bool hasInputProperty(int property) const = 0; + + virtual int32_t getKeyState(int32_t key) const = 0; + virtual int32_t getSwitchState(int32_t sw) const = 0; + virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0; + + virtual void vibrate(nsecs_t duration) = 0; + virtual void cancelVibrate(int32_t deviceId) = 0; + + virtual void disableDriverKeyRepeat() = 0; + +protected: + InputDeviceNode() = default; + virtual ~InputDeviceNode() = default; +}; + +/** Callback interface for receiving input events, including device changes. */ +class InputCallbackInterface { +public: + virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event, + nsecs_t event_time) = 0; + virtual void onDeviceAdded(std::shared_ptr<InputDeviceNode> node) = 0; + virtual void onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) = 0; + +protected: + InputCallbackInterface() = default; + virtual ~InputCallbackInterface() = default; +}; + +/** + * InputHubInterface is responsible for monitoring a set of device paths and + * executing callbacks when events occur. Before calling poll(), you should set + * the device and input callbacks, and register your device path(s). + */ +class InputHubInterface { +public: + virtual status_t registerDevicePath(const std::string& path) = 0; + virtual status_t unregisterDevicePath(const std::string& path) = 0; + + virtual status_t poll() = 0; + virtual status_t wake() = 0; + + virtual void dump(String8& dump) = 0; + +protected: + InputHubInterface() = default; + virtual ~InputHubInterface() = default; +}; + +/** + * An implementation of InputHubInterface that uses epoll to wait for events. + * + * This class is not threadsafe. Any functions called on the InputHub should be + * called on the same thread that is used to call poll(). The only exception is + * wake(), which may be used to return from poll() before an input or device + * event occurs. + */ +class InputHub : public InputHubInterface { +public: + explicit InputHub(std::shared_ptr<InputCallbackInterface> cb); + virtual ~InputHub() override; + + virtual status_t registerDevicePath(const std::string& path) override; + virtual status_t unregisterDevicePath(const std::string& path) override; + + virtual status_t poll() override; + virtual status_t wake() override; + + virtual void dump(String8& dump) override; + +private: + status_t readNotify(); + status_t scanDir(const std::string& path); + status_t openNode(const std::string& path, std::shared_ptr<InputDeviceNode>* outNode); + status_t closeNode(const std::shared_ptr<InputDeviceNode>& node); + status_t closeNodeByFd(int fd); + std::shared_ptr<InputDeviceNode> findNodeByPath(const std::string& path); + + enum class WakeMechanism { + /** + * The kernel supports the EPOLLWAKEUP flag for epoll_ctl. + * + * When using this mechanism, epoll_wait will internally acquire a wake + * lock whenever one of the FDs it is monitoring becomes ready. The wake + * lock is held automatically by the kernel until the next call to + * epoll_wait. + * + * This mechanism only exists in Linux kernel 3.5+. + */ + EPOLL_WAKEUP, + /** + * The kernel evdev driver supports the EVIOCSSUSPENDBLOCK ioctl. + * + * When using this mechanism, the InputHub asks evdev to acquire and + * hold a wake lock whenever its buffer is non-empty. We must take care + * to acquire our own userspace wake lock before draining the buffer to + * prevent actually going back into suspend before we have fully + * processed all of the events. + * + * This mechanism only exists in older Android Linux kernels. + */ + LEGACY_EVDEV_SUSPENDBLOCK_IOCTL, + /** + * The kernel doesn't seem to support any special wake mechanism. + * + * We explicitly acquire and release wake locks when processing input + * events. + */ + LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS, + }; + WakeMechanism mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS; + bool manageWakeLocks() const; + bool mNeedToCheckSuspendBlockIoctl = true; + + int mEpollFd; + int mINotifyFd; + int mWakeEventFd; + int mWakeReadPipeFd; + int mWakeWritePipeFd; + + // Callback for input events + std::shared_ptr<InputCallbackInterface> mInputCallback; + + // Map from watch descriptors to watched paths + std::unordered_map<int, std::string> mWatchedPaths; + // Map from file descriptors to InputDeviceNodes + std::unordered_map<int, std::shared_ptr<InputDeviceNode>> mDeviceNodes; +}; + +} // namespace android + +#endif // ANDROID_INPUT_HUB_H_
diff --git a/libhardware/modules/local_time/Android.bp b/libhardware/modules/local_time/Android.bp new file mode 100644 index 0000000..df32325 --- /dev/null +++ b/libhardware/modules/local_time/Android.bp
@@ -0,0 +1,32 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The default local time HAL module. The default module simply uses the +// system's clock_gettime(CLOCK_MONOTONIC) and does not support HW slewing. +// Devices which use the default implementation should take care to ensure that +// the oscillator backing the CLOCK_MONOTONIC implementation is phase locked to +// the audio and video output hardware. This default implementation is loaded +// if no other device specific modules are present. The exact load order can be +// seen in libhardware/hardware.c +// +// The format of the name is local_time.<hardware>.so +cc_library_shared { + name: "local_time.default", + relative_install_path: "hw", + srcs: ["local_time_hw.c"], + shared_libs: [ + "liblog", + "libcutils", + ], +}
diff --git a/libhardware/modules/local_time/local_time_hw.c b/libhardware/modules/local_time/local_time_hw.c new file mode 100644 index 0000000..ac597f4 --- /dev/null +++ b/libhardware/modules/local_time/local_time_hw.c
@@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "local_time_hw_default" +//#define LOG_NDEBUG 0 + +#include <errno.h> +#include <malloc.h> +#include <stdint.h> +#include <string.h> +#include <sys/time.h> + +#include <cutils/log.h> + +#include <hardware/hardware.h> +#include <hardware/local_time_hal.h> + +struct stub_local_time_device { + struct local_time_hw_device device; +}; + +static int64_t ltdev_get_local_time(struct local_time_hw_device* dev) +{ + struct timespec ts; + uint64_t now; + int ret; + + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + if (ret < 0) { + ALOGW("%s failed to fetch CLOCK_MONOTONIC value! (res = %d)", + dev->common.module->name, ret); + return 0; + } + + now = (((uint64_t)ts.tv_sec) * 1000000000ull) + + ((uint64_t)ts.tv_nsec); + + return (int64_t)now; +} + +static uint64_t ltdev_get_local_freq(struct local_time_hw_device* dev) +{ + // For better or worse, linux clock_gettime routines normalize all clock + // frequencies to 1GHz + return 1000000000ull; +} + +static int ltdev_close(hw_device_t *device) +{ + free(device); + return 0; +} + +static int ltdev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + struct stub_local_time_device *ltdev; + struct timespec ts; + int ret; + + if (strcmp(name, LOCAL_TIME_HARDWARE_INTERFACE) != 0) + return -EINVAL; + + ltdev = calloc(1, sizeof(struct stub_local_time_device)); + if (!ltdev) + return -ENOMEM; + + ltdev->device.common.tag = HARDWARE_DEVICE_TAG; + ltdev->device.common.version = 0; + ltdev->device.common.module = (struct hw_module_t *) module; + ltdev->device.common.close = ltdev_close; + + ltdev->device.get_local_time = ltdev_get_local_time; + ltdev->device.get_local_freq = ltdev_get_local_freq; + ltdev->device.set_local_slew = NULL; + ltdev->device.get_debug_log = NULL; + + *device = <dev->device.common; + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + .open = ltdev_open, +}; + +struct local_time_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = LOCAL_TIME_HARDWARE_MODULE_ID, + .name = "Default local_time HW HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +};
diff --git a/libhardware/modules/nfc-nci/Android.bp b/libhardware/modules/nfc-nci/Android.bp new file mode 100644 index 0000000..fc73761 --- /dev/null +++ b/libhardware/modules/nfc-nci/Android.bp
@@ -0,0 +1,23 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_library_shared { + name: "nfc_nci.default", + relative_install_path: "hw", + srcs: ["nfc_nci_example.c"], + shared_libs: [ + "liblog", + "libcutils", + ], +}
diff --git a/libhardware/modules/nfc-nci/nfc_nci_example.c b/libhardware/modules/nfc-nci/nfc_nci_example.c new file mode 100644 index 0000000..758c2b7 --- /dev/null +++ b/libhardware/modules/nfc-nci/nfc_nci_example.c
@@ -0,0 +1,120 @@ +/* + * Copyright (C) 2012 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 <errno.h> +#include <malloc.h> +#include <string.h> + +#include <cutils/log.h> +#include <hardware/hardware.h> +#include <hardware/nfc.h> + + +/* + * NCI HAL method implementations. These must be overriden + */ +static int hal_open(const struct nfc_nci_device *dev, + nfc_stack_callback_t *p_cback, nfc_stack_data_callback_t *p_data_cback) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_write(const struct nfc_nci_device *dev, + uint16_t data_len, const uint8_t *p_data) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_core_initialized(const struct nfc_nci_device *dev, + uint8_t* p_core_init_rsp_params) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_pre_discover(const struct nfc_nci_device *dev) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_close(const struct nfc_nci_device *dev) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_control_granted (const struct nfc_nci_device *p_dev) +{ + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + + +static int hal_power_cycle (const struct nfc_nci_device *p_dev) +{ + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +/* + * Generic device handling below - can generally be left unchanged. + */ +/* Close an opened nfc device instance */ +static int nfc_close(hw_device_t *dev) { + free(dev); + return 0; +} + +static int nfc_open(const hw_module_t* module, const char* name, + hw_device_t** device) { + if (strcmp(name, NFC_NCI_CONTROLLER) == 0) { + nfc_nci_device_t *dev = calloc(1, sizeof(nfc_nci_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0x00010000; // [31:16] major, [15:0] minor + dev->common.module = (struct hw_module_t*) module; + dev->common.close = nfc_close; + + // NCI HAL method pointers + dev->open = hal_open; + dev->write = hal_write; + dev->core_initialized = hal_core_initialized; + dev->pre_discover = hal_pre_discover; + dev->close = hal_close; + dev->control_granted = hal_control_granted; + dev->power_cycle = hal_power_cycle; + + *device = (hw_device_t*) dev; + + return 0; + } else { + return -EINVAL; + } +} + + +static struct hw_module_methods_t nfc_module_methods = { + .open = nfc_open, +}; + +struct nfc_nci_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = 0x0100, // [15:8] major, [7:0] minor (1.0) + .hal_api_version = 0x00, // 0 is only valid value + .id = NFC_NCI_HARDWARE_MODULE_ID, + .name = "Default NFC NCI HW HAL", + .author = "The Android Open Source Project", + .methods = &nfc_module_methods, + }, +};
diff --git a/libhardware/modules/nfc/Android.bp b/libhardware/modules/nfc/Android.bp new file mode 100644 index 0000000..bd93bb5 --- /dev/null +++ b/libhardware/modules/nfc/Android.bp
@@ -0,0 +1,23 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_library_shared { + name: "nfc.default", + relative_install_path: "hw", + srcs: ["nfc_pn544_example.c"], + shared_libs: [ + "liblog", + "libcutils", + ], +}
diff --git a/libhardware/modules/nfc/nfc_pn544_example.c b/libhardware/modules/nfc/nfc_pn544_example.c new file mode 100644 index 0000000..71bfd6b --- /dev/null +++ b/libhardware/modules/nfc/nfc_pn544_example.c
@@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <errno.h> +#include <malloc.h> +#include <string.h> + +#include <hardware/hardware.h> +#include <hardware/nfc.h> + +/* Close an opened pn544 device instance */ +static int pn544_close(hw_device_t *dev) { + free(dev); + return 0; +} + +/* + * Generic device handling + */ +static int nfc_open(const hw_module_t* module, const char* name, + hw_device_t** device) { + if (strcmp(name, NFC_PN544_CONTROLLER) == 0) { + nfc_pn544_device_t *dev = calloc(1, sizeof(nfc_pn544_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*) module; + dev->common.close = pn544_close; + + /* Example settings */ + dev->num_eeprom_settings = 0; + dev->eeprom_settings = NULL; + dev->linktype = PN544_LINK_TYPE_INVALID; + dev->device_node = NULL; + dev->enable_i2c_workaround = 0; + dev->i2c_device_address = 0; + + *device = (hw_device_t*) dev; + return 0; + } else { + return -EINVAL; + } +} + + +static struct hw_module_methods_t nfc_module_methods = { + .open = nfc_open, +}; + +struct nfc_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = NFC_HARDWARE_MODULE_ID, + .name = "Default NFC HW HAL", + .author = "The Android Open Source Project", + .methods = &nfc_module_methods, + }, +};
diff --git a/libhardware/modules/power/Android.bp b/libhardware/modules/power/Android.bp new file mode 100644 index 0000000..2b86c8b --- /dev/null +++ b/libhardware/modules/power/Android.bp
@@ -0,0 +1,20 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_library_shared { + name: "power.default", + relative_install_path: "hw", + srcs: ["power.c"], + shared_libs: ["liblog"], +}
diff --git a/libhardware/modules/power/power.c b/libhardware/modules/power/power.c new file mode 100644 index 0000000..7cacc09 --- /dev/null +++ b/libhardware/modules/power/power.c
@@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 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 <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define LOG_TAG "Legacy PowerHAL" +#include <utils/Log.h> + +#include <hardware/hardware.h> +#include <hardware/power.h> + +static void power_init(struct power_module *module) +{ +} + +static void power_set_interactive(struct power_module *module, int on) +{ +} + +static void power_hint(struct power_module *module, power_hint_t hint, + void *data) { + switch (hint) { + default: + break; + } +} + +static struct hw_module_methods_t power_module_methods = { + .open = NULL, +}; + +struct power_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = POWER_MODULE_API_VERSION_0_2, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = POWER_HARDWARE_MODULE_ID, + .name = "Default Power HAL", + .author = "The Android Open Source Project", + .methods = &power_module_methods, + }, + + .init = power_init, + .setInteractive = power_set_interactive, + .powerHint = power_hint, +};
diff --git a/libhardware/modules/radio/Android.mk b/libhardware/modules/radio/Android.mk new file mode 100644 index 0000000..f433c85 --- /dev/null +++ b/libhardware/modules/radio/Android.mk
@@ -0,0 +1,27 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +# Stub radio HAL module, used for tests +include $(CLEAR_VARS) + +LOCAL_MODULE := radio.fm.default +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := radio_hw.c +LOCAL_SHARED_LIBRARIES := liblog libcutils libradio_metadata +LOCAL_MODULE_TAGS := optional +LOCAL_32_BIT_ONLY := true + +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/radio/radio_hw.c b/libhardware/modules/radio/radio_hw.c new file mode 100644 index 0000000..9c0f22c --- /dev/null +++ b/libhardware/modules/radio/radio_hw.c
@@ -0,0 +1,744 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "radio_hw_stub" +#define LOG_NDEBUG 0 + +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <pthread.h> +#include <sys/prctl.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <cutils/log.h> +#include <cutils/list.h> +#include <system/radio.h> +#include <system/radio_metadata.h> +#include <hardware/hardware.h> +#include <hardware/radio.h> + +static const radio_hal_properties_t hw_properties = { + .class_id = RADIO_CLASS_AM_FM, + .implementor = "The Android Open Source Project", + .product = "Radio stub HAL", + .version = "0.1", + .serial = "0123456789", + .num_tuners = 1, + .num_audio_sources = 1, + .supports_capture = false, + .num_bands = 2, + .bands = { + { + .type = RADIO_BAND_FM, + .antenna_connected = false, + .lower_limit = 87900, + .upper_limit = 107900, + .num_spacings = 1, + .spacings = { 200 }, + .fm = { + .deemphasis = RADIO_DEEMPHASIS_75, + .stereo = true, + .rds = RADIO_RDS_US, + .ta = false, + .af = false, + } + }, + { + .type = RADIO_BAND_AM, + .antenna_connected = true, + .lower_limit = 540, + .upper_limit = 1610, + .num_spacings = 1, + .spacings = { 10 }, + .am = { + .stereo = true, + } + } + } +}; + +struct stub_radio_tuner { + struct radio_tuner interface; + struct stub_radio_device *dev; + radio_callback_t callback; + void *cookie; + radio_hal_band_config_t config; + radio_program_info_t program; + bool audio; + pthread_t callback_thread; + pthread_mutex_t lock; + pthread_cond_t cond; + struct listnode command_list; +}; + +struct stub_radio_device { + struct radio_hw_device device; + struct stub_radio_tuner *tuner; + pthread_mutex_t lock; +}; + + +typedef enum { + CMD_EXIT, + CMD_CONFIG, + CMD_STEP, + CMD_SCAN, + CMD_TUNE, + CMD_CANCEL, + CMD_METADATA, +} thread_cmd_type_t; + +struct thread_command { + struct listnode node; + thread_cmd_type_t type; + struct timespec ts; + union { + unsigned int param; + radio_hal_band_config_t config; + }; +}; + +/* must be called with out->lock locked */ +static int send_command_l(struct stub_radio_tuner *tuner, + thread_cmd_type_t type, + unsigned int delay_ms, + void *param) +{ + struct thread_command *cmd = (struct thread_command *)calloc(1, sizeof(struct thread_command)); + struct timespec ts; + + if (cmd == NULL) + return -ENOMEM; + + ALOGV("%s %d delay_ms %d", __func__, type, delay_ms); + + cmd->type = type; + if (param != NULL) { + if (cmd->type == CMD_CONFIG) { + cmd->config = *(radio_hal_band_config_t *)param; + ALOGV("%s CMD_CONFIG type %d", __func__, cmd->config.type); + } else + cmd->param = *(unsigned int *)param; + } + + clock_gettime(CLOCK_REALTIME, &ts); + + ts.tv_sec += delay_ms/1000; + ts.tv_nsec += (delay_ms%1000) * 1000000; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ts.tv_sec += 1; + } + cmd->ts = ts; + list_add_tail(&tuner->command_list, &cmd->node); + pthread_cond_signal(&tuner->cond); + return 0; +} + +#define BITMAP_FILE_PATH "/data/misc/media/android.png" + +static int add_bitmap_metadata(radio_metadata_t **metadata, radio_metadata_key_t key, + const char *source) +{ + int fd; + ssize_t ret = 0; + struct stat info; + void *data = NULL; + size_t size; + + fd = open(source, O_RDONLY); + if (fd < 0) + return -EPIPE; + + fstat(fd, &info); + size = info.st_size; + data = malloc(size); + if (data == NULL) { + ret = -ENOMEM; + goto exit; + } + ret = read(fd, data, size); + if (ret < 0) + goto exit; + ret = radio_metadata_add_raw(metadata, key, (const unsigned char *)data, size); + +exit: + close(fd); + free(data); + ALOGE_IF(ret != 0, "%s error %d", __func__, ret); + return (int)ret; +} + +static int prepare_metadata(struct stub_radio_tuner *tuner, + radio_metadata_t **metadata, bool program) +{ + int ret = 0; + char text[RADIO_STRING_LEN_MAX]; + struct timespec ts; + + if (metadata == NULL) + return -EINVAL; + + if (*metadata != NULL) + radio_metadata_deallocate(*metadata); + + *metadata = NULL; + + ret = radio_metadata_allocate(metadata, tuner->program.channel, 0); + if (ret != 0) + return ret; + + if (program) { + ret = radio_metadata_add_int(metadata, RADIO_METADATA_KEY_RBDS_PTY, 5); + if (ret != 0) + goto exit; + ret = radio_metadata_add_text(metadata, RADIO_METADATA_KEY_RDS_PS, "RockBand"); + if (ret != 0) + goto exit; + ret = add_bitmap_metadata(metadata, RADIO_METADATA_KEY_ICON, BITMAP_FILE_PATH); + if (ret != 0) + goto exit; + } else { + ret = add_bitmap_metadata(metadata, RADIO_METADATA_KEY_ART, BITMAP_FILE_PATH); + if (ret != 0) + goto exit; + } + + clock_gettime(CLOCK_REALTIME, &ts); + snprintf(text, RADIO_STRING_LEN_MAX, "Artist %ld", ts.tv_sec % 10); + ret = radio_metadata_add_text(metadata, RADIO_METADATA_KEY_ARTIST, text); + if (ret != 0) + goto exit; + + snprintf(text, RADIO_STRING_LEN_MAX, "Song %ld", ts.tv_nsec % 10); + ret = radio_metadata_add_text(metadata, RADIO_METADATA_KEY_TITLE, text); + if (ret != 0) + goto exit; + + return 0; + +exit: + radio_metadata_deallocate(*metadata); + *metadata = NULL; + return ret; +} + +static void *callback_thread_loop(void *context) +{ + struct stub_radio_tuner *tuner = (struct stub_radio_tuner *)context; + struct timespec ts = {0, 0}; + + ALOGI("%s", __func__); + + prctl(PR_SET_NAME, (unsigned long)"sound trigger callback", 0, 0, 0); + + pthread_mutex_lock(&tuner->lock); + + while (true) { + struct thread_command *cmd = NULL; + struct listnode *item; + struct listnode *tmp; + struct timespec cur_ts; + bool got_cancel = false; + bool send_meta_data = false; + + if (list_empty(&tuner->command_list) || ts.tv_sec != 0) { + ALOGV("%s SLEEPING", __func__); + if (ts.tv_sec != 0) { + ALOGV("%s SLEEPING with timeout", __func__); + pthread_cond_timedwait(&tuner->cond, &tuner->lock, &ts); + } else { + ALOGV("%s SLEEPING forever", __func__); + pthread_cond_wait(&tuner->cond, &tuner->lock); + } + ts.tv_sec = 0; + ALOGV("%s RUNNING", __func__); + } + + clock_gettime(CLOCK_REALTIME, &cur_ts); + + list_for_each_safe(item, tmp, &tuner->command_list) { + cmd = node_to_item(item, struct thread_command, node); + + if (got_cancel && (cmd->type == CMD_STEP || cmd->type == CMD_SCAN || + cmd->type == CMD_TUNE || cmd->type == CMD_METADATA)) { + list_remove(item); + free(cmd); + continue; + } + + if ((cmd->ts.tv_sec < cur_ts.tv_sec) || + ((cmd->ts.tv_sec == cur_ts.tv_sec) && (cmd->ts.tv_nsec < cur_ts.tv_nsec))) { + radio_hal_event_t event; + radio_metadata_t *metadata = NULL; + + event.type = RADIO_EVENT_HW_FAILURE; + list_remove(item); + + ALOGV("%s processing command %d time %ld.%ld", __func__, cmd->type, cmd->ts.tv_sec, + cmd->ts.tv_nsec); + + switch (cmd->type) { + default: + case CMD_EXIT: + free(cmd); + goto exit; + + case CMD_CONFIG: { + tuner->config = cmd->config; + event.type = RADIO_EVENT_CONFIG; + event.config = tuner->config; + ALOGV("%s CMD_CONFIG type %d low %d up %d", + __func__, tuner->config.type, + tuner->config.lower_limit, tuner->config.upper_limit); + if (tuner->config.type == RADIO_BAND_FM) { + ALOGV(" - stereo %d\n - rds %d\n - ta %d\n - af %d", + tuner->config.fm.stereo, tuner->config.fm.rds, + tuner->config.fm.ta, tuner->config.fm.af); + } else { + ALOGV(" - stereo %d", tuner->config.am.stereo); + } + } break; + + case CMD_STEP: { + int frequency; + frequency = tuner->program.channel; + if (cmd->param == RADIO_DIRECTION_UP) { + frequency += tuner->config.spacings[0]; + } else { + frequency -= tuner->config.spacings[0]; + } + if (frequency > (int)tuner->config.upper_limit) { + frequency = tuner->config.lower_limit; + } + if (frequency < (int)tuner->config.lower_limit) { + frequency = tuner->config.upper_limit; + } + tuner->program.channel = frequency; + tuner->program.tuned = (frequency / (tuner->config.spacings[0] * 5)) % 2; + tuner->program.signal_strength = 20; + if (tuner->config.type == RADIO_BAND_FM) + tuner->program.stereo = false; + else + tuner->program.stereo = false; + + event.type = RADIO_EVENT_TUNED; + event.info = tuner->program; + } break; + + case CMD_SCAN: { + int frequency; + frequency = tuner->program.channel; + if (cmd->param == RADIO_DIRECTION_UP) { + frequency += tuner->config.spacings[0] * 25; + } else { + frequency -= tuner->config.spacings[0] * 25; + } + if (frequency > (int)tuner->config.upper_limit) { + frequency = tuner->config.lower_limit; + } + if (frequency < (int)tuner->config.lower_limit) { + frequency = tuner->config.upper_limit; + } + tuner->program.channel = (unsigned int)frequency; + tuner->program.tuned = true; + if (tuner->config.type == RADIO_BAND_FM) + tuner->program.stereo = tuner->config.fm.stereo; + else + tuner->program.stereo = tuner->config.am.stereo; + tuner->program.signal_strength = 50; + + event.type = RADIO_EVENT_TUNED; + event.info = tuner->program; + send_meta_data = true; + } break; + + case CMD_TUNE: { + tuner->program.channel = cmd->param; + tuner->program.tuned = (tuner->program.channel / + (tuner->config.spacings[0] * 5)) % 2; + + if (tuner->program.tuned) { + prepare_metadata(tuner, &tuner->program.metadata, true); + send_command_l(tuner, CMD_METADATA, 5000, NULL); + } else { + if (tuner->program.metadata != NULL) + radio_metadata_deallocate(tuner->program.metadata); + tuner->program.metadata = NULL; + } + tuner->program.signal_strength = 100; + if (tuner->config.type == RADIO_BAND_FM) + tuner->program.stereo = + tuner->program.tuned ? tuner->config.fm.stereo : false; + else + tuner->program.stereo = + tuner->program.tuned ? tuner->config.am.stereo : false; + event.type = RADIO_EVENT_TUNED; + event.info = tuner->program; + send_meta_data = true; + } break; + + case CMD_METADATA: { + int ret = prepare_metadata(tuner, &metadata, false); + if (ret == 0) { + event.type = RADIO_EVENT_METADATA; + event.metadata = metadata; + } + send_meta_data = true; + } break; + + case CMD_CANCEL: { + got_cancel = true; + } break; + + } + if (event.type != RADIO_EVENT_HW_FAILURE && tuner->callback != NULL) { + pthread_mutex_unlock(&tuner->lock); + tuner->callback(&event, tuner->cookie); + pthread_mutex_lock(&tuner->lock); + if (event.type == RADIO_EVENT_METADATA && metadata != NULL) { + radio_metadata_deallocate(metadata); + metadata = NULL; + } + } + ALOGV("%s processed command %d", __func__, cmd->type); + free(cmd); + } else { + if ((ts.tv_sec == 0) || + (cmd->ts.tv_sec < ts.tv_sec) || + ((cmd->ts.tv_sec == ts.tv_sec) && (cmd->ts.tv_nsec < ts.tv_nsec))) { + ts.tv_sec = cmd->ts.tv_sec; + ts.tv_nsec = cmd->ts.tv_nsec; + } + } + } + + if (send_meta_data) { + list_for_each_safe(item, tmp, &tuner->command_list) { + cmd = node_to_item(item, struct thread_command, node); + if (cmd->type == CMD_METADATA) { + list_remove(item); + free(cmd); + } + } + send_command_l(tuner, CMD_METADATA, 100, NULL); + } + } + +exit: + pthread_mutex_unlock(&tuner->lock); + + ALOGV("%s Exiting", __func__); + + return NULL; +} + + +static int tuner_set_configuration(const struct radio_tuner *tuner, + const radio_hal_band_config_t *config) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + int status = 0; + + ALOGI("%s stub_tuner %p", __func__, stub_tuner); + pthread_mutex_lock(&stub_tuner->lock); + if (config == NULL) { + status = -EINVAL; + goto exit; + } + send_command_l(stub_tuner, CMD_CANCEL, 0, NULL); + send_command_l(stub_tuner, CMD_CONFIG, 500, (void *)config); + +exit: + pthread_mutex_unlock(&stub_tuner->lock); + return status; +} + +static int tuner_get_configuration(const struct radio_tuner *tuner, + radio_hal_band_config_t *config) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + int status = 0; + struct listnode *item; + radio_hal_band_config_t *src_config; + + ALOGI("%s stub_tuner %p", __func__, stub_tuner); + pthread_mutex_lock(&stub_tuner->lock); + src_config = &stub_tuner->config; + + if (config == NULL) { + status = -EINVAL; + goto exit; + } + list_for_each(item, &stub_tuner->command_list) { + struct thread_command *cmd = node_to_item(item, struct thread_command, node); + if (cmd->type == CMD_CONFIG) { + src_config = &cmd->config; + } + } + *config = *src_config; + +exit: + pthread_mutex_unlock(&stub_tuner->lock); + return status; +} + +static int tuner_step(const struct radio_tuner *tuner, + radio_direction_t direction, bool skip_sub_channel) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + + ALOGI("%s stub_tuner %p direction %d, skip_sub_channel %d", + __func__, stub_tuner, direction, skip_sub_channel); + + pthread_mutex_lock(&stub_tuner->lock); + send_command_l(stub_tuner, CMD_STEP, 20, &direction); + pthread_mutex_unlock(&stub_tuner->lock); + return 0; +} + +static int tuner_scan(const struct radio_tuner *tuner, + radio_direction_t direction, bool skip_sub_channel) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + + ALOGI("%s stub_tuner %p direction %d, skip_sub_channel %d", + __func__, stub_tuner, direction, skip_sub_channel); + + pthread_mutex_lock(&stub_tuner->lock); + send_command_l(stub_tuner, CMD_SCAN, 200, &direction); + pthread_mutex_unlock(&stub_tuner->lock); + return 0; +} + +static int tuner_tune(const struct radio_tuner *tuner, + unsigned int channel, unsigned int sub_channel) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + + ALOGI("%s stub_tuner %p channel %d, sub_channel %d", + __func__, stub_tuner, channel, sub_channel); + + pthread_mutex_lock(&stub_tuner->lock); + if (channel < stub_tuner->config.lower_limit || channel > stub_tuner->config.upper_limit) { + pthread_mutex_unlock(&stub_tuner->lock); + ALOGI("%s channel out of range", __func__); + return -EINVAL; + } + send_command_l(stub_tuner, CMD_TUNE, 100, &channel); + pthread_mutex_unlock(&stub_tuner->lock); + return 0; +} + +static int tuner_cancel(const struct radio_tuner *tuner) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + + ALOGI("%s stub_tuner %p", __func__, stub_tuner); + + pthread_mutex_lock(&stub_tuner->lock); + send_command_l(stub_tuner, CMD_CANCEL, 0, NULL); + pthread_mutex_unlock(&stub_tuner->lock); + return 0; +} + +static int tuner_get_program_information(const struct radio_tuner *tuner, + radio_program_info_t *info) +{ + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + int status = 0; + radio_metadata_t *metadata; + + ALOGI("%s stub_tuner %p", __func__, stub_tuner); + pthread_mutex_lock(&stub_tuner->lock); + if (info == NULL) { + status = -EINVAL; + goto exit; + } + metadata = info->metadata; + *info = stub_tuner->program; + info->metadata = metadata; + if (metadata != NULL && stub_tuner->program.metadata != NULL) + radio_metadata_add_metadata(&info->metadata, stub_tuner->program.metadata); + +exit: + pthread_mutex_unlock(&stub_tuner->lock); + return status; +} + +static int rdev_get_properties(const struct radio_hw_device *dev, + radio_hal_properties_t *properties) +{ + struct stub_radio_device *rdev = (struct stub_radio_device *)dev; + + ALOGI("%s", __func__); + if (properties == NULL) + return -EINVAL; + memcpy(properties, &hw_properties, sizeof(radio_hal_properties_t)); + return 0; +} + +static int rdev_open_tuner(const struct radio_hw_device *dev, + const radio_hal_band_config_t *config, + bool audio, + radio_callback_t callback, + void *cookie, + const struct radio_tuner **tuner) +{ + struct stub_radio_device *rdev = (struct stub_radio_device *)dev; + int status = 0; + + ALOGI("%s rdev %p", __func__, rdev); + pthread_mutex_lock(&rdev->lock); + + if (rdev->tuner != NULL) { + status = -ENOSYS; + goto exit; + } + + if (config == NULL || callback == NULL || tuner == NULL) { + status = -EINVAL; + goto exit; + } + + rdev->tuner = (struct stub_radio_tuner *)calloc(1, sizeof(struct stub_radio_tuner)); + if (rdev->tuner == NULL) { + status = -ENOMEM; + goto exit; + } + + rdev->tuner->interface.set_configuration = tuner_set_configuration; + rdev->tuner->interface.get_configuration = tuner_get_configuration; + rdev->tuner->interface.scan = tuner_scan; + rdev->tuner->interface.step = tuner_step; + rdev->tuner->interface.tune = tuner_tune; + rdev->tuner->interface.cancel = tuner_cancel; + rdev->tuner->interface.get_program_information = tuner_get_program_information; + + rdev->tuner->audio = audio; + rdev->tuner->callback = callback; + rdev->tuner->cookie = cookie; + + rdev->tuner->dev = rdev; + + pthread_mutex_init(&rdev->tuner->lock, (const pthread_mutexattr_t *) NULL); + pthread_cond_init(&rdev->tuner->cond, (const pthread_condattr_t *) NULL); + pthread_create(&rdev->tuner->callback_thread, (const pthread_attr_t *) NULL, + callback_thread_loop, rdev->tuner); + list_init(&rdev->tuner->command_list); + + pthread_mutex_lock(&rdev->tuner->lock); + send_command_l(rdev->tuner, CMD_CONFIG, 500, (void *)config); + pthread_mutex_unlock(&rdev->tuner->lock); + + *tuner = &rdev->tuner->interface; + +exit: + pthread_mutex_unlock(&rdev->lock); + ALOGI("%s DONE", __func__); + return status; +} + +static int rdev_close_tuner(const struct radio_hw_device *dev, + const struct radio_tuner *tuner) +{ + struct stub_radio_device *rdev = (struct stub_radio_device *)dev; + struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner; + int status = 0; + + ALOGI("%s tuner %p", __func__, tuner); + pthread_mutex_lock(&rdev->lock); + + if (tuner == NULL) { + status = -EINVAL; + goto exit; + } + + pthread_mutex_lock(&stub_tuner->lock); + stub_tuner->callback = NULL; + send_command_l(stub_tuner, CMD_EXIT, 0, NULL); + pthread_mutex_unlock(&stub_tuner->lock); + pthread_join(stub_tuner->callback_thread, (void **) NULL); + + if (stub_tuner->program.metadata != NULL) + radio_metadata_deallocate(stub_tuner->program.metadata); + + free(stub_tuner); + rdev->tuner = NULL; + +exit: + pthread_mutex_unlock(&rdev->lock); + return status; +} + +static int rdev_close(hw_device_t *device) +{ + struct stub_radio_device *rdev = (struct stub_radio_device *)device; + if (rdev != NULL) { + free(rdev->tuner); + } + free(rdev); + return 0; +} + +static int rdev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + struct stub_radio_device *rdev; + int ret; + + if (strcmp(name, RADIO_HARDWARE_DEVICE) != 0) + return -EINVAL; + + rdev = calloc(1, sizeof(struct stub_radio_device)); + if (!rdev) + return -ENOMEM; + + rdev->device.common.tag = HARDWARE_DEVICE_TAG; + rdev->device.common.version = RADIO_DEVICE_API_VERSION_1_0; + rdev->device.common.module = (struct hw_module_t *) module; + rdev->device.common.close = rdev_close; + rdev->device.get_properties = rdev_get_properties; + rdev->device.open_tuner = rdev_open_tuner; + rdev->device.close_tuner = rdev_close_tuner; + + pthread_mutex_init(&rdev->lock, (const pthread_mutexattr_t *) NULL); + + *device = &rdev->device.common; + + return 0; +} + + +static struct hw_module_methods_t hal_module_methods = { + .open = rdev_open, +}; + +struct radio_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = RADIO_MODULE_API_VERSION_1_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = RADIO_HARDWARE_MODULE_ID, + .name = "Stub radio HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +};
diff --git a/libhardware/modules/sensors/Android.mk b/libhardware/modules/sensors/Android.mk new file mode 100644 index 0000000..bf377c9 --- /dev/null +++ b/libhardware/modules/sensors/Android.mk
@@ -0,0 +1,45 @@ +# +# Copyright (C) 2013 The Android Open-Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +ifeq ($(USE_SENSOR_MULTI_HAL),true) + +include $(CLEAR_VARS) + +LOCAL_MODULE := sensors.$(TARGET_BOARD_PLATFORM) + +LOCAL_MODULE_RELATIVE_PATH := hw + +LOCAL_CFLAGS := -DLOG_TAG=\"MultiHal\" + +LOCAL_SRC_FILES := \ + multihal.cpp \ + SensorEventQueue.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libdl \ + liblog \ + libutils \ + +LOCAL_STRIP_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +endif # USE_SENSOR_MULTI_HAL + +include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/libhardware/modules/sensors/SensorEventQueue.cpp b/libhardware/modules/sensors/SensorEventQueue.cpp new file mode 100644 index 0000000..f6144f8 --- /dev/null +++ b/libhardware/modules/sensors/SensorEventQueue.cpp
@@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 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 <hardware/sensors.h> +#include <algorithm> +#include <pthread.h> +#include <cutils/log.h> + +#include "SensorEventQueue.h" + +SensorEventQueue::SensorEventQueue(int capacity) { + mCapacity = capacity; + + mStart = 0; + mSize = 0; + mData = new sensors_event_t[mCapacity]; + pthread_cond_init(&mSpaceAvailableCondition, NULL); +} + +SensorEventQueue::~SensorEventQueue() { + delete[] mData; + mData = NULL; + pthread_cond_destroy(&mSpaceAvailableCondition); +} + +int SensorEventQueue::getWritableRegion(int requestedLength, sensors_event_t** out) { + if (mSize == mCapacity || requestedLength <= 0) { + *out = NULL; + return 0; + } + // Start writing after the last readable record. + int firstWritable = (mStart + mSize) % mCapacity; + + int lastWritable = firstWritable + requestedLength - 1; + + // Don't go past the end of the data array. + if (lastWritable > mCapacity - 1) { + lastWritable = mCapacity - 1; + } + // Don't go into the readable region. + if (firstWritable < mStart && lastWritable >= mStart) { + lastWritable = mStart - 1; + } + *out = &mData[firstWritable]; + return lastWritable - firstWritable + 1; +} + +void SensorEventQueue::markAsWritten(int count) { + mSize += count; +} + +int SensorEventQueue::getSize() { + return mSize; +} + +sensors_event_t* SensorEventQueue::peek() { + if (mSize == 0) return NULL; + return &mData[mStart]; +} + +void SensorEventQueue::dequeue() { + if (mSize == 0) return; + if (mSize == mCapacity) { + pthread_cond_broadcast(&mSpaceAvailableCondition); + } + mSize--; + mStart = (mStart + 1) % mCapacity; +} + +// returns true if it waited, or false if it was a no-op. +bool SensorEventQueue::waitForSpace(pthread_mutex_t* mutex) { + bool waited = false; + while (mSize == mCapacity) { + waited = true; + pthread_cond_wait(&mSpaceAvailableCondition, mutex); + } + return waited; +}
diff --git a/libhardware/modules/sensors/SensorEventQueue.h b/libhardware/modules/sensors/SensorEventQueue.h new file mode 100644 index 0000000..9778e93 --- /dev/null +++ b/libhardware/modules/sensors/SensorEventQueue.h
@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 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 SENSOREVENTQUEUE_H_ +#define SENSOREVENTQUEUE_H_ + +#include <hardware/sensors.h> +#include <pthread.h> + +/* + * Fixed-size circular queue, with an API developed around the sensor HAL poll() method. + * Poll() takes a pointer to a buffer, which is written by poll() before it returns. + * This class can provide a pointer to a spot in its internal buffer for poll() to + * write to, instead of using an intermediate buffer and a memcpy. + * + * Thread safety: + * Reading can be done safely after grabbing the mutex lock, while poll() writing in a separate + * thread without a mutex lock. But there can only be one writer at a time. + */ +class SensorEventQueue { + int mCapacity; + int mStart; // start of readable region + int mSize; // number of readable items + sensors_event_t* mData; + pthread_cond_t mSpaceAvailableCondition; + +public: + explicit SensorEventQueue(int capacity); + ~SensorEventQueue(); + + // Returns length of region, between zero and min(capacity, requestedLength). If there is any + // writable space, it will return a region of at least one. Because it must return + // a pointer to a contiguous region, it may return smaller regions as we approach the end of + // the data array. + // Only call while holding the lock. + // The region is not marked internally in any way. Subsequent calls may return overlapping + // regions. This class expects there to be exactly one writer at a time. + int getWritableRegion(int requestedLength, sensors_event_t** out); + + // After writing to the region returned by getWritableRegion(), call this to indicate how + // many records were actually written. + // This increases size() by count. + // Only call while holding the lock. + void markAsWritten(int count); + + // Gets the number of readable records. + // Only call while holding the lock. + int getSize(); + + // Returns pointer to the first readable record, or NULL if size() is zero. + // Only call this while holding the lock. + sensors_event_t* peek(); + + // This will decrease the size by one, freeing up the oldest readable event's slot for writing. + // Only call while holding the lock. + void dequeue(); + + // Blocks until space is available. No-op if there is already space. + // Returns true if it had to wait. + bool waitForSpace(pthread_mutex_t* mutex); +}; + +#endif // SENSOREVENTQUEUE_H_
diff --git a/libhardware/modules/sensors/multihal.cpp b/libhardware/modules/sensors/multihal.cpp new file mode 100644 index 0000000..8330ff3 --- /dev/null +++ b/libhardware/modules/sensors/multihal.cpp
@@ -0,0 +1,668 @@ +/* + * Copyright (C) 2013 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 <hardware/sensors.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <math.h> +#include <poll.h> +#include <pthread.h> +#include <cutils/atomic.h> + +#define LOG_NDEBUG 1 +#include <cutils/log.h> + +#include <vector> +#include <string> +#include <fstream> +#include <map> +#include <string> + +#include <stdio.h> +#include <dlfcn.h> +#include <SensorEventQueue.h> + +#include <limits.h> +#include <stdlib.h> + +static const char* CONFIG_FILENAME = "/system/etc/sensors/hals.conf"; +static const int MAX_CONF_LINE_LENGTH = 1024; + +static pthread_mutex_t init_modules_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t init_sensors_mutex = PTHREAD_MUTEX_INITIALIZER; + +// This mutex is shared by all queues +static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; + +// Used to pause the multihal poll(). Broadcasted by sub-polling tasks if waiting_for_data. +static pthread_cond_t data_available_cond = PTHREAD_COND_INITIALIZER; +bool waiting_for_data = false; + +/* + * Vector of sub modules, whose indexes are referred to in this file as module_index. + */ +static std::vector<hw_module_t *> *sub_hw_modules = NULL; + +/* + * Comparable class that globally identifies a sensor, by module index and local handle. + * A module index is the module's index in sub_hw_modules. + * A local handle is the handle the sub-module assigns to a sensor. + */ +struct FullHandle { + int moduleIndex; + int localHandle; + + bool operator<(const FullHandle &that) const { + if (moduleIndex < that.moduleIndex) { + return true; + } + if (moduleIndex > that.moduleIndex) { + return false; + } + return localHandle < that.localHandle; + } + + bool operator==(const FullHandle &that) const { + return moduleIndex == that.moduleIndex && localHandle == that.localHandle; + } +}; + +std::map<int, FullHandle> global_to_full; +std::map<FullHandle, int> full_to_global; +int next_global_handle = 1; + +static int assign_global_handle(int module_index, int local_handle) { + int global_handle = next_global_handle++; + FullHandle full_handle; + full_handle.moduleIndex = module_index; + full_handle.localHandle = local_handle; + full_to_global[full_handle] = global_handle; + global_to_full[global_handle] = full_handle; + return global_handle; +} + +// Returns the local handle, or -1 if it does not exist. +static int get_local_handle(int global_handle) { + if (global_to_full.count(global_handle) == 0) { + ALOGW("Unknown global_handle %d", global_handle); + return -1; + } + return global_to_full[global_handle].localHandle; +} + +// Returns the sub_hw_modules index of the module that contains the sensor associates with this +// global_handle, or -1 if that global_handle does not exist. +static int get_module_index(int global_handle) { + if (global_to_full.count(global_handle) == 0) { + ALOGW("Unknown global_handle %d", global_handle); + return -1; + } + FullHandle f = global_to_full[global_handle]; + ALOGV("FullHandle for global_handle %d: moduleIndex %d, localHandle %d", + global_handle, f.moduleIndex, f.localHandle); + return f.moduleIndex; +} + +// Returns the global handle for this full_handle, or -1 if the full_handle is unknown. +static int get_global_handle(FullHandle* full_handle) { + int global_handle = -1; + if (full_to_global.count(*full_handle)) { + global_handle = full_to_global[*full_handle]; + } else { + ALOGW("Unknown FullHandle: moduleIndex %d, localHandle %d", + full_handle->moduleIndex, full_handle->localHandle); + } + return global_handle; +} + +static const int SENSOR_EVENT_QUEUE_CAPACITY = 20; + +struct TaskContext { + sensors_poll_device_t* device; + SensorEventQueue* queue; +}; + +void *writerTask(void* ptr) { + ALOGV("writerTask STARTS"); + TaskContext* ctx = (TaskContext*)ptr; + sensors_poll_device_t* device = ctx->device; + SensorEventQueue* queue = ctx->queue; + sensors_event_t* buffer; + int eventsPolled; + while (1) { + pthread_mutex_lock(&queue_mutex); + if (queue->waitForSpace(&queue_mutex)) { + ALOGV("writerTask waited for space"); + } + int bufferSize = queue->getWritableRegion(SENSOR_EVENT_QUEUE_CAPACITY, &buffer); + // Do blocking poll outside of lock + pthread_mutex_unlock(&queue_mutex); + + ALOGV("writerTask before poll() - bufferSize = %d", bufferSize); + eventsPolled = device->poll(device, buffer, bufferSize); + ALOGV("writerTask poll() got %d events.", eventsPolled); + if (eventsPolled == 0) { + continue; + } + pthread_mutex_lock(&queue_mutex); + queue->markAsWritten(eventsPolled); + ALOGV("writerTask wrote %d events", eventsPolled); + if (waiting_for_data) { + ALOGV("writerTask - broadcast data_available_cond"); + pthread_cond_broadcast(&data_available_cond); + } + pthread_mutex_unlock(&queue_mutex); + } + // never actually returns + return NULL; +} + +/* + * Cache of all sensors, with original handles replaced by global handles. + * This will be handled to get_sensors_list() callers. + */ +static struct sensor_t const* global_sensors_list = NULL; +static int global_sensors_count = -1; + +/* + * Extends a sensors_poll_device_1 by including all the sub-module's devices. + */ +struct sensors_poll_context_t { + /* + * This is the device that SensorDevice.cpp uses to make API calls + * to the multihal, which fans them out to sub-HALs. + */ + sensors_poll_device_1 proxy_device; // must be first + + void addSubHwDevice(struct hw_device_t*); + + int activate(int handle, int enabled); + int setDelay(int handle, int64_t ns); + int poll(sensors_event_t* data, int count); + int batch(int handle, int flags, int64_t period_ns, int64_t timeout); + int flush(int handle); + int close(); + + std::vector<hw_device_t*> sub_hw_devices; + std::vector<SensorEventQueue*> queues; + std::vector<pthread_t> threads; + int nextReadIndex; + + sensors_poll_device_t* get_v0_device_by_handle(int global_handle); + sensors_poll_device_1_t* get_v1_device_by_handle(int global_handle); + int get_device_version_by_handle(int global_handle); + + void copy_event_remap_handle(sensors_event_t* src, sensors_event_t* dest, int sub_index); +}; + +void sensors_poll_context_t::addSubHwDevice(struct hw_device_t* sub_hw_device) { + ALOGV("addSubHwDevice"); + this->sub_hw_devices.push_back(sub_hw_device); + + SensorEventQueue *queue = new SensorEventQueue(SENSOR_EVENT_QUEUE_CAPACITY); + this->queues.push_back(queue); + + TaskContext* taskContext = new TaskContext(); + taskContext->device = (sensors_poll_device_t*) sub_hw_device; + taskContext->queue = queue; + + pthread_t writerThread; + pthread_create(&writerThread, NULL, writerTask, taskContext); + this->threads.push_back(writerThread); +} + +// Returns the device pointer, or NULL if the global handle is invalid. +sensors_poll_device_t* sensors_poll_context_t::get_v0_device_by_handle(int global_handle) { + int sub_index = get_module_index(global_handle); + if (sub_index < 0 || sub_index >= this->sub_hw_devices.size()) { + return NULL; + } + return (sensors_poll_device_t*) this->sub_hw_devices[sub_index]; +} + +// Returns the device pointer, or NULL if the global handle is invalid. +sensors_poll_device_1_t* sensors_poll_context_t::get_v1_device_by_handle(int global_handle) { + int sub_index = get_module_index(global_handle); + if (sub_index < 0 || sub_index >= this->sub_hw_devices.size()) { + return NULL; + } + return (sensors_poll_device_1_t*) this->sub_hw_devices[sub_index]; +} + +// Returns the device version, or -1 if the handle is invalid. +int sensors_poll_context_t::get_device_version_by_handle(int handle) { + sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle); + if (v0) { + return v0->common.version; + } else { + return -1; + } +} + +// Android L requires sensor HALs to be either 1_0 or 1_3 compliant +#define HAL_VERSION_IS_COMPLIANT(version) \ + (version == SENSORS_DEVICE_API_VERSION_1_0 || version >= SENSORS_DEVICE_API_VERSION_1_3) + +// Returns true if HAL is compliant, false if HAL is not compliant or if handle is invalid +static bool halIsCompliant(sensors_poll_context_t *ctx, int handle) { + int version = ctx->get_device_version_by_handle(handle); + return version != -1 && HAL_VERSION_IS_COMPLIANT(version); +} + +const char *apiNumToStr(int version) { + switch(version) { + case SENSORS_DEVICE_API_VERSION_1_0: + return "SENSORS_DEVICE_API_VERSION_1_0"; + case SENSORS_DEVICE_API_VERSION_1_1: + return "SENSORS_DEVICE_API_VERSION_1_1"; + case SENSORS_DEVICE_API_VERSION_1_2: + return "SENSORS_DEVICE_API_VERSION_1_2"; + case SENSORS_DEVICE_API_VERSION_1_3: + return "SENSORS_DEVICE_API_VERSION_1_3"; + default: + return "UNKNOWN"; + } +} + +int sensors_poll_context_t::activate(int handle, int enabled) { + int retval = -EINVAL; + ALOGV("activate"); + int local_handle = get_local_handle(handle); + sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle); + if (halIsCompliant(this, handle) && local_handle >= 0 && v0) { + retval = v0->activate(v0, local_handle, enabled); + } else { + ALOGE("IGNORING activate(enable %d) call to non-API-compliant sensor handle=%d !", + enabled, handle); + } + ALOGV("retval %d", retval); + return retval; +} + +int sensors_poll_context_t::setDelay(int handle, int64_t ns) { + int retval = -EINVAL; + ALOGV("setDelay"); + int local_handle = get_local_handle(handle); + sensors_poll_device_t* v0 = this->get_v0_device_by_handle(handle); + if (halIsCompliant(this, handle) && local_handle >= 0 && v0) { + retval = v0->setDelay(v0, local_handle, ns); + } else { + ALOGE("IGNORING setDelay() call for non-API-compliant sensor handle=%d !", handle); + } + ALOGV("retval %d", retval); + return retval; +} + +void sensors_poll_context_t::copy_event_remap_handle(sensors_event_t* dest, sensors_event_t* src, + int sub_index) { + memcpy(dest, src, sizeof(struct sensors_event_t)); + // A normal event's "sensor" field is a local handle. Convert it to a global handle. + // A meta-data event must have its sensor set to 0, but it has a nested event + // with a local handle that needs to be converted to a global handle. + FullHandle full_handle; + full_handle.moduleIndex = sub_index; + + // If it's a metadata event, rewrite the inner payload, not the sensor field. + // If the event's sensor field is unregistered for any reason, rewrite the sensor field + // with a -1, instead of writing an incorrect but plausible sensor number, because + // get_global_handle() returns -1 for unknown FullHandles. + if (dest->type == SENSOR_TYPE_META_DATA) { + full_handle.localHandle = dest->meta_data.sensor; + dest->meta_data.sensor = get_global_handle(&full_handle); + } else { + full_handle.localHandle = dest->sensor; + dest->sensor = get_global_handle(&full_handle); + } +} + +int sensors_poll_context_t::poll(sensors_event_t *data, int maxReads) { + ALOGV("poll"); + int empties = 0; + int queueCount = 0; + int eventsRead = 0; + + pthread_mutex_lock(&queue_mutex); + queueCount = (int)this->queues.size(); + while (eventsRead == 0) { + while (empties < queueCount && eventsRead < maxReads) { + SensorEventQueue* queue = this->queues.at(this->nextReadIndex); + sensors_event_t* event = queue->peek(); + if (event == NULL) { + empties++; + } else { + empties = 0; + this->copy_event_remap_handle(&data[eventsRead], event, nextReadIndex); + if (data[eventsRead].sensor == -1) { + // Bad handle, do not pass corrupted event upstream ! + ALOGW("Dropping bad local handle event packet on the floor"); + } else { + eventsRead++; + } + queue->dequeue(); + } + this->nextReadIndex = (this->nextReadIndex + 1) % queueCount; + } + if (eventsRead == 0) { + // The queues have been scanned and none contain data, so wait. + ALOGV("poll stopping to wait for data"); + waiting_for_data = true; + pthread_cond_wait(&data_available_cond, &queue_mutex); + waiting_for_data = false; + empties = 0; + } + } + pthread_mutex_unlock(&queue_mutex); + ALOGV("poll returning %d events.", eventsRead); + + return eventsRead; +} + +int sensors_poll_context_t::batch(int handle, int flags, int64_t period_ns, int64_t timeout) { + ALOGV("batch"); + int retval = -EINVAL; + int local_handle = get_local_handle(handle); + sensors_poll_device_1_t* v1 = this->get_v1_device_by_handle(handle); + if (halIsCompliant(this, handle) && local_handle >= 0 && v1) { + retval = v1->batch(v1, local_handle, flags, period_ns, timeout); + } else { + ALOGE("IGNORING batch() call to non-API-compliant sensor handle=%d !", handle); + } + ALOGV("retval %d", retval); + return retval; +} + +int sensors_poll_context_t::flush(int handle) { + ALOGV("flush"); + int retval = -EINVAL; + int local_handle = get_local_handle(handle); + sensors_poll_device_1_t* v1 = this->get_v1_device_by_handle(handle); + if (halIsCompliant(this, handle) && local_handle >= 0 && v1) { + retval = v1->flush(v1, local_handle); + } else { + ALOGE("IGNORING flush() call to non-API-compliant sensor handle=%d !", handle); + } + ALOGV("retval %d", retval); + return retval; +} + +int sensors_poll_context_t::close() { + ALOGV("close"); + for (std::vector<hw_device_t*>::iterator it = this->sub_hw_devices.begin(); + it != this->sub_hw_devices.end(); it++) { + hw_device_t* dev = *it; + int retval = dev->close(dev); + ALOGV("retval %d", retval); + } + return 0; +} + + +static int device__close(struct hw_device_t *dev) { + sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev; + if (ctx != NULL) { + int retval = ctx->close(); + delete ctx; + } + return 0; +} + +static int device__activate(struct sensors_poll_device_t *dev, int handle, + int enabled) { + sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev; + return ctx->activate(handle, enabled); +} + +static int device__setDelay(struct sensors_poll_device_t *dev, int handle, + int64_t ns) { + sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev; + return ctx->setDelay(handle, ns); +} + +static int device__poll(struct sensors_poll_device_t *dev, sensors_event_t* data, + int count) { + sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev; + return ctx->poll(data, count); +} + +static int device__batch(struct sensors_poll_device_1 *dev, int handle, + int flags, int64_t period_ns, int64_t timeout) { + sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev; + return ctx->batch(handle, flags, period_ns, timeout); +} + +static int device__flush(struct sensors_poll_device_1 *dev, int handle) { + sensors_poll_context_t* ctx = (sensors_poll_context_t*) dev; + return ctx->flush(handle); +} + +static int open_sensors(const struct hw_module_t* module, const char* name, + struct hw_device_t** device); + +static bool starts_with(const char* s, const char* prefix) { + if (s == NULL || prefix == NULL) { + return false; + } + size_t s_size = strlen(s); + size_t prefix_size = strlen(prefix); + return s_size >= prefix_size && strncmp(s, prefix, prefix_size) == 0; +} + +/* + * Adds valid paths from the config file to the vector passed in. + * The vector must not be null. + */ +static void get_so_paths(std::vector<std::string> *so_paths) { + std::string line; + std::ifstream conf_file(CONFIG_FILENAME); + + if(!conf_file) { + ALOGW("No multihal config file found at %s", CONFIG_FILENAME); + return; + } + ALOGV("Multihal config file found at %s", CONFIG_FILENAME); + while (std::getline(conf_file, line)) { + ALOGV("config file line: '%s'", line.c_str()); + so_paths->push_back(line); + } +} + +/* + * Ensures that the sub-module array is initialized. + * This can be first called from get_sensors_list or from open_sensors. + */ +static void lazy_init_modules() { + pthread_mutex_lock(&init_modules_mutex); + if (sub_hw_modules != NULL) { + pthread_mutex_unlock(&init_modules_mutex); + return; + } + std::vector<std::string> *so_paths = new std::vector<std::string>(); + get_so_paths(so_paths); + + // dlopen the module files and cache their module symbols in sub_hw_modules + sub_hw_modules = new std::vector<hw_module_t *>(); + dlerror(); // clear any old errors + const char* sym = HAL_MODULE_INFO_SYM_AS_STR; + for (std::vector<std::string>::iterator it = so_paths->begin(); it != so_paths->end(); it++) { + const char* path = it->c_str(); + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle == NULL) { + ALOGW("dlerror(): %s", dlerror()); + } else { + ALOGI("Loaded library from %s", path); + ALOGV("Opening symbol \"%s\"", sym); + // clear old errors + dlerror(); + struct hw_module_t* module = (hw_module_t*) dlsym(lib_handle, sym); + const char* error; + if ((error = dlerror()) != NULL) { + ALOGW("Error calling dlsym: %s", error); + } else if (module == NULL) { + ALOGW("module == NULL"); + } else { + ALOGV("Loaded symbols from \"%s\"", sym); + sub_hw_modules->push_back(module); + } + } + } + pthread_mutex_unlock(&init_modules_mutex); +} + +/* + * Lazy-initializes global_sensors_count, global_sensors_list, and module_sensor_handles. + */ +static void lazy_init_sensors_list() { + ALOGV("lazy_init_sensors_list"); + pthread_mutex_lock(&init_sensors_mutex); + if (global_sensors_list != NULL) { + // already initialized + pthread_mutex_unlock(&init_sensors_mutex); + ALOGV("lazy_init_sensors_list - early return"); + return; + } + + ALOGV("lazy_init_sensors_list needs to do work"); + lazy_init_modules(); + + // Count all the sensors, then allocate an array of blanks. + global_sensors_count = 0; + const struct sensor_t *subhal_sensors_list; + for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin(); + it != sub_hw_modules->end(); it++) { + struct sensors_module_t *module = (struct sensors_module_t*) *it; + global_sensors_count += module->get_sensors_list(module, &subhal_sensors_list); + ALOGV("increased global_sensors_count to %d", global_sensors_count); + } + + // The global_sensors_list is full of consts. + // Manipulate this non-const list, and point the const one to it when we're done. + sensor_t* mutable_sensor_list = new sensor_t[global_sensors_count]; + + // index of the next sensor to set in mutable_sensor_list + int mutable_sensor_index = 0; + int module_index = 0; + + for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin(); + it != sub_hw_modules->end(); it++) { + hw_module_t *hw_module = *it; + ALOGV("examine one module"); + // Read the sub-module's sensor list. + struct sensors_module_t *module = (struct sensors_module_t*) hw_module; + int module_sensor_count = module->get_sensors_list(module, &subhal_sensors_list); + ALOGV("the module has %d sensors", module_sensor_count); + + // Copy the HAL's sensor list into global_sensors_list, + // with the handle changed to be a global handle. + for (int i = 0; i < module_sensor_count; i++) { + ALOGV("examining one sensor"); + const struct sensor_t *local_sensor = &subhal_sensors_list[i]; + int local_handle = local_sensor->handle; + memcpy(&mutable_sensor_list[mutable_sensor_index], local_sensor, + sizeof(struct sensor_t)); + + // Overwrite the global version's handle with a global handle. + int global_handle = assign_global_handle(module_index, local_handle); + + mutable_sensor_list[mutable_sensor_index].handle = global_handle; + ALOGV("module_index %d, local_handle %d, global_handle %d", + module_index, local_handle, global_handle); + + mutable_sensor_index++; + } + module_index++; + } + // Set the const static global_sensors_list to the mutable one allocated by this function. + global_sensors_list = mutable_sensor_list; + + pthread_mutex_unlock(&init_sensors_mutex); + ALOGV("end lazy_init_sensors_list"); +} + +static int module__get_sensors_list(__unused struct sensors_module_t* module, + struct sensor_t const** list) { + ALOGV("module__get_sensors_list start"); + lazy_init_sensors_list(); + *list = global_sensors_list; + ALOGV("global_sensors_count: %d", global_sensors_count); + for (int i = 0; i < global_sensors_count; i++) { + ALOGV("sensor type: %d", global_sensors_list[i].type); + } + return global_sensors_count; +} + +static struct hw_module_methods_t sensors_module_methods = { + open : open_sensors +}; + +struct sensors_module_t HAL_MODULE_INFO_SYM = { + common :{ + tag : HARDWARE_MODULE_TAG, + version_major : 1, + version_minor : 1, + id : SENSORS_HARDWARE_MODULE_ID, + name : "MultiHal Sensor Module", + author : "Google, Inc", + methods : &sensors_module_methods, + dso : NULL, + reserved : {0}, + }, + get_sensors_list : module__get_sensors_list +}; + +static int open_sensors(const struct hw_module_t* hw_module, const char* name, + struct hw_device_t** hw_device_out) { + ALOGV("open_sensors begin..."); + + lazy_init_modules(); + + // Create proxy device, to return later. + sensors_poll_context_t *dev = new sensors_poll_context_t(); + memset(dev, 0, sizeof(sensors_poll_device_1_t)); + dev->proxy_device.common.tag = HARDWARE_DEVICE_TAG; + dev->proxy_device.common.version = SENSORS_DEVICE_API_VERSION_1_3; + dev->proxy_device.common.module = const_cast<hw_module_t*>(hw_module); + dev->proxy_device.common.close = device__close; + dev->proxy_device.activate = device__activate; + dev->proxy_device.setDelay = device__setDelay; + dev->proxy_device.poll = device__poll; + dev->proxy_device.batch = device__batch; + dev->proxy_device.flush = device__flush; + + dev->nextReadIndex = 0; + + // Open() the subhal modules. Remember their devices in a vector parallel to sub_hw_modules. + for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin(); + it != sub_hw_modules->end(); it++) { + sensors_module_t *sensors_module = (sensors_module_t*) *it; + struct hw_device_t* sub_hw_device; + int sub_open_result = sensors_module->common.methods->open(*it, name, &sub_hw_device); + if (!sub_open_result) { + if (!HAL_VERSION_IS_COMPLIANT(sub_hw_device->version)) { + ALOGE("SENSORS_DEVICE_API_VERSION_1_3 is required for all sensor HALs"); + ALOGE("This HAL reports non-compliant API level : %s", + apiNumToStr(sub_hw_device->version)); + ALOGE("Sensors belonging to this HAL will get ignored !"); + } + dev->addSubHwDevice(sub_hw_device); + } + } + + // Prepare the output param and return + *hw_device_out = &dev->proxy_device.common; + ALOGV("...open_sensors end"); + return 0; +}
diff --git a/libhardware/modules/sensors/tests/Android.mk b/libhardware/modules/sensors/tests/Android.mk new file mode 100644 index 0000000..010bb90 --- /dev/null +++ b/libhardware/modules/sensors/tests/Android.mk
@@ -0,0 +1,17 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + SensorEventQueue_test.cpp + +#LOCAL_CFLAGS := -g +LOCAL_MODULE := sensorstests + +LOCAL_STATIC_LIBRARIES := libcutils libutils + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. bionic + +LOCAL_LDLIBS += -lpthread + +include $(BUILD_HOST_EXECUTABLE)
diff --git a/libhardware/modules/sensors/tests/SensorEventQueue_test.cpp b/libhardware/modules/sensors/tests/SensorEventQueue_test.cpp new file mode 100644 index 0000000..3218bb9 --- /dev/null +++ b/libhardware/modules/sensors/tests/SensorEventQueue_test.cpp
@@ -0,0 +1,199 @@ +#include <stdio.h> +#include <stdlib.h> +#include <hardware/sensors.h> +#include <pthread.h> +#include <cutils/atomic.h> + +#include "SensorEventQueue.cpp" + +// Unit tests for the SensorEventQueue. + +// Run it like this: +// +// make sensorstests -j32 && \ +// out/host/linux-x86/obj/EXECUTABLES/sensorstests_intermediates/sensorstests + +bool checkWritableBufferSize(SensorEventQueue* queue, int requested, int expected) { + sensors_event_t* buffer; + int actual = queue->getWritableRegion(requested, &buffer); + if (actual != expected) { + printf("Expected buffer size was %d; actual was %d\n", expected, actual); + return false; + } + return true; +} + +bool checkSize(SensorEventQueue* queue, int expected) { + int actual = queue->getSize(); + if (actual != expected) { + printf("Expected queue size was %d; actual was %d\n", expected, actual); + return false; + } + return true; +} + +bool checkInt(char* msg, int expected, int actual) { + if (actual != expected) { + printf("%s; expected %d; actual was %d\n", msg, expected, actual); + return false; + } + return true; +} + +bool testSimpleWriteSizeCounts() { + printf("testSimpleWriteSizeCounts\n"); + SensorEventQueue* queue = new SensorEventQueue(10); + if (!checkSize(queue, 0)) return false; + if (!checkWritableBufferSize(queue, 11, 10)) return false; + if (!checkWritableBufferSize(queue, 10, 10)) return false; + if (!checkWritableBufferSize(queue, 9, 9)) return false; + + queue->markAsWritten(7); + if (!checkSize(queue, 7)) return false; + if (!checkWritableBufferSize(queue, 4, 3)) return false; + if (!checkWritableBufferSize(queue, 3, 3)) return false; + if (!checkWritableBufferSize(queue, 2, 2)) return false; + + queue->markAsWritten(3); + if (!checkSize(queue, 10)) return false; + if (!checkWritableBufferSize(queue, 1, 0)) return false; + + printf("passed\n"); + return true; +} + +bool testWrappingWriteSizeCounts() { + printf("testWrappingWriteSizeCounts\n"); + SensorEventQueue* queue = new SensorEventQueue(10); + queue->markAsWritten(9); + if (!checkSize(queue, 9)) return false; + + // dequeue from the front + queue->dequeue(); + queue->dequeue(); + if (!checkSize(queue, 7)) return false; + if (!checkWritableBufferSize(queue, 100, 1)) return false; + + // Write all the way to the end. + queue->markAsWritten(1); + if (!checkSize(queue, 8)) return false; + // Now the two free spots in the front are available. + if (!checkWritableBufferSize(queue, 100, 2)) return false; + + // Fill the queue again + queue->markAsWritten(2); + if (!checkSize(queue, 10)) return false; + + printf("passed\n"); + return true; +} + + + +struct TaskContext { + bool success; + SensorEventQueue* queue; +}; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t dataAvailableCond = PTHREAD_COND_INITIALIZER; + +int FULL_QUEUE_CAPACITY = 5; +int FULL_QUEUE_EVENT_COUNT = 31; + +void *fullQueueWriterTask(void* ptr) { + TaskContext* ctx = (TaskContext*)ptr; + SensorEventQueue* queue = ctx->queue; + ctx->success = true; + int totalWaits = 0; + int totalWrites = 0; + sensors_event_t* buffer; + + while (totalWrites < FULL_QUEUE_EVENT_COUNT) { + pthread_mutex_lock(&mutex); + if (queue->waitForSpace(&mutex)) { + totalWaits++; + printf("."); + } + int writableSize = queue->getWritableRegion(FULL_QUEUE_CAPACITY, &buffer); + queue->markAsWritten(writableSize); + totalWrites += writableSize; + for (int i = 0; i < writableSize; i++) { + printf("w"); + } + pthread_cond_broadcast(&dataAvailableCond); + pthread_mutex_unlock(&mutex); + } + printf("\n"); + + ctx->success = + checkInt("totalWrites", FULL_QUEUE_EVENT_COUNT, totalWrites) && + checkInt("totalWaits", FULL_QUEUE_EVENT_COUNT - FULL_QUEUE_CAPACITY, totalWaits); + return NULL; +} + +bool fullQueueReaderShouldRead(int queueSize, int totalReads) { + if (queueSize == 0) { + return false; + } + int totalWrites = totalReads + queueSize; + return queueSize == FULL_QUEUE_CAPACITY || totalWrites == FULL_QUEUE_EVENT_COUNT; +} + +void* fullQueueReaderTask(void* ptr) { + TaskContext* ctx = (TaskContext*)ptr; + SensorEventQueue* queue = ctx->queue; + int totalReads = 0; + while (totalReads < FULL_QUEUE_EVENT_COUNT) { + pthread_mutex_lock(&mutex); + // Only read if there are events, + // and either the queue is full, or if we're reading the last few events. + while (!fullQueueReaderShouldRead(queue->getSize(), totalReads)) { + pthread_cond_wait(&dataAvailableCond, &mutex); + } + queue->dequeue(); + totalReads++; + printf("r"); + pthread_mutex_unlock(&mutex); + } + printf("\n"); + ctx->success = ctx->success && checkInt("totalreads", FULL_QUEUE_EVENT_COUNT, totalReads); + return NULL; +} + +// Test internal queue-full waiting and broadcasting. +bool testFullQueueIo() { + printf("testFullQueueIo\n"); + SensorEventQueue* queue = new SensorEventQueue(FULL_QUEUE_CAPACITY); + + TaskContext readerCtx; + readerCtx.success = true; + readerCtx.queue = queue; + + TaskContext writerCtx; + writerCtx.success = true; + writerCtx.queue = queue; + + pthread_t writer, reader; + pthread_create(&reader, NULL, fullQueueReaderTask, &readerCtx); + pthread_create(&writer, NULL, fullQueueWriterTask, &writerCtx); + + pthread_join(writer, NULL); + pthread_join(reader, NULL); + + if (!readerCtx.success || !writerCtx.success) return false; + printf("passed\n"); + return true; +} + + +int main(int argc, char **argv) { + if (testSimpleWriteSizeCounts() && + testWrappingWriteSizeCounts() && + testFullQueueIo()) { + printf("ALL PASSED\n"); + } else { + printf("SOMETHING FAILED\n"); + } + return EXIT_SUCCESS; +}
diff --git a/libhardware/modules/soundtrigger/Android.mk b/libhardware/modules/soundtrigger/Android.mk new file mode 100644 index 0000000..325980c --- /dev/null +++ b/libhardware/modules/soundtrigger/Android.mk
@@ -0,0 +1,27 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +# Stub sound_trigger HAL module, used for tests +include $(CLEAR_VARS) + +LOCAL_MODULE := sound_trigger.stub.default +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := sound_trigger_hw.c +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_MODULE_TAGS := optional +LOCAL_32_BIT_ONLY := true + +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/soundtrigger/sound_trigger_hw.c b/libhardware/modules/soundtrigger/sound_trigger_hw.c new file mode 100644 index 0000000..e7f9baf --- /dev/null +++ b/libhardware/modules/soundtrigger/sound_trigger_hw.c
@@ -0,0 +1,296 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "sound_trigger_hw_default" +/*#define LOG_NDEBUG 0*/ + +#include <errno.h> +#include <pthread.h> +#include <sys/prctl.h> +#include <cutils/log.h> + +#include <hardware/hardware.h> +#include <system/sound_trigger.h> +#include <hardware/sound_trigger.h> + +static const struct sound_trigger_properties hw_properties = { + "The Android Open Source Project", // implementor + "Sound Trigger stub HAL", // description + 1, // version + { 0xed7a7d60, 0xc65e, 0x11e3, 0x9be4, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid + 1, // max_sound_models + 1, // max_key_phrases + 1, // max_users + RECOGNITION_MODE_VOICE_TRIGGER, // recognition_modes + false, // capture_transition + 0, // max_buffer_ms + false, // concurrent_capture + false, // trigger_in_event + 0 // power_consumption_mw +}; + +struct stub_sound_trigger_device { + struct sound_trigger_hw_device device; + sound_model_handle_t model_handle; + recognition_callback_t recognition_callback; + void *recognition_cookie; + sound_model_callback_t sound_model_callback; + void *sound_model_cookie; + pthread_t callback_thread; + pthread_mutex_t lock; + pthread_cond_t cond; +}; + + +static void *callback_thread_loop(void *context) +{ + struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)context; + ALOGI("%s", __func__); + + prctl(PR_SET_NAME, (unsigned long)"sound trigger callback", 0, 0, 0); + + pthread_mutex_lock(&stdev->lock); + if (stdev->recognition_callback == NULL) { + goto exit; + } + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 3; + ALOGI("%s wait 3 sec", __func__); + int rc = pthread_cond_timedwait(&stdev->cond, &stdev->lock, &ts); + if (rc == ETIMEDOUT && stdev->recognition_callback != NULL) { + char *data = (char *)calloc(1, sizeof(struct sound_trigger_phrase_recognition_event) + 1); + struct sound_trigger_phrase_recognition_event *event = + (struct sound_trigger_phrase_recognition_event *)data; + event->common.status = RECOGNITION_STATUS_SUCCESS; + event->common.type = SOUND_MODEL_TYPE_KEYPHRASE; + event->common.model = stdev->model_handle; + event->num_phrases = 1; + event->phrase_extras[0].recognition_modes = RECOGNITION_MODE_VOICE_TRIGGER; + event->phrase_extras[0].confidence_level = 100; + event->phrase_extras[0].num_levels = 1; + event->phrase_extras[0].levels[0].level = 100; + event->phrase_extras[0].levels[0].user_id = 0; + event->common.data_offset = sizeof(struct sound_trigger_phrase_recognition_event); + event->common.data_size = 1; + data[event->common.data_offset] = 8; + ALOGI("%s send callback model %d", __func__, stdev->model_handle); + stdev->recognition_callback(&event->common, stdev->recognition_cookie); + free(data); + } else { + ALOGI("%s abort recognition model %d", __func__, stdev->model_handle); + } + stdev->recognition_callback = NULL; + +exit: + pthread_mutex_unlock(&stdev->lock); + + return NULL; +} + +static int stdev_get_properties(const struct sound_trigger_hw_device *dev, + struct sound_trigger_properties *properties) +{ + struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev; + + ALOGI("%s", __func__); + if (properties == NULL) + return -EINVAL; + memcpy(properties, &hw_properties, sizeof(struct sound_trigger_properties)); + return 0; +} + +static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev, + struct sound_trigger_sound_model *sound_model, + sound_model_callback_t callback, + void *cookie, + sound_model_handle_t *handle) +{ + struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev; + int status = 0; + + ALOGI("%s stdev %p", __func__, stdev); + pthread_mutex_lock(&stdev->lock); + if (handle == NULL || sound_model == NULL) { + status = -EINVAL; + goto exit; + } + if (sound_model->data_size == 0 || + sound_model->data_offset < sizeof(struct sound_trigger_sound_model)) { + status = -EINVAL; + goto exit; + } + + if (stdev->model_handle == 1) { + status = -ENOSYS; + goto exit; + } + char *data = (char *)sound_model + sound_model->data_offset; + ALOGI("%s data size %d data %d - %d", __func__, + sound_model->data_size, data[0], data[sound_model->data_size - 1]); + stdev->model_handle = 1; + stdev->sound_model_callback = callback; + stdev->sound_model_cookie = cookie; + + *handle = stdev->model_handle; + +exit: + pthread_mutex_unlock(&stdev->lock); + return status; +} + +static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev, + sound_model_handle_t handle) +{ + struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev; + int status = 0; + + ALOGI("%s handle %d", __func__, handle); + pthread_mutex_lock(&stdev->lock); + if (handle != 1) { + status = -EINVAL; + goto exit; + } + if (stdev->model_handle == 0) { + status = -ENOSYS; + goto exit; + } + stdev->model_handle = 0; + if (stdev->recognition_callback != NULL) { + stdev->recognition_callback = NULL; + pthread_cond_signal(&stdev->cond); + pthread_mutex_unlock(&stdev->lock); + pthread_join(stdev->callback_thread, (void **) NULL); + pthread_mutex_lock(&stdev->lock); + } + +exit: + pthread_mutex_unlock(&stdev->lock); + return status; +} + +static int stdev_start_recognition(const struct sound_trigger_hw_device *dev, + sound_model_handle_t sound_model_handle, + const struct sound_trigger_recognition_config *config, + recognition_callback_t callback, + void *cookie) +{ + struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev; + int status = 0; + ALOGI("%s sound model %d", __func__, sound_model_handle); + pthread_mutex_lock(&stdev->lock); + if (stdev->model_handle != sound_model_handle) { + status = -ENOSYS; + goto exit; + } + if (stdev->recognition_callback != NULL) { + status = -ENOSYS; + goto exit; + } + if (config->data_size != 0) { + char *data = (char *)config + config->data_offset; + ALOGI("%s data size %d data %d - %d", __func__, + config->data_size, data[0], data[config->data_size - 1]); + } + + stdev->recognition_callback = callback; + stdev->recognition_cookie = cookie; + pthread_create(&stdev->callback_thread, (const pthread_attr_t *) NULL, + callback_thread_loop, stdev); +exit: + pthread_mutex_unlock(&stdev->lock); + return status; +} + +static int stdev_stop_recognition(const struct sound_trigger_hw_device *dev, + sound_model_handle_t sound_model_handle) +{ + struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev; + int status = 0; + ALOGI("%s sound model %d", __func__, sound_model_handle); + pthread_mutex_lock(&stdev->lock); + if (stdev->model_handle != sound_model_handle) { + status = -ENOSYS; + goto exit; + } + if (stdev->recognition_callback == NULL) { + status = -ENOSYS; + goto exit; + } + stdev->recognition_callback = NULL; + pthread_cond_signal(&stdev->cond); + pthread_mutex_unlock(&stdev->lock); + pthread_join(stdev->callback_thread, (void **) NULL); + pthread_mutex_lock(&stdev->lock); + +exit: + pthread_mutex_unlock(&stdev->lock); + return status; +} + + +static int stdev_close(hw_device_t *device) +{ + free(device); + return 0; +} + +static int stdev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + struct stub_sound_trigger_device *stdev; + int ret; + + if (strcmp(name, SOUND_TRIGGER_HARDWARE_INTERFACE) != 0) + return -EINVAL; + + stdev = calloc(1, sizeof(struct stub_sound_trigger_device)); + if (!stdev) + return -ENOMEM; + + stdev->device.common.tag = HARDWARE_DEVICE_TAG; + stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_0; + stdev->device.common.module = (struct hw_module_t *) module; + stdev->device.common.close = stdev_close; + stdev->device.get_properties = stdev_get_properties; + stdev->device.load_sound_model = stdev_load_sound_model; + stdev->device.unload_sound_model = stdev_unload_sound_model; + stdev->device.start_recognition = stdev_start_recognition; + stdev->device.stop_recognition = stdev_stop_recognition; + + pthread_mutex_init(&stdev->lock, (const pthread_mutexattr_t *) NULL); + pthread_cond_init(&stdev->cond, (const pthread_condattr_t *) NULL); + + *device = &stdev->device.common; + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + .open = stdev_open, +}; + +struct sound_trigger_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = SOUND_TRIGGER_MODULE_API_VERSION_1_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = SOUND_TRIGGER_HARDWARE_MODULE_ID, + .name = "Default sound trigger HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +};
diff --git a/libhardware/modules/tv_input/Android.bp b/libhardware/modules/tv_input/Android.bp new file mode 100644 index 0000000..beac132 --- /dev/null +++ b/libhardware/modules/tv_input/Android.bp
@@ -0,0 +1,23 @@ +// Copyright (C) 2014 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. + +cc_library_shared { + name: "tv_input.default", + relative_install_path: "hw", + shared_libs: [ + "libcutils", + "liblog", + ], + srcs: ["tv_input.cpp"], +}
diff --git a/libhardware/modules/tv_input/tv_input.cpp b/libhardware/modules/tv_input/tv_input.cpp new file mode 100644 index 0000000..114e80e --- /dev/null +++ b/libhardware/modules/tv_input/tv_input.cpp
@@ -0,0 +1,142 @@ +/* + * Copyright 2014 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 <errno.h> +#include <fcntl.h> +#include <malloc.h> + +#include <cutils/log.h> +#include <cutils/native_handle.h> + +#include <hardware/tv_input.h> + +/*****************************************************************************/ + +typedef struct tv_input_private { + tv_input_device_t device; + + // Callback related data + const tv_input_callback_ops_t* callback; + void* callback_data; +} tv_input_private_t; + +static int tv_input_device_open(const struct hw_module_t* module, + const char* name, struct hw_device_t** device); + +static struct hw_module_methods_t tv_input_module_methods = { + open: tv_input_device_open +}; + +tv_input_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 0, + version_minor: 1, + id: TV_INPUT_HARDWARE_MODULE_ID, + name: "Sample TV input module", + author: "The Android Open Source Project", + methods: &tv_input_module_methods, + } +}; + +/*****************************************************************************/ + +static int tv_input_initialize(struct tv_input_device* dev, + const tv_input_callback_ops_t* callback, void* data) +{ + if (dev == NULL || callback == NULL) { + return -EINVAL; + } + tv_input_private_t* priv = (tv_input_private_t*)dev; + if (priv->callback != NULL) { + return -EEXIST; + } + + priv->callback = callback; + priv->callback_data = data; + + return 0; +} + +static int tv_input_get_stream_configurations( + const struct tv_input_device*, int, int*, const tv_stream_config_t**) +{ + return -EINVAL; +} + +static int tv_input_open_stream(struct tv_input_device*, int, tv_stream_t*) +{ + return -EINVAL; +} + +static int tv_input_close_stream(struct tv_input_device*, int, int) +{ + return -EINVAL; +} + +static int tv_input_request_capture( + struct tv_input_device*, int, int, buffer_handle_t, uint32_t) +{ + return -EINVAL; +} + +static int tv_input_cancel_capture(struct tv_input_device*, int, int, uint32_t) +{ + return -EINVAL; +} + +/*****************************************************************************/ + +static int tv_input_device_close(struct hw_device_t *dev) +{ + tv_input_private_t* priv = (tv_input_private_t*)dev; + if (priv) { + free(priv); + } + return 0; +} + +/*****************************************************************************/ + +static int tv_input_device_open(const struct hw_module_t* module, + const char* name, struct hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, TV_INPUT_DEFAULT_DEVICE)) { + tv_input_private_t* dev = (tv_input_private_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1; + dev->device.common.module = const_cast<hw_module_t*>(module); + dev->device.common.close = tv_input_device_close; + + dev->device.initialize = tv_input_initialize; + dev->device.get_stream_configurations = + tv_input_get_stream_configurations; + dev->device.open_stream = tv_input_open_stream; + dev->device.close_stream = tv_input_close_stream; + dev->device.request_capture = tv_input_request_capture; + dev->device.cancel_capture = tv_input_cancel_capture; + + *device = &dev->device.common; + status = 0; + } + return status; +}
diff --git a/libhardware/modules/usbaudio/Android.mk b/libhardware/modules/usbaudio/Android.mk new file mode 100644 index 0000000..9df1e79 --- /dev/null +++ b/libhardware/modules/usbaudio/Android.mk
@@ -0,0 +1,32 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := audio.usb.default +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + audio_hal.c +LOCAL_C_INCLUDES += \ + external/tinyalsa/include \ + $(call include-path-for, audio-utils) \ + $(call include-path-for, alsa-utils) +LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libalsautils +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -Wno-unused-parameter + +include $(BUILD_SHARED_LIBRARY) +
diff --git a/libhardware/modules/usbaudio/audio_hal.c b/libhardware/modules/usbaudio/audio_hal.c new file mode 100644 index 0000000..38fea86 --- /dev/null +++ b/libhardware/modules/usbaudio/audio_hal.c
@@ -0,0 +1,1088 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "modules.usbaudio.audio_hal" +/*#define LOG_NDEBUG 0*/ + +#include <errno.h> +#include <inttypes.h> +#include <pthread.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/time.h> + +#include <log/log.h> +#include <cutils/str_parms.h> +#include <cutils/properties.h> + +#include <hardware/audio.h> +#include <hardware/audio_alsaops.h> +#include <hardware/hardware.h> + +#include <system/audio.h> + +#include <tinyalsa/asoundlib.h> + +#include <audio_utils/channels.h> + +/* FOR TESTING: + * Set k_force_channels to force the number of channels to present to AudioFlinger. + * 0 disables (this is default: present the device channels to AudioFlinger). + * 2 forces to legacy stereo mode. + * + * Others values can be tried (up to 8). + * TODO: AudioFlinger cannot support more than 8 active output channels + * at this time, so limiting logic needs to be put here or communicated from above. + */ +static const unsigned k_force_channels = 0; + +#include "alsa_device_profile.h" +#include "alsa_device_proxy.h" +#include "alsa_logging.h" + +#define DEFAULT_INPUT_BUFFER_SIZE_MS 20 + +// stereo channel count +#define FCC_2 2 +// fixed channel count of 8 limitation (for data processing in AudioFlinger) +#define FCC_8 8 + +struct audio_device { + struct audio_hw_device hw_device; + + pthread_mutex_t lock; /* see note below on mutex acquisition order */ + + /* output */ + alsa_device_profile out_profile; + + /* input */ + alsa_device_profile in_profile; + + bool mic_muted; + + bool standby; +}; + +struct stream_out { + struct audio_stream_out stream; + + pthread_mutex_t lock; /* see note below on mutex acquisition order */ + pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */ + bool standby; + + struct audio_device *dev; /* hardware information - only using this for the lock */ + + alsa_device_profile * profile; /* Points to the alsa_device_profile in the audio_device */ + alsa_device_proxy proxy; /* state of the stream */ + + unsigned hal_channel_count; /* channel count exposed to AudioFlinger. + * This may differ from the device channel count when + * the device is not compatible with AudioFlinger + * capabilities, e.g. exposes too many channels or + * too few channels. */ + audio_channel_mask_t hal_channel_mask; /* channel mask exposed to AudioFlinger. */ + + void * conversion_buffer; /* any conversions are put into here + * they could come from here too if + * there was a previous conversion */ + size_t conversion_buffer_size; /* in bytes */ +}; + +struct stream_in { + struct audio_stream_in stream; + + pthread_mutex_t lock; /* see note below on mutex acquisition order */ + pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by capture thread */ + bool standby; + + struct audio_device *dev; /* hardware information - only using this for the lock */ + + alsa_device_profile * profile; /* Points to the alsa_device_profile in the audio_device */ + alsa_device_proxy proxy; /* state of the stream */ + + unsigned hal_channel_count; /* channel count exposed to AudioFlinger. + * This may differ from the device channel count when + * the device is not compatible with AudioFlinger + * capabilities, e.g. exposes too many channels or + * too few channels. */ + audio_channel_mask_t hal_channel_mask; /* channel mask exposed to AudioFlinger. */ + + /* We may need to read more data from the device in order to data reduce to 16bit, 4chan */ + void * conversion_buffer; /* any conversions are put into here + * they could come from here too if + * there was a previous conversion */ + size_t conversion_buffer_size; /* in bytes */ +}; + +/* + * NOTE: when multiple mutexes have to be acquired, always take the + * stream_in or stream_out mutex first, followed by the audio_device mutex. + * stream pre_lock is always acquired before stream lock to prevent starvation of control thread by + * higher priority playback or capture thread. + */ + +/* + * Extract the card and device numbers from the supplied key/value pairs. + * kvpairs A null-terminated string containing the key/value pairs or card and device. + * i.e. "card=1;device=42" + * card A pointer to a variable to receive the parsed-out card number. + * device A pointer to a variable to receive the parsed-out device number. + * NOTE: The variables pointed to by card and device return -1 (undefined) if the + * associated key/value pair is not found in the provided string. + * Return true if the kvpairs string contain a card/device spec, false otherwise. + */ +static bool parse_card_device_params(const char *kvpairs, int *card, int *device) +{ + struct str_parms * parms = str_parms_create_str(kvpairs); + char value[32]; + int param_val; + + // initialize to "undefined" state. + *card = -1; + *device = -1; + + param_val = str_parms_get_str(parms, "card", value, sizeof(value)); + if (param_val >= 0) { + *card = atoi(value); + } + + param_val = str_parms_get_str(parms, "device", value, sizeof(value)); + if (param_val >= 0) { + *device = atoi(value); + } + + str_parms_destroy(parms); + + return *card >= 0 && *device >= 0; +} + +static char * device_get_parameters(alsa_device_profile * profile, const char * keys) +{ + if (profile->card < 0 || profile->device < 0) { + return strdup(""); + } + + struct str_parms *query = str_parms_create_str(keys); + struct str_parms *result = str_parms_create(); + + /* These keys are from hardware/libhardware/include/audio.h */ + /* supported sample rates */ + if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) { + char* rates_list = profile_get_sample_rate_strs(profile); + str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, + rates_list); + free(rates_list); + } + + /* supported channel counts */ + if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) { + char* channels_list = profile_get_channel_count_strs(profile); + str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, + channels_list); + free(channels_list); + } + + /* supported sample formats */ + if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) { + char * format_params = profile_get_format_strs(profile); + str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, + format_params); + free(format_params); + } + str_parms_destroy(query); + + char* result_str = str_parms_to_str(result); + str_parms_destroy(result); + + ALOGV("device_get_parameters = %s", result_str); + + return result_str; +} + +void lock_input_stream(struct stream_in *in) +{ + pthread_mutex_lock(&in->pre_lock); + pthread_mutex_lock(&in->lock); + pthread_mutex_unlock(&in->pre_lock); +} + +void lock_output_stream(struct stream_out *out) +{ + pthread_mutex_lock(&out->pre_lock); + pthread_mutex_lock(&out->lock); + pthread_mutex_unlock(&out->pre_lock); +} + +/* + * HAl Functions + */ +/** + * NOTE: when multiple mutexes have to be acquired, always respect the + * following order: hw device > out stream + */ + +/* + * OUT functions + */ +static uint32_t out_get_sample_rate(const struct audio_stream *stream) +{ + uint32_t rate = proxy_get_sample_rate(&((struct stream_out*)stream)->proxy); + ALOGV("out_get_sample_rate() = %d", rate); + return rate; +} + +static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + return 0; +} + +static size_t out_get_buffer_size(const struct audio_stream *stream) +{ + const struct stream_out* out = (const struct stream_out*)stream; + size_t buffer_size = + proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream)); + return buffer_size; +} + +static uint32_t out_get_channels(const struct audio_stream *stream) +{ + const struct stream_out *out = (const struct stream_out*)stream; + return out->hal_channel_mask; +} + +static audio_format_t out_get_format(const struct audio_stream *stream) +{ + /* Note: The HAL doesn't do any FORMAT conversion at this time. It + * Relies on the framework to provide data in the specified format. + * This could change in the future. + */ + alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy; + audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy)); + return format; +} + +static int out_set_format(struct audio_stream *stream, audio_format_t format) +{ + return 0; +} + +static int out_standby(struct audio_stream *stream) +{ + struct stream_out *out = (struct stream_out *)stream; + + lock_output_stream(out); + if (!out->standby) { + pthread_mutex_lock(&out->dev->lock); + proxy_close(&out->proxy); + pthread_mutex_unlock(&out->dev->lock); + out->standby = true; + } + pthread_mutex_unlock(&out->lock); + + return 0; +} + +static int out_dump(const struct audio_stream *stream, int fd) +{ + return 0; +} + +static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + ALOGV("out_set_parameters() keys:%s", kvpairs); + + struct stream_out *out = (struct stream_out *)stream; + + int routing = 0; + int ret_value = 0; + int card = -1; + int device = -1; + + if (!parse_card_device_params(kvpairs, &card, &device)) { + // nothing to do + return ret_value; + } + + lock_output_stream(out); + /* Lock the device because that is where the profile lives */ + pthread_mutex_lock(&out->dev->lock); + + if (!profile_is_cached_for(out->profile, card, device)) { + /* cannot read pcm device info if playback is active */ + if (!out->standby) + ret_value = -ENOSYS; + else { + int saved_card = out->profile->card; + int saved_device = out->profile->device; + out->profile->card = card; + out->profile->device = device; + ret_value = profile_read_device_info(out->profile) ? 0 : -EINVAL; + if (ret_value != 0) { + out->profile->card = saved_card; + out->profile->device = saved_device; + } + } + } + + pthread_mutex_unlock(&out->dev->lock); + pthread_mutex_unlock(&out->lock); + + return ret_value; +} + +static char * out_get_parameters(const struct audio_stream *stream, const char *keys) +{ + struct stream_out *out = (struct stream_out *)stream; + lock_output_stream(out); + pthread_mutex_lock(&out->dev->lock); + + char * params_str = device_get_parameters(out->profile, keys); + + pthread_mutex_unlock(&out->lock); + pthread_mutex_unlock(&out->dev->lock); + + return params_str; +} + +static uint32_t out_get_latency(const struct audio_stream_out *stream) +{ + alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy; + return proxy_get_latency(proxy); +} + +static int out_set_volume(struct audio_stream_out *stream, float left, float right) +{ + return -ENOSYS; +} + +/* must be called with hw device and output stream mutexes locked */ +static int start_output_stream(struct stream_out *out) +{ + ALOGV("start_output_stream(card:%d device:%d)", out->profile->card, out->profile->device); + + return proxy_open(&out->proxy); +} + +static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) +{ + int ret; + struct stream_out *out = (struct stream_out *)stream; + + lock_output_stream(out); + if (out->standby) { + pthread_mutex_lock(&out->dev->lock); + ret = start_output_stream(out); + pthread_mutex_unlock(&out->dev->lock); + if (ret != 0) { + goto err; + } + out->standby = false; + } + + alsa_device_proxy* proxy = &out->proxy; + const void * write_buff = buffer; + int num_write_buff_bytes = bytes; + const int num_device_channels = proxy_get_channel_count(proxy); /* what we told alsa */ + const int num_req_channels = out->hal_channel_count; /* what we told AudioFlinger */ + if (num_device_channels != num_req_channels) { + /* allocate buffer */ + const size_t required_conversion_buffer_size = + bytes * num_device_channels / num_req_channels; + if (required_conversion_buffer_size > out->conversion_buffer_size) { + out->conversion_buffer_size = required_conversion_buffer_size; + out->conversion_buffer = realloc(out->conversion_buffer, + out->conversion_buffer_size); + } + /* convert data */ + const audio_format_t audio_format = out_get_format(&(out->stream.common)); + const unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format); + num_write_buff_bytes = + adjust_channels(write_buff, num_req_channels, + out->conversion_buffer, num_device_channels, + sample_size_in_bytes, num_write_buff_bytes); + write_buff = out->conversion_buffer; + } + + if (write_buff != NULL && num_write_buff_bytes != 0) { + proxy_write(&out->proxy, write_buff, num_write_buff_bytes); + } + + pthread_mutex_unlock(&out->lock); + + return bytes; + +err: + pthread_mutex_unlock(&out->lock); + if (ret != 0) { + usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / + out_get_sample_rate(&stream->common)); + } + + return bytes; +} + +static int out_get_render_position(const struct audio_stream_out *stream, uint32_t *dsp_frames) +{ + return -EINVAL; +} + +static int out_get_presentation_position(const struct audio_stream_out *stream, + uint64_t *frames, struct timespec *timestamp) +{ + struct stream_out *out = (struct stream_out *)stream; // discard const qualifier + lock_output_stream(out); + + const alsa_device_proxy *proxy = &out->proxy; + const int ret = proxy_get_presentation_position(proxy, frames, timestamp); + + pthread_mutex_unlock(&out->lock); + ALOGV("out_get_presentation_position() status:%d frames:%llu", + ret, (unsigned long long)*frames); + return ret; +} + +static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + return 0; +} + +static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + return 0; +} + +static int out_get_next_write_timestamp(const struct audio_stream_out *stream, int64_t *timestamp) +{ + return -EINVAL; +} + +static int adev_open_output_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out, + const char *address /*__unused*/) +{ + ALOGV("adev_open_output_stream() handle:0x%X, device:0x%X, flags:0x%X, addr:%s", + handle, devices, flags, address); + + struct audio_device *adev = (struct audio_device *)dev; + + struct stream_out *out; + + out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); + if (!out) + return -ENOMEM; + + /* setup function pointers */ + out->stream.common.get_sample_rate = out_get_sample_rate; + out->stream.common.set_sample_rate = out_set_sample_rate; + out->stream.common.get_buffer_size = out_get_buffer_size; + out->stream.common.get_channels = out_get_channels; + out->stream.common.get_format = out_get_format; + out->stream.common.set_format = out_set_format; + out->stream.common.standby = out_standby; + out->stream.common.dump = out_dump; + out->stream.common.set_parameters = out_set_parameters; + out->stream.common.get_parameters = out_get_parameters; + out->stream.common.add_audio_effect = out_add_audio_effect; + out->stream.common.remove_audio_effect = out_remove_audio_effect; + out->stream.get_latency = out_get_latency; + out->stream.set_volume = out_set_volume; + out->stream.write = out_write; + out->stream.get_render_position = out_get_render_position; + out->stream.get_presentation_position = out_get_presentation_position; + out->stream.get_next_write_timestamp = out_get_next_write_timestamp; + + pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL); + pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL); + + out->dev = adev; + pthread_mutex_lock(&adev->lock); + out->profile = &adev->out_profile; + + // build this to hand to the alsa_device_proxy + struct pcm_config proxy_config; + memset(&proxy_config, 0, sizeof(proxy_config)); + + /* Pull out the card/device pair */ + parse_card_device_params(address, &(out->profile->card), &(out->profile->device)); + + profile_read_device_info(out->profile); + + pthread_mutex_unlock(&adev->lock); + + int ret = 0; + + /* Rate */ + if (config->sample_rate == 0) { + proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile); + } else if (profile_is_sample_rate_valid(out->profile, config->sample_rate)) { + proxy_config.rate = config->sample_rate; + } else { + proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile); + ret = -EINVAL; + } + + /* Format */ + if (config->format == AUDIO_FORMAT_DEFAULT) { + proxy_config.format = profile_get_default_format(out->profile); + config->format = audio_format_from_pcm_format(proxy_config.format); + } else { + enum pcm_format fmt = pcm_format_from_audio_format(config->format); + if (profile_is_format_valid(out->profile, fmt)) { + proxy_config.format = fmt; + } else { + proxy_config.format = profile_get_default_format(out->profile); + config->format = audio_format_from_pcm_format(proxy_config.format); + ret = -EINVAL; + } + } + + /* Channels */ + unsigned proposed_channel_count = 0; + if (k_force_channels) { + proposed_channel_count = k_force_channels; + } else if (config->channel_mask == AUDIO_CHANNEL_NONE) { + proposed_channel_count = profile_get_default_channel_count(out->profile); + } + if (proposed_channel_count != 0) { + if (proposed_channel_count <= FCC_2) { + // use channel position mask for mono and stereo + config->channel_mask = audio_channel_out_mask_from_count(proposed_channel_count); + } else { + // use channel index mask for multichannel + config->channel_mask = + audio_channel_mask_for_index_assignment_from_count(proposed_channel_count); + } + out->hal_channel_count = proposed_channel_count; + } else { + out->hal_channel_count = audio_channel_count_from_out_mask(config->channel_mask); + } + /* we can expose any channel mask, and emulate internally based on channel count. */ + out->hal_channel_mask = config->channel_mask; + + /* no validity checks are needed as proxy_prepare() forces channel_count to be valid. + * and we emulate any channel count discrepancies in out_write(). */ + proxy_config.channels = proposed_channel_count; + + proxy_prepare(&out->proxy, out->profile, &proxy_config); + + /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */ + ret = 0; + + out->conversion_buffer = NULL; + out->conversion_buffer_size = 0; + + out->standby = true; + + *stream_out = &out->stream; + + return ret; + +err_open: + free(out); + *stream_out = NULL; + return -ENOSYS; +} + +static void adev_close_output_stream(struct audio_hw_device *dev, + struct audio_stream_out *stream) +{ + struct stream_out *out = (struct stream_out *)stream; + ALOGV("adev_close_output_stream(c:%d d:%d)", out->profile->card, out->profile->device); + + /* Close the pcm device */ + out_standby(&stream->common); + + free(out->conversion_buffer); + + out->conversion_buffer = NULL; + out->conversion_buffer_size = 0; + + free(stream); +} + +static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, + const struct audio_config *config) +{ + /* TODO This needs to be calculated based on format/channels/rate */ + return 320; +} + +/* + * IN functions + */ +static uint32_t in_get_sample_rate(const struct audio_stream *stream) +{ + uint32_t rate = proxy_get_sample_rate(&((const struct stream_in *)stream)->proxy); + ALOGV("in_get_sample_rate() = %d", rate); + return rate; +} + +static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + ALOGV("in_set_sample_rate(%d) - NOPE", rate); + return -ENOSYS; +} + +static size_t in_get_buffer_size(const struct audio_stream *stream) +{ + const struct stream_in * in = ((const struct stream_in*)stream); + return proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream)); +} + +static uint32_t in_get_channels(const struct audio_stream *stream) +{ + const struct stream_in *in = (const struct stream_in*)stream; + return in->hal_channel_mask; +} + +static audio_format_t in_get_format(const struct audio_stream *stream) +{ + alsa_device_proxy *proxy = &((struct stream_in*)stream)->proxy; + audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy)); + return format; +} + +static int in_set_format(struct audio_stream *stream, audio_format_t format) +{ + ALOGV("in_set_format(%d) - NOPE", format); + + return -ENOSYS; +} + +static int in_standby(struct audio_stream *stream) +{ + struct stream_in *in = (struct stream_in *)stream; + + lock_input_stream(in); + if (!in->standby) { + pthread_mutex_lock(&in->dev->lock); + proxy_close(&in->proxy); + pthread_mutex_unlock(&in->dev->lock); + in->standby = true; + } + + pthread_mutex_unlock(&in->lock); + + return 0; +} + +static int in_dump(const struct audio_stream *stream, int fd) +{ + return 0; +} + +static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + ALOGV("in_set_parameters() keys:%s", kvpairs); + + struct stream_in *in = (struct stream_in *)stream; + + char value[32]; + int param_val; + int routing = 0; + int ret_value = 0; + int card = -1; + int device = -1; + + if (!parse_card_device_params(kvpairs, &card, &device)) { + // nothing to do + return ret_value; + } + + lock_input_stream(in); + pthread_mutex_lock(&in->dev->lock); + + if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) { + /* cannot read pcm device info if playback is active */ + if (!in->standby) + ret_value = -ENOSYS; + else { + int saved_card = in->profile->card; + int saved_device = in->profile->device; + in->profile->card = card; + in->profile->device = device; + ret_value = profile_read_device_info(in->profile) ? 0 : -EINVAL; + if (ret_value != 0) { + in->profile->card = saved_card; + in->profile->device = saved_device; + } + } + } + + pthread_mutex_unlock(&in->dev->lock); + pthread_mutex_unlock(&in->lock); + + return ret_value; +} + +static char * in_get_parameters(const struct audio_stream *stream, const char *keys) +{ + struct stream_in *in = (struct stream_in *)stream; + + lock_input_stream(in); + pthread_mutex_lock(&in->dev->lock); + + char * params_str = device_get_parameters(in->profile, keys); + + pthread_mutex_unlock(&in->dev->lock); + pthread_mutex_unlock(&in->lock); + + return params_str; +} + +static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + return 0; +} + +static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + return 0; +} + +static int in_set_gain(struct audio_stream_in *stream, float gain) +{ + return 0; +} + +/* must be called with hw device and output stream mutexes locked */ +static int start_input_stream(struct stream_in *in) +{ + ALOGV("ustart_input_stream(card:%d device:%d)", in->profile->card, in->profile->device); + + return proxy_open(&in->proxy); +} + +/* TODO mutex stuff here (see out_write) */ +static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes) +{ + size_t num_read_buff_bytes = 0; + void * read_buff = buffer; + void * out_buff = buffer; + int ret = 0; + + struct stream_in * in = (struct stream_in *)stream; + + lock_input_stream(in); + if (in->standby) { + pthread_mutex_lock(&in->dev->lock); + ret = start_input_stream(in); + pthread_mutex_unlock(&in->dev->lock); + if (ret != 0) { + goto err; + } + in->standby = false; + } + + alsa_device_profile * profile = in->profile; + + /* + * OK, we need to figure out how much data to read to be able to output the requested + * number of bytes in the HAL format (16-bit, stereo). + */ + num_read_buff_bytes = bytes; + int num_device_channels = proxy_get_channel_count(&in->proxy); /* what we told Alsa */ + int num_req_channels = in->hal_channel_count; /* what we told AudioFlinger */ + + if (num_device_channels != num_req_channels) { + num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels; + } + + /* Setup/Realloc the conversion buffer (if necessary). */ + if (num_read_buff_bytes != bytes) { + if (num_read_buff_bytes > in->conversion_buffer_size) { + /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats + (and do these conversions themselves) */ + in->conversion_buffer_size = num_read_buff_bytes; + in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size); + } + read_buff = in->conversion_buffer; + } + + ret = proxy_read(&in->proxy, read_buff, num_read_buff_bytes); + if (ret == 0) { + if (num_device_channels != num_req_channels) { + // ALOGV("chans dev:%d req:%d", num_device_channels, num_req_channels); + + out_buff = buffer; + /* Num Channels conversion */ + if (num_device_channels != num_req_channels) { + audio_format_t audio_format = in_get_format(&(in->stream.common)); + unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format); + + num_read_buff_bytes = + adjust_channels(read_buff, num_device_channels, + out_buff, num_req_channels, + sample_size_in_bytes, num_read_buff_bytes); + } + } + + /* no need to acquire in->dev->lock to read mic_muted here as we don't change its state */ + if (num_read_buff_bytes > 0 && in->dev->mic_muted) + memset(buffer, 0, num_read_buff_bytes); + } else { + num_read_buff_bytes = 0; // reset the value after USB headset is unplugged + } + +err: + pthread_mutex_unlock(&in->lock); + + return num_read_buff_bytes; +} + +static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) +{ + return 0; +} + +static int adev_open_input_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in, + audio_input_flags_t flags __unused, + const char *address /*__unused*/, + audio_source_t source __unused) +{ + ALOGV("in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8, + config->sample_rate, config->channel_mask, config->format); + + struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in)); + int ret = 0; + + if (in == NULL) + return -ENOMEM; + + /* setup function pointers */ + in->stream.common.get_sample_rate = in_get_sample_rate; + in->stream.common.set_sample_rate = in_set_sample_rate; + in->stream.common.get_buffer_size = in_get_buffer_size; + in->stream.common.get_channels = in_get_channels; + in->stream.common.get_format = in_get_format; + in->stream.common.set_format = in_set_format; + in->stream.common.standby = in_standby; + in->stream.common.dump = in_dump; + in->stream.common.set_parameters = in_set_parameters; + in->stream.common.get_parameters = in_get_parameters; + in->stream.common.add_audio_effect = in_add_audio_effect; + in->stream.common.remove_audio_effect = in_remove_audio_effect; + + in->stream.set_gain = in_set_gain; + in->stream.read = in_read; + in->stream.get_input_frames_lost = in_get_input_frames_lost; + + pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL); + pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL); + + in->dev = (struct audio_device *)dev; + pthread_mutex_lock(&in->dev->lock); + + in->profile = &in->dev->in_profile; + + struct pcm_config proxy_config; + memset(&proxy_config, 0, sizeof(proxy_config)); + + /* Pull out the card/device pair */ + parse_card_device_params(address, &(in->profile->card), &(in->profile->device)); + + profile_read_device_info(in->profile); + pthread_mutex_unlock(&in->dev->lock); + + /* Rate */ + if (config->sample_rate == 0) { + proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile); + } else if (profile_is_sample_rate_valid(in->profile, config->sample_rate)) { + proxy_config.rate = config->sample_rate; + } else { + proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile); + ret = -EINVAL; + } + + /* Format */ + if (config->format == AUDIO_FORMAT_DEFAULT) { + proxy_config.format = profile_get_default_format(in->profile); + config->format = audio_format_from_pcm_format(proxy_config.format); + } else { + enum pcm_format fmt = pcm_format_from_audio_format(config->format); + if (profile_is_format_valid(in->profile, fmt)) { + proxy_config.format = fmt; + } else { + proxy_config.format = profile_get_default_format(in->profile); + config->format = audio_format_from_pcm_format(proxy_config.format); + ret = -EINVAL; + } + } + + /* Channels */ + unsigned proposed_channel_count = 0; + if (k_force_channels) { + proposed_channel_count = k_force_channels; + } else if (config->channel_mask == AUDIO_CHANNEL_NONE) { + proposed_channel_count = profile_get_default_channel_count(in->profile); + } + if (proposed_channel_count != 0) { + config->channel_mask = audio_channel_in_mask_from_count(proposed_channel_count); + if (config->channel_mask == AUDIO_CHANNEL_INVALID) + config->channel_mask = + audio_channel_mask_for_index_assignment_from_count(proposed_channel_count); + in->hal_channel_count = proposed_channel_count; + } else { + in->hal_channel_count = audio_channel_count_from_in_mask(config->channel_mask); + } + /* we can expose any channel mask, and emulate internally based on channel count. */ + in->hal_channel_mask = config->channel_mask; + + proxy_config.channels = profile_get_default_channel_count(in->profile); + proxy_prepare(&in->proxy, in->profile, &proxy_config); + + in->standby = true; + + in->conversion_buffer = NULL; + in->conversion_buffer_size = 0; + + *stream_in = &in->stream; + + return ret; +} + +static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream) +{ + struct stream_in *in = (struct stream_in *)stream; + + /* Close the pcm device */ + in_standby(&stream->common); + + free(in->conversion_buffer); + + free(stream); +} + +/* + * ADEV Functions + */ +static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) +{ + return 0; +} + +static char * adev_get_parameters(const struct audio_hw_device *dev, const char *keys) +{ + return strdup(""); +} + +static int adev_init_check(const struct audio_hw_device *dev) +{ + return 0; +} + +static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) +{ + return -ENOSYS; +} + +static int adev_set_master_volume(struct audio_hw_device *dev, float volume) +{ + return -ENOSYS; +} + +static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) +{ + return 0; +} + +static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) +{ + struct audio_device * adev = (struct audio_device *)dev; + pthread_mutex_lock(&adev->lock); + adev->mic_muted = state; + pthread_mutex_unlock(&adev->lock); + return -ENOSYS; +} + +static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) +{ + return -ENOSYS; +} + +static int adev_dump(const audio_hw_device_t *device, int fd) +{ + return 0; +} + +static int adev_close(hw_device_t *device) +{ + struct audio_device *adev = (struct audio_device *)device; + free(device); + + return 0; +} + +static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device) +{ + if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) + return -EINVAL; + + struct audio_device *adev = calloc(1, sizeof(struct audio_device)); + if (!adev) + return -ENOMEM; + + profile_init(&adev->out_profile, PCM_OUT); + profile_init(&adev->in_profile, PCM_IN); + + adev->hw_device.common.tag = HARDWARE_DEVICE_TAG; + adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0; + adev->hw_device.common.module = (struct hw_module_t *)module; + adev->hw_device.common.close = adev_close; + + adev->hw_device.init_check = adev_init_check; + adev->hw_device.set_voice_volume = adev_set_voice_volume; + adev->hw_device.set_master_volume = adev_set_master_volume; + adev->hw_device.set_mode = adev_set_mode; + adev->hw_device.set_mic_mute = adev_set_mic_mute; + adev->hw_device.get_mic_mute = adev_get_mic_mute; + adev->hw_device.set_parameters = adev_set_parameters; + adev->hw_device.get_parameters = adev_get_parameters; + adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size; + adev->hw_device.open_output_stream = adev_open_output_stream; + adev->hw_device.close_output_stream = adev_close_output_stream; + adev->hw_device.open_input_stream = adev_open_input_stream; + adev->hw_device.close_input_stream = adev_close_input_stream; + adev->hw_device.dump = adev_dump; + + *device = &adev->hw_device.common; + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + .open = adev_open, +}; + +struct audio_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = AUDIO_MODULE_API_VERSION_0_1, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = AUDIO_HARDWARE_MODULE_ID, + .name = "USB audio HW HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +};
diff --git a/libhardware/modules/usbcamera/Android.mk b/libhardware/modules/usbcamera/Android.mk new file mode 100644 index 0000000..162b158 --- /dev/null +++ b/libhardware/modules/usbcamera/Android.mk
@@ -0,0 +1,45 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := camera.usb.default +LOCAL_MODULE_RELATIVE_PATH := hw + +LOCAL_C_INCLUDES += \ + system/core/include \ + system/media/camera/include \ + +LOCAL_SRC_FILES := \ + CameraHAL.cpp \ + Camera.cpp \ + UsbCamera.cpp \ + Metadata.cpp \ + Stream.cpp \ + HotplugThread.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libcamera_metadata \ + libcutils \ + liblog \ + libsync \ + libutils \ + +LOCAL_CFLAGS += -Wall -Wextra -fvisibility=hidden + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY)
diff --git a/libhardware/modules/usbcamera/Camera.cpp b/libhardware/modules/usbcamera/Camera.cpp new file mode 100644 index 0000000..cf62f7f --- /dev/null +++ b/libhardware/modules/usbcamera/Camera.cpp
@@ -0,0 +1,537 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Camera" +#include <cutils/log.h> + +#include <cstdlib> +#include <stdio.h> +#include <hardware/camera3.h> +#include <system/camera_metadata.h> +#include <system/graphics.h> +#include <utils/Mutex.h> +#include "CameraHAL.h" +#include "Metadata.h" +#include "Stream.h" + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Camera.h" + +namespace usb_camera_hal { + +extern "C" { +// Shim passed to the framework to close an opened device. +static int close_device(hw_device_t* dev) { + camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(dev); + Camera* cam = static_cast<Camera*>(cam_dev->priv); + return cam->close(); +} + +// Get handle to camera from device priv data +static Camera *camdev_to_camera(const camera3_device_t *dev) { + return reinterpret_cast<Camera*>(dev->priv); +} + +static int initialize(const camera3_device_t *dev, + const camera3_callback_ops_t *callback_ops) { + return camdev_to_camera(dev)->initialize(callback_ops); +} + +static int configure_streams(const camera3_device_t *dev, + camera3_stream_configuration_t *stream_list) { + return camdev_to_camera(dev)->configureStreams(stream_list); +} + +static const camera_metadata_t *construct_default_request_settings( + const camera3_device_t *dev, int type) { + return camdev_to_camera(dev)->constructDefaultRequestSettings(type); +} + +static int process_capture_request(const camera3_device_t *dev, + camera3_capture_request_t *request) { + return camdev_to_camera(dev)->processCaptureRequest(request); +} + +static void dump(const camera3_device_t *dev, int fd) { + camdev_to_camera(dev)->dump(fd); +} + +static int flush(const camera3_device_t *dev) { + return camdev_to_camera(dev)->flush(); +} + +} // extern "C" + +const camera3_device_ops_t Camera::sOps = { + .initialize = usb_camera_hal::initialize, + .configure_streams = usb_camera_hal::configure_streams, + .register_stream_buffers = NULL, + .construct_default_request_settings + = usb_camera_hal::construct_default_request_settings, + .process_capture_request = usb_camera_hal::process_capture_request, + .get_metadata_vendor_tag_ops = NULL, + .dump = usb_camera_hal::dump, + .flush = usb_camera_hal::flush, + .reserved = {0}, +}; + +Camera::Camera(int id) + : mId(id), + mStaticInfo(NULL), + mBusy(false), + mCallbackOps(NULL), + mSettings(NULL), + mIsInitialized(false) { + memset(&mTemplates, 0, sizeof(mTemplates)); + memset(&mDevice, 0, sizeof(mDevice)); + mDevice.common.tag = HARDWARE_DEVICE_TAG; + // TODO: Upgrade to HAL3.3 + mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_2; + mDevice.common.close = close_device; + mDevice.ops = const_cast<camera3_device_ops_t*>(&sOps); + mDevice.priv = this; +} + +Camera::~Camera() { + if (mStaticInfo != NULL) { + free_camera_metadata(mStaticInfo); + } + + for (int i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) { + free_camera_metadata(mTemplates[i]); + } + + if (mSettings != NULL) { + free_camera_metadata(mSettings); + } +} + +int Camera::open(const hw_module_t *module, hw_device_t **device) { + ALOGI("%s:%d: Opening camera device", __func__, mId); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + if (mBusy) { + ALOGE("%s:%d: Error! Camera device already opened", __func__, mId); + return -EBUSY; + } + + mBusy = true; + mDevice.common.module = const_cast<hw_module_t*>(module); + *device = &mDevice.common; + return openDevice(); +} + +int Camera::getInfo(struct camera_info *info) { + android::Mutex::Autolock al(mStaticInfoLock); + + // TODO: update to CAMERA_FACING_EXTERNAL once the HAL API changes are merged. + info->facing = CAMERA_FACING_FRONT; + info->orientation = 0; + info->device_version = mDevice.common.version; + if (mStaticInfo == NULL) { + initStaticInfo(); + } + info->static_camera_characteristics = mStaticInfo; + return 0; +} + +void Camera::updateInfo() { + android::Mutex::Autolock al(mStaticInfoLock); + initStaticInfo(); +} + +int Camera::close() { + ALOGI("%s:%d: Closing camera device", __func__, mId); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + if (!mBusy) { + ALOGE("%s:%d: Error! Camera device not open", __func__, mId); + return -EINVAL; + } + + mBusy = false; + mIsInitialized = false; + return closeDevice(); +} + +int Camera::initialize(const camera3_callback_ops_t *callback_ops) { + int res; + + ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + mCallbackOps = callback_ops; + // per-device specific initialization + res = initDevice(); + if (res != 0) { + ALOGE("%s:%d: Failed to initialize device!", __func__, mId); + return res; + } + + mIsInitialized = true; + return 0; +} + +int Camera::configureStreams(camera3_stream_configuration_t *stream_config) { + camera3_stream_t *astream; + android::Vector<Stream *> newStreams; + + ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + if (!mIsInitialized) { + ALOGE("Device is not initialized yet"); + return -EINVAL; + } + + if (stream_config == NULL) { + ALOGE("%s:%d: NULL stream configuration array", __func__, mId); + return -EINVAL; + } + if (stream_config->num_streams == 0) { + ALOGE("%s:%d: Empty stream configuration array", __func__, mId); + return -EINVAL; + } + + ALOGV("%s:%d: Number of Streams: %d", __func__, mId, + stream_config->num_streams); + // Mark all current streams unused for now + for (size_t i = 0; i < mStreams.size(); i++) { + mStreams[i]->mReuse = false; + } + // Fill new stream array with reused streams and new streams + for (unsigned int i = 0; i < stream_config->num_streams; i++) { + astream = stream_config->streams[i]; + if (astream->max_buffers > 0) { + ALOGV("%s:%d: Reusing stream %d", __func__, mId, i); + newStreams.add(reuseStreamLocked(astream)); + } else { + ALOGV("%s:%d: Creating new stream %d", __func__, mId, i); + newStreams.add(new Stream(mId, astream)); + } + + if (newStreams[i] == NULL) { + ALOGE("%s:%d: Error processing stream %d", __func__, mId, i); + goto err_out; + } + astream->priv = reinterpret_cast<void *>(newStreams[i]); + } + + // Verify the set of streams in aggregate + if (!isValidStreamSetLocked(newStreams)) { + ALOGE("%s:%d: Invalid stream set", __func__, mId); + goto err_out; + } + + // Set up all streams (calculate usage/max_buffers for each) + setupStreamsLocked(newStreams); + + // Destroy all old streams and replace stream array with new one + destroyStreamsLocked(mStreams); + mStreams = newStreams; + + // Clear out last seen settings metadata + updateSettingsLocked(NULL); + return 0; + +err_out: + // Clean up temporary streams, preserve existing mStreams + destroyStreamsLocked(newStreams); + return -EINVAL; +} + +void Camera::destroyStreamsLocked(android::Vector<Stream *> &streams) { + for (size_t i = 0; i < streams.size(); i++) { + delete streams[i]; + } + streams.clear(); +} + +Stream *Camera::reuseStreamLocked(camera3_stream_t *astream) { + Stream *priv = reinterpret_cast<Stream*>(astream->priv); + // Verify the re-used stream's parameters match + if (!priv->isValidReuseStream(mId, astream)) { + ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId); + return NULL; + } + // Mark stream to be reused + priv->mReuse = true; + return priv; +} + +bool Camera::isValidStreamSetLocked(const android::Vector<Stream *> &streams) { + int inputs = 0; + int outputs = 0; + + if (streams.isEmpty()) { + ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId); + return false; + } + // Validate there is at most one input stream and at least one output stream + for (size_t i = 0; i < streams.size(); i++) { + // A stream may be both input and output (bidirectional) + if (streams[i]->isInputType()) + inputs++; + if (streams[i]->isOutputType()) + outputs++; + } + ALOGV("%s:%d: Configuring %d output streams and %d input streams", + __func__, mId, outputs, inputs); + if (outputs < 1) { + ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId); + return false; + } + if (inputs > 1) { + ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId); + return false; + } + // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams + return true; +} + +void Camera::setupStreamsLocked(android::Vector<Stream *> &streams) { + /* + * This is where the HAL has to decide internally how to handle all of the + * streams, and then produce usage and max_buffer values for each stream. + * Note, the stream vector has been checked before this point for ALL invalid + * conditions, so it must find a successful configuration for this stream + * array. The HAL may not return an error from this point. + * + * TODO: we just set all streams to be the same dummy values; + * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN. + */ + for (size_t i = 0; i < streams.size(); i++) { + uint32_t usage = 0; + + if (streams[i]->isOutputType()) + usage |= GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_CAMERA_WRITE; + if (streams[i]->isInputType()) + usage |= GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_HW_CAMERA_READ; + + streams[i]->setUsage(usage); + streams[i]->setMaxBuffers(1); + } +} + +bool Camera::isValidTemplateType(int type) { + return type >= 1 && type < CAMERA3_TEMPLATE_COUNT; +} + +const camera_metadata_t* Camera::constructDefaultRequestSettings(int type) { + ALOGV("%s:%d: type=%d", __func__, mId, type); + android::Mutex::Autolock al(mDeviceLock); + + if (!isValidTemplateType(type)) { + ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type); + return NULL; + } + + // DO NOT try to initialize the device here, it will be guaranteed deadlock. + if (!mIsInitialized) { + ALOGE("Device is not initialized yet"); + return NULL; + } + + return mTemplates[type]; +} + +// This implementation is a copy-paste, probably we should override (or move) this to +// device specific class. +int Camera::processCaptureRequest(camera3_capture_request_t *request) { + camera3_capture_result result; + ALOGV("%s:%d: request=%p", __func__, mId, request); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + if (request == NULL) { + ALOGE("%s:%d: NULL request recieved", __func__, mId); + return -EINVAL; + } + + ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId, + request->frame_number, request->settings); + + // NULL indicates use last settings + if (request->settings == NULL) { + if (mSettings == NULL) { + ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p", + __func__, mId, request->frame_number, request); + return -EINVAL; + } + } else { + updateSettingsLocked(request->settings); + } + + if (request->input_buffer != NULL) { + ALOGV("%s:%d: Reprocessing input buffer is not supported yet", __func__, mId); + return -EINVAL; + } else { + ALOGV("%s:%d: Capturing new frame.", __func__, mId); + + if (!isValidCaptureSettings(request->settings)) { + ALOGE("%s:%d: Invalid settings for capture request: %p", + __func__, mId, request->settings); + return -EINVAL; + } + } + + if (request->num_output_buffers <= 0) { + ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId, + request->num_output_buffers); + return -EINVAL; + } + result.num_output_buffers = request->num_output_buffers; + result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers]; + for (unsigned int i = 0; i < request->num_output_buffers; i++) { + int res = processCaptureBuffer(&request->output_buffers[i], + const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i])); + if (res) { + delete [] result.output_buffers; + // TODO: this should probably be a total device failure; transient for now + return -EINVAL; + } + } + + result.frame_number = request->frame_number; + // TODO: return actual captured/reprocessed settings + result.result = request->settings; + // TODO: asynchronously return results + notifyShutter(request->frame_number, 0); + mCallbackOps->process_capture_result(mCallbackOps, &result); + + // Free up capture result related resources, HAL owns the capture result, and it + // is only valid during the process_capture_result call. + delete[] result.output_buffers; + + return 0; +} + +int Camera::flush() { + int res; + + ALOGV("%s:%d: flush device", __func__, mId); + // per-device specific flush + res = flushDevice(); + if (res != 0) { + ALOGE("%s:%d: Failed to flush device!", __func__, mId); + return res; + } + return 0; +} + +void Camera::updateSettingsLocked(const camera_metadata_t *new_settings) { + if (mSettings != NULL) { + free_camera_metadata(mSettings); + mSettings = NULL; + } + + if (new_settings != NULL) + mSettings = clone_camera_metadata(new_settings); +} + +void Camera::notifyShutter(uint32_t frame_number, uint64_t timestamp) { + int res; + struct timespec ts; + + // If timestamp is 0, get timestamp from right now instead + if (timestamp == 0) { + ALOGW("%s:%d: No timestamp provided, using CLOCK_BOOTTIME", + __func__, mId); + res = clock_gettime(CLOCK_BOOTTIME, &ts); + if (res == 0) { + timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + } else { + ALOGE("%s:%d: No timestamp and failed to get CLOCK_BOOTTIME %s(%d)", + __func__, mId, strerror(errno), errno); + } + } + camera3_notify_msg_t m; + memset(&m, 0, sizeof(m)); + m.type = CAMERA3_MSG_SHUTTER; + m.message.shutter.frame_number = frame_number; + m.message.shutter.timestamp = timestamp; + mCallbackOps->notify(mCallbackOps, &m); +} + +void Camera::dump(int fd) { + ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd); + ATRACE_CALL(); + android::Mutex::Autolock al(mDeviceLock); + + dprintf(fd, "Camera ID: %d (Busy: %d)\n", mId, mBusy); + + // TODO: dump all settings + dprintf(fd, "Most Recent Settings: (%p)\n", mSettings); + + dprintf(fd, "Number of streams: %d\n", mStreams.size()); + for (size_t i = 0; i < mStreams.size(); i++) { + dprintf(fd, "Stream %d/%d:\n", i, mStreams.size()); + mStreams[i]->dump(fd); + } +} + +const char* Camera::templateToString(int type) { + switch (type) { + case CAMERA3_TEMPLATE_PREVIEW: + return "CAMERA3_TEMPLATE_PREVIEW"; + case CAMERA3_TEMPLATE_STILL_CAPTURE: + return "CAMERA3_TEMPLATE_STILL_CAPTURE"; + case CAMERA3_TEMPLATE_VIDEO_RECORD: + return "CAMERA3_TEMPLATE_VIDEO_RECORD"; + case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT: + return "CAMERA3_TEMPLATE_VIDEO_SNAPSHOT"; + case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG: + return "CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG"; + case CAMERA3_TEMPLATE_MANUAL: + return "CAMERA3_TEMPLATE_MANUAL"; + } + + return "Invalid template type!"; +} + +int Camera::setTemplate(int type, camera_metadata_t *settings) { + android::Mutex::Autolock al(mDeviceLock); + + if (!isValidTemplateType(type)) { + ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type); + return -EINVAL; + } + + if (mTemplates[type] != NULL) { + ALOGE("%s:%d: Setting already constructed template type %s(%d)", + __func__, mId, templateToString(type), type); + return -EINVAL; + } + + // Make a durable copy of the underlying metadata + mTemplates[type] = clone_camera_metadata(settings); + if (mTemplates[type] == NULL) { + ALOGE("%s:%d: Failed to clone metadata %p for template type %s(%d)", + __func__, mId, settings, templateToString(type), type); + return -EINVAL; + } + return 0; +} + +} // namespace usb_camera_hal
diff --git a/libhardware/modules/usbcamera/Camera.h b/libhardware/modules/usbcamera/Camera.h new file mode 100644 index 0000000..4051345 --- /dev/null +++ b/libhardware/modules/usbcamera/Camera.h
@@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CAMERA_H_ +#define CAMERA_H_ + +#include <hardware/hardware.h> +#include <hardware/camera3.h> +#include <utils/Mutex.h> +#include <utils/Vector.h> +#include "Metadata.h" +#include <sync/sync.h> +#include "Stream.h" + +#define CAMERA_SYNC_TIMEOUT_MS 5000 + +namespace usb_camera_hal { +// Camera represents a physical camera on a device. +// This is constructed when the HAL module is loaded, one per physical camera. +// It is opened by the framework, and must be closed before it can be opened +// again. +// This is an abstract class, containing all logic and data shared between all +// camera devices. +class Camera { + public: + // id is used to distinguish cameras. 0 <= id < NUM_CAMERAS. + // module is a handle to the HAL module, used when the device is opened. + explicit Camera(int id); + virtual ~Camera(); + + // Common Camera Device Operations (see <hardware/camera_common.h>) + int open(const hw_module_t *module, hw_device_t **device); + int getInfo(struct camera_info *info); + int close(); + + // Camera v3 Device Operations (see <hardware/camera3.h>) + int initialize(const camera3_callback_ops_t *callback_ops); + int configureStreams(camera3_stream_configuration_t *stream_list); + const camera_metadata_t *constructDefaultRequestSettings(int type); + int processCaptureRequest(camera3_capture_request_t *request); + int flush(); + void dump(int fd); + + // Update static camera characteristics. This method could be called by + // HAL hotplug thread when camera is plugged. + void updateInfo(); + + protected: + // Initialize static camera characteristics. + virtual int initStaticInfo() = 0; + // Verify settings are valid for a capture + virtual bool isValidCaptureSettings(const camera_metadata_t *) = 0; + // Separate open method for individual devices + virtual int openDevice() = 0; + // Separate initialization method for individual devices when opened + virtual int initDevice() = 0; + // Flush camera pipeline for each individual device + virtual int flushDevice() = 0; + // Separate close method for individual devices + virtual int closeDevice() = 0; + // Capture and file an output buffer for an input buffer. + virtual int processCaptureBuffer(const camera3_stream_buffer_t *in, + camera3_stream_buffer_t *out) = 0; + // Accessor method used by initDevice() to set the templates' metadata + int setTemplate(int type, camera_metadata_t *settings); + // Prettyprint template names + const char* templateToString(int type); + // Process an output buffer + + // Identifier used by framework to distinguish cameras + const int mId; + // Metadata containing persistent camera characteristics + Metadata mMetadata; + // camera_metadata structure containing static characteristics + camera_metadata_t *mStaticInfo; + + private: + // Camera device handle returned to framework for use + camera3_device_t mDevice; + // Reuse a stream already created by this device. Must be called with mDeviceLock held. + Stream *reuseStreamLocked(camera3_stream_t *astream); + // Destroy all streams in a stream array, and the array itself. Must be called with + // mDeviceLock held. + void destroyStreamsLocked(android::Vector<Stream *> &streams); + // Verify a set of streams is valid in aggregate. Must be called with mDeviceLock held. + bool isValidStreamSetLocked(const android::Vector<Stream *> &streams); + // Calculate usage and max_bufs of each stream. Must be called with mDeviceLock held. + void setupStreamsLocked(android::Vector<Stream *> &streams); + // Update new settings for re-use and clean up old settings. Must be called with + // mDeviceLock held. + void updateSettingsLocked(const camera_metadata_t *new_settings); + // Send a shutter notify message with start of exposure time + void notifyShutter(uint32_t frame_number, uint64_t timestamp); + // Is type a valid template type (and valid index into mTemplates) + bool isValidTemplateType(int type); + + // Busy flag indicates camera is in use + bool mBusy; + // Camera device operations handle shared by all devices + const static camera3_device_ops_t sOps; + // Methods used to call back into the framework + const camera3_callback_ops_t *mCallbackOps; + // Lock protecting the Camera object for modifications + android::Mutex mDeviceLock; + // Lock protecting only static camera characteristics, which may + // be accessed without the camera device open + android::Mutex mStaticInfoLock; + // Array of handles to streams currently in use by the device + android::Vector<Stream *> mStreams; + // Static array of standard camera settings templates + camera_metadata_t *mTemplates[CAMERA3_TEMPLATE_COUNT]; + // Most recent request settings seen, memoized to be reused + camera_metadata_t *mSettings; + bool mIsInitialized; +}; +} // namespace usb_camera_hal + +#endif // CAMERA_H_
diff --git a/libhardware/modules/usbcamera/CameraHAL.cpp b/libhardware/modules/usbcamera/CameraHAL.cpp new file mode 100644 index 0000000..652e937 --- /dev/null +++ b/libhardware/modules/usbcamera/CameraHAL.cpp
@@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "UsbCameraHAL" +#include <cutils/log.h> + +#include <cstdlib> +#include <hardware/camera_common.h> +#include <hardware/hardware.h> +#include "UsbCamera.h" +#include "CameraHAL.h" + +/* + * This file serves as the entry point to the HAL. It contains the module + * structure and functions used by the framework to load and interface to this + * HAL, as well as the handles to the individual camera devices. + */ + +namespace usb_camera_hal { + +static CameraHAL gCameraHAL; + +CameraHAL::CameraHAL() + : mCallbacks(NULL) { + // Should not allocate the camera devices for now, as it is unclear if the device is plugged. + + // Start hotplug thread + mHotplugThread = new HotplugThread(this); + mHotplugThread->run("usb-camera-hotplug"); +} + +CameraHAL::~CameraHAL() { + // Stop hotplug thread + { + android::Mutex::Autolock al(mModuleLock); + if (mHotplugThread != NULL) { + mHotplugThread->requestExit(); + } + + // Delete camera device from mCameras + } + + // Joining done without holding mLock, otherwise deadlocks may ensue + // as the threads try to access parent states. + if (mHotplugThread != NULL) { + mHotplugThread->join(); + } + + delete mHotplugThread; +} + +int CameraHAL::getNumberOfCameras() { + android::Mutex::Autolock al(mModuleLock); + ALOGV("%s: %d", __func__, mCameras.size()); + return static_cast<int>(mCameras.size()); +} + +int CameraHAL::getCameraInfo(int id, struct camera_info* info) { + android::Mutex::Autolock al(mModuleLock); + ALOGV("%s: camera id %d: info=%p", __func__, id, info); + if (id < 0 || id >= static_cast<int>(mCameras.size())) { + ALOGE("%s: Invalid camera id %d", __func__, id); + return -ENODEV; + } + + return mCameras[id]->getInfo(info); +} + +int CameraHAL::setCallbacks(const camera_module_callbacks_t *callbacks) { + ALOGV("%s : callbacks=%p", __func__, callbacks); + mCallbacks = callbacks; + return 0; +} + +int CameraHAL::open(const hw_module_t* mod, const char* name, hw_device_t** dev) { + int id; + char *nameEnd; + + android::Mutex::Autolock al(mModuleLock); + ALOGV("%s: module=%p, name=%s, device=%p", __func__, mod, name, dev); + if (*name == '\0') { + ALOGE("%s: Invalid camera id name is NULL", __func__); + return -EINVAL; + } + id = strtol(name, &nameEnd, 10); + if (*nameEnd != '\0') { + ALOGE("%s: Invalid camera id name %s", __func__, name); + return -EINVAL; + } else if (id < 0 || id >= static_cast<int>(mCameras.size())) { + ALOGE("%s: Invalid camera id %d", __func__, id); + return -ENODEV; + } + return mCameras[id]->open(mod, dev); +} + +extern "C" { + +static int get_number_of_cameras() { + return gCameraHAL.getNumberOfCameras(); +} + +static int get_camera_info(int id, struct camera_info* info) { + return gCameraHAL.getCameraInfo(id, info); +} + +static int set_callbacks(const camera_module_callbacks_t *callbacks) { + return gCameraHAL.setCallbacks(callbacks); +} + +static int open_dev(const hw_module_t* mod, const char* name, hw_device_t** dev) { + return gCameraHAL.open(mod, name, dev); +} + +static hw_module_methods_t gCameraModuleMethods = { + open : open_dev +}; + +camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = { + common : { + tag : HARDWARE_MODULE_TAG, + module_api_version : CAMERA_MODULE_API_VERSION_2_4, + hal_api_version : HARDWARE_HAL_API_VERSION, + id : CAMERA_HARDWARE_MODULE_ID, + name : "Default USB Camera HAL", + author : "The Android Open Source Project", + methods : &gCameraModuleMethods, + dso : NULL, + reserved : {0}, + }, + get_number_of_cameras : get_number_of_cameras, + get_camera_info : get_camera_info, + set_callbacks : set_callbacks, + get_vendor_tag_ops : NULL, + open_legacy : NULL, + set_torch_mode : NULL, + init : NULL, + reserved : {0}, +}; +} // extern "C" + +} // namespace usb_camera_hal
diff --git a/libhardware/modules/usbcamera/CameraHAL.h b/libhardware/modules/usbcamera/CameraHAL.h new file mode 100644 index 0000000..1770d95 --- /dev/null +++ b/libhardware/modules/usbcamera/CameraHAL.h
@@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CAMERA_HAL_H_ +#define CAMERA_HAL_H_ + +#include <hardware/hardware.h> +#include <hardware/camera_common.h> +#include <utils/Vector.h> +#include <utils/Mutex.h> +#include "HotplugThread.h" +#include "Camera.h" + +namespace usb_camera_hal { + +class HotplugThread; + +/** + * CameraHAL contains all module state that isn't specific to an individual camera device + */ +class CameraHAL { + public: + CameraHAL(); + ~CameraHAL(); + + // Camera Module Interface (see <hardware/camera_common.h>) + int getNumberOfCameras(); + int getCameraInfo(int camera_id, struct camera_info *info); + int setCallbacks(const camera_module_callbacks_t *callbacks); + void getVendorTagOps(vendor_tag_ops_t* ops); + + // Hardware Module Interface (see <hardware/hardware.h>) + int open(const hw_module_t* mod, const char* name, hw_device_t** dev); + + private: + // Callback handle + const camera_module_callbacks_t *mCallbacks; + android::Vector<Camera*> mCameras; + // Lock to protect the module method calls. + android::Mutex mModuleLock; + // Hot plug thread managing camera hot plug. + HotplugThread *mHotplugThread; + +}; +} // namespace usb_camera_hal + +#endif // CAMERA_HAL_H_
diff --git a/libhardware/modules/usbcamera/HotplugThread.cpp b/libhardware/modules/usbcamera/HotplugThread.cpp new file mode 100644 index 0000000..6c65086 --- /dev/null +++ b/libhardware/modules/usbcamera/HotplugThread.cpp
@@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "HotplugThread" +#include <cutils/log.h> + +#include "HotplugThread.h" + +namespace usb_camera_hal { + +HotplugThread::HotplugThread(CameraHAL *hal) + : mModule(hal) { + +} + +HotplugThread::~HotplugThread() { + +} + +void HotplugThread::requestExit() { + // Call parent to set up shutdown + Thread::requestExit(); + + // Cleanup other states? +} + +bool HotplugThread::threadLoop() { + + /** + * Check camera connection status change, if connected, do below: + * 1. Create camera device, add to mCameras. + * 2. Init static info (mCameras[id]->initStaticInfo()) + * 3. Notify on_status_change callback + * + * If unconnected, similarly, do below: + * 1. Destroy camera device and remove it from mCameras. + * 2. Notify on_status_change callback + * + * DO NOT have a tight polling loop here, to avoid excessive CPU utilization. + */ + + return true; +} + +} // namespace usb_camera_hal
diff --git a/libhardware/modules/usbcamera/HotplugThread.h b/libhardware/modules/usbcamera/HotplugThread.h new file mode 100644 index 0000000..625dcb4 --- /dev/null +++ b/libhardware/modules/usbcamera/HotplugThread.h
@@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HOTPLUG_THREAD_H_ +#define HOTPLUG_THREAD_H_ + +#include <utils/Thread.h> +#include "CameraHAL.h" + +namespace usb_camera_hal { +/** + * Thread for managing usb camera hotplug. It does below: + * 1. Monitor camera hotplug status, and notify the status changes by calling + * module callback methods. + * 2. When camera is plugged, create camera device instance, initialize the camera + * static info. When camera is unplugged, destroy the camera device instance and + * static metadata. As an optimization option, the camera device instance (including + * the static info) could be cached when the same camera plugged/unplugged multiple + * times. + */ + +class CameraHAL; + +class HotplugThread : public android::Thread { + + public: + explicit HotplugThread(CameraHAL *hal); + ~HotplugThread(); + + // Override below two methods for proper cleanup. + virtual bool threadLoop(); + virtual void requestExit(); + + private: + CameraHAL *mModule; +}; + +} // namespace usb_camera_hal + +#endif // HOTPLUG_THREAD_H_
diff --git a/libhardware/modules/usbcamera/Metadata.cpp b/libhardware/modules/usbcamera/Metadata.cpp new file mode 100644 index 0000000..f243834 --- /dev/null +++ b/libhardware/modules/usbcamera/Metadata.cpp
@@ -0,0 +1,160 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Metadata" +#include <cutils/log.h> + +#include <system/camera_metadata.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Metadata.h" + +namespace usb_camera_hal { + +Metadata::Metadata(): + mData(NULL) { +} + +Metadata::~Metadata() { + replace(NULL); +} + +void Metadata::replace(camera_metadata_t *m) { + if (m == mData) { + return; + } + if (mData) + free_camera_metadata(mData); + mData = m; +} + +int Metadata::init(const camera_metadata_t *metadata) { + camera_metadata_t* tmp; + + if (!validate_camera_metadata_structure(metadata, NULL)) + return -EINVAL; + + tmp = clone_camera_metadata(metadata); + if (tmp == NULL) + return -EINVAL; + + replace(tmp); + return 0; +} + +int Metadata::addUInt8(uint32_t tag, int count, const uint8_t *data) { + if (!validate(tag, TYPE_BYTE, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::add1UInt8(uint32_t tag, const uint8_t data) { + return addUInt8(tag, 1, &data); +} + +int Metadata::addInt32(uint32_t tag, int count, const int32_t *data) { + if (!validate(tag, TYPE_INT32, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addFloat(uint32_t tag, int count, const float *data) { + if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addInt64(uint32_t tag, int count, const int64_t *data) { + if (!validate(tag, TYPE_INT64, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addDouble(uint32_t tag, int count, const double *data) { + if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addRational(uint32_t tag, int count, + const camera_metadata_rational_t *data) { + if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL; + return add(tag, count, data); +} + +bool Metadata::validate(uint32_t tag, int tag_type, int count) { + if (get_camera_metadata_tag_type(tag) < 0) { + ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag); + return false; + } + if (tag_type < 0 || tag_type >= NUM_TYPES) { + ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type); + return false; + } + if (tag_type != get_camera_metadata_tag_type(tag)) { + ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag, + camera_metadata_type_names[tag_type], tag_type); + return false; + } + if (count < 1) { + ALOGE("%s: Invalid metadata entry count: %d", __func__, count); + return false; + } + return true; +} + +int Metadata::add(uint32_t tag, int count, const void *tag_data) { + // Opportunistically attempt to add if metadata has room for it + if (!add_camera_metadata_entry(mData, tag, tag_data, count)) { + return 0; + } + + int res; + camera_metadata_t* tmp; + int tag_type = get_camera_metadata_tag_type(tag); + size_t size = calculate_camera_metadata_entry_data_size(tag_type, count); + size_t entry_capacity = get_camera_metadata_entry_count(mData) + 1; + size_t data_capacity = get_camera_metadata_data_count(mData) + size; + + // Double new dimensions to minimize future reallocations + tmp = allocate_camera_metadata(entry_capacity * 2, data_capacity * 2); + if (tmp == NULL) { + ALOGE("%s: Failed to allocate new metadata with %zu entries, %zu data", + __func__, entry_capacity, data_capacity); + return -ENOMEM; + } + // Append the current metadata to the new (empty) metadata + res = append_camera_metadata(tmp, mData); + if (res) { + ALOGE("%s: Failed to append old metadata %p to new %p", + __func__, mData, tmp); + return res; + } + // Add the remaining new item + res = add_camera_metadata_entry(tmp, tag, tag_data, count); + if (res) { + ALOGE("%s: Failed to add new entry (%d, %p, %d) to metadata %p", + __func__, tag, tag_data, count, tmp); + return res; + } + + replace(tmp); + return 0; +} + +camera_metadata_t* Metadata::get() { + return mData; +} + +} // namespace usb_camera_hal
diff --git a/libhardware/modules/usbcamera/Metadata.h b/libhardware/modules/usbcamera/Metadata.h new file mode 100644 index 0000000..288db16 --- /dev/null +++ b/libhardware/modules/usbcamera/Metadata.h
@@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef METADATA_H_ +#define METADATA_H_ + +#include <stdint.h> +#include <hardware/camera3.h> +#include <system/camera_metadata.h> + +namespace usb_camera_hal { +// Metadata is a convenience class for dealing with libcamera_metadata +class Metadata { + public: + Metadata(); + ~Metadata(); + // Initialize with framework metadata + int init(const camera_metadata_t *metadata); + + // Parse and add an entry. Allocates and copies new storage for *data. + int addUInt8(uint32_t tag, int count, const uint8_t *data); + int add1UInt8(uint32_t tag, const uint8_t data); + int addInt32(uint32_t tag, int count, const int32_t *data); + int addFloat(uint32_t tag, int count, const float *data); + int addInt64(uint32_t tag, int count, const int64_t *data); + int addDouble(uint32_t tag, int count, const double *data); + int addRational(uint32_t tag, int count, + const camera_metadata_rational_t *data); + + // Get a handle to the current metadata + // This is not a durable handle, and may be destroyed by add*/init + camera_metadata_t* get(); + + private: + // Actual internal storage + camera_metadata_t* mData; + // Destroy old metadata and replace with new + void replace(camera_metadata_t *m); + // Validate the tag, type and count for a metadata entry + bool validate(uint32_t tag, int tag_type, int count); + // Add a verified tag with data + int add(uint32_t tag, int count, const void *tag_data); +}; +} // namespace usb_camera_hal + +#endif // METADATA_H_
diff --git a/libhardware/modules/usbcamera/Stream.cpp b/libhardware/modules/usbcamera/Stream.cpp new file mode 100644 index 0000000..f56866e --- /dev/null +++ b/libhardware/modules/usbcamera/Stream.cpp
@@ -0,0 +1,180 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Stream" +#include <cutils/log.h> + +#include <stdio.h> +#include <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/graphics.h> +#include <utils/Mutex.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Stream.h" + +namespace usb_camera_hal { + +Stream::Stream(int id, camera3_stream_t *s) + : mReuse(false), + mId(id), + mStream(s){ +} + +Stream::~Stream() { + for (size_t i = 0; i < mBuffers.size(); i++) { + delete mBuffers[i]; + } + + mBuffers.clear(); +} + +void Stream::setUsage(uint32_t usage) { + android::Mutex::Autolock al(mLock); + if (usage != mStream->usage) { + mStream->usage = usage; + } +} + +void Stream::setMaxBuffers(uint32_t max_buffers) { + android::Mutex::Autolock al(mLock); + if (max_buffers != mStream->max_buffers) { + mStream->max_buffers = max_buffers; + } +} + +int Stream::getType() { + return mStream->stream_type; +} + +bool Stream::isInputType() { + return mStream->stream_type == CAMERA3_STREAM_INPUT || + mStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL; +} + +bool Stream::isOutputType() { + return mStream->stream_type == CAMERA3_STREAM_OUTPUT || + mStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL; +} + +const char* Stream::typeToString(int type) { + switch (type) { + case CAMERA3_STREAM_INPUT: + return "CAMERA3_STREAM_INPUT"; + case CAMERA3_STREAM_OUTPUT: + return "CAMERA3_STREAM_OUTPUT"; + case CAMERA3_STREAM_BIDIRECTIONAL: + return "CAMERA3_STREAM_BIDIRECTIONAL"; + } + return "Invalid stream type!"; +} + +const char* Stream::formatToString(int format) { + // See <system/graphics.h> for full list + switch (format) { + case HAL_PIXEL_FORMAT_BGRA_8888: + return "BGRA 8888"; + case HAL_PIXEL_FORMAT_RGBA_8888: + return "RGBA 8888"; + case HAL_PIXEL_FORMAT_RGBX_8888: + return "RGBX 8888"; + case HAL_PIXEL_FORMAT_RGB_888: + return "RGB 888"; + case HAL_PIXEL_FORMAT_RGB_565: + return "RGB 565"; + case HAL_PIXEL_FORMAT_Y8: + return "Y8"; + case HAL_PIXEL_FORMAT_Y16: + return "Y16"; + case HAL_PIXEL_FORMAT_YV12: + return "YV12"; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + return "NV16"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return "NV21"; + case HAL_PIXEL_FORMAT_YCbCr_422_I: + return "YUY2"; + case HAL_PIXEL_FORMAT_RAW10: + return "RAW10"; + case HAL_PIXEL_FORMAT_RAW16: + return "RAW16"; + case HAL_PIXEL_FORMAT_BLOB: + return "BLOB"; + case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: + return "IMPLEMENTATION DEFINED"; + case HAL_PIXEL_FORMAT_YCbCr_420_888: + return "FLEXIBLE YCbCr 420 888"; + } + return "Invalid stream format!"; +} + +bool Stream::isValidReuseStream(int id, camera3_stream_t *s) { + if (id != mId) { + ALOGE("%s:%d: Invalid camera id for reuse. Got %d expect %d", + __func__, mId, id, mId); + return false; + } + if (s != mStream) { + ALOGE("%s:%d: Invalid stream handle for reuse. Got %p expect %p", + __func__, mId, s, mStream); + return false; + } + if (s->stream_type != mStream->stream_type) { + ALOGE("%s:%d: Mismatched type in reused stream. Got %s(%d) " + "expect %s(%d)", __func__, mId, typeToString(s->stream_type), + s->stream_type, typeToString(mStream->stream_type), mStream->stream_type); + return false; + } + if (s->format != mStream->format) { + ALOGE("%s:%d: Mismatched format in reused stream. Got %s(%d) " + "expect %s(%d)", __func__, mId, formatToString(s->format), + s->format, formatToString(mStream->format), mStream->format); + return false; + } + if (s->width != mStream->width) { + ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d", + __func__, mId, s->width, mStream->width); + return false; + } + if (s->height != mStream->height) { + ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d", + __func__, mId, s->height, mStream->height); + return false; + } + return true; +} + +void Stream::dump(int fd) { + android::Mutex::Autolock al(mLock); + + dprintf(fd, "Stream ID: %d (%p)\n", mId, mStream); + dprintf(fd, "Stream Type: %s (%d)\n", typeToString(mStream->stream_type), mStream->stream_type); + dprintf(fd, "Width: %" PRIu32 " Height: %" PRIu32 "\n", mStream->width, mStream->height); + dprintf(fd, "Stream Format: %s (%d)", formatToString(mStream->format), mStream->format); + // ToDo: prettyprint usage mask flags + dprintf(fd, "Gralloc Usage Mask: %#" PRIx32 "\n", mStream->usage); + dprintf(fd, "Max Buffer Count: %" PRIu32 "\n", mStream->max_buffers); + dprintf(fd, "Number of Buffers in use by HAL: %" PRIu32 "\n", mBuffers.size()); + for (size_t i = 0; i < mBuffers.size(); i++) { + dprintf(fd, "Buffer %" PRIu32 "/%" PRIu32 ": %p\n", i, mBuffers.size(), + mBuffers[i]); + } +} + +} // namespace usb_camera_hal
diff --git a/libhardware/modules/usbcamera/Stream.h b/libhardware/modules/usbcamera/Stream.h new file mode 100644 index 0000000..022ca9f --- /dev/null +++ b/libhardware/modules/usbcamera/Stream.h
@@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STREAM_H_ +#define STREAM_H_ + +#include <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/graphics.h> +#include <utils/Mutex.h> +#include <utils/Vector.h> + +namespace usb_camera_hal { +// Stream represents a single input or output stream for a camera device. +class Stream { + public: + Stream(int id, camera3_stream_t *s); + ~Stream(); + + // validate that a stream's parameters match this stream's parameters + bool isValidReuseStream(int id, camera3_stream_t *s); + + void setUsage(uint32_t usage); + void setMaxBuffers(uint32_t max_buffers); + + int getType(); + bool isInputType(); + bool isOutputType(); + const char* typeToString(int type); + const char* formatToString(int format); + void dump(int fd); + + // This stream is being reused. Used in stream configuration passes + bool mReuse; + + private: + // The camera device id this stream belongs to + const int mId; + // Handle to framework's stream, used as a cookie for buffers + camera3_stream_t *mStream; + // Array of handles to buffers currently in use by the stream + android::Vector<buffer_handle_t *> mBuffers; + // Lock protecting the Stream object for modifications + android::Mutex mLock; +}; +} // namespace usb_camera_hal + +#endif // STREAM_H_
diff --git a/libhardware/modules/usbcamera/UsbCamera.cpp b/libhardware/modules/usbcamera/UsbCamera.cpp new file mode 100644 index 0000000..d0aaded --- /dev/null +++ b/libhardware/modules/usbcamera/UsbCamera.cpp
@@ -0,0 +1,321 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "UsbCameraDevice" +#include <cutils/log.h> + +#include <system/camera_metadata.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <utils/Trace.h> + +#include "Camera.h" +#include "UsbCamera.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +namespace usb_camera_hal { + +UsbCamera::UsbCamera(int id) : Camera(id) { +} + +UsbCamera::~UsbCamera() { +} + +int UsbCamera::initStaticInfo() { + /* + * Setup static camera info. This will have to customized per camera + * device. + * TODO: this is just some sample code, need tailor for USB cameras. + */ + if (mStaticInfo != NULL) { + free_camera_metadata(mStaticInfo); + } + + Metadata m; + + /* android.control */ + int32_t android_control_ae_available_target_fps_ranges[] = {30, 30}; + m.addInt32(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + ARRAY_SIZE(android_control_ae_available_target_fps_ranges), + android_control_ae_available_target_fps_ranges); + + int32_t android_control_ae_compensation_range[] = {-4, 4}; + m.addInt32(ANDROID_CONTROL_AE_COMPENSATION_RANGE, + ARRAY_SIZE(android_control_ae_compensation_range), + android_control_ae_compensation_range); + + camera_metadata_rational_t android_control_ae_compensation_step[] = {{2,1}}; + m.addRational(ANDROID_CONTROL_AE_COMPENSATION_STEP, + ARRAY_SIZE(android_control_ae_compensation_step), + android_control_ae_compensation_step); + + int32_t android_control_max_regions[] = {/*AE*/ 1,/*AWB*/ 1,/*AF*/ 1}; + m.addInt32(ANDROID_CONTROL_MAX_REGIONS, + ARRAY_SIZE(android_control_max_regions), + android_control_max_regions); + + /* android.jpeg */ + int32_t android_jpeg_available_thumbnail_sizes[] = {0, 0, 128, 96}; + m.addInt32(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, + ARRAY_SIZE(android_jpeg_available_thumbnail_sizes), + android_jpeg_available_thumbnail_sizes); + + int32_t android_jpeg_max_size[] = {13 * 1024 * 1024}; // 13MB + m.addInt32(ANDROID_JPEG_MAX_SIZE, + ARRAY_SIZE(android_jpeg_max_size), + android_jpeg_max_size); + + /* android.lens */ + float android_lens_info_available_focal_lengths[] = {1.0}; + m.addFloat(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, + ARRAY_SIZE(android_lens_info_available_focal_lengths), + android_lens_info_available_focal_lengths); + + /* android.request */ + int32_t android_request_max_num_output_streams[] = {0, 3, 1}; + m.addInt32(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, + ARRAY_SIZE(android_request_max_num_output_streams), + android_request_max_num_output_streams); + + /* android.scaler */ + int32_t android_scaler_available_formats[] = { + HAL_PIXEL_FORMAT_RAW16, + HAL_PIXEL_FORMAT_BLOB, + HAL_PIXEL_FORMAT_RGBA_8888, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + // These are handled by YCbCr_420_888 + // HAL_PIXEL_FORMAT_YV12, + // HAL_PIXEL_FORMAT_YCrCb_420_SP, + HAL_PIXEL_FORMAT_YCbCr_420_888}; + m.addInt32(ANDROID_SCALER_AVAILABLE_FORMATS, + ARRAY_SIZE(android_scaler_available_formats), + android_scaler_available_formats); + + int64_t android_scaler_available_jpeg_min_durations[] = {1}; + m.addInt64(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_jpeg_min_durations), + android_scaler_available_jpeg_min_durations); + + int32_t android_scaler_available_jpeg_sizes[] = {640, 480}; + m.addInt32(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, + ARRAY_SIZE(android_scaler_available_jpeg_sizes), + android_scaler_available_jpeg_sizes); + + float android_scaler_available_max_digital_zoom[] = {1}; + m.addFloat(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, + ARRAY_SIZE(android_scaler_available_max_digital_zoom), + android_scaler_available_max_digital_zoom); + + int64_t android_scaler_available_processed_min_durations[] = {1}; + m.addInt64(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_processed_min_durations), + android_scaler_available_processed_min_durations); + + int32_t android_scaler_available_processed_sizes[] = {640, 480}; + m.addInt32(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, + ARRAY_SIZE(android_scaler_available_processed_sizes), + android_scaler_available_processed_sizes); + + int64_t android_scaler_available_raw_min_durations[] = {1}; + m.addInt64(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_raw_min_durations), + android_scaler_available_raw_min_durations); + + int32_t android_scaler_available_raw_sizes[] = {640, 480}; + m.addInt32(ANDROID_SCALER_AVAILABLE_RAW_SIZES, + ARRAY_SIZE(android_scaler_available_raw_sizes), + android_scaler_available_raw_sizes); + + /* android.sensor */ + + int32_t android_sensor_info_active_array_size[] = {0, 0, 640, 480}; + m.addInt32(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, + ARRAY_SIZE(android_sensor_info_active_array_size), + android_sensor_info_active_array_size); + + int32_t android_sensor_info_sensitivity_range[] = + {100, 1600}; + m.addInt32(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE, + ARRAY_SIZE(android_sensor_info_sensitivity_range), + android_sensor_info_sensitivity_range); + + int64_t android_sensor_info_max_frame_duration[] = {30000000000}; + m.addInt64(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, + ARRAY_SIZE(android_sensor_info_max_frame_duration), + android_sensor_info_max_frame_duration); + + float android_sensor_info_physical_size[] = {3.2, 2.4}; + m.addFloat(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, + ARRAY_SIZE(android_sensor_info_physical_size), + android_sensor_info_physical_size); + + int32_t android_sensor_info_pixel_array_size[] = {640, 480}; + m.addInt32(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, + ARRAY_SIZE(android_sensor_info_pixel_array_size), + android_sensor_info_pixel_array_size); + + int32_t android_sensor_orientation[] = {0}; + m.addInt32(ANDROID_SENSOR_ORIENTATION, + ARRAY_SIZE(android_sensor_orientation), + android_sensor_orientation); + + /* End of static camera characteristics */ + + mStaticInfo = clone_camera_metadata(m.get()); + + return 0; +} + +int UsbCamera::openDevice() { + // TODO: implement usb camera device open sequence: open device nodes etc. + + return 0; +} + +int UsbCamera::closeDevice() { + // TODO: implement usb camera device close sequence: close device nodes etc. + + return 0; +} + +int UsbCamera::processCaptureBuffer(const camera3_stream_buffer_t *in, + camera3_stream_buffer_t *out) { + if (in->acquire_fence != -1) { + int res = sync_wait(in->acquire_fence, CAMERA_SYNC_TIMEOUT_MS); + if (res == -ETIME) { + ALOGE("%s:%d: Timeout waiting on buffer acquire fence", + __func__, mId); + return res; + } else if (res) { + ALOGE("%s:%d: Error waiting on buffer acquire fence: %s(%d)", + __func__, mId, strerror(-res), res); + return res; + } + } + + out->stream = in->stream; + out->buffer = in->buffer; + out->status = CAMERA3_BUFFER_STATUS_OK; + // TODO: use driver-backed release fences + out->acquire_fence = -1; + out->release_fence = -1; + + // TODO: lock and software-paint buffer + return 0; +} + +int UsbCamera::initDevice() { + int res; + Metadata base; + + // Create standard settings templates from copies of base metadata + res = base.add1UInt8(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_OFF); + if (res) + return res; + + // Use base settings to create all other templates and set them. This is just some samples, + // More initialization may be needed. + res = initPreviewTemplate(base); + if (res) + return res; + res = initStillTemplate(base); + if (res) + return res; + res = initRecordTemplate(base); + if (res) + return res; + res = initSnapshotTemplate(base); + if (res) + return res; + res = initZslTemplate(base); + if (res) + return res; + res = initManualTemplate(base); + if (res) + return res; + + return 0; +} + +int UsbCamera::initPreviewTemplate(Metadata m) { + // Setup default preview controls + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW); + + if (res) + return res; + // TODO: set fast auto-focus, auto-whitebalance, auto-exposure, auto flash + return setTemplate(CAMERA3_TEMPLATE_PREVIEW, m.get()); +} + +int UsbCamera::initStillTemplate(Metadata m) { + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE); + // Setup default still capture controls + if (res) + return res; + // TODO: set fast auto-focus, auto-whitebalance, auto-exposure, auto flash + return setTemplate(CAMERA3_TEMPLATE_STILL_CAPTURE, m.get()); +} + +int UsbCamera::initRecordTemplate(Metadata m) { + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + // Setup default video record controls + if (res) + return res; + // TODO: set slow auto-focus, auto-whitebalance, auto-exposure, flash off + return setTemplate(CAMERA3_TEMPLATE_VIDEO_RECORD, m.get()); +} + +int UsbCamera::initSnapshotTemplate(Metadata m) { + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT); + // Setup default video snapshot controls + if (res) + return res; + // TODO: set slow auto-focus, auto-whitebalance, auto-exposure, flash off + return setTemplate(CAMERA3_TEMPLATE_VIDEO_SNAPSHOT, m.get()); +} + +int UsbCamera::initZslTemplate(Metadata m) { + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG); + // Setup default zero shutter lag controls + if (res) + return res; + // TODO: set reprocessing parameters for zsl input queue + return setTemplate(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG, m.get()); +} + +int UsbCamera::initManualTemplate(Metadata m) { + int res = m.add1UInt8(ANDROID_CONTROL_CAPTURE_INTENT, + ANDROID_CONTROL_CAPTURE_INTENT_MANUAL); + // Setup manual controls + if (res) + return res; + // TODO: set reprocessing parameters for zsl input queue + return setTemplate(CAMERA3_TEMPLATE_MANUAL, m.get()); +} + +bool UsbCamera::isValidCaptureSettings(const camera_metadata_t* settings) { + // TODO: reject settings that cannot be captured + return true; +} + +} // namespace usb_camera_hal
diff --git a/libhardware/modules/usbcamera/UsbCamera.h b/libhardware/modules/usbcamera/UsbCamera.h new file mode 100644 index 0000000..57017fe --- /dev/null +++ b/libhardware/modules/usbcamera/UsbCamera.h
@@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EXAMPLE_CAMERA_H_ +#define EXAMPLE_CAMERA_H_ + +#include <system/camera_metadata.h> +#include "Camera.h" + +namespace usb_camera_hal { +/** + * UsbCamera is an example for a specific camera device. The Camera instance contains + * a specific camera device (e.g. UsbCamera) holds all specific metadata and logic about + * that device. + */ +class UsbCamera : public Camera { + public: + explicit UsbCamera(int id); + ~UsbCamera(); + + private: + // Initialize static camera characteristics for individual device + int initStaticInfo(); + int openDevice(); + // Initialize whole device (templates/etc) when opened + int initDevice(); + int flushDevice(); + int closeDevice(); + int processCaptureBuffer(const camera3_stream_buffer_t *in, camera3_stream_buffer_t *out); + // Initialize each template metadata controls + int initPreviewTemplate(Metadata m); + int initStillTemplate(Metadata m); + int initRecordTemplate(Metadata m); + int initSnapshotTemplate(Metadata m); + int initZslTemplate(Metadata m); + int initManualTemplate(Metadata m); + // Verify settings are valid for a capture with this device + bool isValidCaptureSettings(const camera_metadata_t* settings); +}; +} // namespace usb_camera_hal + +#endif // CAMERA_H_
diff --git a/libhardware/modules/vibrator/Android.bp b/libhardware/modules/vibrator/Android.bp new file mode 100644 index 0000000..f9afd45 --- /dev/null +++ b/libhardware/modules/vibrator/Android.bp
@@ -0,0 +1,24 @@ +// Copyright (C) 2012 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. + +cc_library_shared { + name: "vibrator.default", + + // HAL module implementation stored in + // hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so + relative_install_path: "hw", + include_dirs: ["hardware/libhardware"], + srcs: ["vibrator.c"], + shared_libs: ["liblog"], +}
diff --git a/libhardware/modules/vibrator/vibrator.c b/libhardware/modules/vibrator/vibrator.c new file mode 100644 index 0000000..c3c2951 --- /dev/null +++ b/libhardware/modules/vibrator/vibrator.c
@@ -0,0 +1,194 @@ +/* + * Copyright (C) 2013 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 <hardware/vibrator.h> +#include <hardware/hardware.h> + +#include <cutils/log.h> + +#include <malloc.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> + +#define TIMEOUT_STR_LEN 20 + +static const char THE_DEVICE[] = "/sys/class/timed_output/vibrator/enable"; + +static int vibra_exists() { + int fd; + + fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR)); + if(fd < 0) { + return 0; + } + + close(fd); + return 1; +} + +static int write_value(const char *file, const char *value) +{ + int to_write, written, ret, fd; + + fd = TEMP_FAILURE_RETRY(open(file, O_WRONLY)); + if (fd < 0) { + return -errno; + } + + to_write = strlen(value) + 1; + written = TEMP_FAILURE_RETRY(write(fd, value, to_write)); + if (written == -1) { + ret = -errno; + } else if (written != to_write) { + /* even though EAGAIN is an errno value that could be set + by write() in some cases, none of them apply here. So, this return + value can be clearly identified when debugging and suggests the + caller that it may try to call vibrator_on() again */ + ret = -EAGAIN; + } else { + ret = 0; + } + + errno = 0; + close(fd); + + return ret; +} + +static int sendit(unsigned int timeout_ms) +{ + char value[TIMEOUT_STR_LEN]; /* large enough for millions of years */ + + snprintf(value, sizeof(value), "%u", timeout_ms); + return write_value(THE_DEVICE, value); +} + +static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms) +{ + /* constant on, up to maximum allowed time */ + return sendit(timeout_ms); +} + +static int vibra_off(vibrator_device_t* vibradev __unused) +{ + return sendit(0); +} + +static const char LED_DEVICE[] = "/sys/class/leds/vibrator"; + +static int write_led_file(const char *file, const char *value) +{ + char file_str[50]; + + snprintf(file_str, sizeof(file_str), "%s/%s", LED_DEVICE, file); + return write_value(file_str, value); +} + +static int vibra_led_exists() +{ + return !write_led_file("trigger", "transient"); +} + +static int vibra_led_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms) +{ + int ret; + char value[TIMEOUT_STR_LEN]; /* large enough for millions of years */ + + ret = write_led_file("state", "1"); + if (ret) + return ret; + + snprintf(value, sizeof(value), "%u\n", timeout_ms); + ret = write_led_file("duration", value); + if (ret) + return ret; + + return write_led_file("activate", "1"); +} + +static int vibra_led_off(vibrator_device_t* vibradev __unused) +{ + return write_led_file("activate", "0"); +} + +static int vibra_close(hw_device_t *device) +{ + free(device); + return 0; +} + +static int vibra_open(const hw_module_t* module, const char* id __unused, + hw_device_t** device __unused) { + bool use_led; + + if (vibra_exists()) { + ALOGD("Vibrator using timed_output"); + use_led = false; + } else if (vibra_led_exists()) { + ALOGD("Vibrator using LED trigger"); + use_led = true; + } else { + ALOGE("Vibrator device does not exist. Cannot start vibrator"); + return -ENODEV; + } + + vibrator_device_t *vibradev = calloc(1, sizeof(vibrator_device_t)); + + if (!vibradev) { + ALOGE("Can not allocate memory for the vibrator device"); + return -ENOMEM; + } + + vibradev->common.tag = HARDWARE_DEVICE_TAG; + vibradev->common.module = (hw_module_t *) module; + vibradev->common.version = HARDWARE_DEVICE_API_VERSION(1,0); + vibradev->common.close = vibra_close; + + if (use_led) { + vibradev->vibrator_on = vibra_led_on; + vibradev->vibrator_off = vibra_led_off; + } else { + vibradev->vibrator_on = vibra_on; + vibradev->vibrator_off = vibra_off; + } + + *device = (hw_device_t *) vibradev; + + return 0; +} + +/*===========================================================================*/ +/* Default vibrator HW module interface definition */ +/*===========================================================================*/ + +static struct hw_module_methods_t vibrator_module_methods = { + .open = vibra_open, +}; + +struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = VIBRATOR_API_VERSION, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = VIBRATOR_HARDWARE_MODULE_ID, + .name = "Default vibrator HAL", + .author = "The Android Open Source Project", + .methods = &vibrator_module_methods, +};
diff --git a/libhardware/tests/Android.mk b/libhardware/tests/Android.mk new file mode 100644 index 0000000..5053e7d --- /dev/null +++ b/libhardware/tests/Android.mk
@@ -0,0 +1 @@ +include $(call all-subdir-makefiles)
diff --git a/libhardware/tests/camera2/Android.mk b/libhardware/tests/camera2/Android.mk new file mode 100644 index 0000000..e45f467 --- /dev/null +++ b/libhardware/tests/camera2/Android.mk
@@ -0,0 +1,43 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + camera2_utils.cpp \ + main.cpp \ + CameraMetadataTests.cpp \ + CameraModuleTests.cpp \ + CameraStreamTests.cpp \ + CameraFrameTests.cpp \ + CameraBurstTests.cpp \ + CameraMultiStreamTests.cpp\ + ForkedTests.cpp \ + TestForkerEventListener.cpp \ + TestSettings.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libutils \ + libcutils \ + libhardware \ + libcamera_metadata \ + libcameraservice \ + libcamera_client \ + libgui \ + libsync \ + libui \ + libdl + +LOCAL_C_INCLUDES += \ + system/media/camera/include \ + frameworks/av/include/ \ + frameworks/av/services/camera/libcameraservice \ + frameworks/native/include \ + +LOCAL_CFLAGS += -Wall -Wextra +LOCAL_MODULE:= camera2_test +LOCAL_MODULE_STEM_32 := camera2_test +LOCAL_MODULE_STEM_64 := camera2_test64 +LOCAL_MULTILIB := both +LOCAL_MODULE_TAGS := tests + +include $(BUILD_NATIVE_TEST)
diff --git a/libhardware/tests/camera2/CameraBurstTests.cpp b/libhardware/tests/camera2/CameraBurstTests.cpp new file mode 100644 index 0000000..198c0c1 --- /dev/null +++ b/libhardware/tests/camera2/CameraBurstTests.cpp
@@ -0,0 +1,731 @@ +/* + * Copyright (C) 2012 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 <gtest/gtest.h> +#include <inttypes.h> + +#define LOG_TAG "CameraBurstTest" +//#define LOG_NDEBUG 0 +#include <utils/Log.h> +#include <utils/Timers.h> + +#include <cmath> + +#include "CameraStreamFixture.h" +#include "TestExtensions.h" + +#define CAMERA_FRAME_TIMEOUT 1000000000LL //nsecs (1 secs) +#define CAMERA_HEAP_COUNT 2 //HALBUG: 1 means registerBuffers fails +#define CAMERA_BURST_DEBUGGING 0 +#define CAMERA_FRAME_BURST_COUNT 10 + +/* constants for the exposure test */ +#define CAMERA_EXPOSURE_DOUBLE 2 +#define CAMERA_EXPOSURE_DOUBLING_THRESHOLD 1.0f +#define CAMERA_EXPOSURE_DOUBLING_COUNT 4 +#define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT +#define CAMERA_EXPOSURE_STARTING 100000 // 1/10ms, up to 51.2ms with 10 steps + +#define USEC 1000LL // in ns +#define MSEC 1000000LL // in ns +#define SEC 1000000000LL // in ns + +#if CAMERA_BURST_DEBUGGING +#define dout std::cout +#else +#define dout if (0) std::cout +#endif + +#define WARN_UNLESS(condition) if(!(condition)) std::cerr << "Warning: " +#define WARN_LE(exp, act) WARN_UNLESS((exp) <= (act)) +#define WARN_LT(exp, act) WARN_UNLESS((exp) < (act)) +#define WARN_GT(exp, act) WARN_UNLESS((exp) > (act)) + +using namespace android; +using namespace android::camera2; + +namespace android { +namespace camera2 { +namespace tests { + +static CameraStreamParams STREAM_PARAMETERS = { + /*mFormat*/ CAMERA_EXPOSURE_FORMAT, + /*mHeapCount*/ CAMERA_HEAP_COUNT +}; + +class CameraBurstTest + : public ::testing::Test, + public CameraStreamFixture { + +public: + CameraBurstTest() : CameraStreamFixture(STREAM_PARAMETERS) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + + if (HasFatalFailure()) { + return; + } + + CreateStream(); + } + + ~CameraBurstTest() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + + if (mDevice.get()) { + mDevice->waitUntilDrained(); + } + DeleteStream(); + } + + virtual void SetUp() { + TEST_EXTENSION_FORKING_SET_UP; + } + virtual void TearDown() { + TEST_EXTENSION_FORKING_TEAR_DOWN; + } + + /* this assumes the format is YUV420sp or flexible YUV */ + long long TotalBrightness(const CpuConsumer::LockedBuffer& imgBuffer, + int *underexposed, + int *overexposed) const { + + const uint8_t* buf = imgBuffer.data; + size_t stride = imgBuffer.stride; + + /* iterate over the Y plane only */ + long long acc = 0; + + *underexposed = 0; + *overexposed = 0; + + for (size_t y = 0; y < imgBuffer.height; ++y) { + for (size_t x = 0; x < imgBuffer.width; ++x) { + const uint8_t p = buf[y * stride + x]; + + if (p == 0) { + if (underexposed) { + ++*underexposed; + } + continue; + } else if (p == 255) { + if (overexposed) { + ++*overexposed; + } + continue; + } + + acc += p; + } + } + + return acc; + } + + // Parses a comma-separated string list into a Vector + template<typename T> + void ParseList(const char *src, Vector<T> &list) { + std::istringstream s(src); + while (!s.eof()) { + char c = s.peek(); + if (c == ',' || c == ' ') { + s.ignore(1, EOF); + continue; + } + T val; + s >> val; + list.push_back(val); + } + } + +}; + +TEST_F(CameraBurstTest, ManualExposureControl) { + + TEST_EXTENSION_FORKING_INIT; + + // Range of valid exposure times, in nanoseconds + int64_t minExp, maxExp; + { + camera_metadata_ro_entry exposureTimeRange = + GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE); + + ASSERT_EQ(2u, exposureTimeRange.count); + minExp = exposureTimeRange.data.i64[0]; + maxExp = exposureTimeRange.data.i64[1]; + } + + dout << "Min exposure is " << minExp; + dout << " max exposure is " << maxExp << std::endl; + + // Calculate some set of valid exposure times for each request + int64_t exposures[CAMERA_FRAME_BURST_COUNT]; + exposures[0] = CAMERA_EXPOSURE_STARTING; + for (int i = 1; i < CAMERA_FRAME_BURST_COUNT; ++i) { + exposures[i] = exposures[i-1] * CAMERA_EXPOSURE_DOUBLE; + } + // Our calculated exposure times should be in [minExp, maxExp] + EXPECT_LE(minExp, exposures[0]) + << "Minimum exposure range is too high, wanted at most " + << exposures[0] << "ns"; + EXPECT_GE(maxExp, exposures[CAMERA_FRAME_BURST_COUNT-1]) + << "Maximum exposure range is too low, wanted at least " + << exposures[CAMERA_FRAME_BURST_COUNT-1] << "ns"; + + // Create a preview request, turning off all 3A + CameraMetadata previewRequest; + ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, + &previewRequest)); + { + Vector<int32_t> outputStreamIds; + outputStreamIds.push(mStreamId); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, + outputStreamIds)); + + // Disable all 3A routines + uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF); + ASSERT_EQ(OK, previewRequest.update(ANDROID_CONTROL_MODE, + &cmOff, 1)); + + int requestId = 1; + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID, + &requestId, 1)); + + if (CAMERA_BURST_DEBUGGING) { + int frameCount = 0; + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_FRAME_COUNT, + &frameCount, 1)); + } + } + + if (CAMERA_BURST_DEBUGGING) { + previewRequest.dump(STDOUT_FILENO); + } + + // Submit capture requests + for (int i = 0; i < CAMERA_FRAME_BURST_COUNT; ++i) { + CameraMetadata tmpRequest = previewRequest; + ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_EXPOSURE_TIME, + &exposures[i], 1)); + ALOGV("Submitting capture request %d with exposure %" PRId64, i, + exposures[i]); + dout << "Capture request " << i << " exposure is " + << (exposures[i]/1e6f) << std::endl; + ASSERT_EQ(OK, mDevice->capture(tmpRequest)); + } + + dout << "Buffer dimensions " << mWidth << "x" << mHeight << std::endl; + + float brightnesses[CAMERA_FRAME_BURST_COUNT]; + // Get each frame (metadata) and then the buffer. Calculate brightness. + for (int i = 0; i < CAMERA_FRAME_BURST_COUNT; ++i) { + ALOGV("Reading capture request %d with exposure %" PRId64, i, exposures[i]); + ASSERT_EQ(OK, mDevice->waitForNextFrame(CAMERA_FRAME_TIMEOUT)); + ALOGV("Reading capture request-1 %d", i); + CaptureResult result; + ASSERT_EQ(OK, mDevice->getNextResult(&result)); + ALOGV("Reading capture request-2 %d", i); + + ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT)); + ALOGV("We got the frame now"); + + CpuConsumer::LockedBuffer imgBuffer; + ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer)); + + int underexposed, overexposed; + long long brightness = TotalBrightness(imgBuffer, &underexposed, + &overexposed); + float avgBrightness = brightness * 1.0f / + (mWidth * mHeight - (underexposed + overexposed)); + ALOGV("Total brightness for frame %d was %lld (underexposed %d, " + "overexposed %d), avg %f", i, brightness, underexposed, + overexposed, avgBrightness); + dout << "Average brightness (frame " << i << ") was " << avgBrightness + << " (underexposed " << underexposed << ", overexposed " + << overexposed << ")" << std::endl; + + ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer)); + + brightnesses[i] = avgBrightness; + } + + // Calculate max consecutive frame exposure doubling + float prev = brightnesses[0]; + int doubling_count = 1; + int max_doubling_count = 0; + for (int i = 1; i < CAMERA_FRAME_BURST_COUNT; ++i) { + if (fabs(brightnesses[i] - prev*CAMERA_EXPOSURE_DOUBLE) + <= CAMERA_EXPOSURE_DOUBLING_THRESHOLD) { + doubling_count++; + } + else { + max_doubling_count = std::max(max_doubling_count, doubling_count); + doubling_count = 1; + } + prev = brightnesses[i]; + } + + dout << "max doubling count: " << max_doubling_count << std::endl; + + /** + * Make this check warning only, since the brightness calculation is not reliable + * and we have separate test to cover this case. Plus it is pretty subtle to make + * it right without complicating the test too much. + */ + WARN_LE(CAMERA_EXPOSURE_DOUBLING_COUNT, max_doubling_count) + << "average brightness should double at least " + << CAMERA_EXPOSURE_DOUBLING_COUNT + << " times over each consecutive frame as the exposure is doubled" + << std::endl; +} + +/** + * This test varies exposure time, frame duration, and sensitivity for a + * burst of captures. It picks values by default, but the selection can be + * overridden with the environment variables + * CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES + * CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS + * CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES + * which must all be a list of comma-separated values, and each list must be + * the same length. In addition, if the environment variable + * CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES + * is set to 1, then the YUV buffers are dumped into files named + * "camera2_test_variable_burst_frame_NNN.yuv" + * + * For example: + * $ setenv CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES 10000000,20000000 + * $ setenv CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS 40000000,40000000 + * $ setenv CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES 200,100 + * $ setenv CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES 1 + * $ /data/nativetest/camera2_test/camera2_test --gtest_filter="*VariableBurst" + */ +TEST_F(CameraBurstTest, VariableBurst) { + + TEST_EXTENSION_FORKING_INIT; + + // Bounds for checking frame duration is within range + const nsecs_t DURATION_UPPER_BOUND = 10 * MSEC; + const nsecs_t DURATION_LOWER_BOUND = 20 * MSEC; + + // Threshold for considering two captures to have equivalent exposure value, + // as a ratio of the smaller EV to the larger EV. + const float EV_MATCH_BOUND = 0.95; + // Bound for two captures with equivalent exp values to have the same + // measured brightness, in 0-255 luminance. + const float BRIGHTNESS_MATCH_BOUND = 5; + + // Environment variables to look for to override test settings + const char *expEnv = "CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES"; + const char *durationEnv = "CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS"; + const char *sensitivityEnv = "CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES"; + const char *dumpFrameEnv = "CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES"; + + // Range of valid exposure times, in nanoseconds + int64_t minExp = 0, maxExp = 0; + // List of valid sensor sensitivities + Vector<int32_t> sensitivities; + // Range of valid frame durations, in nanoseconds + int64_t minDuration = 0, maxDuration = 0; + + { + camera_metadata_ro_entry exposureTimeRange = + GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE); + + EXPECT_EQ(2u, exposureTimeRange.count) << "Bad exposure time range tag." + "Using default values"; + if (exposureTimeRange.count == 2) { + minExp = exposureTimeRange.data.i64[0]; + maxExp = exposureTimeRange.data.i64[1]; + } + + EXPECT_LT(0, minExp) << "Minimum exposure time is 0"; + EXPECT_LT(0, maxExp) << "Maximum exposure time is 0"; + EXPECT_LE(minExp, maxExp) << "Minimum exposure is greater than maximum"; + + if (minExp == 0) { + minExp = 1 * MSEC; // Fallback minimum exposure time + } + + if (maxExp == 0) { + maxExp = 10 * SEC; // Fallback maximum exposure time + } + } + + camera_metadata_ro_entry hardwareLevel = + GetStaticEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL); + ASSERT_EQ(1u, hardwareLevel.count); + uint8_t level = hardwareLevel.data.u8[0]; + ASSERT_GE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED); + ASSERT_LE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); + if (level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + std::cerr << "Skipping test " + << test_info->test_case_name() << "." + << test_info->name() + << " because HAL hardware supported level is limited " + << std::endl; + return; + } + + dout << "Stream size is " << mWidth << " x " << mHeight << std::endl; + dout << "Valid exposure range is: " << + minExp << " - " << maxExp << " ns " << std::endl; + + { + camera_metadata_ro_entry sensivityRange = + GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE); + EXPECT_EQ(2u, sensivityRange.count) << "No sensitivity range listed." + "Falling back to default set."; + int32_t minSensitivity = 100; + int32_t maxSensitivity = 800; + if (sensivityRange.count == 2) { + ASSERT_GT(sensivityRange.data.i32[0], 0); + ASSERT_GT(sensivityRange.data.i32[1], 0); + minSensitivity = sensivityRange.data.i32[0]; + maxSensitivity = sensivityRange.data.i32[1]; + } + int32_t count = (maxSensitivity - minSensitivity + 99) / 100; + sensitivities.push_back(minSensitivity); + for (int i = 1; i < count; i++) { + sensitivities.push_back(minSensitivity + i * 100); + } + sensitivities.push_back(maxSensitivity); + } + + dout << "Available sensitivities: "; + for (size_t i = 0; i < sensitivities.size(); i++) { + dout << sensitivities[i] << " "; + } + dout << std::endl; + + { + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + camera_metadata_ro_entry availableProcessedSizes = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES); + + camera_metadata_ro_entry availableProcessedMinFrameDurations = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS); + + EXPECT_EQ(availableProcessedSizes.count, + availableProcessedMinFrameDurations.count * 2) << + "The number of minimum frame durations doesn't match the number of " + "available sizes. Using fallback values"; + + if (availableProcessedSizes.count == + availableProcessedMinFrameDurations.count * 2) { + bool gotSize = false; + for (size_t i = 0; i < availableProcessedSizes.count; i += 2) { + if (availableProcessedSizes.data.i32[i] == mWidth && + availableProcessedSizes.data.i32[i+1] == mHeight) { + gotSize = true; + minDuration = availableProcessedMinFrameDurations.data.i64[i/2]; + } + } + EXPECT_TRUE(gotSize) << "Can't find stream size in list of " + "available sizes: " << mWidth << ", " << mHeight; + } + if (minDuration == 0) { + minDuration = 1 * SEC / 30; // Fall back to 30 fps as minimum duration + } + } else { + minDuration = getMinFrameDurationFor( + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, mWidth, mHeight); + } + ASSERT_LT(0, minDuration); + + camera_metadata_ro_entry maxFrameDuration = + GetStaticEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION); + + EXPECT_EQ(1u, maxFrameDuration.count) << "No valid maximum frame duration"; + + if (maxFrameDuration.count == 1) { + maxDuration = maxFrameDuration.data.i64[0]; + } + + EXPECT_GT(maxDuration, 0) << "Max duration is 0 or not given, using fallback"; + + if (maxDuration == 0) { + maxDuration = 10 * SEC; // Fall back to 10 seconds as max duration + } + + } + dout << "Available frame duration range for configured stream size: " + << minDuration << " - " << maxDuration << " ns" << std::endl; + + // Get environment variables if set + const char *expVal = getenv(expEnv); + const char *durationVal = getenv(durationEnv); + const char *sensitivityVal = getenv(sensitivityEnv); + + bool gotExp = (expVal != NULL); + bool gotDuration = (durationVal != NULL); + bool gotSensitivity = (sensitivityVal != NULL); + + // All or none must be provided if using override envs + ASSERT_TRUE( (gotDuration && gotExp && gotSensitivity) || + (!gotDuration && !gotExp && !gotSensitivity) ) << + "Incomplete set of environment variable overrides provided"; + + Vector<int64_t> expList, durationList; + Vector<int32_t> sensitivityList; + if (gotExp) { + ParseList(expVal, expList); + ParseList(durationVal, durationList); + ParseList(sensitivityVal, sensitivityList); + + ASSERT_TRUE( + (expList.size() == durationList.size()) && + (durationList.size() == sensitivityList.size())) << + "Mismatched sizes in env lists, or parse error"; + + dout << "Using burst list from environment with " << expList.size() << + " captures" << std::endl; + } else { + // Create a default set of controls based on the available ranges + + int64_t e; + int64_t d; + int32_t s; + + // Exposure ramp + + e = minExp; + d = minDuration; + s = sensitivities[0]; + while (e < maxExp) { + expList.push_back(e); + durationList.push_back(d); + sensitivityList.push_back(s); + e = e * 2; + } + e = maxExp; + expList.push_back(e); + durationList.push_back(d); + sensitivityList.push_back(s); + + // Duration ramp + + e = 30 * MSEC; + d = minDuration; + s = sensitivities[0]; + while (d < maxDuration) { + // make sure exposure <= frame duration + expList.push_back(e > d ? d : e); + durationList.push_back(d); + sensitivityList.push_back(s); + d = d * 2; + } + + // Sensitivity ramp + + e = 30 * MSEC; + d = 30 * MSEC; + d = d > minDuration ? d : minDuration; + for (size_t i = 0; i < sensitivities.size(); i++) { + expList.push_back(e); + durationList.push_back(d); + sensitivityList.push_back(sensitivities[i]); + } + + // Constant-EV ramp, duration == exposure + + e = 30 * MSEC; // at ISO 100 + for (size_t i = 0; i < sensitivities.size(); i++) { + int64_t e_adj = e * 100 / sensitivities[i]; + expList.push_back(e_adj); + durationList.push_back(e_adj > minDuration ? e_adj : minDuration); + sensitivityList.push_back(sensitivities[i]); + } + + dout << "Default burst sequence created with " << expList.size() << + " entries" << std::endl; + } + + // Validate the list, but warn only + for (size_t i = 0; i < expList.size(); i++) { + EXPECT_GE(maxExp, expList[i]) + << "Capture " << i << " exposure too long: " << expList[i]; + EXPECT_LE(minExp, expList[i]) + << "Capture " << i << " exposure too short: " << expList[i]; + EXPECT_GE(maxDuration, durationList[i]) + << "Capture " << i << " duration too long: " << durationList[i]; + EXPECT_LE(minDuration, durationList[i]) + << "Capture " << i << " duration too short: " << durationList[i]; + bool validSensitivity = false; + for (size_t j = 0; j < sensitivities.size(); j++) { + if (sensitivityList[i] == sensitivities[j]) { + validSensitivity = true; + break; + } + } + EXPECT_TRUE(validSensitivity) + << "Capture " << i << " sensitivity not in list: " << sensitivityList[i]; + } + + // Check if debug yuv dumps are requested + + bool dumpFrames = false; + { + const char *frameDumpVal = getenv(dumpFrameEnv); + if (frameDumpVal != NULL) { + if (frameDumpVal[0] == '1') dumpFrames = true; + } + } + + dout << "Dumping YUV frames " << + (dumpFrames ? "enabled, not checking timing" : "disabled") << std::endl; + + // Create a base preview request, turning off all 3A + CameraMetadata previewRequest; + ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, + &previewRequest)); + { + Vector<int32_t> outputStreamIds; + outputStreamIds.push(mStreamId); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, + outputStreamIds)); + + // Disable all 3A routines + uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF); + ASSERT_EQ(OK, previewRequest.update(ANDROID_CONTROL_MODE, + &cmOff, 1)); + + int requestId = 1; + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID, + &requestId, 1)); + } + + // Submit capture requests + + for (size_t i = 0; i < expList.size(); ++i) { + CameraMetadata tmpRequest = previewRequest; + ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_EXPOSURE_TIME, + &expList[i], 1)); + ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_FRAME_DURATION, + &durationList[i], 1)); + ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_SENSITIVITY, + &sensitivityList[i], 1)); + ALOGV("Submitting capture %zu with exposure %" PRId64 ", frame duration %" PRId64 ", sensitivity %d", + i, expList[i], durationList[i], sensitivityList[i]); + dout << "Capture request " << i << + ": exposure is " << (expList[i]/1e6f) << " ms" << + ", frame duration is " << (durationList[i]/1e6f) << " ms" << + ", sensitivity is " << sensitivityList[i] << + std::endl; + ASSERT_EQ(OK, mDevice->capture(tmpRequest)); + } + + Vector<float> brightnesses; + Vector<nsecs_t> captureTimes; + brightnesses.setCapacity(expList.size()); + captureTimes.setCapacity(expList.size()); + + // Get each frame (metadata) and then the buffer. Calculate brightness. + for (size_t i = 0; i < expList.size(); ++i) { + + ALOGV("Reading request %zu", i); + dout << "Waiting for capture " << i << ": " << + " exposure " << (expList[i]/1e6f) << " ms," << + " frame duration " << (durationList[i]/1e6f) << " ms," << + " sensitivity " << sensitivityList[i] << + std::endl; + + // Set wait limit based on expected frame duration, or minimum timeout + int64_t waitLimit = CAMERA_FRAME_TIMEOUT; + if (expList[i] * 2 > waitLimit) waitLimit = expList[i] * 2; + if (durationList[i] * 2 > waitLimit) waitLimit = durationList[i] * 2; + + ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit)); + ALOGV("Reading capture request-1 %zu", i); + CaptureResult result; + ASSERT_EQ(OK, mDevice->getNextResult(&result)); + ALOGV("Reading capture request-2 %zu", i); + + ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT)); + ALOGV("We got the frame now"); + + captureTimes.push_back(systemTime()); + + CpuConsumer::LockedBuffer imgBuffer; + ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer)); + + int underexposed, overexposed; + float avgBrightness = 0; + long long brightness = TotalBrightness(imgBuffer, &underexposed, + &overexposed); + int numValidPixels = mWidth * mHeight - (underexposed + overexposed); + if (numValidPixels != 0) { + avgBrightness = brightness * 1.0f / numValidPixels; + } else if (underexposed < overexposed) { + avgBrightness = 255; + } + + ALOGV("Total brightness for frame %zu was %lld (underexposed %d, " + "overexposed %d), avg %f", i, brightness, underexposed, + overexposed, avgBrightness); + dout << "Average brightness (frame " << i << ") was " << avgBrightness + << " (underexposed " << underexposed << ", overexposed " + << overexposed << ")" << std::endl; + brightnesses.push_back(avgBrightness); + + if (i != 0) { + float prevEv = static_cast<float>(expList[i - 1]) * sensitivityList[i - 1]; + float currentEv = static_cast<float>(expList[i]) * sensitivityList[i]; + float evRatio = (prevEv > currentEv) ? (currentEv / prevEv) : + (prevEv / currentEv); + if ( evRatio > EV_MATCH_BOUND ) { + WARN_LT(fabs(brightnesses[i] - brightnesses[i - 1]), + BRIGHTNESS_MATCH_BOUND) << + "Capture brightness different from previous, even though " + "they have the same EV value. Ev now: " << currentEv << + ", previous: " << prevEv << ". Brightness now: " << + brightnesses[i] << ", previous: " << brightnesses[i-1] << + std::endl; + } + // Only check timing if not saving to disk, since that slows things + // down substantially + if (!dumpFrames) { + nsecs_t timeDelta = captureTimes[i] - captureTimes[i-1]; + nsecs_t expectedDelta = expList[i] > durationList[i] ? + expList[i] : durationList[i]; + WARN_LT(timeDelta, expectedDelta + DURATION_UPPER_BOUND) << + "Capture took " << timeDelta << " ns to receive, but expected" + " frame duration was " << expectedDelta << " ns." << + std::endl; + WARN_GT(timeDelta, expectedDelta - DURATION_LOWER_BOUND) << + "Capture took " << timeDelta << " ns to receive, but expected" + " frame duration was " << expectedDelta << " ns." << + std::endl; + dout << "Time delta from previous frame: " << timeDelta / 1e6 << + " ms. Expected " << expectedDelta / 1e6 << " ms" << std::endl; + } + } + + if (dumpFrames) { + String8 dumpName = + String8::format("/data/local/tmp/camera2_test_variable_burst_frame_%03zu.yuv", i); + dout << " Writing YUV dump to " << dumpName << std::endl; + DumpYuvToFile(dumpName, imgBuffer); + } + + ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer)); + } + +} + +} +} +}
diff --git a/libhardware/tests/camera2/CameraFrameTests.cpp b/libhardware/tests/camera2/CameraFrameTests.cpp new file mode 100644 index 0000000..3c5abf7 --- /dev/null +++ b/libhardware/tests/camera2/CameraFrameTests.cpp
@@ -0,0 +1,140 @@ +/* + * Copyright (C) 2012 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 <gtest/gtest.h> + +#define LOG_TAG "CameraFrameTest" +//#define LOG_NDEBUG 0 +#include <utils/Log.h> + +#include "hardware/hardware.h" +#include "hardware/camera2.h" + +#include <common/CameraDeviceBase.h> +#include <utils/StrongPointer.h> +#include <gui/CpuConsumer.h> +#include <gui/Surface.h> + +#include <unistd.h> + +#include "CameraStreamFixture.h" +#include "TestExtensions.h" + +#define CAMERA_FRAME_TIMEOUT 1000000000 //nsecs (1 secs) +#define CAMERA_HEAP_COUNT 2 //HALBUG: 1 means registerBuffers fails +#define CAMERA_FRAME_DEBUGGING 0 + +using namespace android; +using namespace android::camera2; + +namespace android { +namespace camera2 { +namespace tests { + +static CameraStreamParams STREAM_PARAMETERS = { + /*mFormat*/ CAMERA_STREAM_AUTO_CPU_FORMAT, + /*mHeapCount*/ CAMERA_HEAP_COUNT +}; + +class CameraFrameTest + : public ::testing::TestWithParam<int>, + public CameraStreamFixture { + +public: + CameraFrameTest() : CameraStreamFixture(STREAM_PARAMETERS) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + + if (!HasFatalFailure()) { + CreateStream(); + } + } + + ~CameraFrameTest() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + + if (mDevice.get()) { + mDevice->waitUntilDrained(); + } + } + + virtual void SetUp() { + TEST_EXTENSION_FORKING_SET_UP; + } + virtual void TearDown() { + TEST_EXTENSION_FORKING_TEAR_DOWN; + } + +protected: + +}; + +TEST_P(CameraFrameTest, GetFrame) { + + TEST_EXTENSION_FORKING_INIT; + + /* Submit a PREVIEW type request, then wait until we get the frame back */ + CameraMetadata previewRequest; + ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, + &previewRequest)); + { + Vector<int32_t> outputStreamIds; + outputStreamIds.push(mStreamId); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, + outputStreamIds)); + if (CAMERA_FRAME_DEBUGGING) { + int frameCount = 0; + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_FRAME_COUNT, + &frameCount, 1)); + } + } + + if (CAMERA_FRAME_DEBUGGING) { + previewRequest.dump(STDOUT_FILENO); + } + + for (int i = 0; i < GetParam(); ++i) { + ALOGV("Submitting capture request %d", i); + CameraMetadata tmpRequest = previewRequest; + ASSERT_EQ(OK, mDevice->capture(tmpRequest)); + } + + for (int i = 0; i < GetParam(); ++i) { + ALOGV("Reading capture request %d", i); + ASSERT_EQ(OK, mDevice->waitForNextFrame(CAMERA_FRAME_TIMEOUT)); + + CaptureResult result; + ASSERT_EQ(OK, mDevice->getNextResult(&result)); + + // wait for buffer to be available + ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT)); + ALOGV("We got the frame now"); + + // mark buffer consumed so producer can re-dequeue it + CpuConsumer::LockedBuffer imgBuffer; + ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer)); + ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer)); + } + +} + +//FIXME: dont hardcode stream params, and also test multistream +INSTANTIATE_TEST_CASE_P(FrameParameterCombinations, CameraFrameTest, + testing::Range(1, 10)); + + +} +} +}
diff --git a/libhardware/tests/camera2/CameraMetadataTests.cpp b/libhardware/tests/camera2/CameraMetadataTests.cpp new file mode 100644 index 0000000..da5b748 --- /dev/null +++ b/libhardware/tests/camera2/CameraMetadataTests.cpp
@@ -0,0 +1,197 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "CameraMetadataTestFunctional" +#include "cutils/log.h" +#include "cutils/properties.h" +#include "utils/Errors.h" + +#include "gtest/gtest.h" +#include "system/camera_metadata.h" +#include "hardware/hardware.h" +#include "hardware/camera2.h" + +#include "common/CameraDeviceBase.h" +#include "utils/StrongPointer.h" + +#include <gui/CpuConsumer.h> +#include <gui/Surface.h> + +#include <string> + +#include "CameraStreamFixture.h" +#include "TestExtensions.h" + +namespace android { +namespace camera2 { +namespace tests { + +//FIXME: dont hardcode +static CameraStreamParams METADATA_STREAM_PARAMETERS = { + /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP, + /*mHeapCount*/ 2 +}; + +class CameraMetadataTest + : public ::testing::Test, + public CameraStreamFixture { + +public: + CameraMetadataTest() + : CameraStreamFixture(METADATA_STREAM_PARAMETERS) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + } + + ~CameraMetadataTest() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + } + + int GetTypeFromTag(uint32_t tag) const { + return get_camera_metadata_tag_type(tag); + } + + int GetTypeFromStaticTag(uint32_t tag) const { + const CameraMetadata& staticInfo = mDevice->info(); + camera_metadata_ro_entry entry = staticInfo.find(tag); + return entry.type; + } + + int GetEntryCountFromStaticTag(uint32_t tag) const { + const CameraMetadata& staticInfo = mDevice->info(); + camera_metadata_ro_entry entry = staticInfo.find(tag); + return entry.count; + } + + bool HasElementInArrayFromStaticTag(uint32_t tag, int32_t element) const { + const CameraMetadata& staticInfo = mDevice->info(); + camera_metadata_ro_entry entry = staticInfo.find(tag); + for (size_t i = 0; i < entry.count; ++i) { + if (entry.data.i32[i] == element) + return true; + } + return false; + } + +protected: + +}; + +TEST_F(CameraMetadataTest, types) { + + TEST_EXTENSION_FORKING_INIT; + + //FIXME: set this up in an external file of some sort (xml?) + { + char value[PROPERTY_VALUE_MAX]; + property_get("ro.build.id", value, ""); + std::string str_value(value); + + if (str_value == "manta") + { + EXPECT_EQ(TYPE_BYTE, + GetTypeFromStaticTag(ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO)); + EXPECT_EQ(TYPE_BYTE, + GetTypeFromStaticTag(ANDROID_QUIRKS_USE_ZSL_FORMAT)); + EXPECT_EQ(TYPE_BYTE, + GetTypeFromStaticTag(ANDROID_QUIRKS_METERING_CROP_REGION)); + } + } + + /* + TODO: + go through all static metadata and make sure all fields we expect + that are there, ARE there. + + dont worry about the type as its enforced by the metadata api + we can probably check the range validity though + */ + + if (0) { + camera_metadata_ro_entry entry; + EXPECT_EQ(TYPE_BYTE, entry.type); + EXPECT_EQ(TYPE_INT32, entry.type); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ(TYPE_INT64, entry.type); + EXPECT_EQ(TYPE_DOUBLE, entry.type); + EXPECT_EQ(TYPE_RATIONAL, entry.type); + } +} + +TEST_F(CameraMetadataTest, RequiredFormats) { + TEST_EXTENSION_FORKING_INIT; + + EXPECT_TRUE( + HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS, + HAL_PIXEL_FORMAT_BLOB)); // JPEG + + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_0) { + // HAL2 can support either flexible YUV or YV12 + NV21 + if (!HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS, + HAL_PIXEL_FORMAT_YCbCr_420_888)) { + + EXPECT_TRUE( + HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS, + HAL_PIXEL_FORMAT_YCrCb_420_SP)); // NV21 + + EXPECT_TRUE( + HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS, + HAL_PIXEL_FORMAT_YV12)); + } + } else { + // HAL3 must support flexible YUV + EXPECT_TRUE(HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS, + HAL_PIXEL_FORMAT_YCbCr_420_888)); + } + +} + +TEST_F(CameraMetadataTest, SaneResolutions) { + TEST_EXTENSION_FORKING_INIT; + + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + // Iff there are listed raw resolutions, the format should be available + int rawResolutionsCount = + GetEntryCountFromStaticTag(ANDROID_SCALER_AVAILABLE_RAW_SIZES); + if (rawResolutionsCount > 0) { + EXPECT_TRUE( + HasElementInArrayFromStaticTag(ANDROID_SCALER_AVAILABLE_FORMATS, + HAL_PIXEL_FORMAT_RAW16)); + } + + // Required processed sizes. + int processedSizeCount = + GetEntryCountFromStaticTag(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES); + EXPECT_NE(0, processedSizeCount); + EXPECT_EQ(0, processedSizeCount % 2); // multiple of 2 (w,h) + + // Required JPEG sizes + int jpegSizeCount = + GetEntryCountFromStaticTag(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); + EXPECT_NE(0, jpegSizeCount); + EXPECT_EQ(0, jpegSizeCount % 2); // multiple of 2 (w,h) + } else { + int strmConfigCount = + GetEntryCountFromStaticTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS); + EXPECT_NE(0, strmConfigCount); + EXPECT_EQ(0, strmConfigCount % 4); // multiple of 4 (format,w,h,output?) + } + +} + +} +} +}
diff --git a/libhardware/tests/camera2/CameraModuleFixture.h b/libhardware/tests/camera2/CameraModuleFixture.h new file mode 100644 index 0000000..102fa6d --- /dev/null +++ b/libhardware/tests/camera2/CameraModuleFixture.h
@@ -0,0 +1,166 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA2_TESTS_MODULE_FIXTURE__ +#define __ANDROID_HAL_CAMERA2_TESTS_MODULE_FIXTURE__ + +#include <gtest/gtest.h> + +#include "hardware/hardware.h" +#include "hardware/camera2.h" + +#include <common/CameraModule.h> +#include <device2/Camera2Device.h> +#include <device3/Camera3Device.h> + +#include "camera2_utils.h" +#include "TestExtensions.h" + +namespace android { +namespace camera2 { +namespace tests { + +template <bool InfoQuirk = false> +struct CameraModuleFixture { + + explicit CameraModuleFixture(int CameraID = -1) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + + mCameraID = CameraID; + } + + ~CameraModuleFixture() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + } + + camera_metadata_ro_entry GetStaticEntry(uint32_t tag) const { + const CameraMetadata& staticInfo = mDevice->info(); + camera_metadata_ro_entry entry = staticInfo.find(tag); + return entry; + } + + void SetUp() { + TEST_EXTENSION_FORKING_SET_UP; + + camera_module_t *rawModule; + ASSERT_LE(0, hw_get_module(CAMERA_HARDWARE_MODULE_ID, + (const hw_module_t **)&rawModule)) << "Could not load camera module"; + ASSERT_NE((void*)0, rawModule); + mModule = new CameraModule(rawModule); + + mNumberOfCameras = mModule->getNumberOfCameras(); + ASSERT_LE(0, mNumberOfCameras); + + ASSERT_LE( + CAMERA_MODULE_API_VERSION_2_0, mModule->getModuleApiVersion()) + << "Wrong module API version"; + + /* For using this fixture in other tests only */ + SetUpMixin(); + } + + void TearDown() { + TEST_EXTENSION_FORKING_TEAR_DOWN; + + delete mModule; + TearDownMixin(); + + /* important: device must be destructed before closing module, + since it calls back into HAL */ + mDevice.clear(); + + if (!TEST_EXTENSION_FORKING_ENABLED) { + ASSERT_EQ(0, HWModuleHelpers::closeModule(mModule->getDso())) + << "Failed to close camera HAL module"; + } + } + + void CreateCamera(int cameraID, /*out*/ sp<CameraDeviceBase> *device) { + struct camera_info info; + ASSERT_EQ(OK, mModule->getCameraInfo(cameraID, &info)); + + ASSERT_GE((int)info.device_version, CAMERA_DEVICE_API_VERSION_2_0) << + "Device version too old for camera " << cameraID << ". Version: " << + info.device_version; + switch(info.device_version) { + case CAMERA_DEVICE_API_VERSION_2_0: + case CAMERA_DEVICE_API_VERSION_2_1: + *device = new Camera2Device(cameraID); + break; + case CAMERA_DEVICE_API_VERSION_3_0: + case CAMERA_DEVICE_API_VERSION_3_1: + case CAMERA_DEVICE_API_VERSION_3_2: + *device = new Camera3Device(cameraID); + break; + default: + device->clear(); + FAIL() << "Device version unknown for camera " << cameraID << ". Version: " << + info.device_version; + } + + } + + int getDeviceVersion() { + return getDeviceVersion(mCameraID); + } + + int getDeviceVersion(int cameraId, status_t* status = NULL) { + camera_info info; + status_t res; + res = mModule->getCameraInfo(cameraId, &info); + if (status != NULL) *status = res; + + return info.device_version; + } + +private: + + void SetUpMixin() { + /* For using this fixture in other tests only */ + if (mCameraID != -1) { + EXPECT_LE(0, mCameraID); + EXPECT_LT(mCameraID, mNumberOfCameras); + + /* HALBUG (Exynos5); crashes if we skip calling get_camera_info + before initializing. Need info anyway now. */ + + CreateCamera(mCameraID, &mDevice); + + ASSERT_TRUE(mDevice != NULL) << "Failed to open device " << mCameraID; + ASSERT_EQ(OK, mDevice->initialize(mModule)) + << "Failed to initialize device " << mCameraID; + } + } + + void TearDownMixin() { + + } + +protected: + int mNumberOfCameras; + CameraModule *mModule; + sp<CameraDeviceBase> mDevice; + +private: + int mCameraID; +}; + + +} +} +} + +#endif
diff --git a/libhardware/tests/camera2/CameraModuleTests.cpp b/libhardware/tests/camera2/CameraModuleTests.cpp new file mode 100644 index 0000000..2b6c757 --- /dev/null +++ b/libhardware/tests/camera2/CameraModuleTests.cpp
@@ -0,0 +1,141 @@ +/* + * Copyright (C) 2012 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 <gtest/gtest.h> + +#define LOG_TAG "CameraModuleTest" +#define LOG_NDEBUG 0 +#include <utils/Log.h> +#include <utils/StrongPointer.h> +#include <common/CameraDeviceBase.h> + +#include "hardware/hardware.h" +#include "hardware/camera2.h" + +#include "CameraModuleFixture.h" + +namespace android { +namespace camera2 { +namespace tests { + +class CameraModuleTest : public ::testing::Test, + public CameraModuleFixture<> { + +public: + CameraModuleTest() { + CameraModuleFixture::SetUp(); + } + + ~CameraModuleTest() { + CameraModuleFixture::TearDown(); + } + + status_t initializeDevice(int cameraId) { + + // ignore HAL1s. count as test pass + status_t stat; + if (isDeviceVersionHal2(cameraId, &stat) && stat == OK) { + stat = mDevice->initialize(mModule); + } + + return stat; + } + + bool isDeviceVersionHal2(int cameraId, status_t* status) { + return getDeviceVersion(cameraId, status) + >= CAMERA_DEVICE_API_VERSION_2_0; + } +}; + +TEST_F(CameraModuleTest, LoadModule) { + + TEST_EXTENSION_FORKING_INIT; + + status_t stat; + for (int i = 0; i < mNumberOfCameras; ++i) { + if (isDeviceVersionHal2(i, &stat) && stat == OK) { + CreateCamera(i, &mDevice); + ASSERT_EQ(OK, initializeDevice(i)) + << "Failed to initialize device " << i; + mDevice.clear(); + } else { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + std::cerr << "Skipping test " + << test_info->test_case_name() << "." + << test_info->name() + << " because HAL device version is V1" + << std::endl; + } + } + +} + +TEST_F(CameraModuleTest, LoadModuleBadIndices) { + + TEST_EXTENSION_FORKING_INIT; + + int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 }; + hw_device_t *device = NULL; + + for (unsigned i = 0; i < sizeof(idx)/sizeof(idx[0]); ++i) { + String8 deviceName = String8::format("%d", idx[i]); + status_t res = mModule->open(deviceName, &device); + EXPECT_NE(OK, res); + EXPECT_EQ(-ENODEV, res) + << "Incorrect error code when trying to open camera with invalid id " + << deviceName; + } +} + +TEST_F(CameraModuleTest, GetCameraInfo) { + + TEST_EXTENSION_FORKING_INIT; + + for (int i = 0; i < mNumberOfCameras; ++i) { + struct camera_info info; + ASSERT_EQ(OK, mModule->getCameraInfo(i, &info)); + } + +} + +TEST_F(CameraModuleTest, GetCameraInfoBadIndices) { + + TEST_EXTENSION_FORKING_INIT; + + int idx[] = { -1, mNumberOfCameras, mNumberOfCameras + 1 }; + for (unsigned i = 0; i < sizeof(idx)/sizeof(idx[0]); ++i) { + struct camera_info info; + EXPECT_NE(OK, mModule->getCameraInfo(idx[i], &info)); + EXPECT_EQ(-EINVAL, mModule->getCameraInfo(idx[i], &info)) + << "Incorrect error code for get_camera_info idx= " + << idx[i]; + } +} + +/** + * TODO: Additional test to add: open two cameras at once. + * (is allowed to fail, at least for now, but should not blow up) + * - open same device multiple times + * - close same device multiple times + */ + + + + +} +} +}
diff --git a/libhardware/tests/camera2/CameraMultiStreamTests.cpp b/libhardware/tests/camera2/CameraMultiStreamTests.cpp new file mode 100644 index 0000000..f4aeab7 --- /dev/null +++ b/libhardware/tests/camera2/CameraMultiStreamTests.cpp
@@ -0,0 +1,713 @@ +/* + * Copyright (C) 2013 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 <inttypes.h> +#define LOG_TAG "CameraMultiStreamTest" +//#define LOG_NDEBUG 0 +#include "CameraStreamFixture.h" +#include "TestExtensions.h" + +#include <gtest/gtest.h> +#include <utils/Log.h> +#include <utils/StrongPointer.h> +#include <common/CameraDeviceBase.h> +#include <hardware/hardware.h> +#include <hardware/camera2.h> +#include <gui/SurfaceComposerClient.h> +#include <gui/Surface.h> + +#define DEFAULT_FRAME_DURATION 33000000LL // 33ms +#define CAMERA_HEAP_COUNT 1 +#define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT +#define CAMERA_DISPLAY_FORMAT HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED +#define CAMERA_MULTI_STREAM_DEBUGGING 0 +#define CAMERA_FRAME_TIMEOUT 1000000000LL // nsecs (1 secs) +#define PREVIEW_RENDERING_TIME_INTERVAL 200000 // in unit of us, 200ms +// 1% tolerance margin for exposure sanity check against metadata +#define TOLERANCE_MARGIN_METADATA 0.01 +// 5% tolerance margin for exposure sanity check against capture times +#define TOLERANCE_MARGIN_CAPTURE 0.05 +/* constants for display */ +#define DISPLAY_BUFFER_HEIGHT 1024 +#define DISPLAY_BUFFER_WIDTH 1024 +#define DISPLAY_BUFFER_FORMAT PIXEL_FORMAT_RGB_888 + +// This test intends to test large preview size but less than 1080p. +#define PREVIEW_WIDTH_CAP 1920 +#define PREVIEW_HEIGHT_CAP 1080 +// This test intends to test small metering burst size that is less than 640x480 +#define METERING_WIDTH_CAP 640 +#define METERING_HEIGHT_CAP 480 + +#define EXP_WAIT_MULTIPLIER 2 + +namespace android { +namespace camera2 { +namespace tests { + +static const CameraStreamParams DEFAULT_STREAM_PARAMETERS = { + /*mFormat*/ CAMERA_EXPOSURE_FORMAT, + /*mHeapCount*/ CAMERA_HEAP_COUNT +}; + +static const CameraStreamParams DISPLAY_STREAM_PARAMETERS = { + /*mFormat*/ CAMERA_DISPLAY_FORMAT, + /*mHeapCount*/ CAMERA_HEAP_COUNT +}; + +class CameraMultiStreamTest + : public ::testing::Test, + public CameraStreamFixture { + +public: + CameraMultiStreamTest() : CameraStreamFixture(DEFAULT_STREAM_PARAMETERS) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + + if (HasFatalFailure()) { + return; + } + /** + * Don't create default stream, each test is in charge of creating + * its own streams. + */ + } + + ~CameraMultiStreamTest() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + } + + sp<SurfaceComposerClient> mComposerClient; + sp<SurfaceControl> mSurfaceControl; + + void CreateOnScreenSurface(sp<Surface>& surface) { + mComposerClient = new SurfaceComposerClient; + ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + + mSurfaceControl = mComposerClient->createSurface( + String8("CameraMultiStreamTest StreamingImage Surface"), + DISPLAY_BUFFER_HEIGHT, DISPLAY_BUFFER_WIDTH, + DISPLAY_BUFFER_FORMAT, 0); + + ASSERT_NE((void*)NULL, mSurfaceControl.get()); + ASSERT_TRUE(mSurfaceControl->isValid()); + + SurfaceComposerClient::openGlobalTransaction(); + ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); + ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); + SurfaceComposerClient::closeGlobalTransaction(); + + surface = mSurfaceControl->getSurface(); + + ASSERT_NE((void*)NULL, surface.get()); + } + + struct Size { + int32_t width; + int32_t height; + }; + + // Select minimal size by number of pixels. + void GetMinSize(const int32_t* data, size_t count, + Size* min, int32_t* idx) { + ASSERT_NE((int32_t*)NULL, data); + int32_t minIdx = 0; + int32_t minSize = INT_MAX, tempSize; + for (size_t i = 0; i < count; i+=2) { + tempSize = data[i] * data[i+1]; + if (minSize > tempSize) { + minSize = tempSize; + minIdx = i; + } + } + min->width = data[minIdx]; + min->height = data[minIdx + 1]; + *idx = minIdx; + } + + // Select maximal size by number of pixels. + void GetMaxSize(const int32_t* data, size_t count, + Size* max, int32_t* idx) { + ASSERT_NE((int32_t*)NULL, data); + int32_t maxIdx = 0; + int32_t maxSize = INT_MIN, tempSize; + for (size_t i = 0; i < count; i+=2) { + tempSize = data[i] * data[i+1]; + if (maxSize < tempSize) { + maxSize = tempSize; + maxIdx = i; + } + } + max->width = data[maxIdx]; + max->height = data[maxIdx + 1]; + *idx = maxIdx; + } + + // Cap size by number of pixels. + Size CapSize(Size cap, Size input) { + if (input.width * input.height > cap.width * cap.height) { + return cap; + } + return input; + } + + struct CameraStream : public RefBase { + + public: + /** + * Only initialize the variables here, do the ASSERT check in + * SetUp function. To make this stream useful, the SetUp must + * be called before using it. + */ + CameraStream( + int width, + int height, + const sp<CameraDeviceBase>& device, + CameraStreamParams param, sp<Surface> surface, + bool useCpuConsumer) + : mDevice(device), + mWidth(width), + mHeight(height) { + mFormat = param.mFormat; + if (useCpuConsumer) { + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mCpuConsumer = new CpuConsumer(consumer, param.mHeapCount); + mCpuConsumer->setName(String8( + "CameraMultiStreamTest::mCpuConsumer")); + mSurface = new Surface(producer); + } else { + // Render the stream to screen. + mCpuConsumer = NULL; + mSurface = surface; + } + + mFrameListener = new FrameListener(); + if (mCpuConsumer != 0) { + mCpuConsumer->setFrameAvailableListener(mFrameListener); + } + } + + /** + * Finally create camera stream, and do the ASSERT check, since we + * can not do it in ctor. + */ + void SetUp() { + ASSERT_EQ(OK, + mDevice->createStream(mSurface, + mWidth, mHeight, mFormat, HAL_DATASPACE_UNKNOWN, + CAMERA3_STREAM_ROTATION_0, &mStreamId)); + + ASSERT_NE(-1, mStreamId); + } + + int GetStreamId() { return mStreamId; } + sp<CpuConsumer> GetConsumer() { return mCpuConsumer; } + sp<FrameListener> GetFrameListener() { return mFrameListener; } + + protected: + ~CameraStream() { + if (mDevice.get()) { + mDevice->waitUntilDrained(); + mDevice->deleteStream(mStreamId); + } + // Clear producer before consumer. + mSurface.clear(); + mCpuConsumer.clear(); + } + + private: + sp<FrameListener> mFrameListener; + sp<CpuConsumer> mCpuConsumer; + sp<Surface> mSurface; + sp<CameraDeviceBase> mDevice; + int mStreamId; + int mWidth; + int mHeight; + int mFormat; + }; + + int64_t GetExposureValue(const CameraMetadata& metaData) { + camera_metadata_ro_entry_t entry = + metaData.find(ANDROID_SENSOR_EXPOSURE_TIME); + EXPECT_EQ(1u, entry.count); + if (entry.count == 1) { + return entry.data.i64[0]; + } + return -1; + } + + int32_t GetSensitivity(const CameraMetadata& metaData) { + camera_metadata_ro_entry_t entry = + metaData.find(ANDROID_SENSOR_SENSITIVITY); + EXPECT_EQ(1u, entry.count); + if (entry.count == 1) { + return entry.data.i32[0]; + } + return -1; + } + + int64_t GetFrameDuration(const CameraMetadata& metaData) { + camera_metadata_ro_entry_t entry = + metaData.find(ANDROID_SENSOR_FRAME_DURATION); + EXPECT_EQ(1u, entry.count); + if (entry.count == 1) { + return entry.data.i64[0]; + } + return -1; + } + + void CreateRequests(CameraMetadata& previewRequest, + CameraMetadata& meteringRequest, + CameraMetadata& captureRequest, + int previewStreamId, + int meteringStreamId, + int captureStreamId) { + int32_t requestId = 0; + Vector<int32_t> previewStreamIds; + previewStreamIds.push(previewStreamId); + ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, + &previewRequest)); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, + previewStreamIds)); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID, + &requestId, 1)); + + // Create metering request, manual settings + // Manual control: Disable 3A, noise reduction, edge sharping + uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF); + uint8_t nrOff = static_cast<uint8_t>(ANDROID_NOISE_REDUCTION_MODE_OFF); + uint8_t sharpOff = static_cast<uint8_t>(ANDROID_EDGE_MODE_OFF); + Vector<int32_t> meteringStreamIds; + meteringStreamIds.push(meteringStreamId); + ASSERT_EQ(OK, mDevice->createDefaultRequest( + CAMERA2_TEMPLATE_PREVIEW, + &meteringRequest)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_REQUEST_OUTPUT_STREAMS, + meteringStreamIds)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_CONTROL_MODE, + &cmOff, 1)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_NOISE_REDUCTION_MODE, + &nrOff, 1)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_EDGE_MODE, + &sharpOff, 1)); + + // Create capture request, manual settings + Vector<int32_t> captureStreamIds; + captureStreamIds.push(captureStreamId); + ASSERT_EQ(OK, mDevice->createDefaultRequest( + CAMERA2_TEMPLATE_PREVIEW, + &captureRequest)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_REQUEST_OUTPUT_STREAMS, + captureStreamIds)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_CONTROL_MODE, + &cmOff, 1)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_NOISE_REDUCTION_MODE, + &nrOff, 1)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_EDGE_MODE, + &sharpOff, 1)); + } + + sp<CameraStream> CreateStream( + int width, + int height, + const sp<CameraDeviceBase>& device, + CameraStreamParams param = DEFAULT_STREAM_PARAMETERS, + const sp<Surface>& surface = NULL, + bool useCpuConsumer = true) { + param.mFormat = MapAutoFormat(param.mFormat); + return new CameraStream(width, height, device, + param, surface, useCpuConsumer); + } + + void CaptureBurst(CameraMetadata& request, size_t requestCount, + const Vector<int64_t>& exposures, + const Vector<int32_t>& sensitivities, + const sp<CameraStream>& stream, + int64_t minFrameDuration, + int32_t* requestIdStart) { + ASSERT_EQ(OK, request.update(ANDROID_SENSOR_FRAME_DURATION, + &minFrameDuration, 1)); + // Submit a series of requests with the specified exposure/gain values. + int32_t targetRequestId = *requestIdStart; + for (size_t i = 0; i < requestCount; i++) { + ASSERT_EQ(OK, request.update(ANDROID_REQUEST_ID, requestIdStart, 1)); + ASSERT_EQ(OK, request.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposures[i], 1)); + ASSERT_EQ(OK, request.update(ANDROID_SENSOR_SENSITIVITY, &sensitivities[i], 1)); + ASSERT_EQ(OK, mDevice->capture(request)); + ALOGV("Submitting request with: id %d with exposure %" PRId64 ", sensitivity %d", + *requestIdStart, exposures[i], sensitivities[i]); + if (CAMERA_MULTI_STREAM_DEBUGGING) { + request.dump(STDOUT_FILENO); + } + (*requestIdStart)++; + } + // Get capture burst results. + Vector<nsecs_t> captureBurstTimes; + sp<CpuConsumer> consumer = stream->GetConsumer(); + sp<FrameListener> listener = stream->GetFrameListener(); + + // Set wait limit based on expected frame duration. + int64_t waitLimit = CAMERA_FRAME_TIMEOUT; + for (size_t i = 0; i < requestCount; i++) { + ALOGV("Reading request result %zu", i); + + /** + * Raise the timeout to be at least twice as long as the exposure + * time. to avoid a false positive when the timeout is too short. + */ + if ((exposures[i] * EXP_WAIT_MULTIPLIER) > waitLimit) { + waitLimit = exposures[i] * EXP_WAIT_MULTIPLIER; + } + + CaptureResult result; + CameraMetadata frameMetadata; + int32_t resultRequestId; + do { + ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit)); + ASSERT_EQ(OK, mDevice->getNextResult(&result)); + frameMetadata = result.mMetadata; + + camera_metadata_entry_t resultEntry = frameMetadata.find(ANDROID_REQUEST_ID); + ASSERT_EQ(1u, resultEntry.count); + resultRequestId = resultEntry.data.i32[0]; + if (CAMERA_MULTI_STREAM_DEBUGGING) { + std::cout << "capture result req id: " << resultRequestId << std::endl; + } + } while (resultRequestId != targetRequestId); + targetRequestId++; + ALOGV("Got capture burst result for request %zu", i); + + // Validate capture result + if (CAMERA_MULTI_STREAM_DEBUGGING) { + frameMetadata.dump(STDOUT_FILENO); + } + + // TODO: Need revisit it to figure out an accurate margin. + int64_t resultExposure = GetExposureValue(frameMetadata); + int32_t resultSensitivity = GetSensitivity(frameMetadata); + EXPECT_LE(sensitivities[i] * (1.0 - TOLERANCE_MARGIN_METADATA), resultSensitivity); + EXPECT_GE(sensitivities[i] * (1.0 + TOLERANCE_MARGIN_METADATA), resultSensitivity); + EXPECT_LE(exposures[i] * (1.0 - TOLERANCE_MARGIN_METADATA), resultExposure); + EXPECT_GE(exposures[i] * (1.0 + TOLERANCE_MARGIN_METADATA), resultExposure); + + ASSERT_EQ(OK, listener->waitForFrame(waitLimit)); + captureBurstTimes.push_back(systemTime()); + CpuConsumer::LockedBuffer imgBuffer; + ASSERT_EQ(OK, consumer->lockNextBuffer(&imgBuffer)); + ALOGV("Got capture buffer for request %zu", i); + + /** + * TODO: Validate capture buffer. Current brightness calculation + * is too slow, it also doesn't account for saturation effects, + * which is quite common since we are going over a significant + * range of EVs. we need figure out some reliable way to validate + * buffer data. + */ + + ASSERT_EQ(OK, consumer->unlockBuffer(imgBuffer)); + if (i > 0) { + nsecs_t timeDelta = + captureBurstTimes[i] - captureBurstTimes[i-1]; + EXPECT_GE(timeDelta * ( 1 + TOLERANCE_MARGIN_CAPTURE), exposures[i]); + } + } + } + + /** + * Intentionally shadow default CreateStream function from base class, + * because we don't want any test in this class to use the default + * stream creation function. + */ + void CreateStream() { + } +}; + +/** + * This test adds multiple stream use case test, basically, test 3 + * streams: + * + * 1. Preview stream, with large size that is no bigger than 1080p + * we render this stream to display and vary the exposure time for + * for certain amount of time for visualization purpose. + * + * 2. Metering stream, with small size that is no bigger than VGA size. + * a burst is issued for different exposure times and analog gains + * (or analog gain implemented sensitivities) then check if the capture + * result metadata matches the request. + * + * 3. Capture stream, this is basically similar as meterting stream, but + * has large size, which is the largest supported JPEG capture size. + * + * This multiple stream test is to test if HAL supports: + * + * 1. Multiple streams like above, HAL should support at least 3 streams + * concurrently: one preview stream, 2 other YUV stream. + * + * 2. Manual control(gain/exposure) of mutiple burst capture. + */ +// Disable this test for now, as we need cleanup the usage of the deprecated tag quite a bit. +TEST_F(CameraMultiStreamTest, DISABLED_MultiBurst) { + + TEST_EXTENSION_FORKING_INIT; + + const int32_t* implDefData; + size_t implDefCount; + const int32_t* jpegData; + size_t jpegCount; + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + camera_metadata_ro_entry availableProcessedSizes = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES); + ASSERT_EQ(0u, availableProcessedSizes.count % 2); + ASSERT_GE(availableProcessedSizes.count, 2u); + camera_metadata_ro_entry availableProcessedMinFrameDurations = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS); + EXPECT_EQ(availableProcessedSizes.count, + availableProcessedMinFrameDurations.count * 2); + + camera_metadata_ro_entry availableJpegSizes = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); + ASSERT_EQ(0u, availableJpegSizes.count % 2); + ASSERT_GE(availableJpegSizes.count, 2u); + implDefData = availableProcessedSizes.data.i32; + implDefCount = availableProcessedSizes.count; + jpegData = availableJpegSizes.data.i32; + jpegCount = availableJpegSizes.count; + } else { + getResolutionList(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, &implDefData, &implDefCount); + ASSERT_NE(0u, implDefCount) + << "Missing implementation defined sizes"; + ASSERT_EQ(0u, implDefCount % 2); + ASSERT_GE(implDefCount, 2u); + + getResolutionList(HAL_PIXEL_FORMAT_BLOB, &jpegData, &jpegCount); + ASSERT_EQ(0u, jpegCount % 2); + ASSERT_GE(jpegCount, 2u); + } + + camera_metadata_ro_entry hardwareLevel = + GetStaticEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL); + ASSERT_EQ(1u, hardwareLevel.count); + uint8_t level = hardwareLevel.data.u8[0]; + ASSERT_GE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED); + ASSERT_LE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL); + if (level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + std::cerr << "Skipping test " + << test_info->test_case_name() << "." + << test_info->name() + << " because HAL hardware supported level is limited " + << std::endl; + return; + } + + // Find the right sizes for preview, metering, and capture streams + int64_t minFrameDuration = DEFAULT_FRAME_DURATION; + Size processedMinSize = {0, 0}, processedMaxSize = {0, 0}; + Size jpegMaxSize = {0, 0}; + + int32_t minIdx, maxIdx; + GetMinSize(implDefData, implDefCount, &processedMinSize, &minIdx); + GetMaxSize(implDefData, implDefCount, &processedMaxSize, &maxIdx); + ALOGV("Found processed max size: %dx%d, min size = %dx%d", + processedMaxSize.width, processedMaxSize.height, + processedMinSize.width, processedMinSize.height); + + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + camera_metadata_ro_entry availableProcessedMinFrameDurations = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS); + minFrameDuration = + availableProcessedMinFrameDurations.data.i64[maxIdx / 2]; + } else { + minFrameDuration = getMinFrameDurationFor( + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + processedMaxSize.width, processedMaxSize.height); + } + + EXPECT_GT(minFrameDuration, 0); + + if (minFrameDuration <= 0) { + minFrameDuration = DEFAULT_FRAME_DURATION; + } + + ALOGV("targeted minimal frame duration is: %" PRId64 "ns", minFrameDuration); + + GetMaxSize(jpegData, jpegCount, &jpegMaxSize, &maxIdx); + ALOGV("Found Jpeg size max idx = %d", maxIdx); + + // Max Jpeg size should be available in processed sizes. Use it for + // YUV capture anyway. + EXPECT_EQ(processedMaxSize.width, jpegMaxSize.width); + EXPECT_EQ(processedMaxSize.height, jpegMaxSize.height); + + // Cap preview size. + Size previewLimit = { PREVIEW_WIDTH_CAP, PREVIEW_HEIGHT_CAP }; + // FIXME: need make sure the previewLimit is supported by HAL. + Size previewSize = CapSize(previewLimit, processedMaxSize); + // Cap Metering size. + Size meteringLimit = { METERING_WIDTH_CAP, METERING_HEIGHT_CAP }; + // Cap metering size to VGA (VGA is mandatory by CDD) + Size meteringSize = CapSize(meteringLimit, processedMinSize); + // Capture stream should be the max size of jpeg sizes. + ALOGV("preview size: %dx%d, metering size: %dx%d, capture size: %dx%d", + previewSize.width, previewSize.height, + meteringSize.width, meteringSize.height, + jpegMaxSize.width, jpegMaxSize.height); + + // Create streams + // Preview stream: small resolution, render on the screen. + sp<CameraStream> previewStream; + { + sp<Surface> surface; + ASSERT_NO_FATAL_FAILURE(CreateOnScreenSurface(/*out*/surface)); + previewStream = CreateStream( + previewSize.width, + previewSize.height, + mDevice, + DISPLAY_STREAM_PARAMETERS, + surface, + false); + ASSERT_NE((void*)NULL, previewStream.get()); + ASSERT_NO_FATAL_FAILURE(previewStream->SetUp()); + } + // Metering burst stream: small resolution yuv stream + sp<CameraStream> meteringStream = + CreateStream( + meteringSize.width, + meteringSize.height, + mDevice); + ASSERT_NE((void*)NULL, meteringStream.get()); + ASSERT_NO_FATAL_FAILURE(meteringStream->SetUp()); + // Capture burst stream: full resolution yuv stream + sp<CameraStream> captureStream = + CreateStream( + jpegMaxSize.width, + jpegMaxSize.height, + mDevice); + ASSERT_NE((void*)NULL, captureStream.get()); + ASSERT_NO_FATAL_FAILURE(captureStream->SetUp()); + + // Create Preview request. + CameraMetadata previewRequest, meteringRequest, captureRequest; + ASSERT_NO_FATAL_FAILURE(CreateRequests(previewRequest, meteringRequest, + captureRequest, previewStream->GetStreamId(), + meteringStream->GetStreamId(), captureStream->GetStreamId())); + + // Start preview + if (CAMERA_MULTI_STREAM_DEBUGGING) { + previewRequest.dump(STDOUT_FILENO); + } + + // Generate exposure and sensitivity lists + camera_metadata_ro_entry exposureTimeRange = + GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE); + ASSERT_EQ(exposureTimeRange.count, 2u); + int64_t minExp = exposureTimeRange.data.i64[0]; + int64_t maxExp = exposureTimeRange.data.i64[1]; + ASSERT_GT(maxExp, minExp); + + camera_metadata_ro_entry sensivityRange = + GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE); + ASSERT_EQ(2u, sensivityRange.count); + int32_t minSensitivity = sensivityRange.data.i32[0]; + int32_t maxSensitivity = sensivityRange.data.i32[1]; + camera_metadata_ro_entry maxAnalogSenEntry = + GetStaticEntry(ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY); + EXPECT_EQ(1u, maxAnalogSenEntry.count); + int32_t maxAnalogSensitivity = maxAnalogSenEntry.data.i32[0]; + EXPECT_LE(maxAnalogSensitivity, maxSensitivity); + // Only test the sensitivity implemented by analog gain. + if (maxAnalogSensitivity > maxSensitivity) { + // Fallback to maxSensitity + maxAnalogSensitivity = maxSensitivity; + } + + // sensitivity list, only include the sensitivities that are implemented + // purely by analog gain if possible. + Vector<int32_t> sensitivities; + Vector<int64_t> exposures; + size_t count = (maxAnalogSensitivity - minSensitivity + 99) / 100; + sensitivities.push_back(minSensitivity); + for (size_t i = 1; i < count; i++) { + sensitivities.push_back(minSensitivity + i * 100); + } + sensitivities.push_back(maxAnalogSensitivity); + ALOGV("Sensitivity Range: min=%d, max=%d", minSensitivity, + maxAnalogSensitivity); + int64_t exp = minExp; + while (exp < maxExp) { + exposures.push_back(exp); + exp *= 2; + } + // Sweep the exposure value for preview, just for visual inspection purpose. + uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF); + for (size_t i = 0; i < exposures.size(); i++) { + ASSERT_EQ(OK, previewRequest.update( + ANDROID_CONTROL_MODE, + &cmOff, 1)); + ASSERT_EQ(OK, previewRequest.update( + ANDROID_SENSOR_EXPOSURE_TIME, + &exposures[i], 1)); + ALOGV("Submitting preview request %zu with exposure %" PRId64, + i, exposures[i]); + + ASSERT_EQ(OK, mDevice->setStreamingRequest(previewRequest)); + + // Let preview run 200ms on screen for each exposure time. + usleep(PREVIEW_RENDERING_TIME_INTERVAL); + } + + size_t requestCount = sensitivities.size(); + if (requestCount > exposures.size()) { + requestCount = exposures.size(); + } + + // To maintain the request id uniqueness (preview request id is 0), make burst capture start + // request id 1 here. + int32_t requestIdStart = 1; + /** + * Submit metering request, set default frame duration to minimal possible + * value, we want the capture to run as fast as possible. HAL should adjust + * the frame duration to minimal necessary value to support the requested + * exposure value if exposure is larger than frame duration. + */ + CaptureBurst(meteringRequest, requestCount, exposures, sensitivities, + meteringStream, minFrameDuration, &requestIdStart); + + /** + * Submit capture request, set default frame duration to minimal possible + * value, we want the capture to run as fast as possible. HAL should adjust + * the frame duration to minimal necessary value to support the requested + * exposure value if exposure is larger than frame duration. + */ + CaptureBurst(captureRequest, requestCount, exposures, sensitivities, + captureStream, minFrameDuration, &requestIdStart); + + ASSERT_EQ(OK, mDevice->clearStreamingRequest()); +} + +} +} +}
diff --git a/libhardware/tests/camera2/CameraStreamFixture.h b/libhardware/tests/camera2/CameraStreamFixture.h new file mode 100644 index 0000000..92ff05b --- /dev/null +++ b/libhardware/tests/camera2/CameraStreamFixture.h
@@ -0,0 +1,377 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA2_TESTS_STREAM_FIXTURE__ +#define __ANDROID_HAL_CAMERA2_TESTS_STREAM_FIXTURE__ + +#include <gtest/gtest.h> +#include <iostream> +#include <fstream> + +#include <gui/CpuConsumer.h> +#include <gui/Surface.h> +#include <utils/Condition.h> +#include <utils/Mutex.h> +#include <system/camera_metadata.h> + +#include "CameraModuleFixture.h" +#include "TestExtensions.h" + +#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) + +namespace android { +namespace camera2 { +namespace tests { + +// Format specifier for picking the best format for CPU reading the given device +// version +#define CAMERA_STREAM_AUTO_CPU_FORMAT (-1) + +struct CameraStreamParams; + +void PrintTo(const CameraStreamParams& p, ::std::ostream* os); + +struct CameraStreamParams { + int mFormat; + int mHeapCount; + +}; + +inline ::std::ostream& operator<<(::std::ostream& os, const CameraStreamParams &p) { + PrintTo(p, &os); + return os; +} + +inline void PrintTo(const CameraStreamParams& p, ::std::ostream* os) { + char fmt[100]; + camera_metadata_enum_snprint( + ANDROID_SCALER_AVAILABLE_FORMATS, p.mFormat, fmt, sizeof(fmt)); + + *os << "{ "; + *os << "Format: 0x" << std::hex << p.mFormat << ", "; + *os << "Format name: " << fmt << ", "; + *os << "HeapCount: " << p.mHeapCount; + *os << " }"; +} + +class CameraStreamFixture + : public CameraModuleFixture</*InfoQuirk*/true> { + +public: + explicit CameraStreamFixture(CameraStreamParams p) + : CameraModuleFixture(TestSettings::DeviceId()) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + + mParam = p; + + SetUp(); + } + + ~CameraStreamFixture() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + + TearDown(); + } + +private: + + void SetUp() { + TEST_EXTENSION_FORKING_SET_UP; + + CameraModuleFixture::SetUp(); + + sp<CameraDeviceBase> device = mDevice; + + /* use an arbitrary w,h */ + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + const int tag = ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES; + + const CameraMetadata& staticInfo = device->info(); + camera_metadata_ro_entry entry = staticInfo.find(tag); + ASSERT_NE(0u, entry.count) + << "Missing tag android.scaler.availableProcessedSizes"; + + ASSERT_LE(2u, entry.count); + /* this seems like it would always be the smallest w,h + but we actually make no contract that it's sorted asc */ + mWidth = entry.data.i32[0]; + mHeight = entry.data.i32[1]; + } else { + buildOutputResolutions(); + const int32_t *implDefResolutions = NULL; + size_t implDefResolutionsCount; + + int format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; + + getResolutionList(format, + &implDefResolutions, &implDefResolutionsCount); + ASSERT_NE(0u, implDefResolutionsCount) + << "Missing implementation defined sizes"; + mWidth = implDefResolutions[0]; + mHeight = implDefResolutions[1]; + } + } + void TearDown() { + TEST_EXTENSION_FORKING_TEAR_DOWN; + + // important: shut down HAL before releasing streams + CameraModuleFixture::TearDown(); + + deleteOutputResolutions(); + mSurface.clear(); + mCpuConsumer.clear(); + mFrameListener.clear(); + } + +protected: + + int64_t getMinFrameDurationFor(int32_t format, int32_t width, int32_t height) { + int64_t minFrameDuration = -1L; + const int tag = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS; + sp<CameraDeviceBase> device = mDevice; + const CameraMetadata& staticInfo = device->info(); + camera_metadata_ro_entry_t availableMinDurations = staticInfo.find(tag); + for (uint32_t i = 0; i < availableMinDurations.count; i += 4) { + if (format == availableMinDurations.data.i64[i] && + width == availableMinDurations.data.i64[i + 1] && + height == availableMinDurations.data.i64[i + 2]) { + minFrameDuration = availableMinDurations.data.i64[i + 3]; + break; + } + } + return minFrameDuration; + } + + void buildOutputResolutions() { + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + return; + } + if (mOutputResolutions.isEmpty()) { + const int tag = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS; + const CameraMetadata& staticInfo = mDevice->info(); + camera_metadata_ro_entry_t availableStrmConfigs = staticInfo.find(tag); + ASSERT_EQ(0u, availableStrmConfigs.count % 4); + for (uint32_t i = 0; i < availableStrmConfigs.count; i += 4) { + int32_t format = availableStrmConfigs.data.i32[i]; + int32_t width = availableStrmConfigs.data.i32[i + 1]; + int32_t height = availableStrmConfigs.data.i32[i + 2]; + int32_t inOrOut = availableStrmConfigs.data.i32[i + 3]; + if (inOrOut == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) { + int index = mOutputResolutions.indexOfKey(format); + if (index < 0) { + index = mOutputResolutions.add(format, new Vector<int32_t>()); + ASSERT_TRUE(index >= 0); + } + Vector<int32_t> *resolutions = mOutputResolutions.editValueAt(index); + resolutions->add(width); + resolutions->add(height); + } + } + } + } + + void getResolutionList(int32_t format, + const int32_t **list, + size_t *count) { + ALOGV("Getting resolutions for format %x", format); + if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) { + return; + } + int index = mOutputResolutions.indexOfKey(format); + ASSERT_TRUE(index >= 0); + Vector<int32_t>* resolutions = mOutputResolutions.valueAt(index); + *list = resolutions->array(); + *count = resolutions->size(); + } + + void deleteOutputResolutions() { + for (uint32_t i = 0; i < mOutputResolutions.size(); i++) { + Vector<int32_t>* resolutions = mOutputResolutions.editValueAt(i); + delete resolutions; + } + mOutputResolutions.clear(); + } + + struct FrameListener : public ConsumerBase::FrameAvailableListener { + + FrameListener() { + mPendingFrames = 0; + } + + // CpuConsumer::FrameAvailableListener implementation + virtual void onFrameAvailable(const BufferItem& /* item */) { + ALOGV("Frame now available (start)"); + + Mutex::Autolock lock(mMutex); + mPendingFrames++; + mCondition.signal(); + + ALOGV("Frame now available (end)"); + } + + status_t waitForFrame(nsecs_t timeout) { + status_t res; + Mutex::Autolock lock(mMutex); + while (mPendingFrames == 0) { + res = mCondition.waitRelative(mMutex, timeout); + if (res != OK) return res; + } + mPendingFrames--; + return OK; + } + + private: + Mutex mMutex; + Condition mCondition; + int mPendingFrames; + }; + + void CreateStream() { + sp<CameraDeviceBase> device = mDevice; + CameraStreamParams p = mParam; + + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mCpuConsumer = new CpuConsumer(consumer, p.mHeapCount); + mCpuConsumer->setName(String8("CameraStreamTest::mCpuConsumer")); + + mSurface = new Surface(producer); + + int format = MapAutoFormat(p.mFormat); + + ASSERT_EQ(OK, + device->createStream(mSurface, + mWidth, mHeight, format, + HAL_DATASPACE_UNKNOWN, + CAMERA3_STREAM_ROTATION_0, + &mStreamId)); + + ASSERT_NE(-1, mStreamId); + + // do not make 'this' a FrameListener or the lifetime policy will clash + mFrameListener = new FrameListener(); + mCpuConsumer->setFrameAvailableListener(mFrameListener); + } + + void DeleteStream() { + ASSERT_EQ(OK, mDevice->deleteStream(mStreamId)); + } + + int MapAutoFormat(int format) { + if (format == CAMERA_STREAM_AUTO_CPU_FORMAT) { + if (getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_0) { + format = HAL_PIXEL_FORMAT_YCbCr_420_888; + } else { + format = HAL_PIXEL_FORMAT_YCrCb_420_SP; + } + } + return format; + } + + void DumpYuvToFile(const String8 &fileName, const CpuConsumer::LockedBuffer &img) { + uint8_t *dataCb, *dataCr; + uint32_t stride; + uint32_t chromaStride; + uint32_t chromaStep; + + switch (img.format) { + case HAL_PIXEL_FORMAT_YCbCr_420_888: + stride = img.stride; + chromaStride = img.chromaStride; + chromaStep = img.chromaStep; + dataCb = img.dataCb; + dataCr = img.dataCr; + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + stride = img.width; + chromaStride = img.width; + chromaStep = 2; + dataCr = img.data + img.width * img.height; + dataCb = dataCr + 1; + break; + case HAL_PIXEL_FORMAT_YV12: + stride = img.stride; + chromaStride = ALIGN(img.width / 2, 16); + chromaStep = 1; + dataCr = img.data + img.stride * img.height; + dataCb = dataCr + chromaStride * img.height/2; + break; + default: + ALOGE("Unknown format %d, not dumping", img.format); + return; + } + + // Write Y + FILE *yuvFile = fopen(fileName.string(), "w"); + + size_t bytes; + + for (size_t y = 0; y < img.height; ++y) { + bytes = fwrite( + reinterpret_cast<const char*>(img.data + stride * y), + 1, img.width, yuvFile); + if (bytes != img.width) { + ALOGE("Unable to write to file %s", fileName.string()); + fclose(yuvFile); + return; + } + } + + // Write Cb/Cr + uint8_t *src = dataCb; + for (int c = 0; c < 2; ++c) { + for (size_t y = 0; y < img.height / 2; ++y) { + uint8_t *px = src + y * chromaStride; + if (chromaStep != 1) { + for (size_t x = 0; x < img.width / 2; ++x) { + fputc(*px, yuvFile); + px += chromaStep; + } + } else { + bytes = fwrite(reinterpret_cast<const char*>(px), + 1, img.width / 2, yuvFile); + if (bytes != img.width / 2) { + ALOGE("Unable to write to file %s", fileName.string()); + fclose(yuvFile); + return; + } + } + } + src = dataCr; + } + fclose(yuvFile); + } + + int mWidth; + int mHeight; + + int mStreamId; + + android::sp<FrameListener> mFrameListener; + android::sp<CpuConsumer> mCpuConsumer; + android::sp<Surface> mSurface; + KeyedVector<int32_t, Vector<int32_t>* > mOutputResolutions; + +private: + CameraStreamParams mParam; +}; + +} +} +} + +#endif
diff --git a/libhardware/tests/camera2/CameraStreamTests.cpp b/libhardware/tests/camera2/CameraStreamTests.cpp new file mode 100644 index 0000000..a3b8c47 --- /dev/null +++ b/libhardware/tests/camera2/CameraStreamTests.cpp
@@ -0,0 +1,188 @@ +/* + * Copyright (C) 2012 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 <iostream> +#include <iomanip> +#include <gtest/gtest.h> + +#define LOG_TAG "CameraStreamTest" +#define LOG_NDEBUG 0 +#include <utils/Log.h> + +#include "hardware/hardware.h" +#include "hardware/camera2.h" + +#include <utils/StrongPointer.h> +#include <gui/CpuConsumer.h> +#include <gui/Surface.h> + +#include <device2/Camera2Device.h> + +#include "CameraStreamFixture.h" +#include "TestExtensions.h" + +using namespace android; +using namespace android::camera2; + +namespace android { +namespace camera2 { +namespace tests { + +class CameraStreamTest + : public ::testing::TestWithParam<CameraStreamParams>, + public CameraStreamFixture { + +public: + CameraStreamTest() : CameraStreamFixture(GetParam()) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + } + + ~CameraStreamTest() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + } + + virtual void SetUp() { + TEST_EXTENSION_FORKING_SET_UP; + } + virtual void TearDown() { + TEST_EXTENSION_FORKING_TEAR_DOWN; + } + +protected: + +}; + +TEST_P(CameraStreamTest, CreateStream) { + + TEST_EXTENSION_FORKING_INIT; + + /** Make sure the format requested is supported. PASS this test if it's not + * not supported. + * + * TODO: would be nice of not running this test in the first place + * somehow. + */ + { + camera_metadata_ro_entry availableFormats = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_FORMATS); + + bool hasFormat = false; + for (size_t i = 0; i < availableFormats.count; ++i) { + if (availableFormats.data.i32[i] == GetParam().mFormat) { + hasFormat = true; + break; + } + } + + if (!hasFormat) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + std::cerr << "Skipping test " + << test_info->test_case_name() << "." + << test_info->name() + << " because the format was not available: " + << GetParam() << std::endl; + return; + } + } + + ASSERT_NO_FATAL_FAILURE(CreateStream()); + ASSERT_NO_FATAL_FAILURE(DeleteStream()); +} + +//TODO: use a combinatoric generator +static CameraStreamParams TestParameters[] = { + { + /*mFormat*/ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + /*mHeapCount*/ 1 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + /*mHeapCount*/ 2 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + /*mHeapCount*/ 3 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP, // NV21 + /*mHeapCount*/ 1 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP, + /*mHeapCount*/ 2 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_YCrCb_420_SP, + /*mHeapCount*/ 3 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_YV12, + /*mHeapCount*/ 1 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_YV12, + /*mHeapCount*/ 2 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_YV12, + /*mHeapCount*/ 3 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_Y8, + /*mHeapCount*/ 1 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_Y8, + /*mHeapCount*/ 2 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_Y8, + /*mHeapCount*/ 3 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_Y16, + /*mHeapCount*/ 1 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_Y16, + /*mHeapCount*/ 2 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_Y16, + /*mHeapCount*/ 3 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_RAW16, + /*mHeapCount*/ 1 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_RAW16, + /*mHeapCount*/ 2 + }, + { + /*mFormat*/ HAL_PIXEL_FORMAT_RAW16, + /*mHeapCount*/ 3 + }, +}; + +INSTANTIATE_TEST_CASE_P(StreamParameterCombinations, CameraStreamTest, + testing::ValuesIn(TestParameters)); + + +} +} +}
diff --git a/libhardware/tests/camera2/ForkedTests.cpp b/libhardware/tests/camera2/ForkedTests.cpp new file mode 100644 index 0000000..39599da --- /dev/null +++ b/libhardware/tests/camera2/ForkedTests.cpp
@@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 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 <gtest/gtest.h> + +#include <stdlib.h> + +#include "TestExtensions.h" + +namespace android { +namespace camera2 { +namespace tests { + +// Intentionally disabled since 2 of these tests are supposed to fail +class DISABLED_ForkedTest : public ::testing::Test { + + virtual void SetUp() { + TEST_EXTENSION_FORKING_SET_UP; + } + + virtual void TearDown() { + TEST_EXTENSION_FORKING_TEAR_DOWN; + } +}; + +// intentionally fail +TEST_F(DISABLED_ForkedTest, FailCrash) { + TEST_EXTENSION_FORKING_INIT; + abort(); +} + +TEST_F(DISABLED_ForkedTest, SucceedNormal) { + TEST_EXTENSION_FORKING_INIT; + + EXPECT_TRUE(true); +} + +// intentionally fail +TEST_F(DISABLED_ForkedTest, FailNormal) { + TEST_EXTENSION_FORKING_INIT; + + EXPECT_TRUE(false); +} + +} +} +} +
diff --git a/libhardware/tests/camera2/TestExtensions.h b/libhardware/tests/camera2/TestExtensions.h new file mode 100644 index 0000000..2af587d --- /dev/null +++ b/libhardware/tests/camera2/TestExtensions.h
@@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA2_TESTS_EXTENSIONS__ +#define __ANDROID_HAL_CAMERA2_TESTS_EXTENSIONS__ + +#include "TestForkerEventListener.h" +#include "TestSettings.h" + +// Use at the beginning of each Test::SetUp() impl +#define TEST_EXTENSION_FORKING_SET_UP \ + do { \ + if (TEST_EXTENSION_FORKING_ENABLED) { \ + if (!TestForkerEventListener::mIsForked) { \ + return; \ + } \ + } \ + } while (false) \ + +// Use at the beginning of each Test::TearDown() impl +#define TEST_EXTENSION_FORKING_TEAR_DOWN TEST_EXTENSION_FORKING_SET_UP + +// Use at the beginning of each Test::Test constructor +#define TEST_EXTENSION_FORKING_CONSTRUCTOR TEST_EXTENSION_FORKING_SET_UP + +// Use at the beginning of each Test::~Test destructor +#define TEST_EXTENSION_FORKING_DESTRUCTOR TEST_EXTENSION_FORKING_TEAR_DOWN + +// Use at the beginning of each test body, e.g. TEST(x,y), TEST_F(x,y), etc +#define TEST_EXTENSION_FORKING_INIT \ + do { \ + TEST_EXTENSION_FORKING_SET_UP; \ + if (HasFatalFailure()) return; \ + } while(false) \ + +// Are we running each test by forking it? +#define TEST_EXTENSION_FORKING_ENABLED \ + (android::camera2::tests::TestSettings::ForkingEnabled()) + + + +#endif +
diff --git a/libhardware/tests/camera2/TestForkerEventListener.cpp b/libhardware/tests/camera2/TestForkerEventListener.cpp new file mode 100644 index 0000000..9416db2 --- /dev/null +++ b/libhardware/tests/camera2/TestForkerEventListener.cpp
@@ -0,0 +1,117 @@ +/* + * Copyright (C) 2012 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 <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <string.h> + +#include <gtest/gtest.h> + +#include "TestForkerEventListener.h" +#include "TestExtensions.h" + +#define DEBUG_TEST_FORKER_EVENT_LISTENER 0 + +#define RETURN_CODE_PASSED 0 +#define RETURN_CODE_FAILED 1 + +namespace android { +namespace camera2 { +namespace tests { + +bool TestForkerEventListener::mIsForked = false; + +TestForkerEventListener::TestForkerEventListener() { + mIsForked = false; + mHasSucceeded = true; + mTermSignal = 0; +} + +// Called before a test starts. +void TestForkerEventListener::OnTestStart(const ::testing::TestInfo&) { + + if (!TEST_EXTENSION_FORKING_ENABLED) { + return; + } + + pid_t childPid = fork(); + if (childPid != 0) { + int status; + waitpid(childPid, &status, /*options*/0); + + // terminated normally? + mHasSucceeded = WIFEXITED(status); + // terminate with return code 0 = test passed, 1 = test failed + if (mHasSucceeded) { + mHasSucceeded = WEXITSTATUS(status) == RETURN_CODE_PASSED; + } else if (WIFSIGNALED(status)) { + mTermSignal = WTERMSIG(status); + } + + /* the test is then skipped by inserting the various + TEST_EXTENSION_ macros in TestExtensions.h */ + + } else { + mIsForked = true; + } +} + +// Called after a failed assertion or a SUCCEED() invocation. +void TestForkerEventListener::OnTestPartResult( + const ::testing::TestPartResult& test_part_result) { + + if (DEBUG_TEST_FORKER_EVENT_LISTENER) { + printf("%s in %s:%d\n%s\n", + test_part_result.failed() ? "*** Failure" : "Success", + test_part_result.file_name(), + test_part_result.line_number(), + test_part_result.summary()); + } +} + +// Called after a test ends. +void TestForkerEventListener::OnTestEnd(const ::testing::TestInfo& test_info) { + + if (!TEST_EXTENSION_FORKING_ENABLED) { + return; + } + + if (mIsForked) { + exit(test_info.result()->Passed() + ? RETURN_CODE_PASSED : RETURN_CODE_FAILED); + } else if (!mHasSucceeded && mTermSignal != 0) { + + printf("*** Test %s.%s crashed with signal = %s\n", + test_info.test_case_name(), test_info.name(), + strsignal(mTermSignal)); + } + + //TODO: overload the default event listener to suppress this message + // dynamically (e.g. by skipping OnTestPartResult after OnTestEnd ) + + // trigger a test failure if the child has failed + if (!mHasSucceeded) { + ADD_FAILURE(); + } + mTermSignal = 0; +} + + +} +} +} +
diff --git a/libhardware/tests/camera2/TestForkerEventListener.h b/libhardware/tests/camera2/TestForkerEventListener.h new file mode 100644 index 0000000..347a06b --- /dev/null +++ b/libhardware/tests/camera2/TestForkerEventListener.h
@@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA2_TESTS_FORKER_EVENT_LISTENER__ +#define __ANDROID_HAL_CAMERA2_TESTS_FORKER_EVENT_LISTENER__ + +#include <gtest/gtest.h> + +namespace android { +namespace camera2 { +namespace tests { + +// Fork before each test runs. +class TestForkerEventListener : public ::testing::EmptyTestEventListener { + +public: + + TestForkerEventListener(); + +private: + + // Called before a test starts. + virtual void OnTestStart(const ::testing::TestInfo& test_info); + + // Called after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult( + const ::testing::TestPartResult& test_part_result); + + // Called after a test ends. + virtual void OnTestEnd(const ::testing::TestInfo& test_info); + + bool mHasSucceeded; + int mTermSignal; + +public: + // do not read directly. use TEST_EXTENSION macros instead + static bool mIsForked; +}; + +} +} +} + +#endif
diff --git a/libhardware/tests/camera2/TestSettings.cpp b/libhardware/tests/camera2/TestSettings.cpp new file mode 100644 index 0000000..f07adc8 --- /dev/null +++ b/libhardware/tests/camera2/TestSettings.cpp
@@ -0,0 +1,167 @@ +/* + * Copyright (C) 2012 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 <cstdlib> +#include <getopt.h> +#include <cstring> +#include <iostream> + +#include "TestSettings.h" + +#include "TestForkerEventListener.h" + +namespace android { +namespace camera2 { +namespace tests { + +bool TestSettings::mForkingDisabled = false; +int TestSettings::mDeviceId = 0; +char* const* TestSettings::mArgv; + +// --forking-disabled, false by default +bool TestSettings::ForkingDisabled() { + return mForkingDisabled; +} + +// reverse of --forking-disabled (not a flag), true by default +bool TestSettings::ForkingEnabled() { + return !ForkingDisabled(); +} + +// --device-id, 0 by default +int TestSettings::DeviceId() { + return mDeviceId; +} + +// returns false if usage should be printed and we should exit early +bool TestSettings::ParseArgs(int argc, char* const argv[]) +{ + { + char *env = getenv("CAMERA2_TEST_FORKING_DISABLED"); + if (env) { + mForkingDisabled = atoi(env); + } + + env = getenv("CAMERA2_TEST_DEVICE_ID"); + if (env) { + mDeviceId = atoi(env); + } + } + + bool printHelp = false; + bool unknownArgs = false; + + opterr = 0; // do not print errors for unknown arguments + while (true) { + int c; + int option_index = 0; + + static struct option long_options[] = { + /* name has_arg flag val */ + {"forking-disabled", optional_argument, 0, 0 }, + {"device-id", required_argument, 0, 0 }, + {"help", no_argument, 0, 'h' }, + {0, 0, 0, 0 } + }; + + // Note: '+' in optstring means do not mutate argv + c = getopt_long(argc, argv, "+h", long_options, &option_index); + + if (c == -1) { // All arguments exhausted + break; + } + if (c == '?') { // Argument not in option lists + const char *arg = argv[optind-1]; + // Anything beginning with gtest_ will get handled by gtest + if (strstr(arg, "--gtest_") != arg) { + std::cerr << "Unknown argument: " << arg << std::endl; + unknownArgs = true; + } + continue; + } + + switch (c) { + case 0: // long option + switch (option_index) { + case 0: { + const char *arg = optarg ?: "1"; + mForkingDisabled = atoi(arg); + break; + } + case 1: { + mDeviceId = atoi(optarg); + break; + } + default: + std::cerr << "Unknown long option: " << option_index << std::endl; + break; + } + break; // case 0 + case 'h': // help + printHelp = true; + break; + default: // case '?' + std::cerr << "Unknown option: " << optarg << std::endl; + } + } + + if (unknownArgs) { + std::cerr << std::endl; + } + + mArgv = argv; + + if (printHelp || unknownArgs) { + return false; + } + + std::cerr << "Forking Disabled: " + << (mForkingDisabled ? "yes" : "no") << std::endl; + + std::cerr << "Device ID: " << mDeviceId << std::endl; + + return true; +} + +// print usage/help list of commands (non-gtest) +void TestSettings::PrintUsage() { + std::cerr << "Usage: " << mArgv[0] << " [OPTIONS]" << std::endl; + std::cerr << std::endl; + + std::cerr << "Main modes of operation:" + << std::endl; + std::cerr << " --forking-disabled[=1] don't fork process before " + << std::endl + << " running a new test." + << std::endl + << " (default enabled)" + << std::endl; + std::cerr << " --device-id=ID specify a different camera ID" + << std::endl + << " (default 0)" + << std::endl; + + std::cerr << " -h, --help print this help listing" + << std::endl; + + + std::cerr << std::endl; +} + +} +} +} +
diff --git a/libhardware/tests/camera2/TestSettings.h b/libhardware/tests/camera2/TestSettings.h new file mode 100644 index 0000000..6164de5 --- /dev/null +++ b/libhardware/tests/camera2/TestSettings.h
@@ -0,0 +1,56 @@ +/* +:qa + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA2_TESTS_SETTINGS__ +#define __ANDROID_HAL_CAMERA2_TESTS_SETTINGS__ + +namespace android { +namespace camera2 { +namespace tests { + +class TestSettings { + +public: + // --forking-disabled, false by default + static bool ForkingDisabled(); + + // reverse of --forking-disabled (not a flag), true by default + static bool ForkingEnabled(); + + // --device-id, 0 by default + static int DeviceId(); + + // returns false if usage should be printed and we should exit early + static bool ParseArgs(int argc, char* const argv[]); + + // print usage/help list of commands (non-gtest) + static void PrintUsage(); + +private: + TestSettings(); + ~TestSettings(); + + static bool mForkingDisabled; + static int mDeviceId; + static char* const* mArgv; +}; + +} +} +} + +#endif
diff --git a/libhardware/tests/camera2/camera2_utils.cpp b/libhardware/tests/camera2/camera2_utils.cpp new file mode 100644 index 0000000..dab0ae9 --- /dev/null +++ b/libhardware/tests/camera2/camera2_utils.cpp
@@ -0,0 +1,609 @@ +/* + * Copyright (C) 2012 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. + */ + +// Utility classes for camera2 HAL testing + +#define LOG_TAG "Camera2_test_utils" +#define LOG_NDEBUG 0 + +#include "utils/Log.h" +#include "camera2_utils.h" +#include <dlfcn.h> + +namespace android { +namespace camera2 { +namespace tests { + +/** + * MetadataQueue + */ + +MetadataQueue::MetadataQueue(): + mDevice(NULL), + mFrameCount(0), + mCount(0), + mStreamSlotCount(0), + mSignalConsumer(true) +{ + camera2_request_queue_src_ops::dequeue_request = consumer_dequeue; + camera2_request_queue_src_ops::request_count = consumer_buffer_count; + camera2_request_queue_src_ops::free_request = consumer_free; + + camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue; + camera2_frame_queue_dst_ops::cancel_frame = producer_cancel; + camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue; +} + +MetadataQueue::~MetadataQueue() { + freeBuffers(mEntries.begin(), mEntries.end()); + freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); +} + +// Interface to camera2 HAL as consumer (input requests/reprocessing) +const camera2_request_queue_src_ops_t* MetadataQueue::getToConsumerInterface() { + return static_cast<camera2_request_queue_src_ops_t*>(this); +} + +void MetadataQueue::setFromConsumerInterface(camera2_device_t *d) { + mDevice = d; +} + +const camera2_frame_queue_dst_ops_t* MetadataQueue::getToProducerInterface() { + return static_cast<camera2_frame_queue_dst_ops_t*>(this); +} + +// Real interfaces +status_t MetadataQueue::enqueue(camera_metadata_t *buf) { + Mutex::Autolock l(mMutex); + + mCount++; + mEntries.push_back(buf); + notEmpty.signal(); + + if (mSignalConsumer && mDevice != NULL) { + mSignalConsumer = false; + + mMutex.unlock(); + ALOGV("%s: Signaling consumer", __FUNCTION__); + mDevice->ops->notify_request_queue_not_empty(mDevice); + mMutex.lock(); + } + return OK; +} + +int MetadataQueue::getBufferCount() { + Mutex::Autolock l(mMutex); + if (mStreamSlotCount > 0) { + return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS; + } + return mCount; +} + +status_t MetadataQueue::dequeue(camera_metadata_t **buf, bool incrementCount) { + Mutex::Autolock l(mMutex); + + if (mCount == 0) { + if (mStreamSlotCount == 0) { + ALOGV("%s: Empty", __FUNCTION__); + *buf = NULL; + mSignalConsumer = true; + return OK; + } + ALOGV("%s: Streaming %d frames to queue", __FUNCTION__, + mStreamSlotCount); + + for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin(); + slotEntry != mStreamSlot.end(); + slotEntry++ ) { + size_t entries = get_camera_metadata_entry_count(*slotEntry); + size_t dataBytes = get_camera_metadata_data_count(*slotEntry); + + camera_metadata_t *copy = allocate_camera_metadata(entries, dataBytes); + append_camera_metadata(copy, *slotEntry); + mEntries.push_back(copy); + } + mCount = mStreamSlotCount; + } + ALOGV("MetadataQueue: deque (%d buffers)", mCount); + camera_metadata_t *b = *(mEntries.begin()); + mEntries.erase(mEntries.begin()); + + if (incrementCount) { + add_camera_metadata_entry(b, + ANDROID_REQUEST_FRAME_COUNT, + (void**)&mFrameCount, 1); + mFrameCount++; + } + + *buf = b; + mCount--; + + return OK; +} + +status_t MetadataQueue::waitForBuffer(nsecs_t timeout) { + Mutex::Autolock l(mMutex); + status_t res; + while (mCount == 0) { + res = notEmpty.waitRelative(mMutex,timeout); + if (res != OK) return res; + } + return OK; +} + +status_t MetadataQueue::setStreamSlot(camera_metadata_t *buf) { + if (buf == NULL) { + freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); + mStreamSlotCount = 0; + return OK; + } + if (mStreamSlotCount > 1) { + List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin(); + freeBuffers(++mStreamSlot.begin(), mStreamSlot.end()); + mStreamSlotCount = 1; + } + if (mStreamSlotCount == 1) { + free_camera_metadata( *(mStreamSlot.begin()) ); + *(mStreamSlot.begin()) = buf; + } else { + mStreamSlot.push_front(buf); + mStreamSlotCount = 1; + } + return OK; +} + +status_t MetadataQueue::setStreamSlot(const List<camera_metadata_t*> &bufs) { + if (mStreamSlotCount > 0) { + freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); + } + mStreamSlot = bufs; + mStreamSlotCount = mStreamSlot.size(); + + return OK; +} + +status_t MetadataQueue::freeBuffers(List<camera_metadata_t*>::iterator start, + const List<camera_metadata_t*>::iterator& end) { + while (start != end) { + free_camera_metadata(*start); + start = mStreamSlot.erase(start); + } + return OK; +} + +MetadataQueue* MetadataQueue::getInstance( + const camera2_request_queue_src_ops_t *q) { + const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q); + return const_cast<MetadataQueue*>(cmq); +} + +MetadataQueue* MetadataQueue::getInstance( + const camera2_frame_queue_dst_ops_t *q) { + const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q); + return const_cast<MetadataQueue*>(cmq); +} + +int MetadataQueue::consumer_buffer_count( + const camera2_request_queue_src_ops_t *q) { + MetadataQueue *queue = getInstance(q); + return queue->getBufferCount(); +} + +int MetadataQueue::consumer_dequeue(const camera2_request_queue_src_ops_t *q, + camera_metadata_t **buffer) { + MetadataQueue *queue = getInstance(q); + return queue->dequeue(buffer, true); +} + +int MetadataQueue::consumer_free(const camera2_request_queue_src_ops_t * /* q */, + camera_metadata_t *old_buffer) { + free_camera_metadata(old_buffer); + return OK; +} + +int MetadataQueue::producer_dequeue(const camera2_frame_queue_dst_ops_t * /* q */, + size_t entries, size_t bytes, + camera_metadata_t **buffer) { + camera_metadata_t *new_buffer = + allocate_camera_metadata(entries, bytes); + if (new_buffer == NULL) return NO_MEMORY; + *buffer = new_buffer; + return OK; +} + +int MetadataQueue::producer_cancel(const camera2_frame_queue_dst_ops_t * /* q */, + camera_metadata_t *old_buffer) { + free_camera_metadata(old_buffer); + return OK; +} + +int MetadataQueue::producer_enqueue(const camera2_frame_queue_dst_ops_t *q, + camera_metadata_t *filled_buffer) { + MetadataQueue *queue = getInstance(q); + return queue->enqueue(filled_buffer); +} + +/** + * NotifierListener + */ + +NotifierListener::NotifierListener() { +} + +status_t NotifierListener::getNotificationsFrom(camera2_device *dev) { + if (!dev) return BAD_VALUE; + status_t err; + err = dev->ops->set_notify_callback(dev, + notify_callback_dispatch, + (void*)this); + return err; +} + +status_t NotifierListener::getNextNotification(int32_t *msg_type, + int32_t *ext1, + int32_t *ext2, + int32_t *ext3) { + Mutex::Autolock l(mMutex); + if (mNotifications.size() == 0) return BAD_VALUE; + return getNextNotificationLocked(msg_type, ext1, ext2, ext3); +} + +status_t NotifierListener::waitForNotification(int32_t *msg_type, + int32_t *ext1, + int32_t *ext2, + int32_t *ext3) { + Mutex::Autolock l(mMutex); + while (mNotifications.size() == 0) { + mNewNotification.wait(mMutex); + } + return getNextNotificationLocked(msg_type, ext1, ext2, ext3); +} + +int NotifierListener::numNotifications() { + Mutex::Autolock l(mMutex); + return mNotifications.size(); +} + +status_t NotifierListener::getNextNotificationLocked(int32_t *msg_type, + int32_t *ext1, + int32_t *ext2, + int32_t *ext3) { + *msg_type = mNotifications.begin()->msg_type; + *ext1 = mNotifications.begin()->ext1; + *ext2 = mNotifications.begin()->ext2; + *ext3 = mNotifications.begin()->ext3; + mNotifications.erase(mNotifications.begin()); + return OK; +} + +void NotifierListener::onNotify(int32_t msg_type, + int32_t ext1, + int32_t ext2, + int32_t ext3) { + Mutex::Autolock l(mMutex); + mNotifications.push_back(Notification(msg_type, ext1, ext2, ext3)); + mNewNotification.signal(); +} + +void NotifierListener::notify_callback_dispatch(int32_t msg_type, + int32_t ext1, + int32_t ext2, + int32_t ext3, + void *user) { + NotifierListener *me = reinterpret_cast<NotifierListener*>(user); + me->onNotify(msg_type, ext1, ext2, ext3); +} + +/** + * StreamAdapter + */ + +#ifndef container_of +#define container_of(ptr, type, member) \ + (type *)((char*)(ptr) - offsetof(type, member)) +#endif + +StreamAdapter::StreamAdapter(sp<IGraphicBufferProducer> consumer): + mState(UNINITIALIZED), mDevice(NULL), + mId(-1), + mWidth(0), mHeight(0), mFormat(0) +{ + mConsumerInterface = new Surface(consumer); + camera2_stream_ops::dequeue_buffer = dequeue_buffer; + camera2_stream_ops::enqueue_buffer = enqueue_buffer; + camera2_stream_ops::cancel_buffer = cancel_buffer; + camera2_stream_ops::set_crop = set_crop; +} + +StreamAdapter::~StreamAdapter() { + disconnect(); +} + +status_t StreamAdapter::connectToDevice(camera2_device_t *d, + uint32_t width, uint32_t height, int format) { + if (mState != UNINITIALIZED) return INVALID_OPERATION; + if (d == NULL) { + ALOGE("%s: Null device passed to stream adapter", __FUNCTION__); + return BAD_VALUE; + } + + status_t res; + + mWidth = width; + mHeight = height; + mFormat = format; + + // Allocate device-side stream interface + + uint32_t id; + uint32_t formatActual; // ignored + uint32_t usage; + uint32_t maxBuffers = 2; + res = d->ops->allocate_stream(d, + mWidth, mHeight, mFormat, getStreamOps(), + &id, &formatActual, &usage, &maxBuffers); + if (res != OK) { + ALOGE("%s: Device stream allocation failed: %s (%d)", + __FUNCTION__, strerror(-res), res); + mState = UNINITIALIZED; + return res; + } + mDevice = d; + + mId = id; + mUsage = usage; + mMaxProducerBuffers = maxBuffers; + + // Configure consumer-side ANativeWindow interface + + res = native_window_api_connect(mConsumerInterface.get(), + NATIVE_WINDOW_API_CAMERA); + if (res != OK) { + ALOGE("%s: Unable to connect to native window for stream %d", + __FUNCTION__, mId); + mState = ALLOCATED; + return res; + } + + res = native_window_set_usage(mConsumerInterface.get(), mUsage); + if (res != OK) { + ALOGE("%s: Unable to configure usage %08x for stream %d", + __FUNCTION__, mUsage, mId); + mState = CONNECTED; + return res; + } + + res = native_window_set_buffers_dimensions(mConsumerInterface.get(), + mWidth, mHeight); + if (res != OK) { + ALOGE("%s: Unable to configure buffer dimensions" + " %d x %d for stream %d", + __FUNCTION__, mWidth, mHeight, mId); + mState = CONNECTED; + return res; + } + res = native_window_set_buffers_format(mConsumerInterface.get(), + mFormat); + if (res != OK) { + ALOGE("%s: Unable to configure buffer format" + " 0x%x for stream %d", + __FUNCTION__, mFormat, mId); + mState = CONNECTED; + return res; + } + + int maxConsumerBuffers; + res = mConsumerInterface->query(mConsumerInterface.get(), + NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); + if (res != OK) { + ALOGE("%s: Unable to query consumer undequeued" + " buffer count for stream %d", __FUNCTION__, mId); + mState = CONNECTED; + return res; + } + mMaxConsumerBuffers = maxConsumerBuffers; + + ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__, + mMaxProducerBuffers, mMaxConsumerBuffers); + + int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers; + + res = native_window_set_buffer_count(mConsumerInterface.get(), + totalBuffers); + if (res != OK) { + ALOGE("%s: Unable to set buffer count for stream %d", + __FUNCTION__, mId); + mState = CONNECTED; + return res; + } + + // Register allocated buffers with HAL device + buffer_handle_t *buffers = new buffer_handle_t[totalBuffers]; + ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers]; + int bufferIdx = 0; + for (; bufferIdx < totalBuffers; bufferIdx++) { + res = native_window_dequeue_buffer_and_wait(mConsumerInterface.get(), + &anwBuffers[bufferIdx]); + if (res != OK) { + ALOGE("%s: Unable to dequeue buffer %d for initial registration for" + "stream %d", __FUNCTION__, bufferIdx, mId); + mState = CONNECTED; + goto cleanUpBuffers; + } + buffers[bufferIdx] = anwBuffers[bufferIdx]->handle; + } + + res = mDevice->ops->register_stream_buffers(mDevice, + mId, + totalBuffers, + buffers); + if (res != OK) { + ALOGE("%s: Unable to register buffers with HAL device for stream %d", + __FUNCTION__, mId); + mState = CONNECTED; + } else { + mState = ACTIVE; + } + +cleanUpBuffers: + for (int i = 0; i < bufferIdx; i++) { + res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(), + anwBuffers[i], -1); + } + delete[] anwBuffers; + delete[] buffers; + + return res; +} + +status_t StreamAdapter::disconnect() { + status_t res; + if (mState >= ALLOCATED) { + res = mDevice->ops->release_stream(mDevice, mId); + if (res != OK) { + ALOGE("%s: Unable to release stream %d", + __FUNCTION__, mId); + return res; + } + } + if (mState >= CONNECTED) { + res = native_window_api_disconnect(mConsumerInterface.get(), + NATIVE_WINDOW_API_CAMERA); + if (res != OK) { + ALOGE("%s: Unable to disconnect stream %d from native window", + __FUNCTION__, mId); + return res; + } + } + mId = -1; + mState = DISCONNECTED; + return OK; +} + +int StreamAdapter::getId() { + return mId; +} + +const camera2_stream_ops *StreamAdapter::getStreamOps() { + return static_cast<camera2_stream_ops *>(this); +} + +ANativeWindow* StreamAdapter::toANW(const camera2_stream_ops_t *w) { + return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get(); +} + +int StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w, + buffer_handle_t** buffer) { + int res; + int state = static_cast<const StreamAdapter*>(w)->mState; + if (state != ACTIVE) { + ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); + return INVALID_OPERATION; + } + + ANativeWindow *a = toANW(w); + ANativeWindowBuffer* anb; + res = native_window_dequeue_buffer_and_wait(a, &anb); + if (res != OK) return res; + + *buffer = &(anb->handle); + + return res; +} + +int StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w, + int64_t timestamp, + buffer_handle_t* buffer) { + int state = static_cast<const StreamAdapter*>(w)->mState; + if (state != ACTIVE) { + ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); + return INVALID_OPERATION; + } + ANativeWindow *a = toANW(w); + status_t err; + err = native_window_set_buffers_timestamp(a, timestamp); + if (err != OK) return err; + return a->queueBuffer(a, + container_of(buffer, ANativeWindowBuffer, handle), -1); +} + +int StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w, + buffer_handle_t* buffer) { + int state = static_cast<const StreamAdapter*>(w)->mState; + if (state != ACTIVE) { + ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); + return INVALID_OPERATION; + } + ANativeWindow *a = toANW(w); + return a->cancelBuffer(a, + container_of(buffer, ANativeWindowBuffer, handle), -1); +} + +int StreamAdapter::set_crop(const camera2_stream_ops_t* w, + int left, int top, int right, int bottom) { + int state = static_cast<const StreamAdapter*>(w)->mState; + if (state != ACTIVE) { + ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); + return INVALID_OPERATION; + } + ANativeWindow *a = toANW(w); + android_native_rect_t crop = { left, top, right, bottom }; + return native_window_set_crop(a, &crop); +} + +/** + * FrameWaiter + */ + +FrameWaiter::FrameWaiter(): + mPendingFrames(0) { +} + +status_t FrameWaiter::waitForFrame(nsecs_t timeout) { + status_t res; + Mutex::Autolock lock(mMutex); + while (mPendingFrames == 0) { + res = mCondition.waitRelative(mMutex, timeout); + if (res != OK) return res; + } + mPendingFrames--; + return OK; +} + +void FrameWaiter::onFrameAvailable(const BufferItem& /* item */) { + Mutex::Autolock lock(mMutex); + mPendingFrames++; + mCondition.signal(); +} + +int HWModuleHelpers::closeModule(void *dso) { + int status; + if (!dso) { + return -EINVAL; + } + + status = dlclose(dso); + if (status != 0) { + char const *err_str = dlerror(); + ALOGE("%s dlclose failed, error: %s", __func__, err_str ?: "unknown"); + } + + return status; +} + +} // namespace tests +} // namespace camera2 +} // namespace android
diff --git a/libhardware/tests/camera2/camera2_utils.h b/libhardware/tests/camera2/camera2_utils.h new file mode 100644 index 0000000..274ee76 --- /dev/null +++ b/libhardware/tests/camera2/camera2_utils.h
@@ -0,0 +1,250 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA2_TESTS_UTILS__ +#define __ANDROID_HAL_CAMERA2_TESTS_UTILS__ + +// Utility classes for camera2 HAL testing + +#include <system/camera_metadata.h> +#include <hardware/camera2.h> + +#include <gui/Surface.h> +#include <gui/CpuConsumer.h> + +#include <utils/List.h> +#include <utils/Mutex.h> +#include <utils/Condition.h> + +namespace android { +namespace camera2 { +namespace tests { + +/** + * Queue class for both sending requests to a camera2 device, and for receiving + * frames from a camera2 device. + */ +class MetadataQueue: public camera2_request_queue_src_ops_t, + public camera2_frame_queue_dst_ops_t { + public: + MetadataQueue(); + ~MetadataQueue(); + + // Interface to camera2 HAL device, either for requests (device is consumer) + // or for frames (device is producer) + const camera2_request_queue_src_ops_t* getToConsumerInterface(); + void setFromConsumerInterface(camera2_device_t *d); + + const camera2_frame_queue_dst_ops_t* getToProducerInterface(); + + // Real interfaces. On enqueue, queue takes ownership of buffer pointer + // On dequeue, user takes ownership of buffer pointer. + status_t enqueue(camera_metadata_t *buf); + status_t dequeue(camera_metadata_t **buf, bool incrementCount = true); + int getBufferCount(); + status_t waitForBuffer(nsecs_t timeout); + + // Set repeating buffer(s); if the queue is empty on a dequeue call, the + // queue copies the contents of the stream slot into the queue, and then + // dequeues the first new entry. + status_t setStreamSlot(camera_metadata_t *buf); + status_t setStreamSlot(const List<camera_metadata_t*> &bufs); + + private: + status_t freeBuffers(List<camera_metadata_t*>::iterator start, + const List<camera_metadata_t*>::iterator& end); + + camera2_device_t *mDevice; + + Mutex mMutex; + Condition notEmpty; + + int mFrameCount; + + int mCount; + List<camera_metadata_t*> mEntries; + int mStreamSlotCount; + List<camera_metadata_t*> mStreamSlot; + + bool mSignalConsumer; + + static MetadataQueue* getInstance(const camera2_frame_queue_dst_ops_t *q); + static MetadataQueue* getInstance(const camera2_request_queue_src_ops_t *q); + + static int consumer_buffer_count(const camera2_request_queue_src_ops_t *q); + + static int consumer_dequeue(const camera2_request_queue_src_ops_t *q, + camera_metadata_t **buffer); + + static int consumer_free(const camera2_request_queue_src_ops_t *q, + camera_metadata_t *old_buffer); + + static int producer_dequeue(const camera2_frame_queue_dst_ops_t *q, + size_t entries, size_t bytes, + camera_metadata_t **buffer); + + static int producer_cancel(const camera2_frame_queue_dst_ops_t *q, + camera_metadata_t *old_buffer); + + static int producer_enqueue(const camera2_frame_queue_dst_ops_t *q, + camera_metadata_t *filled_buffer); + +}; + +/** + * Basic class to receive and queue up notifications from the camera device + */ + +class NotifierListener { + public: + + NotifierListener(); + + status_t getNotificationsFrom(camera2_device *dev); + + status_t getNextNotification(int32_t *msg_type, int32_t *ext1, + int32_t *ext2, int32_t *ext3); + + status_t waitForNotification(int32_t *msg_type, int32_t *ext1, + int32_t *ext2, int32_t *ext3); + + int numNotifications(); + + private: + + status_t getNextNotificationLocked(int32_t *msg_type, + int32_t *ext1, int32_t *ext2, int32_t *ext3); + + struct Notification { + Notification(int32_t type, int32_t e1, int32_t e2, int32_t e3): + msg_type(type), + ext1(e1), + ext2(e2), + ext3(e3) + {} + + int32_t msg_type; + int32_t ext1; + int32_t ext2; + int32_t ext3; + }; + + List<Notification> mNotifications; + + Mutex mMutex; + Condition mNewNotification; + + void onNotify(int32_t msg_type, + int32_t ext1, + int32_t ext2, + int32_t ext3); + + static void notify_callback_dispatch(int32_t msg_type, + int32_t ext1, + int32_t ext2, + int32_t ext3, + void *user); + +}; + +/** + * Adapter from an IGraphicBufferProducer interface to camera2 device stream ops. + * Also takes care of allocating/deallocating stream in device interface + */ +class StreamAdapter: public camera2_stream_ops { + public: + explicit StreamAdapter(sp<IGraphicBufferProducer> consumer); + + ~StreamAdapter(); + + status_t connectToDevice(camera2_device_t *d, + uint32_t width, uint32_t height, int format); + + status_t disconnect(); + + // Get stream ID. Only valid after a successful connectToDevice call. + int getId(); + + private: + enum { + ERROR = -1, + DISCONNECTED = 0, + UNINITIALIZED, + ALLOCATED, + CONNECTED, + ACTIVE + } mState; + + sp<ANativeWindow> mConsumerInterface; + camera2_device_t *mDevice; + + uint32_t mId; + uint32_t mWidth; + uint32_t mHeight; + uint32_t mFormat; + uint32_t mUsage; + uint32_t mMaxProducerBuffers; + uint32_t mMaxConsumerBuffers; + + const camera2_stream_ops *getStreamOps(); + + static ANativeWindow* toANW(const camera2_stream_ops_t *w); + + static int dequeue_buffer(const camera2_stream_ops_t *w, + buffer_handle_t** buffer); + + static int enqueue_buffer(const camera2_stream_ops_t* w, + int64_t timestamp, + buffer_handle_t* buffer); + + static int cancel_buffer(const camera2_stream_ops_t* w, + buffer_handle_t* buffer); + + static int set_crop(const camera2_stream_ops_t* w, + int left, int top, int right, int bottom); + +}; + +/** + * Simple class to wait on the CpuConsumer to have a frame available + */ +class FrameWaiter : public CpuConsumer::FrameAvailableListener { + public: + FrameWaiter(); + + /** + * Wait for max timeout nanoseconds for a new frame. Returns + * OK if a frame is available, TIMED_OUT if the timeout was reached. + */ + status_t waitForFrame(nsecs_t timeout); + + virtual void onFrameAvailable(const BufferItem& item); + + int mPendingFrames; + Mutex mMutex; + Condition mCondition; +}; + +struct HWModuleHelpers { + /* attempt to unload the library with dlclose */ + static int closeModule(void* dso); +}; + +} +} +} + +#endif
diff --git a/libhardware/tests/camera2/main.cpp b/libhardware/tests/camera2/main.cpp new file mode 100644 index 0000000..e0ebbe9 --- /dev/null +++ b/libhardware/tests/camera2/main.cpp
@@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 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 <gtest/gtest.h> +#include "TestForkerEventListener.h" +#include "TestSettings.h" + +using android::camera2::tests::TestForkerEventListener; +using android::camera2::tests::TestSettings; + +int main(int argc, char **argv) { + + bool printUsage = !TestSettings::ParseArgs(argc, argv); + + ::testing::InitGoogleTest(&argc, argv); + + if (printUsage) { + TestSettings::PrintUsage(); + return 0; + } + + // Gets hold of the event listener list. + ::testing::TestEventListeners& listeners = + ::testing::UnitTest::GetInstance()->listeners(); + // Adds a listener to the end. Google Test takes the ownership. + listeners.Append(new TestForkerEventListener()); + + int ret = RUN_ALL_TESTS(); + + return ret; +}
diff --git a/libhardware/tests/camera3/Android.mk b/libhardware/tests/camera3/Android.mk new file mode 100644 index 0000000..652851a --- /dev/null +++ b/libhardware/tests/camera3/Android.mk
@@ -0,0 +1,20 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + camera3tests.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libhardware \ + libcamera_metadata \ + +LOCAL_C_INCLUDES += \ + system/media/camera/include \ + +LOCAL_CFLAGS += -Wall -Wextra + +LOCAL_MODULE:= camera3_tests +LOCAL_MODULE_TAGS := tests + +include $(BUILD_NATIVE_TEST)
diff --git a/libhardware/tests/camera3/camera3test_fixtures.h b/libhardware/tests/camera3/camera3test_fixtures.h new file mode 100644 index 0000000..17e3d45 --- /dev/null +++ b/libhardware/tests/camera3/camera3test_fixtures.h
@@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_CAMERA3_TEST_COMMON__ +#define __ANDROID_HAL_CAMERA3_TEST_COMMON__ + +#include <gtest/gtest.h> +#include <hardware/hardware.h> +#include <hardware/camera3.h> + +namespace tests { + +static const int kMmaxCams = 2; +static const uint16_t kVersion3_0 = HARDWARE_MODULE_API_VERSION(3, 0); + +class Camera3Module : public testing::Test { + public: + Camera3Module() : + num_cams_(0), + cam_module_(NULL) {} + ~Camera3Module() {} + protected: + virtual void SetUp() { + const hw_module_t *hw_module = NULL; + ASSERT_EQ(0, hw_get_module(CAMERA_HARDWARE_MODULE_ID, &hw_module)) + << "Can't get camera module"; + ASSERT_TRUE(NULL != hw_module) + << "hw_get_module didn't return a valid camera module"; + + cam_module_ = reinterpret_cast<const camera_module_t*>(hw_module); + ASSERT_TRUE(NULL != cam_module_->get_number_of_cameras) + << "get_number_of_cameras is not implemented"; + num_cams_ = cam_module_->get_number_of_cameras(); + } + int num_cams() { return num_cams_; } + const camera_module_t * cam_module() { return cam_module_; } + private: + int num_cams_; + const camera_module_t *cam_module_; +}; + +class Camera3Device : public Camera3Module { + public: + Camera3Device() : + cam_device_(NULL) {} + ~Camera3Device() {} + protected: + virtual void SetUp() { + Camera3Module::SetUp(); + hw_device_t *device = NULL; + ASSERT_TRUE(NULL != cam_module()->common.methods->open) + << "Camera open() is unimplemented"; + ASSERT_EQ(0, cam_module()->common.methods->open( + (const hw_module_t*)cam_module(), "0", &device)) + << "Can't open camera device"; + ASSERT_TRUE(NULL != device) + << "Camera open() returned a NULL device"; + ASSERT_LE(kVersion3_0, device->version) + << "The device does not support HAL3"; + cam_device_ = reinterpret_cast<camera3_device_t*>(device); + } + camera3_device_t* cam_device() { return cam_device_; } + private: + camera3_device *cam_device_; +}; + +} // namespace tests + +#endif // __ANDROID_HAL_CAMERA3_TEST_COMMON__
diff --git a/libhardware/tests/camera3/camera3tests.cpp b/libhardware/tests/camera3/camera3tests.cpp new file mode 100644 index 0000000..5dbe588 --- /dev/null +++ b/libhardware/tests/camera3/camera3tests.cpp
@@ -0,0 +1,71 @@ +/* + * Copyright (C) 2013 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 <gtest/gtest.h> +#include "camera3test_fixtures.h" + +namespace tests { + +TEST_F(Camera3Module, NumberOfCameras) { + ASSERT_LT(0, num_cams()) << "No cameras found"; + ASSERT_GE(kMmaxCams, num_cams()) << "Too many cameras found"; +} + +TEST_F(Camera3Module, IsActiveArraySizeSubsetPixelArraySize) { + for (int i = 0; i < num_cams(); ++i) { + ASSERT_TRUE(NULL != cam_module()->get_camera_info) + << "get_camera_info is not implemented"; + + camera_info info; + ASSERT_EQ(0, cam_module()->get_camera_info(i, &info)) + << "Can't get camera info for" << i; + + camera_metadata_entry entry; + ASSERT_EQ(0, find_camera_metadata_entry( + const_cast<camera_metadata_t*>( + info.static_camera_characteristics), + ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, &entry)) + << "Can't find the sensor pixel array size."; + int pixel_array_w = entry.data.i32[0]; + int pixel_array_h = entry.data.i32[1]; + + ASSERT_EQ(0, find_camera_metadata_entry( + const_cast<camera_metadata_t*>( + info.static_camera_characteristics), + ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &entry)) + << "Can't find the sensor active array size."; + int active_array_w = entry.data.i32[0]; + int active_array_h = entry.data.i32[1]; + + EXPECT_LE(active_array_h, pixel_array_h); + EXPECT_LE(active_array_w, pixel_array_w); + } +} + +TEST_F(Camera3Device, DefaultSettingsStillCaptureHasAndroidControlMode) { + ASSERT_TRUE(NULL != cam_device()->ops) << "Camera device ops are NULL"; + const camera_metadata_t *default_settings = + cam_device()->ops->construct_default_request_settings(cam_device(), + CAMERA3_TEMPLATE_STILL_CAPTURE); + ASSERT_TRUE(NULL != default_settings) << "Camera default settings are NULL"; + camera_metadata_entry entry; + ASSERT_EQ(0, find_camera_metadata_entry( + const_cast<camera_metadata_t*>(default_settings), + ANDROID_CONTROL_MODE, &entry)) + << "Can't find ANDROID_CONTROL_MODE in default settings."; +} + +} // namespace tests
diff --git a/libhardware/tests/fingerprint/Android.bp b/libhardware/tests/fingerprint/Android.bp new file mode 100644 index 0000000..7de3dee --- /dev/null +++ b/libhardware/tests/fingerprint/Android.bp
@@ -0,0 +1,14 @@ +cc_test { + name: "fingerprint_tests", + srcs: ["fingerprint_tests.cpp"], + + shared_libs: [ + "liblog", + "libhardware", + ], + + cflags: [ + "-Wall", + "-Wextra", + ], +}
diff --git a/libhardware/tests/fingerprint/fingerprint_test_fixtures.h b/libhardware/tests/fingerprint/fingerprint_test_fixtures.h new file mode 100644 index 0000000..a526203 --- /dev/null +++ b/libhardware/tests/fingerprint/fingerprint_test_fixtures.h
@@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ANDROID_HAL_FINGERPRINT_TEST_COMMON__ +#define __ANDROID_HAL_FINGERPRINT_TEST_COMMON__ + +#include <gtest/gtest.h> +#include <hardware/hardware.h> +#include <hardware/fingerprint.h> + +namespace tests { + +static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(1, 0); + +class FingerprintModule : public testing::Test { + public: + FingerprintModule() : + fp_module_(NULL) {} + ~FingerprintModule() {} + protected: + virtual void SetUp() { + const hw_module_t *hw_module = NULL; + ASSERT_EQ(0, hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module)) + << "Can't get fingerprint module"; + ASSERT_TRUE(NULL != hw_module) + << "hw_get_module didn't return a valid fingerprint module"; + + fp_module_ = reinterpret_cast<const fingerprint_module_t*>(hw_module); + } + const fingerprint_module_t* fp_module() { return fp_module_; } + private: + const fingerprint_module_t *fp_module_; +}; + +class FingerprintDevice : public FingerprintModule { + public: + FingerprintDevice() : + fp_device_(NULL) {} + ~FingerprintDevice() {} + protected: + virtual void SetUp() { + FingerprintModule::SetUp(); + hw_device_t *device = NULL; + ASSERT_TRUE(NULL != fp_module()->common.methods->open) + << "Fingerprint open() is unimplemented"; + ASSERT_EQ(0, fp_module()->common.methods->open( + (const hw_module_t*)fp_module(), NULL, &device)) + << "Can't open fingerprint device"; + ASSERT_TRUE(NULL != device) + << "Fingerprint open() returned a NULL device"; + ASSERT_EQ(kVersion, device->version) + << "Unsupported version"; + fp_device_ = reinterpret_cast<fingerprint_device_t*>(device); + } + fingerprint_device_t* fp_device() { return fp_device_; } + private: + fingerprint_device_t *fp_device_; +}; + +} // namespace tests + +#endif // __ANDROID_HAL_FINGERPRINT_TEST_COMMON__
diff --git a/libhardware/tests/fingerprint/fingerprint_tests.cpp b/libhardware/tests/fingerprint/fingerprint_tests.cpp new file mode 100644 index 0000000..dbb248f --- /dev/null +++ b/libhardware/tests/fingerprint/fingerprint_tests.cpp
@@ -0,0 +1,62 @@ +/* + * Copyright (C) 2014 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 <gtest/gtest.h> +#include "fingerprint_test_fixtures.h" + +namespace tests { + +TEST_F(FingerprintDevice, isThereEnroll) { + ASSERT_TRUE(NULL != fp_device()->enroll) + << "enroll() function is not implemented"; +} + +TEST_F(FingerprintDevice, isTherePreEnroll) { + ASSERT_TRUE(NULL != fp_device()->pre_enroll) + << "pre_enroll() function is not implemented"; +} + +TEST_F(FingerprintDevice, isThereGetAuthenticatorId) { + ASSERT_TRUE(NULL != fp_device()->get_authenticator_id) + << "get_authenticator_id() function is not implemented"; +} + +TEST_F(FingerprintDevice, isThereCancel) { + ASSERT_TRUE(NULL != fp_device()->cancel) + << "cancel() function is not implemented"; +} + +TEST_F(FingerprintDevice, isThereRemove) { + ASSERT_TRUE(NULL != fp_device()->remove) + << "remove() function is not implemented"; +} + +TEST_F(FingerprintDevice, isThereAuthenticate) { + ASSERT_TRUE(NULL != fp_device()->authenticate) + << "authenticate() function is not implemented"; +} + +TEST_F(FingerprintDevice, isThereSetActiveGroup) { + ASSERT_TRUE(NULL != fp_device()->set_active_group) + << "set_active_group() function is not implemented"; +} + +TEST_F(FingerprintDevice, isThereSetNotify) { + ASSERT_TRUE(NULL != fp_device()->set_notify) + << "set_notify() function is not implemented"; +} + +} // namespace tests
diff --git a/libhardware/tests/hardware/Android.bp b/libhardware/tests/hardware/Android.bp new file mode 100644 index 0000000..668e28f --- /dev/null +++ b/libhardware/tests/hardware/Android.bp
@@ -0,0 +1,15 @@ +cc_library_static { + name: "static-hal-check", + srcs: [ + "struct-size.cpp", + "struct-offset.cpp", + "struct-last.cpp", + ], + shared_libs: ["libhardware"], + cflags: [ + "-std=gnu++11", + "-O0", + ], + + include_dirs: ["system/media/camera/include"], +}
diff --git a/libhardware/tests/hardware/struct-last.cpp b/libhardware/tests/hardware/struct-last.cpp new file mode 100644 index 0000000..44a7b2d --- /dev/null +++ b/libhardware/tests/hardware/struct-last.cpp
@@ -0,0 +1,69 @@ +/* + * Copyright (C) 2013 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 <cstddef> +#include <system/window.h> +#include <hardware/hardware.h> +#include <hardware/sensors.h> +#include <hardware/fb.h> +#include <hardware/hwcomposer.h> +#include <hardware/gralloc.h> +#include <hardware/consumerir.h> +#include <hardware/camera_common.h> +#include <hardware/camera3.h> + +#define GET_PADDING(align, size) (((align) - ((size) % (align))) % (align)) + +#define CHECK_LAST_MEMBER(type, member) \ +do { \ +static constexpr size_t calc_size = offsetof(type, member) + sizeof(((type *)0)->member); \ +static_assert(sizeof(type) == calc_size + GET_PADDING(alignof(type), calc_size), \ +"" #member " is not the last element of " #type); \ +} while (0) + +void CheckSizes(void) { + //Types defined in hardware.h + CHECK_LAST_MEMBER(hw_module_t, reserved); + CHECK_LAST_MEMBER(hw_device_t, close); + + //Types defined in sensors.h + CHECK_LAST_MEMBER(sensors_vec_t, reserved); + CHECK_LAST_MEMBER(sensors_event_t, reserved1); + CHECK_LAST_MEMBER(struct sensor_t, reserved); + CHECK_LAST_MEMBER(sensors_poll_device_1_t, reserved_procs); + + //Types defined in fb.h + CHECK_LAST_MEMBER(framebuffer_device_t, reserved_proc); + + //Types defined in hwcomposer.h + CHECK_LAST_MEMBER(hwc_layer_1_t, reserved); + CHECK_LAST_MEMBER(hwc_composer_device_1_t, reserved_proc); + + //Types defined in gralloc.h + CHECK_LAST_MEMBER(gralloc_module_t, reserved_proc); + CHECK_LAST_MEMBER(alloc_device_t, reserved_proc); + + //Types defined in consumerir.h + CHECK_LAST_MEMBER(consumerir_device_t, reserved); + + //Types defined in camera_common.h + CHECK_LAST_MEMBER(vendor_tag_ops_t, reserved); + CHECK_LAST_MEMBER(camera_module_t, reserved); + + //Types defined in camera3.h + CHECK_LAST_MEMBER(camera3_device_ops_t, reserved); +} +
diff --git a/libhardware/tests/hardware/struct-offset.cpp b/libhardware/tests/hardware/struct-offset.cpp new file mode 100644 index 0000000..10c0895 --- /dev/null +++ b/libhardware/tests/hardware/struct-offset.cpp
@@ -0,0 +1,231 @@ +/* + * Copyright (C) 2012 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 <cstddef> +#include <system/window.h> +#include <hardware/hardware.h> +#include <hardware/sensors.h> +#include <hardware/fb.h> +#include <hardware/hwcomposer.h> +#include <hardware/gralloc.h> +#include <hardware/consumerir.h> +#include <hardware/camera_common.h> +#include <hardware/camera3.h> + +//Ideally this would print type.member instead we need to rely on the line number from the output +template <size_t actual, size_t expected> void check_member(void) { + static_assert(actual == expected, ""); +} + +#ifdef __LP64__ +#define CHECK_MEMBER_AT(type, member, off32, off64) \ + check_member<offsetof(type, member), off64>() +#else +#define CHECK_MEMBER_AT(type, member, off32, off64) \ + check_member<offsetof(type, member), off32>() +#endif + +void CheckOffsets(void) { + //Types defined in hardware.h + CHECK_MEMBER_AT(hw_module_t, tag, 0, 0); + CHECK_MEMBER_AT(hw_module_t, module_api_version, 4, 4); + CHECK_MEMBER_AT(hw_module_t, hal_api_version, 6, 6); + CHECK_MEMBER_AT(hw_module_t, id, 8, 8); + CHECK_MEMBER_AT(hw_module_t, name, 12, 16); + CHECK_MEMBER_AT(hw_module_t, author, 16, 24); + CHECK_MEMBER_AT(hw_module_t, methods, 20, 32); + CHECK_MEMBER_AT(hw_module_t, dso, 24, 40); + CHECK_MEMBER_AT(hw_module_t, reserved, 28, 48); + + CHECK_MEMBER_AT(hw_device_t, tag, 0, 0); + CHECK_MEMBER_AT(hw_device_t, version, 4, 4); + CHECK_MEMBER_AT(hw_device_t, module, 8, 8); + CHECK_MEMBER_AT(hw_device_t, reserved, 12, 16); + CHECK_MEMBER_AT(hw_device_t, close, 60, 112); + + //Types defined in sensors.h + CHECK_MEMBER_AT(sensors_vec_t, v, 0, 0); + CHECK_MEMBER_AT(sensors_vec_t, x, 0, 0); + CHECK_MEMBER_AT(sensors_vec_t, y, 4, 4); + CHECK_MEMBER_AT(sensors_vec_t, z, 8, 8); + CHECK_MEMBER_AT(sensors_vec_t, azimuth, 0, 0); + CHECK_MEMBER_AT(sensors_vec_t, pitch, 4, 4); + CHECK_MEMBER_AT(sensors_vec_t, roll, 8, 8); + CHECK_MEMBER_AT(sensors_vec_t, status, 12, 12); + CHECK_MEMBER_AT(sensors_vec_t, reserved, 13, 13); + + CHECK_MEMBER_AT(sensors_event_t, version, 0, 0); + CHECK_MEMBER_AT(sensors_event_t, sensor, 4, 4); + CHECK_MEMBER_AT(sensors_event_t, type, 8, 8); + CHECK_MEMBER_AT(sensors_event_t, reserved0, 12, 12); + CHECK_MEMBER_AT(sensors_event_t, timestamp, 16, 16); + CHECK_MEMBER_AT(sensors_event_t, data, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, acceleration, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, magnetic, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, orientation, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, gyro, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, temperature, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, distance, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, light, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, pressure, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, relative_humidity, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, uncalibrated_gyro, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, uncalibrated_magnetic, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, meta_data, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, u64, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, u64.data, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, u64.step_counter, 24, 24); + CHECK_MEMBER_AT(sensors_event_t, flags, 88, 88); + CHECK_MEMBER_AT(sensors_event_t, reserved1, 92, 92); + + CHECK_MEMBER_AT(struct sensor_t, name, 0, 0); + CHECK_MEMBER_AT(struct sensor_t, vendor, 4, 8); + CHECK_MEMBER_AT(struct sensor_t, version, 8, 16); + CHECK_MEMBER_AT(struct sensor_t, handle, 12, 20); + CHECK_MEMBER_AT(struct sensor_t, type, 16, 24); + CHECK_MEMBER_AT(struct sensor_t, maxRange, 20, 28); + CHECK_MEMBER_AT(struct sensor_t, resolution, 24, 32); + CHECK_MEMBER_AT(struct sensor_t, power, 28, 36); + CHECK_MEMBER_AT(struct sensor_t, minDelay, 32, 40); + CHECK_MEMBER_AT(struct sensor_t, fifoReservedEventCount, 36, 44); + CHECK_MEMBER_AT(struct sensor_t, fifoMaxEventCount, 40, 48); + CHECK_MEMBER_AT(struct sensor_t, stringType, 44, 56); + CHECK_MEMBER_AT(struct sensor_t, requiredPermission, 48, 64); + CHECK_MEMBER_AT(struct sensor_t, maxDelay, 52, 72); + CHECK_MEMBER_AT(struct sensor_t, flags, 56, 80); + CHECK_MEMBER_AT(struct sensor_t, reserved, 60, 88); + + CHECK_MEMBER_AT(sensors_poll_device_1_t, v0, 0, 0); + CHECK_MEMBER_AT(sensors_poll_device_1_t, common, 0, 0); + CHECK_MEMBER_AT(sensors_poll_device_1_t, activate, 64, 120); + CHECK_MEMBER_AT(sensors_poll_device_1_t, setDelay, 68, 128); + CHECK_MEMBER_AT(sensors_poll_device_1_t, poll, 72, 136); + CHECK_MEMBER_AT(sensors_poll_device_1_t, batch, 76, 144); + CHECK_MEMBER_AT(sensors_poll_device_1_t, flush, 80, 152); + CHECK_MEMBER_AT(sensors_poll_device_1_t, inject_sensor_data, 84, 160); + CHECK_MEMBER_AT(sensors_poll_device_1_t, reserved_procs, 88, 168); + + //Types defined in fb.h + CHECK_MEMBER_AT(framebuffer_device_t, common, 0, 0); + CHECK_MEMBER_AT(framebuffer_device_t, flags, 64, 120); + CHECK_MEMBER_AT(framebuffer_device_t, width, 68, 124); + CHECK_MEMBER_AT(framebuffer_device_t, height, 72, 128); + CHECK_MEMBER_AT(framebuffer_device_t, stride, 76, 132); + CHECK_MEMBER_AT(framebuffer_device_t, format, 80, 136); + CHECK_MEMBER_AT(framebuffer_device_t, xdpi, 84, 140); + CHECK_MEMBER_AT(framebuffer_device_t, ydpi, 88, 144); + CHECK_MEMBER_AT(framebuffer_device_t, fps, 92, 148); + CHECK_MEMBER_AT(framebuffer_device_t, minSwapInterval, 96, 152); + CHECK_MEMBER_AT(framebuffer_device_t, maxSwapInterval, 100, 156); + CHECK_MEMBER_AT(framebuffer_device_t, numFramebuffers, 104, 160); + CHECK_MEMBER_AT(framebuffer_device_t, reserved, 108, 164); + CHECK_MEMBER_AT(framebuffer_device_t, setSwapInterval, 136, 192); + CHECK_MEMBER_AT(framebuffer_device_t, setUpdateRect, 140, 200); + CHECK_MEMBER_AT(framebuffer_device_t, post, 144, 208); + CHECK_MEMBER_AT(framebuffer_device_t, compositionComplete, 148, 216); + CHECK_MEMBER_AT(framebuffer_device_t, dump, 152, 224); + CHECK_MEMBER_AT(framebuffer_device_t, enableScreen, 156, 232); + CHECK_MEMBER_AT(framebuffer_device_t, reserved_proc, 160, 240); + + //Types defined in hwcomposer.h + CHECK_MEMBER_AT(hwc_layer_1_t, compositionType, 0, 0); + CHECK_MEMBER_AT(hwc_layer_1_t, hints, 4, 4); + CHECK_MEMBER_AT(hwc_layer_1_t, flags, 8, 8); + CHECK_MEMBER_AT(hwc_layer_1_t, backgroundColor, 12, 16); + CHECK_MEMBER_AT(hwc_layer_1_t, handle, 12, 16); + CHECK_MEMBER_AT(hwc_layer_1_t, transform, 16, 24); + CHECK_MEMBER_AT(hwc_layer_1_t, blending, 20, 28); + CHECK_MEMBER_AT(hwc_layer_1_t, sourceCropi, 24, 32); + CHECK_MEMBER_AT(hwc_layer_1_t, sourceCrop, 24, 32); + CHECK_MEMBER_AT(hwc_layer_1_t, sourceCropf, 24, 32); + CHECK_MEMBER_AT(hwc_layer_1_t, displayFrame, 40, 48); + CHECK_MEMBER_AT(hwc_layer_1_t, visibleRegionScreen, 56, 64); + CHECK_MEMBER_AT(hwc_layer_1_t, acquireFenceFd, 64, 80); + CHECK_MEMBER_AT(hwc_layer_1_t, releaseFenceFd, 68, 84); + CHECK_MEMBER_AT(hwc_layer_1_t, planeAlpha, 72, 88); + CHECK_MEMBER_AT(hwc_layer_1_t, _pad, 73, 89); + + CHECK_MEMBER_AT(hwc_composer_device_1_t, common, 0, 0); + CHECK_MEMBER_AT(hwc_composer_device_1_t, prepare, 64, 120); + CHECK_MEMBER_AT(hwc_composer_device_1_t, set, 68, 128); + CHECK_MEMBER_AT(hwc_composer_device_1_t, eventControl, 72, 136); + CHECK_MEMBER_AT(hwc_composer_device_1_t, blank, 76, 144); + CHECK_MEMBER_AT(hwc_composer_device_1_t, query, 80, 152); + CHECK_MEMBER_AT(hwc_composer_device_1_t, registerProcs, 84, 160); + CHECK_MEMBER_AT(hwc_composer_device_1_t, dump, 88, 168); + CHECK_MEMBER_AT(hwc_composer_device_1_t, getDisplayConfigs, 92, 176); + CHECK_MEMBER_AT(hwc_composer_device_1_t, getDisplayAttributes, 96, 184); + CHECK_MEMBER_AT(hwc_composer_device_1_t, getActiveConfig, 100, 192); + CHECK_MEMBER_AT(hwc_composer_device_1_t, setActiveConfig, 104, 200); + CHECK_MEMBER_AT(hwc_composer_device_1_t, setCursorPositionAsync, 108, 208); + CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 112, 216); + + //Types defined in gralloc.h + CHECK_MEMBER_AT(gralloc_module_t, common, 0, 0); + CHECK_MEMBER_AT(gralloc_module_t, registerBuffer, 128, 248); + CHECK_MEMBER_AT(gralloc_module_t, unregisterBuffer, 132, 256); + CHECK_MEMBER_AT(gralloc_module_t, lock, 136, 264); + CHECK_MEMBER_AT(gralloc_module_t, unlock, 140, 272); + CHECK_MEMBER_AT(gralloc_module_t, perform, 144, 280); + CHECK_MEMBER_AT(gralloc_module_t, lock_ycbcr, 148, 288); + CHECK_MEMBER_AT(gralloc_module_t, lockAsync, 152, 296); + CHECK_MEMBER_AT(gralloc_module_t, unlockAsync, 156, 304); + CHECK_MEMBER_AT(gralloc_module_t, lockAsync_ycbcr, 160, 312); + CHECK_MEMBER_AT(gralloc_module_t, reserved_proc, 164, 320); + + CHECK_MEMBER_AT(alloc_device_t, common, 0, 0); + CHECK_MEMBER_AT(alloc_device_t, alloc, 64, 120); + CHECK_MEMBER_AT(alloc_device_t, free, 68, 128); + CHECK_MEMBER_AT(alloc_device_t, dump, 72, 136); + CHECK_MEMBER_AT(alloc_device_t, reserved_proc, 76, 144); + + //Types defined in consumerir.h + CHECK_MEMBER_AT(consumerir_device_t, common, 0, 0); + CHECK_MEMBER_AT(consumerir_device_t, transmit, 64, 120); + CHECK_MEMBER_AT(consumerir_device_t, get_num_carrier_freqs, 68, 128); + CHECK_MEMBER_AT(consumerir_device_t, get_carrier_freqs, 72, 136); + CHECK_MEMBER_AT(consumerir_device_t, reserved, 76, 144); + + //Types defined in camera_common.h + CHECK_MEMBER_AT(vendor_tag_ops_t, get_tag_count, 0, 0); + CHECK_MEMBER_AT(vendor_tag_ops_t, get_all_tags, 4, 8); + CHECK_MEMBER_AT(vendor_tag_ops_t, get_section_name, 8, 16); + CHECK_MEMBER_AT(vendor_tag_ops_t, get_tag_name, 12, 24); + CHECK_MEMBER_AT(vendor_tag_ops_t, get_tag_type, 16, 32); + CHECK_MEMBER_AT(vendor_tag_ops_t, reserved, 20, 40); + + CHECK_MEMBER_AT(camera_module_t, common, 0, 0); + CHECK_MEMBER_AT(camera_module_t, get_number_of_cameras, 128, 248); + CHECK_MEMBER_AT(camera_module_t, get_camera_info, 132, 256); + CHECK_MEMBER_AT(camera_module_t, set_callbacks, 136, 264); + CHECK_MEMBER_AT(camera_module_t, get_vendor_tag_ops, 140, 272); + CHECK_MEMBER_AT(camera_module_t, open_legacy, 144, 280); + CHECK_MEMBER_AT(camera_module_t, set_torch_mode, 148, 288); + CHECK_MEMBER_AT(camera_module_t, init, 152, 296); + CHECK_MEMBER_AT(camera_module_t, reserved, 156, 304); + + //Types defined in camera3.h + CHECK_MEMBER_AT(camera3_device_ops_t, initialize, 0, 0); + CHECK_MEMBER_AT(camera3_device_ops_t, configure_streams, 4, 8); + CHECK_MEMBER_AT(camera3_device_ops_t, register_stream_buffers, 8, 16); + CHECK_MEMBER_AT(camera3_device_ops_t, construct_default_request_settings, 12, 24); + CHECK_MEMBER_AT(camera3_device_ops_t, process_capture_request, 16, 32); + CHECK_MEMBER_AT(camera3_device_ops_t, get_metadata_vendor_tag_ops, 20, 40); + CHECK_MEMBER_AT(camera3_device_ops_t, dump, 24, 48); + CHECK_MEMBER_AT(camera3_device_ops_t, flush, 28, 56); + CHECK_MEMBER_AT(camera3_device_ops_t, reserved, 32, 64); +} +
diff --git a/libhardware/tests/hardware/struct-size.cpp b/libhardware/tests/hardware/struct-size.cpp new file mode 100644 index 0000000..acb9d2d --- /dev/null +++ b/libhardware/tests/hardware/struct-size.cpp
@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 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 <system/window.h> +#include <hardware/hardware.h> +#include <hardware/sensors.h> +#include <hardware/fb.h> +#include <hardware/hwcomposer.h> +#include <hardware/gralloc.h> +#include <hardware/consumerir.h> +#include <hardware/camera_common.h> +#include <hardware/camera3.h> + +template<size_t> static constexpr size_t CheckSizeHelper(size_t, size_t); + +template<> constexpr size_t CheckSizeHelper<4>(size_t size32, size_t /* size64 */) { + return size32; +} + +template<> constexpr size_t CheckSizeHelper<8>(size_t /* size32 */, size_t size64) { + return size64; +} + +template<typename T, size_t size32, size_t size64> static void CheckTypeSize() { + const size_t mySize = CheckSizeHelper<sizeof(void *)>(size32, size64); + + static_assert(sizeof(T) == mySize, "struct is the wrong size"); +} + +void CheckSizes(void) { + //Types defined in hardware.h + CheckTypeSize<hw_module_t, 128, 248>(); + CheckTypeSize<hw_device_t, 64, 120>(); + + //Types defined in sensors.h + CheckTypeSize<sensors_vec_t, 16, 16>(); + CheckTypeSize<sensors_event_t, 104, 104>(); + CheckTypeSize<struct sensor_t, 68, 104>(); + CheckTypeSize<sensors_poll_device_1_t, 116, 224>(); + + //Types defined in fb.h + CheckTypeSize<framebuffer_device_t, 184, 288>(); + + //Types defined in hwcomposer.h + CheckTypeSize<hwc_layer_1_t, 96, 120>(); + CheckTypeSize<hwc_composer_device_1_t, 116, 224>(); + + //Types defined in gralloc.h + CheckTypeSize<gralloc_module_t, 176, 344>(); + CheckTypeSize<alloc_device_t, 104, 200>(); + + //Types defined in consumerir.h + CheckTypeSize<consumerir_device_t, 96, 184>(); + + //Types defined in camera_common.h + CheckTypeSize<vendor_tag_ops_t, 52, 104>(); + CheckTypeSize<camera_module_t, 176, 344>(); + + //Types defined in camera3.h + CheckTypeSize<camera3_device_ops_t, 64, 128>(); +} +
diff --git a/libhardware/tests/hwc/Android.mk b/libhardware/tests/hwc/Android.mk new file mode 100644 index 0000000..367f5f4 --- /dev/null +++ b/libhardware/tests/hwc/Android.mk
@@ -0,0 +1,15 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libcnativewindow +LOCAL_SRC_FILES := cnativewindow.c util.c +LOCAL_CFLAGS := -Wno-unused-parameter +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := hwc-test-arrows +LOCAL_SRC_FILES := test-arrows.c +LOCAL_STATIC_LIBRARIES := libcnativewindow +LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libdl libhardware +LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES +include $(BUILD_EXECUTABLE)
diff --git a/libhardware/tests/hwc/cnativewindow.c b/libhardware/tests/hwc/cnativewindow.c new file mode 100644 index 0000000..5b1d78e --- /dev/null +++ b/libhardware/tests/hwc/cnativewindow.c
@@ -0,0 +1,578 @@ +/* + * Copyright (C) 2013 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 <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> + +#include <pthread.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> +#include <hardware/hwcomposer.h> + +#include <system/window.h> +#include <cutils/native_handle.h> + +// normalize and shorten type names +typedef struct android_native_base_t aBase; +typedef struct ANativeWindowBuffer aBuffer; +typedef struct ANativeWindow aWindow; + +static int trace_level = 1; + +#define _TRACE(n,fmt...) \ + do { if (trace_level >= (n)) fprintf(stderr, "CNW: " fmt); } while (0) + +#define ERROR(fmt...) _TRACE(0, fmt) +#define INFO(fmt...) _TRACE(1, fmt) +#define LOG(fmt...) _TRACE(2, fmt) +#define TRACE(fmt...) _TRACE(3, fmt) + +#define QCT_WORKAROUND 1 + +typedef struct CNativeBuffer { + aBuffer base; + struct CNativeBuffer *next; + struct CNativeBuffer *prev; + int ffd; +} CNativeBuffer; + +typedef struct CNativeWindow { + aWindow base; + + hwc_composer_device_1_t *hwc; + framebuffer_device_t *fb; + alloc_device_t *gr; + + pthread_mutex_t lock; + pthread_cond_t cvar; + + aBuffer *front; + aBuffer *spare; + + CNativeBuffer free_buffer_queue; + + unsigned width; + unsigned height; + unsigned xdpi; + unsigned ydpi; + unsigned format; + + hwc_display_contents_1_t *dclist[HWC_NUM_PHYSICAL_DISPLAY_TYPES]; + + hwc_display_contents_1_t dc; + hwc_layer_1_t layer[4]; +} CNativeWindow; + +static inline CNativeBuffer *from_abuffer(aBuffer *buf) { + return (CNativeBuffer*) buf; +} + +static CNativeBuffer *get_front(struct CNativeBuffer *queue) { + CNativeBuffer *buf = queue->next; + if (buf == queue) + return 0; + buf->next->prev = queue; + queue->next = buf->next; + buf->next = buf->prev = 0; + return buf; +} + +static void put_front(struct CNativeBuffer *queue, aBuffer *_buf) { + struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf; + buf->prev = queue; + buf->next = queue->next; + queue->next->prev = buf; + queue->next = buf; +} + +static void put_back(struct CNativeBuffer *queue, aBuffer *_buf) { + struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf; + buf->next = queue; + buf->prev = queue->prev; + queue->prev->next = buf; + queue->prev = buf; +} + +static void cnw_inc_ref(aBase *base) { TRACE("buf %p ref++\n",base); } +static void cnw_dec_ref(aBase *base) { TRACE("buf %p ref--\n",base); } + +static inline CNativeWindow *from_base(aWindow *base) { + return (CNativeWindow *) base; +} + +static inline CNativeWindow *from_base_const(const aWindow *base) { + return (CNativeWindow *) base; +} + +static int cnw_set_swap_interval(aWindow *base, int interval) { + CNativeWindow *win = from_base(base); + if (win->fb && win->fb->setSwapInterval) + return win->fb->setSwapInterval(win->fb, interval); + return 0; +} + +static int cnw_dequeue_buffer1(aWindow *base, aBuffer **buf, int *ffd) { + CNativeWindow *win = from_base(base); + CNativeBuffer *cnb; + + pthread_mutex_lock(&win->lock); + + while ((cnb = get_front(&win->free_buffer_queue)) == 0) { + pthread_cond_wait(&win->cvar, &win->lock); + } + + *ffd = cnb->ffd; + *buf = &cnb->base; + cnb->ffd = -1; + LOG("<< dequeue buffer %p %d\n", *buf, *ffd); + + pthread_mutex_unlock(&win->lock); + return 0; +} + +static int cnw_lock_buffer0(aWindow *base, aBuffer *buffer) { + return 0; +} + +static void set_layer(hwc_layer_1_t *dl, aBuffer *buf, int ffd) { + int right = buf->width; + int bottom = buf->height; + + dl->compositionType = HWC_FRAMEBUFFER; + dl->hints = 0; + dl->flags = 0; + + dl->handle = buf->handle; + dl->transform = 0; + dl->blending = HWC_BLENDING_NONE; + dl->sourceCrop.left = 0; + dl->sourceCrop.top = 0; + dl->sourceCrop.right = right; + dl->sourceCrop.bottom = bottom; + dl->displayFrame.left = 0; + dl->displayFrame.top = 0; + dl->displayFrame.right = right; + dl->displayFrame.bottom = bottom; + dl->visibleRegionScreen.numRects = 1; + dl->visibleRegionScreen.rects = &dl->displayFrame; + + dl->acquireFenceFd = ffd; + dl->releaseFenceFd = -1; +} + +static void hwc_post(CNativeWindow *win, aBuffer *buf, int ffd) { + hwc_composer_device_1_t *hwc = win->hwc; + hwc_display_contents_1_t *dc = &(win->dc); + hwc_layer_1_t *dl = win->dc.hwLayers; + int r, i; + + dc->retireFenceFd = -1; + dc->outbufAcquireFenceFd = -1; + dc->flags = HWC_GEOMETRY_CHANGED; + dc->numHwLayers = 1; + + // some hwcomposers fail if these are NULL + dc->dpy = (void*) 0xdeadbeef; + dc->sur = (void*) 0xdeadbeef; + + set_layer(&dl[0], buf, ffd); + + if (QCT_WORKAROUND) { + set_layer(&dl[1], win->spare, -1); + dl[1].compositionType = HWC_FRAMEBUFFER_TARGET; + dc->numHwLayers++; + } + + r = hwc->prepare(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist); + if (r) { + ERROR("hwc->prepare failed r=%d\n",r); + return; + } + +// for (i = 0; i < dc->numHwLayers; i++) +// LOG("dl[%d] ctype=0x%08x hints=0x%08x flags=0x%08x\n", i, +// dl[i].compositionType, dl[0].hints, dl[0].flags); + + r = hwc->set(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist); + if (r) { + ERROR("hwc->set failed, r=%d\n", r); + return; + } + + if (dc->retireFenceFd != -1) + close(dc->retireFenceFd); + if (dl->releaseFenceFd != -1) { + CNativeBuffer *cnb = from_abuffer(buf); + cnb->ffd = dl->releaseFenceFd; + } + if (QCT_WORKAROUND) + if (dl[1].releaseFenceFd != -1) + close(dl[1].releaseFenceFd); +} + +static int cnw_queue_buffer1(aWindow *base, aBuffer *buffer, int ffd) { + CNativeWindow *win = from_base(base); + int res; + LOG(">> queue buffer %p %d\n", buffer, ffd); + if (win->fb) { + res = win->fb->post(win->fb, buffer->handle); + if (ffd != -1) + close(ffd); + } else { + hwc_post(win, buffer, ffd); + res = 0; + } + pthread_mutex_lock(&win->lock); + if (win->front) + put_back(&win->free_buffer_queue, win->front); + win->front = buffer; + pthread_cond_signal(&win->cvar); + pthread_mutex_unlock(&win->lock); + + return res; +} + +static int cnw_cancel_buffer1(aWindow *base, aBuffer *buf, int ffd) { + CNativeWindow *win = from_base(base); + CNativeBuffer *cnb = from_abuffer(buf); + LOG("<< cancel buffer %p %d\n", buf, ffd); + cnb->ffd = ffd; + pthread_mutex_lock(&win->lock); + put_front(&win->free_buffer_queue, buf); + pthread_mutex_unlock(&win->lock); + return 0; +} + +static int cnw_dequeue_buffer0(aWindow *base, aBuffer **buf) { + int ffd = -1; + int r; + r = cnw_dequeue_buffer1(base, buf, &ffd); + if (ffd != -1) + close(ffd); + return r; +} + +static int cnw_queue_buffer0(aWindow *base, aBuffer *buf) { + return cnw_queue_buffer1(base, buf, -1); +} + +static int cnw_cancel_buffer0(aWindow *base, aBuffer *buf) { + return cnw_cancel_buffer1(base, buf, -1); +} + +static int cnw_query(const aWindow *base, int what, int *value) { + CNativeWindow *win = from_base_const(base); + + switch (what) { + case NATIVE_WINDOW_WIDTH: + case NATIVE_WINDOW_DEFAULT_WIDTH: + *value = win->width; + TRACE("query window width: %d\n", *value); + return 0; + case NATIVE_WINDOW_HEIGHT: + case NATIVE_WINDOW_DEFAULT_HEIGHT: + *value = win->height; + TRACE("query window height: %d\n", *value); + return 0; + case NATIVE_WINDOW_FORMAT: + *value = win->format; + TRACE("query window format: %d\n", *value); + return 0; + case NATIVE_WINDOW_TRANSFORM_HINT: + TRACE("query transform hint: 0\n"); + *value = 0; + return 0; + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: + TRACE("query min undequeued buffers: 1\n"); + *value = 1; + return 0; + default: + *value = 0; + ERROR("query %d unknown!\n", what); + return -EINVAL; + } +} + +static int cnw_perform(aWindow *base, int op, ...) { + CNativeWindow *win = from_base(base); + va_list ap; + va_start(ap, op); + + switch (op) { + case NATIVE_WINDOW_SET_USAGE: + TRACE("set usage %d\n", va_arg(ap,int)); + return 0; + case NATIVE_WINDOW_CONNECT: + case NATIVE_WINDOW_DISCONNECT: + case NATIVE_WINDOW_API_CONNECT: + case NATIVE_WINDOW_API_DISCONNECT: + return 0; + case NATIVE_WINDOW_SET_BUFFERS_FORMAT: + TRACE("set buffers format %d\n", va_arg(ap,int)); + return 0; + case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: + TRACE("set buffers transform %d\n", va_arg(ap,int)); + return 0; + case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: + TRACE("set buffers timestamp %lld\n", va_arg(ap,long long)); + return 0; + case NATIVE_WINDOW_SET_SCALING_MODE: + TRACE("set scaling mode %d\n", va_arg(ap,int)); + return 0; + case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: { + unsigned int w = va_arg(ap,unsigned int); + unsigned int h = va_arg(ap,unsigned int); + if ((w == win->width) && (h == win->height)) { + TRACE("set buffers dimensions %d x %d\n", w, h); + return 0; + } + ERROR("cannot resize buffers to %d x %d\n", w, h); + return -1; + } + default: + ERROR("perform %d unknown!\n", op); + return -ENODEV; + } +} + +static void hwc_invalidate(const struct hwc_procs *procs) {} +static void hwc_vsync(const struct hwc_procs *procs, int disp, int64_t ts) {} +static void hwc_hotplug(const struct hwc_procs *procs, int disp, int conn) {} + +struct hwc_procs hprocs = { + .invalidate = hwc_invalidate, + .vsync = hwc_vsync, + .hotplug = hwc_hotplug, +}; + +uint32_t attrs[] = { + HWC_DISPLAY_WIDTH, + HWC_DISPLAY_HEIGHT, + HWC_DISPLAY_VSYNC_PERIOD, + HWC_DISPLAY_DPI_X, + HWC_DISPLAY_DPI_Y, + HWC_DISPLAY_NO_ATTRIBUTE, +}; + +static int hwc_init(CNativeWindow *win) { + hw_module_t const* module; + hwc_composer_device_1_t *hwc; + unsigned i; + int r; + uint32_t configs[32]; + size_t numconfigs = 32; + int32_t values[8]; + + if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) { + ERROR("cannot open hw composer module\n"); + return -ENODEV; + } + + if (hwc_open_1(module, &hwc)) { + ERROR("cannot open hwc device\n"); + return -ENODEV; + } + win->hwc = hwc; + + LOG("hwc version 0x%08x\n", hwc->common.version); + + if ((hwc->common.version & 0xFFFF0000) < 0x01010000) { + ERROR("hwc version less than 1.1\n"); + hwc_close_1(hwc); + return -ENODEV; + } + + hwc->registerProcs(hwc, &hprocs); + + if (hwc->getDisplayConfigs(hwc, 0, configs, &numconfigs)) { + ERROR("cannot get configs\n"); + return -ENODEV; + } + for (i = 0; i < numconfigs; i++) + LOG("cfg[%d] = 0x%08x\n", i, configs[i]); + + if ((r = hwc->getDisplayAttributes(hwc, 0, configs[0], attrs, values))) { + ERROR("cannot get attributes %d\n", r); + return -ENODEV; + } + + win->width = values[0]; + win->height = values[1]; + win->xdpi = values[3]; + win->ydpi = values[4]; + win->format = HAL_PIXEL_FORMAT_RGBA_8888; + + hwc->blank(hwc, 0, 0); + + win->dclist[0] = &(win->dc); + return 0; +} + +static aBuffer *cnw_alloc(CNativeWindow *win, unsigned format, unsigned usage) { + CNativeBuffer *cnb; + aBuffer *buf; + int err; + + if (!(cnb = malloc(sizeof(CNativeBuffer)))) + return 0; + + buf = &cnb->base; + cnb->ffd = -1; + + buf->common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + buf->common.version = sizeof(aBuffer); + buf->common.incRef = cnw_inc_ref; + buf->common.decRef = cnw_dec_ref; + + buf->width = win->width; + buf->height = win->height; + buf->format = format; + buf->usage = usage; + + err = win->gr->alloc(win->gr, win->width, win->height, + format, usage, &buf->handle, &buf->stride); + if (err) { + ERROR("gralloc of %d x %d failed: err=%d\n", + win->width, win->height, err); + free(buf); + return 0; + } + INFO("alloc buffer %p %d x %d\n", buf, win->width, win->height); + return buf; +} + +static int cnw_init(CNativeWindow *win) { + hw_module_t const* module; + framebuffer_device_t *fb = NULL; + alloc_device_t *gr; + int err, i, n; + unsigned usage, format; + + memset(win, 0, sizeof(CNativeWindow)); + + win->free_buffer_queue.next = &(win->free_buffer_queue); + win->free_buffer_queue.prev = &(win->free_buffer_queue); + + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) { + ERROR("cannot open gralloc module\n"); + return -ENODEV; + } + + if (hwc_init(win)) { + ERROR("cannot open hwcomposer, trying legacy fb HAL\n"); + err = framebuffer_open(module, &fb); + if (err) { + ERROR("cannot open fb HAL (%s)", strerror(-err)); + return -ENODEV; + } + win->width = fb->width; + win->height = fb->height; + win->format = fb->format; + win->xdpi = fb->xdpi; + win->ydpi = fb->ydpi; + win->fb = fb; + } + + INFO("display %d x %d fmt=%d\n", + win->width, win->height, win->format); + + err = gralloc_open(module, &gr); + if (err) { + ERROR("couldn't open gralloc HAL (%s)", strerror(-err)); + return -ENODEV; + } + win->gr = gr; + + usage = GRALLOC_USAGE_HW_FB | + GRALLOC_USAGE_HW_COMPOSER | + GRALLOC_USAGE_HW_RENDER; + + for (i = 0; i < 2; i++) { + aBuffer *buf = cnw_alloc(win, win->format, usage); + if (!buf) + return -ENOMEM; + put_back(&win->free_buffer_queue, buf); + } + + if (!win->fb && QCT_WORKAROUND) { + win->spare = cnw_alloc(win, win->format, usage); + if (!win->spare) + return -ENOMEM; + } + + // Disgusting, but we need to init these "const" fields + // and unlike C++ we can't use const_cast<> + *((float*) &win->base.xdpi) = win->xdpi; + *((float*) &win->base.ydpi) = win->ydpi; + *((int*) &win->base.minSwapInterval) = 1; + *((int*) &win->base.maxSwapInterval) = 1; + + win->base.common.magic = ANDROID_NATIVE_WINDOW_MAGIC; + win->base.common.version = sizeof(aWindow); + win->base.common.incRef = cnw_inc_ref; + win->base.common.decRef = cnw_dec_ref; + + win->base.setSwapInterval = cnw_set_swap_interval; + win->base.dequeueBuffer_DEPRECATED = cnw_dequeue_buffer0; + win->base.lockBuffer_DEPRECATED = cnw_lock_buffer0; + win->base.queueBuffer_DEPRECATED = cnw_queue_buffer0; + win->base.query = cnw_query; + win->base.perform = cnw_perform; + win->base.cancelBuffer_DEPRECATED = cnw_cancel_buffer0; + win->base.dequeueBuffer = cnw_dequeue_buffer1; + win->base.queueBuffer = cnw_queue_buffer1; + win->base.cancelBuffer = cnw_cancel_buffer1; + + pthread_mutex_init(&win->lock, NULL); + pthread_cond_init(&win->cvar, NULL); + + return 0; +} + +void cnw_destroy(CNativeWindow *win) { + if (win->fb) + framebuffer_close(win->fb); + if (win->hwc) + hwc_close_1(win->hwc); + if (win->gr) + gralloc_close(win->gr); + free(win); +} + +CNativeWindow *cnw_create(void) { + CNativeWindow *win; + char *x; + if ((x = getenv("CNWDEBUG"))) + trace_level = atoi(x); + if (!(win = malloc(sizeof(CNativeWindow)))) + return NULL; + if (cnw_init(win)) { + cnw_destroy(win); + return NULL; + } + return win; +} + +void cnw_info(CNativeWindow *win, unsigned *w, unsigned *h, unsigned *fmt) { + *w = win->width; + *h = win->height; + *fmt = win->format; +} +
diff --git a/libhardware/tests/hwc/test-arrows.c b/libhardware/tests/hwc/test-arrows.c new file mode 100644 index 0000000..12e7c8f --- /dev/null +++ b/libhardware/tests/hwc/test-arrows.c
@@ -0,0 +1,164 @@ +/* + * Copyright (C) 2013 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 <stdlib.h> +#include <stdio.h> + +#include <EGL/egl.h> +#include <GLES2/gl2.h> + +#include "util.h" + +static const char gVertexShader[] = + "attribute vec4 aPosition;\n" + "uniform mat4 uTransform;\n" + "varying vec4 vTexCoord;\n" + "void main() {\n" + " gl_Position = aPosition * uTransform;\n" + " vTexCoord = aPosition * vec4(1.0/16.0,-1.0/16.0,0.0,0.0);\n" + "}\n"; + +static const char gFragmentShader[] = + "precision mediump float;\n" + "uniform sampler2D uTexture;\n" + "uniform float uAnim;\n" + "varying vec4 vTexCoord;\n" + "void main() {\n" + " vec2 tc = vec2(vTexCoord.x, uAnim + vTexCoord.y);\n" + " gl_FragColor = texture2D(uTexture, tc);\n" + "}\n"; + +static GLuint pgm; +static GLint aPosition, uTransform, uTexture, uAnim; + +static GLfloat vtx[2 * 3 * 2]; +static GLfloat mtx[16]; + +//#define R (0xFF0000FF) +#define R (0xFF000000) +#define G (0xFF00FF00) +uint32_t t32[] = { + R, R, R, R, R, R, R, G, G, R, R, R, R, R, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, G, G, G, G, G, G, R, R, R, R, R, + R, R, R, R, G, G, G, G, G, G, G, G, R, R, R, R, + R, R, R, G, G, G, G, G, G, G, G, G, G, R, R, R, + R, R, G, G, G, G, G, G, G, G, G, G, G, G, R, R, + R, R, G, G, G, G, G, G, G, G, G, G, G, G, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, R, G, G, G, G, R, R, R, R, R, R, + R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, + R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, + R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, +}; +#undef R +#undef G + +int prepare(int w, int h) { + GLuint texid; + + int left = w / 4; + int top = h / 4; + int right = (w / 4) * 3; + int bottom = (h / 4) * 3; + + vtx[0] = left; + vtx[1] = top; + vtx[2] = left; + vtx[3] = bottom; + vtx[4] = right; + vtx[5] = bottom; + + vtx[6] = right; + vtx[7] = bottom; + vtx[8] = right; + vtx[9] = top; + vtx[10] = left; + vtx[11] = top; + + matrix_init_ortho(mtx, w, h); + + pgm = load_program(gVertexShader, gFragmentShader); + if (!pgm) + return -1; + + aPosition = glGetAttribLocation(pgm, "aPosition"); + uTexture = glGetUniformLocation(pgm, "uTexture"); + uTransform = glGetUniformLocation(pgm, "uTransform"); + uAnim = glGetUniformLocation(pgm, "uAnim"); + + glViewport(0, 0, w, h); + + glGenTextures(1, &texid); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texid); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glEnable(GL_TEXTURE_2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, + GL_RGBA, GL_UNSIGNED_BYTE, t32); + + return 0; +} + +static float anim = 0.0; + +void render() { + anim += 0.1; + if (anim >= 16.0) anim = 0.0; + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glUseProgram(pgm); + glUniform1i(uTexture, 0); + glUniform1f(uAnim, anim); + glUniformMatrix4fv(uTransform, 1, 0, mtx); + glVertexAttribPointer(aPosition, 2, GL_FLOAT, GL_FALSE, 0, vtx); + glEnableVertexAttribArray(aPosition); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + +int main(int argc, char **argv) { + EGLDisplay display; + EGLSurface surface; + int w, h, count = 0; + + if (argc > 1) + count = atoi(argv[1]); + + if (egl_create(&display, &surface, &w, &h)) + return -1; + + if (prepare(w, h)) + return -1; + + for (;;) { + render(); + eglSwapBuffers(display, surface); + if (count > 0) + if (--count == 0) + break; + } + + egl_destroy(display, surface); + return 0; +}
diff --git a/libhardware/tests/hwc/util.c b/libhardware/tests/hwc/util.c new file mode 100644 index 0000000..8931305 --- /dev/null +++ b/libhardware/tests/hwc/util.c
@@ -0,0 +1,236 @@ +/* + * Copyright (C) 2013 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 <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#include <EGL/egl.h> +#include <GLES2/gl2.h> + +#include <system/graphics.h> + +#include "util.h" + +void matrix_init_ortho(GLfloat *m, float w, float h) { + m[0] = 2.0 / w; + m[1] = 0.0; + m[2] = 0.0; + m[3] = -1.0; + m[4] = 0.0; + m[5] = 2.0 / h; + m[6] = 0.0; + m[7] = -1.0; + m[8] = 0.0; + m[9] = 0.0; + m[10] -1.0; + m[11] = 0.0; + m[12] = 0.0; + m[13] = 0.0; + m[14] = 0.0; + m[15] = 1.0; +} + +static GLuint load_shader(GLenum shaderType, const char *src) { + GLint status = 0, len = 0; + GLuint shader; + + if (!(shader = glCreateShader(shaderType))) + return 0; + + glShaderSource(shader, 1, &src, NULL); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + if (status) + return shader; + + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); + if (len) { + char *msg = malloc(len); + if (msg) { + glGetShaderInfoLog(shader, len, NULL, msg); + msg[len-1] = 0; + fprintf(stderr, "error compiling shader:\n%s\n", msg); + free(msg); + } + } + glDeleteShader(shader); + return 0; +} + +GLuint load_program(const char *vert_src, const char *frag_src) { + GLuint vert, frag, prog; + GLint status = 0, len = 0; + + if (!(vert = load_shader(GL_VERTEX_SHADER, vert_src))) + return 0; + if (!(frag = load_shader(GL_FRAGMENT_SHADER, frag_src))) + goto fail_frag; + if (!(prog = glCreateProgram())) + goto fail_prog; + + glAttachShader(prog, vert); + glAttachShader(prog, frag); + glLinkProgram(prog); + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status) + return prog; + + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len); + if (len) { + char *buf = (char*) malloc(len); + if (buf) { + glGetProgramInfoLog(prog, len, NULL, buf); + buf[len-1] = 0; + fprintf(stderr, "error linking program:\n%s\n", buf); + free(buf); + } + } + glDeleteProgram(prog); +fail_prog: + glDeleteShader(frag); +fail_frag: + glDeleteShader(vert); + return 0; +} + +int select_config_for_window(EGLDisplay dpy, EGLint *attr, + unsigned format, EGLConfig *config) { + EGLint R,G,B,A,r,g,b,a; + EGLint i, n, max; + EGLConfig *cfg; + + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + R = G = B = A = 8; + break; + case HAL_PIXEL_FORMAT_RGB_565: + R = 5; G = 6; B = 5; A = 0; + break; + default: + fprintf(stderr, "unknown fb pixel format %d\n", format); + return -1; + } + + if (eglGetConfigs(dpy, NULL, 0, &max) == EGL_FALSE) { + fprintf(stderr, "no EGL configurations available?!\n"); + return -1; + } + + cfg = (EGLConfig*) malloc(sizeof(EGLConfig) * max); + if (!cfg) + return -1; + + if (eglChooseConfig(dpy, attr, cfg, max, &n) == EGL_FALSE) { + fprintf(stderr, "eglChooseConfig failed\n"); + return -1; + } + + for (i = 0; i < n; i++) { + EGLint r,g,b,a; + eglGetConfigAttrib(dpy, cfg[i], EGL_RED_SIZE, &r); + eglGetConfigAttrib(dpy, cfg[i], EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(dpy, cfg[i], EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(dpy, cfg[i], EGL_ALPHA_SIZE, &a); + if (r == R && g == G && b == B && a == A) { + *config = cfg[i]; + free(cfg); + return 0; + } + } + + fprintf(stderr, "cannot find matching config\n"); + free(cfg); + return -1; +} + +static struct CNativeWindow *_cnw = 0; + +int egl_create(EGLDisplay *_display, EGLSurface *_surface, int *_w, int *_h) { + EGLBoolean res; + EGLConfig config = { 0 }; + EGLint context_attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + EGLint config_attrs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE }; + EGLint major, minor; + EGLContext context; + EGLSurface surface; + EGLint w, h; + EGLDisplay display; + EGLNativeWindowType window; + unsigned width, height, format; + struct CNativeWindow *cnw; + + display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (display == EGL_NO_DISPLAY) + return -1; + + if (!(res = eglInitialize(display, &major, &minor))) + return -1; + + fprintf(stderr, "egl version: %d.%d\n", major, minor); + + if ((cnw = cnw_create()) == 0) + return -1; + + cnw_info(cnw, &width, &height, &format); + window = (EGLNativeWindowType) cnw; + + if ((res = select_config_for_window(display, config_attrs, format, &config))) + goto fail; + + surface = eglCreateWindowSurface(display, config, window, NULL); + if (surface == EGL_NO_SURFACE) + goto fail; + + context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attrs); + if (context == EGL_NO_CONTEXT) + goto fail; + + if (!(res = eglMakeCurrent(display, surface, surface, context))) + goto fail; + + eglQuerySurface(display, surface, EGL_WIDTH, &w); + eglQuerySurface(display, surface, EGL_HEIGHT, &h); + + fprintf(stderr, "window: %d x %d\n", w, h); + + *_display = display; + *_surface = surface; + *_w = w; + *_h = h; + + _cnw = cnw; + return 0; + +fail: + cnw_destroy(cnw); + return -1; +} + +void egl_destroy(EGLDisplay display, EGLSurface surface) { + if (_cnw) { + eglDestroySurface(display, surface); + eglTerminate(display); + cnw_destroy(_cnw); + _cnw = 0; + } +}
diff --git a/libhardware/tests/hwc/util.h b/libhardware/tests/hwc/util.h new file mode 100644 index 0000000..a0d38ce --- /dev/null +++ b/libhardware/tests/hwc/util.h
@@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 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 _GL_UTIL_H_ +#define _GL_UTIL_H_ + +/* convenience */ + +GLuint load_program(const char *vert_src, const char *frag_src); +void matrix_init_ortho(GLfloat *m, float w, float h); + +/* context setup / teardown */ + +int egl_create(EGLDisplay *_display, EGLSurface *_surface, int *_w, int *_h); +void egl_destroy(EGLDisplay display, EGLSurface surface); + +/* internals needed by util.c */ + +struct CNativeWindow; +struct CNativeWindow *cnw_create(void); +void cnw_destroy(struct CNativeWindow *win); +void cnw_info(struct CNativeWindow *win, + unsigned *w, unsigned *h, unsigned *fmt); + +#endif
diff --git a/libhardware/tests/input/Android.mk b/libhardware/tests/input/Android.mk new file mode 100644 index 0000000..3011b2e --- /dev/null +++ b/libhardware/tests/input/Android.mk
@@ -0,0 +1,19 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libhardware/tests/input/evdev/Android.mk b/libhardware/tests/input/evdev/Android.mk new file mode 100644 index 0000000..8761da8 --- /dev/null +++ b/libhardware/tests/input/evdev/Android.mk
@@ -0,0 +1,28 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES += hardware/libhardware/modules/input/evdev + +LOCAL_SRC_FILES:= \ + InputDevice_test.cpp \ + InputHub_test.cpp \ + TestHelpers.cpp + +LOCAL_SHARED_LIBRARIES := \ + libinput_evdev \ + liblog \ + libutils + +LOCAL_CLANG := true +LOCAL_CFLAGS += -Wall -Wextra -Wno-unused-parameter +LOCAL_CPPFLAGS += -std=c++14 + +# TestHelpers uses mktemp. As the path is given to TempFile, we can't do too much +# here (e.g., use mkdtemp first). At least races will lead to an early failure, as +# mkfifo fails on existing files. +LOCAL_CFLAGS += -Wno-deprecated-declarations + +LOCAL_MODULE := libinput_evdevtests +LOCAL_MODULE_TAGS := tests + +include $(BUILD_NATIVE_TEST)
diff --git a/libhardware/tests/input/evdev/InputDevice_test.cpp b/libhardware/tests/input/evdev/InputDevice_test.cpp new file mode 100644 index 0000000..a96d664 --- /dev/null +++ b/libhardware/tests/input/evdev/InputDevice_test.cpp
@@ -0,0 +1,134 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "InputHub_test" +//#define LOG_NDEBUG 0 + +#include <linux/input.h> + +#include <gtest/gtest.h> + +#include <utils/Timers.h> + +#include "InputDevice.h" +#include "InputHub.h" + +// # of milliseconds to allow for timing measurements +#define TIMING_TOLERANCE_MS 25 + +#define MSC_ANDROID_TIME_SEC 0x6 +#define MSC_ANDROID_TIME_USEC 0x7 + +namespace android { +namespace tests { + +class MockInputDeviceNode : public InputDeviceNode { + virtual const std::string& getPath() const override { return mPath; } + + virtual const std::string& getName() const override { return mName; } + virtual const std::string& getLocation() const override { return mLocation; } + virtual const std::string& getUniqueId() const override { return mUniqueId; } + + virtual uint16_t getBusType() const override { return 0; } + virtual uint16_t getVendorId() const override { return 0; } + virtual uint16_t getProductId() const override { return 0; } + virtual uint16_t getVersion() const override { return 0; } + + virtual bool hasKey(int32_t key) const { return false; } + virtual bool hasRelativeAxis(int axis) const { return false; } + virtual bool hasInputProperty(int property) const { return false; } + + virtual int32_t getKeyState(int32_t key) const { return 0; } + virtual int32_t getSwitchState(int32_t sw) const { return 0; } + virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const { return nullptr; } + virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const { return 0; } + + virtual void vibrate(nsecs_t duration) {} + virtual void cancelVibrate(int32_t deviceId) {} + + virtual void disableDriverKeyRepeat() {} + +private: + std::string mPath = "/test"; + std::string mName = "Test Device"; + std::string mLocation = "test/0"; + std::string mUniqueId = "test-id"; +}; + +TEST(EvdevDeviceTest, testOverrideTime) { + auto node = std::make_shared<MockInputDeviceNode>(); + auto device = std::make_unique<EvdevDevice>(node); + ASSERT_TRUE(device != nullptr); + + // Send two timestamp override events before an input event. + nsecs_t when = 2ULL; + InputEvent msc1 = { when, EV_MSC, MSC_ANDROID_TIME_SEC, 1 }; + InputEvent msc2 = { when, EV_MSC, MSC_ANDROID_TIME_USEC, 900000 }; + + // Send a key down and syn. Should get the overridden timestamp. + InputEvent keyDown = { when, EV_KEY, KEY_HOME, 1 }; + InputEvent syn = { when, EV_SYN, SYN_REPORT, 0 }; + + // Send a key up, which should be at the reported timestamp. + InputEvent keyUp = { when, EV_KEY, KEY_HOME, 0 }; + + device->processInput(msc1, when); + device->processInput(msc2, when); + device->processInput(keyDown, when); + device->processInput(syn, when); + device->processInput(keyUp, when); + + nsecs_t expectedWhen = s2ns(1) + us2ns(900000); + EXPECT_EQ(expectedWhen, keyDown.when); + EXPECT_EQ(expectedWhen, syn.when); + EXPECT_EQ(when, keyUp.when); +} + +TEST(EvdevDeviceTest, testWrongClockCorrection) { + auto node = std::make_shared<MockInputDeviceNode>(); + auto device = std::make_unique<EvdevDevice>(node); + ASSERT_TRUE(device != nullptr); + + auto now = systemTime(SYSTEM_TIME_MONOTONIC); + + // Input event that supposedly comes from 1 minute in the future. In + // reality, the timestamps would be much further off. + InputEvent event = { now + s2ns(60), EV_KEY, KEY_HOME, 1 }; + + device->processInput(event, now); + + EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS)); +} + +TEST(EvdevDeviceTest, testClockCorrectionOk) { + auto node = std::make_shared<MockInputDeviceNode>(); + auto device = std::make_unique<EvdevDevice>(node); + ASSERT_TRUE(device != nullptr); + + auto now = systemTime(SYSTEM_TIME_MONOTONIC); + + // Input event from now, but will be reported as if it came early. + InputEvent event = { now, EV_KEY, KEY_HOME, 1 }; + + // event_time parameter is 11 seconds in the past, so it looks like we used + // the wrong clock. + device->processInput(event, now - s2ns(11)); + + EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS)); +} + +} // namespace tests +} // namespace android
diff --git a/libhardware/tests/input/evdev/InputHub_test.cpp b/libhardware/tests/input/evdev/InputHub_test.cpp new file mode 100644 index 0000000..14f08fc --- /dev/null +++ b/libhardware/tests/input/evdev/InputHub_test.cpp
@@ -0,0 +1,259 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "InputHub_test" +//#define LOG_NDEBUG 0 + +#include <linux/input.h> + +#include <chrono> +#include <memory> +#include <mutex> + +#include <gtest/gtest.h> + +#include <utils/Log.h> +#include <utils/StopWatch.h> +#include <utils/Timers.h> + +#include "InputHub.h" +#include "TestHelpers.h" + +// # of milliseconds to fudge stopwatch measurements +#define TIMING_TOLERANCE_MS 25 +#define NO_TIMEOUT (-1) + +namespace android { +namespace tests { + +using namespace std::literals::chrono_literals; + +using InputCbFunc = std::function<void(std::shared_ptr<InputDeviceNode>, InputEvent&, nsecs_t)>; +using DeviceCbFunc = std::function<void(std::shared_ptr<InputDeviceNode>)>; + +static const InputCbFunc kNoopInputCb = [](const std::shared_ptr<InputDeviceNode>&, InputEvent&, nsecs_t){}; +static const DeviceCbFunc kNoopDeviceCb = [](const std::shared_ptr<InputDeviceNode>&){}; + +class TestInputCallback : public InputCallbackInterface { +public: + TestInputCallback() : + mInputCb(kNoopInputCb), mDeviceAddedCb(kNoopDeviceCb), mDeviceRemovedCb(kNoopDeviceCb) {} + virtual ~TestInputCallback() = default; + + void setInputCallback(const InputCbFunc& cb) { mInputCb = cb; } + void setDeviceAddedCallback(const DeviceCbFunc& cb) { mDeviceAddedCb = cb; } + void setDeviceRemovedCallback(const DeviceCbFunc& cb) { mDeviceRemovedCb = cb; } + + virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event, + nsecs_t event_time) override { + mInputCb(node, event, event_time); + } + virtual void onDeviceAdded(std::shared_ptr<InputDeviceNode> node) override { + mDeviceAddedCb(node); + } + virtual void onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) override { + mDeviceRemovedCb(node); + } + +private: + InputCbFunc mInputCb; + DeviceCbFunc mDeviceAddedCb; + DeviceCbFunc mDeviceRemovedCb; +}; + +class InputHubTest : public ::testing::Test { + protected: + virtual void SetUp() { + mCallback = std::make_shared<TestInputCallback>(); + mInputHub = std::make_shared<InputHub>(mCallback); + } + + std::shared_ptr<TestInputCallback> mCallback; + std::shared_ptr<InputHub> mInputHub; +}; + +TEST_F(InputHubTest, testWake) { + // Call wake() after 100ms. + auto f = delay_async(100ms, [&]() { EXPECT_EQ(OK, mInputHub->wake()); }); + + StopWatch stopWatch("poll"); + EXPECT_EQ(OK, mInputHub->poll()); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS); +} + +TEST_F(InputHubTest, DISABLED_testDeviceAdded) { + auto tempDir = std::make_shared<TempDir>(); + std::string pathname; + // Expect that this callback will run and set handle and pathname. + mCallback->setDeviceAddedCallback( + [&](std::shared_ptr<InputDeviceNode> node) { + pathname = node->getPath(); + }); + + ASSERT_EQ(OK, mInputHub->registerDevicePath(tempDir->getName())); + + // Create a new file in tempDir after 100ms. + std::unique_ptr<TempFile> tempFile; + std::mutex tempFileMutex; + auto f = delay_async(100ms, + [&]() { + std::lock_guard<std::mutex> lock(tempFileMutex); + tempFile.reset(tempDir->newTempFile()); + }); + + StopWatch stopWatch("poll"); + EXPECT_EQ(OK, mInputHub->poll()); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS); + std::lock_guard<std::mutex> lock(tempFileMutex); + EXPECT_EQ(tempFile->getName(), pathname); +} + +TEST_F(InputHubTest, DISABLED_testDeviceRemoved) { + // Create a temp dir and file. Save its name and handle (to be filled in + // once InputHub scans the dir). + auto tempDir = std::make_unique<TempDir>(); + auto deviceFile = std::unique_ptr<TempFile>(tempDir->newTempFile()); + std::string tempFileName(deviceFile->getName()); + + std::shared_ptr<InputDeviceNode> tempNode; + // Expect that these callbacks will run for the above device file. + mCallback->setDeviceAddedCallback( + [&](std::shared_ptr<InputDeviceNode> node) { + tempNode = node; + }); + mCallback->setDeviceRemovedCallback( + [&](std::shared_ptr<InputDeviceNode> node) { + EXPECT_EQ(tempNode, node); + }); + + ASSERT_EQ(OK, mInputHub->registerDevicePath(tempDir->getName())); + // Ensure that tempDir was scanned to find the device. + ASSERT_TRUE(tempNode != nullptr); + + auto f = delay_async(100ms, [&]() { deviceFile.reset(); }); + + StopWatch stopWatch("poll"); + EXPECT_EQ(OK, mInputHub->poll()); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS); +} + +TEST_F(InputHubTest, DISABLED_testInputEvent) { + // Create a temp dir and file. Save its name and handle (to be filled in + // once InputHub scans the dir.) + auto tempDir = std::make_unique<TempDir>(); + auto deviceFile = std::unique_ptr<TempFile>(tempDir->newTempFile()); + std::string tempFileName(deviceFile->getName()); + + // Send a key event corresponding to HOME. + struct input_event iev; + iev.time = { 1, 0 }; + iev.type = EV_KEY; + iev.code = KEY_HOME; + iev.value = 0x01; + + auto inputDelayMs = 100ms; + auto f = delay_async(inputDelayMs, [&] { + ssize_t nWrite = TEMP_FAILURE_RETRY(write(deviceFile->getFd(), &iev, sizeof(iev))); + + ASSERT_EQ(static_cast<ssize_t>(sizeof(iev)), nWrite) << "could not write to " + << deviceFile->getFd() << ". errno: " << errno; + }); + + // Expect this callback to run when the input event is read. + nsecs_t expectedWhen = systemTime(CLOCK_MONOTONIC) + ms2ns(inputDelayMs.count()); + mCallback->setInputCallback( + [&](std::shared_ptr<InputDeviceNode> node, InputEvent& event, nsecs_t event_time) { + EXPECT_NEAR(expectedWhen, event_time, ms2ns(TIMING_TOLERANCE_MS)); + EXPECT_EQ(s2ns(1), event.when); + EXPECT_EQ(tempFileName, node->getPath()); + EXPECT_EQ(EV_KEY, event.type); + EXPECT_EQ(KEY_HOME, event.code); + EXPECT_EQ(0x01, event.value); + }); + ASSERT_EQ(OK, mInputHub->registerDevicePath(tempDir->getName())); + + StopWatch stopWatch("poll"); + EXPECT_EQ(OK, mInputHub->poll()); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS); +} + +TEST_F(InputHubTest, DISABLED_testCallbackOrder) { + // Create two "devices": one to receive input and the other to go away. + auto tempDir = std::make_unique<TempDir>(); + auto deviceFile1 = std::unique_ptr<TempFile>(tempDir->newTempFile()); + auto deviceFile2 = std::unique_ptr<TempFile>(tempDir->newTempFile()); + std::string tempFileName(deviceFile2->getName()); + + bool inputCallbackFinished = false, deviceCallbackFinished = false; + + // Setup the callback for input events. Should run before the device + // callback. + mCallback->setInputCallback( + [&](std::shared_ptr<InputDeviceNode>, InputEvent&, nsecs_t) { + ASSERT_FALSE(deviceCallbackFinished); + inputCallbackFinished = true; + }); + + // Setup the callback for device removal. Should run after the input + // callback. + mCallback->setDeviceRemovedCallback( + [&](std::shared_ptr<InputDeviceNode> node) { + ASSERT_TRUE(inputCallbackFinished) + << "input callback did not run before device changed callback"; + // Make sure the correct device was removed. + EXPECT_EQ(tempFileName, node->getPath()); + deviceCallbackFinished = true; + }); + ASSERT_EQ(OK, mInputHub->registerDevicePath(tempDir->getName())); + + auto f = delay_async(100ms, + [&]() { + // Delete the second device file first. + deviceFile2.reset(); + + // Then inject an input event into the first device. + struct input_event iev; + iev.time = { 1, 0 }; + iev.type = EV_KEY; + iev.code = KEY_HOME; + iev.value = 0x01; + + ssize_t nWrite = TEMP_FAILURE_RETRY(write(deviceFile1->getFd(), &iev, sizeof(iev))); + + ASSERT_EQ(static_cast<ssize_t>(sizeof(iev)), nWrite) << "could not write to " + << deviceFile1->getFd() << ". errno: " << errno; + }); + + StopWatch stopWatch("poll"); + EXPECT_EQ(OK, mInputHub->poll()); + int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); + + EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS); + EXPECT_TRUE(inputCallbackFinished); + EXPECT_TRUE(deviceCallbackFinished); +} + +} // namespace tests +} // namespace android
diff --git a/libhardware/tests/input/evdev/TestHelpers.cpp b/libhardware/tests/input/evdev/TestHelpers.cpp new file mode 100644 index 0000000..63b579e --- /dev/null +++ b/libhardware/tests/input/evdev/TestHelpers.cpp
@@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "TestHelpers" +#define LOG_NDEBUG 0 + +#include <dirent.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include <utils/Log.h> + +#include "TestHelpers.h" + +namespace android { + +static const char kTmpDirTemplate[] = "/data/local/tmp/XXXXXX"; + +TempFile::TempFile(const char* path) { + bool needTrailingSlash = path[strlen(path) - 1] != '/'; + // name = path + XXXXXX + \0 + size_t nameLen = strlen(path) + 6 + 1; + if (needTrailingSlash) nameLen++; + + mName = new char[nameLen]; + strcpy(mName, path); + if (needTrailingSlash) { + strcat(mName, "/"); + } + strcat(mName, "XXXXXX"); + mName = mktemp(mName); + LOG_FATAL_IF(mName == nullptr, "could not create temp filename %s. errno=%d", mName, errno); + + int result = TEMP_FAILURE_RETRY(mkfifo(mName, S_IRWXU)); + LOG_FATAL_IF(result < 0, "could not create fifo %s. errno=%d", mName, errno); + + mFd = TEMP_FAILURE_RETRY(open(mName, O_RDWR | O_NONBLOCK)); + LOG_FATAL_IF(mFd < 0, "could not open fifo %s. errno=%d", mName, errno); +} + +TempFile::~TempFile() { + if (unlink(mName) < 0) { + ALOGE("could not unlink %s. errno=%d", mName, errno); + } + if (close(mFd) < 0) { + ALOGE("could not close %d. errno=%d", mFd, errno); + } + delete[] mName; +} + +TempDir::TempDir() { + mName = new char[sizeof(kTmpDirTemplate)]; + strcpy(mName, kTmpDirTemplate); + mName = mkdtemp(mName); + LOG_FATAL_IF(mName == nullptr, "could not allocate tempdir %s", mName); +} + +TempDir::~TempDir() { + auto tmpDir = opendir(mName); + while (auto entry = readdir(tmpDir)) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) { + continue; + } + ALOGD("stale file %s, removing", entry->d_name); + unlink(entry->d_name); + } + closedir(tmpDir); + rmdir(mName); + delete mName; +} + +TempFile* TempDir::newTempFile() { + return new TempFile(mName); +} + +} // namespace android
diff --git a/libhardware/tests/input/evdev/TestHelpers.h b/libhardware/tests/input/evdev/TestHelpers.h new file mode 100644 index 0000000..d26adfb --- /dev/null +++ b/libhardware/tests/input/evdev/TestHelpers.h
@@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_TEST_HELPERS_H_ +#define ANDROID_TEST_HELPERS_H_ + +#include <future> +#include <thread> + +namespace android { + +/** + * Runs the given function after the specified delay. + * NOTE: if the std::future returned from std::async is not bound, this function + * will block until the task completes. This is almost certainly NOT what you + * want, so save the return value from delay_async into a variable: + * + * auto f = delay_async(100ms, []{ ALOGD("Hello world"); }); + */ +template<class Function, class Duration> +decltype(auto) delay_async(Duration&& delay, Function&& task) +{ + return std::async(std::launch::async, [=]{ std::this_thread::sleep_for(delay); task(); }); +} + +/** + * Creates and opens a temporary file at the given path. The file is unlinked + * and closed in the destructor. + */ +class TempFile { +public: + explicit TempFile(const char* path); + ~TempFile(); + + // No copy or assign + TempFile(const TempFile&) = delete; + TempFile& operator=(const TempFile&) = delete; + + const char* getName() const { return mName; } + int getFd() const { return mFd; } + +private: + char* mName; + int mFd; +}; + +/** + * Creates a temporary directory that can create temporary files. The directory + * is emptied and deleted in the destructor. + */ +class TempDir { +public: + TempDir(); + ~TempDir(); + + // No copy or assign + TempDir(const TempDir&) = delete; + TempDir& operator=(const TempDir&) = delete; + + const char* getName() const { return mName; } + + TempFile* newTempFile(); + +private: + char* mName; +}; + +} // namespace android + +#endif // ANDROID_TEST_HELPERS_H_
diff --git a/libhardware/tests/keymaster/Android.mk b/libhardware/tests/keymaster/Android.mk new file mode 100644 index 0000000..0c11795 --- /dev/null +++ b/libhardware/tests/keymaster/Android.mk
@@ -0,0 +1,19 @@ +# Build the keymaster unit tests + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + keymaster_test.cpp + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libutils \ + libcrypto \ + libhardware \ + +LOCAL_MODULE := keymaster_test + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_NATIVE_TEST)
diff --git a/libhardware/tests/keymaster/keymaster_test.cpp b/libhardware/tests/keymaster/keymaster_test.cpp new file mode 100644 index 0000000..3040a5c --- /dev/null +++ b/libhardware/tests/keymaster/keymaster_test.cpp
@@ -0,0 +1,1284 @@ +/* + * Copyright (C) 2012 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 <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <fstream> +#include <iostream> + +#include <gtest/gtest.h> + +#include <openssl/bn.h> +#include <openssl/evp.h> +#include <openssl/x509.h> + +#define LOG_TAG "keymaster_test" +#include <utils/Log.h> + +#include <UniquePtr.h> + +#include <hardware/keymaster0.h> + +namespace android { + +class UniqueBlob : public UniquePtr<uint8_t[]> { +public: + explicit UniqueBlob(size_t length) : + mLength(length) { + } + + UniqueBlob(uint8_t* bytes, size_t length) : + UniquePtr<uint8_t[]>(bytes), mLength(length) { + } + + bool operator==(const UniqueBlob &other) const { + if (other.length() != mLength) { + return false; + } + + const uint8_t* mine = get(); + const uint8_t* theirs = other.get(); + + for (size_t i = 0; i < mLength; i++) { + if (mine[i] != theirs[i]) { + return false; + } + } + + return true; + } + + size_t length() const { + return mLength; + } + + friend std::ostream &operator<<(std::ostream &stream, const UniqueBlob& blob); + +private: + size_t mLength; +}; + +std::ostream &operator<<(std::ostream &stream, const UniqueBlob& blob) { + const size_t length = blob.mLength; + stream << "Blob length=" << length << " < "; + + const uint8_t* data = blob.get(); + for (size_t i = 0; i < length; i++) { + stream << std::hex << std::setw(2) << std::setfill('0') + << static_cast<unsigned int>(data[i]) << ' '; + } + stream << '>' << std::endl; + + return stream; +} + +class UniqueKey : public UniqueBlob { +public: + UniqueKey(keymaster0_device_t** dev, uint8_t* bytes, size_t length) : + UniqueBlob(bytes, length), mDevice(dev) { + } + + ~UniqueKey() { + if (mDevice != NULL && *mDevice != NULL) { + keymaster0_device_t* dev = *mDevice; + if (dev->delete_keypair != NULL) { + dev->delete_keypair(dev, get(), length()); + } + } + } + +private: + keymaster0_device_t** mDevice; +}; + +class UniqueReadOnlyBlob { +public: + UniqueReadOnlyBlob(uint8_t* data, size_t dataSize) : + mDataSize(dataSize) { + int pageSize = sysconf(_SC_PAGE_SIZE); + if (pageSize == -1) { + return; + } + + int fd = open("/dev/zero", O_RDONLY); + if (fd == -1) { + return; + } + + mBufferSize = (dataSize + pageSize - 1) & ~(pageSize - 1); + uint8_t* buffer = (uint8_t*) mmap(NULL, mBufferSize, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0); + close(fd); + + if (buffer == NULL) { + return; + } + + memcpy(buffer, data, dataSize); + if (mprotect(buffer, mBufferSize, PROT_READ) == -1) { + munmap(buffer, mBufferSize); + return; + } + + mBuffer = buffer; + } + + ~UniqueReadOnlyBlob() { + munmap(mBuffer, mBufferSize); + } + + uint8_t* get() const { + return mBuffer; + } + + size_t length() const { + return mDataSize; + } + +private: + uint8_t* mBuffer; + size_t mBufferSize; + size_t mDataSize; +}; + +struct BIGNUM_Delete { + void operator()(BIGNUM* p) const { + BN_free(p); + } +}; +typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM; + +struct EVP_PKEY_Delete { + void operator()(EVP_PKEY* p) const { + EVP_PKEY_free(p); + } +}; +typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY; + +struct PKCS8_PRIV_KEY_INFO_Delete { + void operator()(PKCS8_PRIV_KEY_INFO* p) const { + PKCS8_PRIV_KEY_INFO_free(p); + } +}; +typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO; + +struct RSA_Delete { + void operator()(RSA* p) const { + RSA_free(p); + } +}; +typedef UniquePtr<RSA, RSA_Delete> Unique_RSA; + +struct EC_KEY_Delete { + void operator()(EC_KEY* p) const { + EC_KEY_free(p); + } +}; +typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY; + + +/* + * DER-encoded PKCS#8 format RSA key. Generated using: + * + * openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -outform der | recode ../x1 + */ +static uint8_t TEST_RSA_KEY_1[] = { + 0x30, 0x82, 0x04, 0xBE, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x04, 0xA8, 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xD8, 0x58, 0xD4, 0x9F, 0xC0, 0xE8, 0xF0, 0xFF, 0x87, 0x27, + 0x43, 0xE6, 0x2E, 0xE6, 0x9A, 0x42, 0x3B, 0x39, 0x94, 0x84, 0x43, 0x55, + 0x8D, 0x20, 0x5B, 0x71, 0x88, 0xE6, 0xD1, 0x62, 0xC8, 0xF2, 0x20, 0xD0, + 0x75, 0x13, 0x83, 0xA3, 0x5D, 0x19, 0xA8, 0x62, 0xD0, 0x5F, 0x3E, 0x8A, + 0x7C, 0x0E, 0x26, 0xA9, 0xFF, 0xB2, 0x5E, 0x63, 0xAA, 0x3C, 0x8D, 0x13, + 0x41, 0xAA, 0xD5, 0x03, 0x01, 0x01, 0x53, 0xC9, 0x02, 0x1C, 0xEC, 0xE8, + 0xC4, 0x70, 0x3F, 0x43, 0xE5, 0x51, 0xD0, 0x6E, 0x52, 0x0B, 0xC4, 0x0A, + 0xA3, 0x61, 0xDE, 0xE3, 0x72, 0x0C, 0x94, 0xF1, 0x1C, 0x2D, 0x36, 0x77, + 0xBB, 0x16, 0xA8, 0x63, 0x4B, 0xD1, 0x07, 0x00, 0x42, 0x2D, 0x2B, 0x10, + 0x80, 0x45, 0xF3, 0x0C, 0xF9, 0xC5, 0xAC, 0xCC, 0x64, 0x87, 0xFD, 0x5D, + 0xC8, 0x51, 0xD4, 0x1C, 0x9E, 0x6E, 0x9B, 0xC4, 0x27, 0x5E, 0x73, 0xA7, + 0x2A, 0xF6, 0x90, 0x42, 0x0C, 0x34, 0x93, 0xB7, 0x02, 0x19, 0xA9, 0x64, + 0x6C, 0x46, 0x3B, 0x40, 0x02, 0x2F, 0x54, 0x69, 0x79, 0x26, 0x7D, 0xF6, + 0x85, 0x90, 0x01, 0xD0, 0x21, 0x07, 0xD0, 0x14, 0x00, 0x65, 0x9C, 0xAC, + 0x24, 0xE8, 0x78, 0x42, 0x3B, 0x90, 0x75, 0x19, 0x55, 0x11, 0x4E, 0xD9, + 0xE6, 0x97, 0x87, 0xBC, 0x8D, 0x2C, 0x9B, 0xF0, 0x1F, 0x14, 0xEB, 0x6A, + 0x57, 0xCE, 0x78, 0xAD, 0xCE, 0xD9, 0xFB, 0xB9, 0xA1, 0xEF, 0x0C, 0x1F, + 0xDD, 0xE3, 0x5B, 0x73, 0xA0, 0xEC, 0x37, 0x9C, 0xE1, 0xFD, 0x86, 0x28, + 0xC3, 0x4A, 0x42, 0xD0, 0xA3, 0xFE, 0x57, 0x09, 0x29, 0xD8, 0xF6, 0xEC, + 0xE3, 0xC0, 0x71, 0x7C, 0x29, 0x27, 0xC2, 0xD1, 0x3E, 0x22, 0xBC, 0xBD, + 0x5A, 0x85, 0x41, 0xF6, 0x15, 0xDA, 0x0C, 0x58, 0x5A, 0x61, 0x5B, 0x78, + 0xB8, 0xAA, 0xEC, 0x5C, 0x1C, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x82, 0x01, 0x00, 0x1D, 0x10, 0x31, 0xE0, 0x14, 0x26, 0x36, 0xD9, 0xDC, + 0xEA, 0x25, 0x70, 0xF2, 0xB3, 0xFF, 0xDD, 0x0D, 0xDF, 0xBA, 0x57, 0xDA, + 0x43, 0xCF, 0xE5, 0x9C, 0xE3, 0x2F, 0xA4, 0xF2, 0x53, 0xF6, 0xF2, 0xAF, + 0xFD, 0xD0, 0xFC, 0x82, 0x1E, 0x9C, 0x0F, 0x2A, 0x53, 0xBB, 0xF2, 0x4F, + 0x90, 0x83, 0x01, 0xD3, 0xA7, 0xDA, 0xB5, 0xB7, 0x80, 0x64, 0x0A, 0x26, + 0x59, 0x83, 0xE4, 0xD3, 0x20, 0xC8, 0x2D, 0xC9, 0x77, 0xA3, 0x55, 0x07, + 0x6E, 0x6D, 0x95, 0x36, 0xAA, 0x84, 0x4F, 0xED, 0x54, 0x24, 0xA9, 0x77, + 0xF8, 0x85, 0xE2, 0x4B, 0xF2, 0xFA, 0x0B, 0x3E, 0xA6, 0xF5, 0x46, 0x0D, + 0x9F, 0x1F, 0xFE, 0xF7, 0x37, 0xFF, 0xA3, 0x60, 0xF1, 0x63, 0xF2, 0x75, + 0x6A, 0x8E, 0x10, 0xD7, 0x89, 0xD2, 0xB3, 0xFF, 0x76, 0xA5, 0xBA, 0xAF, + 0x0A, 0xBE, 0x32, 0x5F, 0xF0, 0x48, 0x48, 0x4B, 0x9C, 0x9A, 0x3D, 0x12, + 0xA7, 0xD2, 0x07, 0xC7, 0x59, 0x32, 0x94, 0x95, 0x65, 0x2F, 0x87, 0x34, + 0x76, 0xBA, 0x7C, 0x08, 0x4B, 0xAB, 0xA6, 0x24, 0xDF, 0x64, 0xDB, 0x48, + 0x63, 0x42, 0x06, 0xE2, 0x2C, 0x3D, 0xFB, 0xE5, 0x47, 0x81, 0x94, 0x98, + 0xF7, 0x32, 0x4B, 0x28, 0xEB, 0x42, 0xB8, 0xE9, 0x8E, 0xFC, 0xC9, 0x43, + 0xC9, 0x47, 0xE6, 0xE7, 0x1C, 0xDC, 0x71, 0xEF, 0x4D, 0x8A, 0xB1, 0xFC, + 0x45, 0x37, 0xEC, 0xB3, 0x16, 0x88, 0x5B, 0xE2, 0xEC, 0x8B, 0x6B, 0x75, + 0x16, 0xBE, 0x6B, 0xF8, 0x2C, 0xF8, 0xC9, 0xD1, 0xF7, 0x55, 0x87, 0x57, + 0x5F, 0xDE, 0xF4, 0x7E, 0x72, 0x13, 0x06, 0x2A, 0x21, 0xB7, 0x78, 0x21, + 0x05, 0xFD, 0xE2, 0x5F, 0x7B, 0x7C, 0xF0, 0x26, 0x2B, 0x75, 0x7F, 0x68, + 0xF9, 0xA6, 0x98, 0xFD, 0x54, 0x0E, 0xCC, 0x22, 0x41, 0x7F, 0x29, 0x81, + 0x2F, 0xA3, 0x3C, 0x3D, 0x64, 0xC8, 0x41, 0x02, 0x81, 0x81, 0x00, 0xFA, + 0xFA, 0xE4, 0x2E, 0x30, 0xF0, 0x7A, 0x8D, 0x95, 0xB8, 0x39, 0x58, 0x27, + 0x0F, 0x89, 0x0C, 0xDF, 0xFE, 0x2F, 0x55, 0x3B, 0x6F, 0xDD, 0x5F, 0x12, + 0xB3, 0xD1, 0xCF, 0x5B, 0x8D, 0xB6, 0x10, 0x1C, 0x87, 0x0C, 0x30, 0x89, + 0x2D, 0xBB, 0xB8, 0xA1, 0x78, 0x0F, 0x54, 0xA6, 0x36, 0x46, 0x05, 0x8B, + 0x5A, 0xFF, 0x48, 0x03, 0x13, 0xAE, 0x95, 0x96, 0x5D, 0x6C, 0xDA, 0x5D, + 0xF7, 0xAD, 0x1D, 0x33, 0xED, 0x23, 0xF5, 0x4B, 0x03, 0x78, 0xE7, 0x50, + 0xD1, 0x2D, 0x95, 0x22, 0x35, 0x02, 0x5B, 0x4A, 0x4E, 0x73, 0xC9, 0xB7, + 0x05, 0xC4, 0x21, 0x86, 0x1F, 0x1E, 0x40, 0x83, 0xBC, 0x8A, 0x3A, 0x95, + 0x24, 0x62, 0xF4, 0x58, 0x38, 0x64, 0x4A, 0x89, 0x8A, 0x27, 0x59, 0x12, + 0x9D, 0x21, 0xC3, 0xA6, 0x42, 0x1E, 0x2A, 0x3F, 0xD8, 0x65, 0x1F, 0x6E, + 0x3E, 0x4D, 0x5C, 0xCC, 0xEA, 0x8E, 0x15, 0x02, 0x81, 0x81, 0x00, 0xDC, + 0xAC, 0x9B, 0x00, 0xDB, 0xF9, 0xB2, 0xBF, 0xC4, 0x5E, 0xB6, 0xB7, 0x63, + 0xEB, 0x13, 0x4B, 0xE2, 0xA6, 0xC8, 0x72, 0x90, 0xD8, 0xC2, 0x33, 0x33, + 0xF0, 0x66, 0x75, 0xBD, 0x50, 0x7C, 0xA4, 0x8F, 0x82, 0xFB, 0xFF, 0x44, + 0x3B, 0xE7, 0x15, 0x3A, 0x0C, 0x7A, 0xF8, 0x92, 0x86, 0x4A, 0x79, 0x32, + 0x08, 0x82, 0x1D, 0x6A, 0xBA, 0xAD, 0x8A, 0xB3, 0x3D, 0x7F, 0xA5, 0xB4, + 0x6F, 0x67, 0x86, 0x7E, 0xB2, 0x9C, 0x2A, 0xF6, 0x7C, 0x49, 0x21, 0xC5, + 0x3F, 0x00, 0x3F, 0x9B, 0xF7, 0x0F, 0x6C, 0x35, 0x80, 0x75, 0x73, 0xC0, + 0xF8, 0x3E, 0x30, 0x5F, 0x74, 0x2F, 0x15, 0x41, 0xEA, 0x0F, 0xCE, 0x0E, + 0x18, 0x17, 0x68, 0xBA, 0xC4, 0x29, 0xF2, 0xE2, 0x2C, 0x1D, 0x55, 0x83, + 0xB6, 0x64, 0x2E, 0x03, 0x12, 0xA4, 0x0D, 0xBF, 0x4F, 0x2E, 0xBE, 0x7C, + 0x41, 0xD9, 0xCD, 0xD0, 0x52, 0x91, 0xD5, 0x02, 0x81, 0x81, 0x00, 0xD4, + 0x55, 0xEB, 0x32, 0xC1, 0x28, 0xD3, 0x26, 0x72, 0x22, 0xB8, 0x31, 0x42, + 0x6A, 0xBC, 0x52, 0x6E, 0x37, 0x48, 0xA8, 0x5D, 0x6E, 0xD8, 0xE5, 0x14, + 0x97, 0x99, 0xCC, 0x4A, 0xF2, 0xEB, 0xB3, 0x59, 0xCF, 0x4F, 0x9A, 0xC8, + 0x94, 0x2E, 0x9B, 0x97, 0xD0, 0x51, 0x78, 0x16, 0x5F, 0x18, 0x82, 0x9C, + 0x51, 0xD2, 0x64, 0x84, 0x65, 0xE4, 0x70, 0x9E, 0x14, 0x50, 0x81, 0xB6, + 0xBA, 0x52, 0x75, 0xC0, 0x76, 0xC2, 0xD3, 0x46, 0x31, 0x9B, 0xDA, 0x67, + 0xDF, 0x71, 0x27, 0x19, 0x17, 0xAB, 0xF4, 0xBC, 0x3A, 0xFF, 0x6F, 0x0B, + 0x2F, 0x0F, 0xAE, 0x25, 0x20, 0xB2, 0xA1, 0x76, 0x52, 0xCE, 0xC7, 0x9D, + 0x62, 0x79, 0x6D, 0xAC, 0x2D, 0x99, 0x7C, 0x0E, 0x3D, 0x19, 0xE9, 0x1B, + 0xFC, 0x60, 0x92, 0x7C, 0x58, 0xB7, 0xD8, 0x9A, 0xC7, 0x63, 0x56, 0x62, + 0x18, 0xC7, 0xAE, 0xD9, 0x97, 0x1F, 0xB9, 0x02, 0x81, 0x81, 0x00, 0x91, + 0x40, 0xC4, 0x1E, 0x82, 0xAD, 0x0F, 0x6D, 0x8E, 0xD2, 0x51, 0x2E, 0xD1, + 0x84, 0x30, 0x85, 0x68, 0xC1, 0x23, 0x7B, 0xD5, 0xBF, 0xF7, 0xC4, 0x40, + 0x51, 0xE2, 0xFF, 0x69, 0x07, 0x8B, 0xA3, 0xBE, 0x1B, 0x17, 0xC8, 0x64, + 0x9F, 0x91, 0x71, 0xB5, 0x6D, 0xF5, 0x9B, 0x9C, 0xC6, 0xEC, 0x4A, 0x6E, + 0x16, 0x8F, 0x9E, 0xD1, 0x5B, 0xE3, 0x53, 0x42, 0xBC, 0x1E, 0x43, 0x72, + 0x4B, 0x4A, 0x37, 0x8B, 0x3A, 0x01, 0xF5, 0x7D, 0x9D, 0x3D, 0x7E, 0x0F, + 0x19, 0x73, 0x0E, 0x6B, 0x98, 0xE9, 0xFB, 0xEE, 0x13, 0x8A, 0x3C, 0x11, + 0x2E, 0xD5, 0xB0, 0x7D, 0x84, 0x3A, 0x61, 0xA1, 0xAB, 0x71, 0x8F, 0xCE, + 0x53, 0x29, 0x45, 0x74, 0x7A, 0x1E, 0xAA, 0x93, 0x19, 0x3A, 0x8D, 0xC9, + 0x4E, 0xCB, 0x0E, 0x46, 0x53, 0x84, 0xCC, 0xCF, 0xBA, 0x4D, 0x28, 0x71, + 0x1D, 0xDF, 0x41, 0xCB, 0xF8, 0x2D, 0xA9, 0x02, 0x81, 0x80, 0x04, 0x8B, + 0x4A, 0xEA, 0xBD, 0x39, 0x0B, 0x96, 0xC5, 0x1D, 0xA4, 0x47, 0xFD, 0x46, + 0xD2, 0x8A, 0xEA, 0x2A, 0xF3, 0x9D, 0x3A, 0x7E, 0x16, 0x74, 0xFC, 0x13, + 0xDE, 0x4D, 0xA9, 0x85, 0x42, 0x33, 0x02, 0x92, 0x0B, 0xB6, 0xDB, 0x7E, + 0xEA, 0x85, 0xC2, 0x94, 0x43, 0x52, 0x37, 0x5A, 0x77, 0xAB, 0xCB, 0x61, + 0x88, 0xDE, 0xF8, 0xFA, 0xDB, 0xE8, 0x0B, 0x95, 0x7D, 0x39, 0x19, 0xA2, + 0x89, 0xB9, 0x32, 0xB2, 0x50, 0x38, 0xF7, 0x88, 0x69, 0xFD, 0xA4, 0x63, + 0x1F, 0x9B, 0x03, 0xD8, 0xA6, 0x7A, 0x05, 0x76, 0x02, 0x28, 0x93, 0x82, + 0x73, 0x7F, 0x14, 0xCC, 0xBE, 0x29, 0x10, 0xAD, 0x8A, 0x2E, 0xAC, 0xED, + 0x11, 0xA7, 0x72, 0x7C, 0x60, 0x78, 0x72, 0xFB, 0x78, 0x20, 0x18, 0xC9, + 0x7E, 0x63, 0xAD, 0x55, 0x54, 0x51, 0xDB, 0x9F, 0x7B, 0xD4, 0x8F, 0xB2, + 0xDE, 0x3B, 0xF1, 0x70, 0x23, 0xE5, +}; + +/* + * DER-encoded PKCS#8 format EC key. Generated using: + * + * openssl ecparam -name prime256v1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -outform der | recode ../x1 + */ +static uint8_t TEST_EC_KEY_1[] = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x25, 0xAC, 0x77, 0x2B, 0x04, 0x33, 0xC8, 0x16, 0x59, 0xA3, 0xC7, 0xE7, + 0x11, 0x42, 0xD0, 0x11, 0x71, 0x30, 0x7B, 0xB8, 0xD2, 0x67, 0xFF, 0x9C, + 0x5F, 0x50, 0x2E, 0xAB, 0x67, 0xD4, 0x17, 0x51, 0xA1, 0x44, 0x03, 0x42, + 0x00, 0x04, 0xCF, 0xCE, 0xB8, 0x7F, 0x88, 0x36, 0xC4, 0xF8, 0x51, 0x29, + 0xE2, 0xA7, 0x21, 0xC3, 0x3B, 0xFF, 0x88, 0xE3, 0x87, 0x98, 0xD1, 0xA6, + 0x4B, 0xB3, 0x4B, 0xD5, 0x44, 0xF8, 0xE0, 0x43, 0x6B, 0x50, 0x74, 0xFB, + 0xB0, 0xAD, 0x41, 0x1C, 0x11, 0x9D, 0xC6, 0x1E, 0x83, 0x8C, 0x49, 0xCA, + 0xBE, 0xC6, 0xCE, 0xB6, 0xC9, 0xA1, 0xBF, 0x69, 0xA9, 0xA0, 0xA3, 0x80, + 0x14, 0x39, 0x57, 0x94, 0xDA, 0x5D +}; + + +/* + * Generated using keys on the keyboard and lack of imagination. + */ +static unsigned char BOGUS_KEY_1[] = { 0xFF, 0xFF, 0xFF, 0xFF }; + + +class KeymasterBaseTest : public ::testing::Test { +public: + static void SetUpTestCase() { + const hw_module_t* mod; + ASSERT_EQ(0, hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod)) + << "Should be able to find a keymaster hardware module"; + + std::cout << "Using keymaster module: " << mod->name << std::endl; + + ASSERT_EQ(0, keymaster0_open(mod, &sDevice)) + << "Should be able to open the keymaster device"; + + ASSERT_EQ(KEYMASTER_MODULE_API_VERSION_0_2, mod->module_api_version) + << "Keymaster should implement API version 2"; + + ASSERT_TRUE(sDevice->generate_keypair != NULL) + << "Should implement generate_keypair"; + + ASSERT_TRUE(sDevice->import_keypair != NULL) + << "Should implement import_keypair"; + + ASSERT_TRUE(sDevice->get_keypair_public != NULL) + << "Should implement get_keypair_public"; + + ASSERT_TRUE(sDevice->sign_data != NULL) + << "Should implement sign_data"; + + ASSERT_TRUE(sDevice->verify_data != NULL) + << "Should implement verify_data"; + } + + static void TearDownTestCase() { + ASSERT_EQ(0, keymaster0_close(sDevice)); + } + +protected: + static keymaster0_device_t* sDevice; +}; + +keymaster0_device_t* KeymasterBaseTest::sDevice = NULL; + +class KeymasterTest : public KeymasterBaseTest { +}; + +class KeymasterAllTypesTest : public KeymasterBaseTest, + public ::testing::WithParamInterface<keymaster_keypair_t> { +}; + +class KeymasterGenerateRSATest : public KeymasterBaseTest, + public ::testing::WithParamInterface<uint32_t> { +}; + +class KeymasterGenerateDSATest : public KeymasterBaseTest, + public ::testing::WithParamInterface<uint32_t> { +}; + +class KeymasterGenerateECTest : public KeymasterBaseTest, + public ::testing::WithParamInterface<uint32_t> { +}; + +TEST_P(KeymasterGenerateRSATest, GenerateKeyPair_RSA_Success) { + keymaster_keypair_t key_type = TYPE_RSA; + keymaster_rsa_keygen_params_t params = { + .modulus_size = GetParam(), + .public_exponent = RSA_F4, + }; + + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(0, + sDevice->generate_keypair(sDevice, key_type, ¶ms, &key_blob, &key_blob_length)) + << "Should generate an RSA key with " << GetParam() << " bit modulus size"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + uint8_t* x509_data = NULL; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve RSA public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); + ASSERT_FALSE(x509_blob.get() == NULL) + << "X509 data should be allocated"; + + const unsigned char *tmp = static_cast<const unsigned char*>(x509_blob.get()); + Unique_EVP_PKEY actual(d2i_PUBKEY((EVP_PKEY**) NULL, &tmp, + static_cast<long>(x509_blob.length()))); + + ASSERT_EQ(EVP_PKEY_RSA, EVP_PKEY_type(actual.get()->type)) + << "Generated key type should be of type RSA"; + + Unique_RSA rsa(EVP_PKEY_get1_RSA(actual.get())); + ASSERT_FALSE(rsa.get() == NULL) + << "Should be able to extract RSA key from EVP_PKEY"; + + ASSERT_EQ(static_cast<unsigned long>(RSA_F4), BN_get_word(rsa.get()->e)) + << "Exponent should be RSA_F4"; + + ASSERT_EQ((GetParam() + 7) / 8, static_cast<uint32_t>(RSA_size(rsa.get()))) + << "Modulus size should be the specified parameter"; +} + +INSTANTIATE_TEST_CASE_P(RSA, + KeymasterGenerateRSATest, + ::testing::Values(512U, 1024U, 2048U, 3072U, 4096U)); + + +TEST_P(KeymasterGenerateECTest, GenerateKeyPair_EC_Success) { + keymaster_keypair_t key_type = TYPE_EC; + keymaster_ec_keygen_params_t params = { + .field_size = GetParam(), + }; + + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(0, + sDevice->generate_keypair(sDevice, key_type, ¶ms, &key_blob, &key_blob_length)) + << "Should generate an EC key with " << GetParam() << " field size"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + uint8_t* x509_data = NULL; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve EC public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); + ASSERT_FALSE(x509_blob.get() == NULL) + << "X509 data should be allocated"; + + const unsigned char *tmp = static_cast<const unsigned char*>(x509_blob.get()); + Unique_EVP_PKEY actual(d2i_PUBKEY((EVP_PKEY**) NULL, &tmp, + static_cast<long>(x509_blob.length()))); + + ASSERT_EQ(EVP_PKEY_EC, EVP_PKEY_type(actual.get()->type)) + << "Generated key type should be of type EC"; + + Unique_EC_KEY ecKey(EVP_PKEY_get1_EC_KEY(actual.get())); + ASSERT_FALSE(ecKey.get() == NULL) + << "Should be able to extract EC key from EVP_PKEY"; + + ASSERT_FALSE(EC_KEY_get0_group(ecKey.get()) == NULL) + << "EC key should have a EC_GROUP"; + + ASSERT_TRUE(EC_KEY_check_key(ecKey.get())) + << "EC key should check correctly"; +} + +INSTANTIATE_TEST_CASE_P(EC, + KeymasterGenerateECTest, + ::testing::Values(192U, 224U, 256U, 384U, 521U)); + + +TEST_P(KeymasterAllTypesTest, GenerateKeyPair_NullParams_Failure) { + keymaster_keypair_t key_type = GetParam(); + + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(-1, + sDevice->generate_keypair(sDevice, key_type, NULL, &key_blob, &key_blob_length)) + << "Should not be able to generate a key with null params"; +} + +INSTANTIATE_TEST_CASE_P(Types, + KeymasterAllTypesTest, + ::testing::Values(TYPE_RSA, TYPE_DSA, TYPE_EC)); + +TEST_F(KeymasterTest, GenerateKeyPair_UnknownType_Failure) { + keymaster_keypair_t key_type = static_cast<keymaster_keypair_t>(0xFFFF); + + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(-1, + sDevice->generate_keypair(sDevice, key_type, NULL, &key_blob, &key_blob_length)) + << "Should not generate an unknown key type"; +} + +TEST_F(KeymasterTest, ImportKeyPair_RSA_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + uint8_t* x509_data; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve RSA public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); + + const unsigned char *tmp = static_cast<const unsigned char*>(x509_blob.get()); + Unique_EVP_PKEY actual(d2i_PUBKEY((EVP_PKEY**) NULL, &tmp, + static_cast<long>(x509_blob.length()))); + + ASSERT_EQ(EVP_PKEY_type(actual.get()->type), EVP_PKEY_RSA) + << "Generated key type should be of type RSA"; + + const unsigned char *expectedTmp = static_cast<const unsigned char*>(TEST_RSA_KEY_1); + Unique_PKCS8_PRIV_KEY_INFO expectedPkcs8( + d2i_PKCS8_PRIV_KEY_INFO((PKCS8_PRIV_KEY_INFO**) NULL, &expectedTmp, + sizeof(TEST_RSA_KEY_1))); + + Unique_EVP_PKEY expected(EVP_PKCS82PKEY(expectedPkcs8.get())); + + ASSERT_EQ(1, EVP_PKEY_cmp(expected.get(), actual.get())) + << "Expected and actual keys should match"; +} + +TEST_F(KeymasterTest, ImportKeyPair_EC_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, TEST_EC_KEY_1, sizeof(TEST_EC_KEY_1), + &key_blob, &key_blob_length)) + << "Should successfully import an EC key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + uint8_t* x509_data; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve EC public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); + + const unsigned char *tmp = static_cast<const unsigned char*>(x509_blob.get()); + Unique_EVP_PKEY actual(d2i_PUBKEY((EVP_PKEY**) NULL, &tmp, + static_cast<long>(x509_blob.length()))); + + ASSERT_EQ(EVP_PKEY_type(actual.get()->type), EVP_PKEY_EC) + << "Generated key type should be of type EC"; + + const unsigned char *expectedTmp = static_cast<const unsigned char*>(TEST_EC_KEY_1); + Unique_PKCS8_PRIV_KEY_INFO expectedPkcs8( + d2i_PKCS8_PRIV_KEY_INFO((PKCS8_PRIV_KEY_INFO**) NULL, &expectedTmp, + sizeof(TEST_EC_KEY_1))); + + Unique_EVP_PKEY expected(EVP_PKCS82PKEY(expectedPkcs8.get())); + + ASSERT_EQ(1, EVP_PKEY_cmp(expected.get(), actual.get())) + << "Expected and actual keys should match"; +} + +TEST_F(KeymasterTest, ImportKeyPair_BogusKey_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(-1, + sDevice->import_keypair(sDevice, BOGUS_KEY_1, sizeof(BOGUS_KEY_1), + &key_blob, &key_blob_length)) + << "Should not import an unknown key type"; +} + +TEST_F(KeymasterTest, ImportKeyPair_NullKey_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(-1, + sDevice->import_keypair(sDevice, NULL, 0, + &key_blob, &key_blob_length)) + << "Should not import a null key"; +} + +TEST_F(KeymasterTest, GetKeypairPublic_RSA_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + uint8_t* x509_data; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve RSA public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); +} + +TEST_F(KeymasterTest, GetKeypairPublic_EC_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_EC_KEY_1, sizeof(TEST_EC_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an EC key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + uint8_t* x509_data; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve EC public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); +} + +TEST_F(KeymasterTest, GetKeypairPublic_NullKey_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + uint8_t* x509_data = NULL; + size_t x509_data_length; + ASSERT_EQ(-1, + sDevice->get_keypair_public(sDevice, NULL, 0, + &x509_data, &x509_data_length)) + << "Should not be able to retrieve public key from null key"; + UniqueBlob x509_blob(x509_data, x509_data_length); +} + +TEST_F(KeymasterTest, GetKeypairPublic_RSA_NullDestination_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + ASSERT_EQ(-1, + sDevice->get_keypair_public(sDevice, key.get(), key.length(), + NULL, NULL)) + << "Should not be able to succeed with NULL destination blob"; +} + +TEST_F(KeymasterTest, GetKeypairPublic_EC_NullDestination_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_EC_KEY_1, sizeof(TEST_EC_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + ASSERT_EQ(-1, + sDevice->get_keypair_public(sDevice, key.get(), key.length(), + NULL, NULL)) + << "Should not be able to succeed with NULL destination blob"; +} + +TEST_F(KeymasterTest, DeleteKeyPair_RSA_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); +} + +TEST_F(KeymasterTest, DeleteKeyPair_RSA_DoubleDelete_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + /* + * This is only run if the module indicates it implements key deletion + * by implementing delete_keypair. + */ + if (sDevice->delete_keypair != NULL) { + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueBlob blob(key_blob, key_blob_length); + + ASSERT_EQ(0, sDevice->delete_keypair(sDevice, key_blob, key_blob_length)) + << "Should delete key after import"; + + ASSERT_EQ(-1, sDevice->delete_keypair(sDevice, key_blob, key_blob_length)) + << "Should not be able to delete key twice"; + } +} + +TEST_F(KeymasterTest, DeleteKeyPair_RSA_NullKey_Failure) { + /* + * This is only run if the module indicates it implements key deletion + * by implementing delete_keypair. + */ + if (sDevice->delete_keypair != NULL) { + ASSERT_EQ(-1, sDevice->delete_keypair(sDevice, NULL, 0)) + << "Should not be able to delete null key"; + } +} + +/* + * DER-encoded PKCS#8 format RSA key. Generated using: + * + * openssl genrsa 512 | openssl pkcs8 -topk8 -nocrypt -outform der | recode ../x1 + */ +static uint8_t TEST_SIGN_RSA_KEY_1[] = { + 0x30, 0x82, 0x01, 0x56, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x01, 0x40, 0x30, 0x82, 0x01, 0x3C, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, + 0xBD, 0xC0, 0x7F, 0xEF, 0x75, 0x1D, 0x63, 0x2A, 0xD0, 0x9A, 0x26, 0xE5, + 0x5B, 0xB9, 0x84, 0x7C, 0xE5, 0xC7, 0xE7, 0xDE, 0xFE, 0xB6, 0x54, 0xD9, + 0xF0, 0x9B, 0xC2, 0xCF, 0x36, 0xDA, 0xE5, 0x4D, 0xC5, 0xD9, 0x25, 0x78, + 0xBD, 0x55, 0x05, 0xBD, 0x86, 0xFB, 0x37, 0x15, 0x33, 0x42, 0x52, 0xED, + 0xE5, 0xCD, 0xCB, 0xB7, 0xA2, 0x51, 0xFA, 0x36, 0xE9, 0x9C, 0x2E, 0x5D, + 0xE3, 0xA5, 0x1F, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x41, 0x00, + 0x96, 0x71, 0xDE, 0xBD, 0x83, 0x94, 0x96, 0x40, 0xA6, 0xFD, 0xE1, 0xA2, + 0xED, 0xD3, 0xAC, 0x28, 0xBE, 0xA2, 0x7D, 0xC3, 0xFF, 0x1D, 0x9F, 0x2E, + 0xE0, 0xA7, 0x0E, 0x90, 0xEE, 0x44, 0x25, 0x92, 0xE3, 0x54, 0xDD, 0x55, + 0xA3, 0xEF, 0x42, 0xF5, 0x52, 0x55, 0x41, 0x47, 0x5E, 0x00, 0xFB, 0x8B, + 0x47, 0x5E, 0x45, 0x49, 0xEA, 0x3D, 0x2C, 0xFD, 0x9F, 0xEC, 0xC8, 0x4E, + 0x4E, 0x86, 0x90, 0x31, 0x02, 0x21, 0x00, 0xE6, 0xA5, 0x55, 0xB3, 0x64, + 0xAB, 0x90, 0x5E, 0xA2, 0xF5, 0x6B, 0x21, 0x4B, 0x15, 0xD6, 0x4A, 0xB6, + 0x60, 0x24, 0x95, 0x65, 0xA2, 0xBE, 0xBA, 0x2A, 0x73, 0xFB, 0xFF, 0x2C, + 0x61, 0x88, 0x9D, 0x02, 0x21, 0x00, 0xD2, 0x9C, 0x5B, 0xFE, 0x82, 0xA5, + 0xFC, 0x52, 0x6A, 0x29, 0x38, 0xDB, 0x22, 0x3B, 0xEB, 0x74, 0x3B, 0xCA, + 0xB4, 0xDD, 0x1D, 0xE4, 0x48, 0x60, 0x70, 0x19, 0x9B, 0x81, 0xC1, 0x83, + 0x28, 0xB5, 0x02, 0x21, 0x00, 0x89, 0x2D, 0xFE, 0xF9, 0xF2, 0xBF, 0x43, + 0xDF, 0xB5, 0xA6, 0xA8, 0x30, 0x26, 0x1B, 0x77, 0xD7, 0xF9, 0xFE, 0xD6, + 0xE3, 0x70, 0x8E, 0xCA, 0x47, 0xA9, 0xA6, 0x50, 0x54, 0x25, 0xCE, 0x60, + 0xD5, 0x02, 0x21, 0x00, 0xBE, 0x5A, 0xF8, 0x82, 0xE6, 0xCE, 0xE3, 0x6A, + 0x11, 0xED, 0xC4, 0x27, 0xBB, 0x9F, 0x70, 0xC6, 0x93, 0xAC, 0x39, 0x20, + 0x89, 0x7D, 0xE5, 0x34, 0xD4, 0xDD, 0x30, 0x42, 0x6D, 0x07, 0x00, 0xE9, + 0x02, 0x20, 0x05, 0x91, 0xEF, 0x12, 0xD2, 0xD3, 0x6A, 0xD2, 0x96, 0x6B, + 0x10, 0x62, 0xF9, 0xBA, 0xA4, 0x91, 0x48, 0x84, 0x40, 0x61, 0x67, 0x80, + 0x68, 0x68, 0xC8, 0x60, 0xB3, 0x66, 0xC8, 0xF9, 0x08, 0x9A, +}; + +/* + * DER-encoded PKCS#8 format EC key. Generated using: + * + * openssl ecparam -name prime256v1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -outform der | recode ../x1 + */ +static uint8_t TEST_SIGN_EC_KEY_1[] = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x9E, 0x66, 0x11, 0x6A, 0x89, 0xF5, 0x78, 0x57, 0xF3, 0x35, 0xA2, 0x46, + 0x09, 0x06, 0x4B, 0x4D, 0x81, 0xEC, 0xD3, 0x9B, 0x0A, 0xC4, 0x68, 0x06, + 0xB8, 0x42, 0x24, 0x5E, 0x74, 0x2C, 0x62, 0x79, 0xA1, 0x44, 0x03, 0x42, + 0x00, 0x04, 0x35, 0xB5, 0x9A, 0x5C, 0xE5, 0x52, 0x35, 0xF2, 0x10, 0x6C, + 0xD9, 0x98, 0x67, 0xED, 0x5E, 0xCB, 0x6B, 0xB8, 0x96, 0x5E, 0x54, 0x7C, + 0x34, 0x2A, 0xA3, 0x3B, 0xF3, 0xD1, 0x39, 0x48, 0x36, 0x7A, 0xEA, 0xD8, + 0xCA, 0xDD, 0x40, 0x8F, 0xE9, 0xE0, 0x95, 0x2E, 0x3F, 0x95, 0x0F, 0x14, + 0xD6, 0x14, 0x78, 0xB5, 0xAD, 0x17, 0xD2, 0x5A, 0x41, 0x96, 0x99, 0x20, + 0xC7, 0x5B, 0x0F, 0x60, 0xFD, 0xBA +}; + +/* + * PKCS#1 v1.5 padded raw "Hello, world" Can be generated be generated by verifying + * the signature below in no padding mode: + * + * openssl rsautl -keyform der -inkey rsa.der -raw -verify -in test.sig + */ +static uint8_t TEST_SIGN_DATA_1[] = { + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x77, + 0x6F, 0x72, 0x6C, 0x64, +}; + +/* + * Signature of TEST_SIGN_DATA_1 using TEST_SIGN_RSA_KEY_1. Generated using: + * + * echo 'Hello, world' | openssl rsautl -keyform der -inkey rsa.der -sign | recode ../x1 + */ +static uint8_t TEST_SIGN_RSA_SIGNATURE_1[] = { + 0xA4, 0xBB, 0x76, 0x87, 0xFE, 0x61, 0x0C, 0x9D, 0xD6, 0xFF, 0x4B, 0x76, + 0x96, 0x08, 0x36, 0x23, 0x11, 0xC6, 0x44, 0x3F, 0x88, 0x77, 0x97, 0xB2, + 0xA8, 0x3B, 0xFB, 0x9C, 0x3C, 0xD3, 0x20, 0x65, 0xFD, 0x26, 0x3B, 0x2A, + 0xB8, 0xB6, 0xD4, 0xDC, 0x91, 0xF7, 0xE2, 0xDE, 0x4D, 0xF7, 0x0E, 0xB9, + 0x72, 0xA7, 0x29, 0x72, 0x82, 0x12, 0x7C, 0x53, 0x23, 0x21, 0xC4, 0xFF, + 0x79, 0xE4, 0x91, 0x40, +}; + +/* + * Identical to TEST_SIGN_RSA_SIGNATURE_1 except the last octet is '1' instead of '0' + * This should fail any test. + */ +static uint8_t TEST_SIGN_SIGNATURE_BOGUS_1[] = { + 0xA4, 0xBB, 0x76, 0x87, 0xFE, 0x61, 0x0C, 0x9D, 0xD6, 0xFF, 0x4B, 0x76, + 0x96, 0x08, 0x36, 0x23, 0x11, 0xC6, 0x44, 0x3F, 0x88, 0x77, 0x97, 0xB2, + 0xA8, 0x3B, 0xFB, 0x9C, 0x3C, 0xD3, 0x20, 0x65, 0xFD, 0x26, 0x3B, 0x2A, + 0xB8, 0xB6, 0xD4, 0xDC, 0x91, 0xF7, 0xE2, 0xDE, 0x4D, 0xF7, 0x0E, 0xB9, + 0x72, 0xA7, 0x29, 0x72, 0x82, 0x12, 0x7C, 0x53, 0x23, 0x21, 0xC4, 0xFF, + 0x79, 0xE4, 0x91, 0x41, +}; + +TEST_F(KeymasterTest, SignData_RSA_Raw_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(0, + sDevice->sign_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + &sig, &sig_length)) + << "Should sign data successfully"; + UniqueBlob sig_blob(sig, sig_length); + + UniqueBlob expected_sig(TEST_SIGN_RSA_SIGNATURE_1, sizeof(TEST_SIGN_RSA_SIGNATURE_1)); + + ASSERT_EQ(expected_sig, sig_blob) + << "Generated signature should match expected signature"; + + // The expected signature is actually stack data, so don't let it try to free. + uint8_t* unused __attribute__((unused)) = expected_sig.release(); +} + +TEST_F(KeymasterTest, SignData_EC_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_EC_KEY_1, sizeof(TEST_SIGN_EC_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an EC key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_ec_sign_params_t params = { + .digest_type = DIGEST_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(0, + sDevice->sign_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + &sig, &sig_length)) + << "Should sign data successfully"; + UniqueBlob sig_blob(sig, sig_length); + + uint8_t* x509_data; + size_t x509_data_length; + ASSERT_EQ(0, + sDevice->get_keypair_public(sDevice, key_blob, key_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve RSA public key successfully"; + UniqueBlob x509_blob(x509_data, x509_data_length); + + const unsigned char *tmp = static_cast<const unsigned char*>(x509_blob.get()); + Unique_EVP_PKEY expected(d2i_PUBKEY((EVP_PKEY**) NULL, &tmp, + static_cast<long>(x509_blob.length()))); + + Unique_EC_KEY ecKey(EVP_PKEY_get1_EC_KEY(expected.get())); + + ASSERT_EQ(1, ECDSA_verify(0, testData.get(), testData.length(), sig_blob.get(), sig_blob.length(), ecKey.get())) + << "Signature should verify"; +} + +TEST_F(KeymasterTest, SignData_RSA_Raw_InvalidSizeInput_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + UniqueReadOnlyBlob testData(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(-1, + sDevice->sign_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + &sig, &sig_length)) + << "Should not be able to do raw signature on incorrect size data"; +} + +TEST_F(KeymasterTest, SignData_RSA_Raw_NullKey_Failure) { + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + UniqueReadOnlyBlob testData(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(-1, + sDevice->sign_data(sDevice, ¶ms, NULL, 0, + testData.get(), testData.length(), + &sig, &sig_length)) + << "Should not be able to do raw signature on incorrect size data"; +} + +TEST_F(KeymasterTest, SignData_RSA_Raw_NullInput_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + ASSERT_EQ(-1, + sDevice->sign_data(sDevice, ¶ms, key_blob, key_blob_length, + NULL, 0, + &sig, &sig_length)) + << "Should error when input data is null"; +} + +TEST_F(KeymasterTest, SignData_RSA_Raw_NullOutput_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + UniqueReadOnlyBlob testData(TEST_RSA_KEY_1, sizeof(TEST_RSA_KEY_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(-1, + sDevice->sign_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + NULL, NULL)) + << "Should error when output is null"; +} + +TEST_F(KeymasterTest, VerifyData_RSA_Raw_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1)); + ASSERT_TRUE(testData.get() != NULL); + + UniqueReadOnlyBlob testSig(TEST_SIGN_RSA_SIGNATURE_1, sizeof(TEST_SIGN_RSA_SIGNATURE_1)); + ASSERT_TRUE(testSig.get() != NULL); + + ASSERT_EQ(0, + sDevice->verify_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + testSig.get(), testSig.length())) + << "Should verify data successfully"; +} + +TEST_F(KeymasterTest, VerifyData_EC_Raw_Success) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_EC_KEY_1, sizeof(TEST_SIGN_EC_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_ec_sign_params_t params = { + .digest_type = DIGEST_NONE, + }; + + uint8_t* sig; + size_t sig_length; + + UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(0, + sDevice->sign_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + &sig, &sig_length)) + << "Should sign data successfully"; + UniqueBlob sig_blob(sig, sig_length); + + ASSERT_EQ(0, + sDevice->verify_data(sDevice, ¶ms, key_blob, key_blob_length, + testData.get(), testData.length(), + sig_blob.get(), sig_blob.length())) + << "Should verify data successfully"; +} + +TEST_F(KeymasterTest, VerifyData_RSA_Raw_BadSignature_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + ASSERT_EQ(-1, + sDevice->verify_data(sDevice, ¶ms, key_blob, key_blob_length, + TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1), + TEST_SIGN_SIGNATURE_BOGUS_1, sizeof(TEST_SIGN_SIGNATURE_BOGUS_1))) + << "Should sign data successfully"; +} + +TEST_F(KeymasterTest, VerifyData_EC_Raw_BadSignature_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_EC_KEY_1, sizeof(TEST_SIGN_EC_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_ec_sign_params_t params = { + .digest_type = DIGEST_NONE, + }; + + ASSERT_EQ(-1, + sDevice->verify_data(sDevice, ¶ms, key_blob, key_blob_length, + TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1), + TEST_SIGN_SIGNATURE_BOGUS_1, sizeof(TEST_SIGN_SIGNATURE_BOGUS_1))) + << "Should sign data successfully"; +} + +TEST_F(KeymasterTest, VerifyData_RSA_Raw_NullKey_Failure) { + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1)); + ASSERT_TRUE(testData.get() != NULL); + + UniqueReadOnlyBlob testSig(TEST_SIGN_SIGNATURE_BOGUS_1, sizeof(TEST_SIGN_SIGNATURE_BOGUS_1)); + ASSERT_TRUE(testSig.get() != NULL); + + ASSERT_EQ(-1, + sDevice->verify_data(sDevice, ¶ms, NULL, 0, + testData.get(), testData.length(), + testSig.get(), testSig.length())) + << "Should fail when key is null"; +} + +TEST_F(KeymasterTest, VerifyData_RSA_NullInput_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + UniqueReadOnlyBlob testSig(TEST_SIGN_RSA_SIGNATURE_1, sizeof(TEST_SIGN_RSA_SIGNATURE_1)); + ASSERT_TRUE(testSig.get() != NULL); + + ASSERT_EQ(-1, + sDevice->verify_data(sDevice, ¶ms, key_blob, key_blob_length, + NULL, 0, + testSig.get(), testSig.length())) + << "Should fail on null input"; +} + +TEST_F(KeymasterTest, VerifyData_RSA_NullSignature_Failure) { + uint8_t* key_blob; + size_t key_blob_length; + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key_blob, &key_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key(&sDevice, key_blob, key_blob_length); + + keymaster_rsa_sign_params_t params = { + .digest_type = DIGEST_NONE, + .padding_type = PADDING_NONE, + }; + + UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1)); + ASSERT_TRUE(testData.get() != NULL); + + ASSERT_EQ(-1, + sDevice->verify_data(sDevice, ¶ms, key.get(), key.length(), + testData.get(), testData.length(), + NULL, 0)) + << "Should fail on null signature"; +} + +TEST_F(KeymasterTest, EraseAll_Success) { + uint8_t *key1_blob, *key2_blob; + size_t key1_blob_length, key2_blob_length; + + // Only test this if the device says it supports delete_all + if (sDevice->delete_all == NULL) { + return; + } + + UniqueReadOnlyBlob testKey(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey.get(), testKey.length(), + &key1_blob, &key1_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key1(&sDevice, key1_blob, key1_blob_length); + + UniqueReadOnlyBlob testKey2(TEST_SIGN_RSA_KEY_1, sizeof(TEST_SIGN_RSA_KEY_1)); + ASSERT_TRUE(testKey2.get() != NULL); + + ASSERT_EQ(0, + sDevice->import_keypair(sDevice, testKey2.get(), testKey2.length(), + &key2_blob, &key2_blob_length)) + << "Should successfully import an RSA key"; + UniqueKey key2(&sDevice, key2_blob, key2_blob_length); + + ASSERT_EQ(0, sDevice->delete_all(sDevice)) + << "Should erase all keys"; + + key1.reset(); + + uint8_t* x509_data; + size_t x509_data_length; + ASSERT_EQ(-1, + sDevice->get_keypair_public(sDevice, key1_blob, key1_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve RSA public key 1 successfully"; + + ASSERT_EQ(-1, + sDevice->get_keypair_public(sDevice, key2_blob, key2_blob_length, + &x509_data, &x509_data_length)) + << "Should be able to retrieve RSA public key 2 successfully"; +} + +}
diff --git a/libhardware/tests/nusensors/Android.bp b/libhardware/tests/nusensors/Android.bp new file mode 100644 index 0000000..e923468 --- /dev/null +++ b/libhardware/tests/nusensors/Android.bp
@@ -0,0 +1,10 @@ +cc_binary { + name: "test-nusensors", + + srcs: ["nusensors.cpp"], + + shared_libs: [ + "libcutils", + "libhardware", + ], +}
diff --git a/libhardware/tests/nusensors/nusensors.cpp b/libhardware/tests/nusensors/nusensors.cpp new file mode 100644 index 0000000..55b7785 --- /dev/null +++ b/libhardware/tests/nusensors/nusensors.cpp
@@ -0,0 +1,195 @@ +/* + * Copyright (C) 2008 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 <inttypes.h> +#include <string.h> +#include <stdint.h> +#include <string.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <cutils/log.h> + +#include <hardware/sensors.h> +#include <utils/Timers.h> + +char const* getSensorName(int type) { + switch(type) { + case SENSOR_TYPE_ACCELEROMETER: + return "Acc"; + case SENSOR_TYPE_MAGNETIC_FIELD: + return "Mag"; + case SENSOR_TYPE_ORIENTATION: + return "Ori"; + case SENSOR_TYPE_GYROSCOPE: + return "Gyr"; + case SENSOR_TYPE_LIGHT: + return "Lux"; + case SENSOR_TYPE_PRESSURE: + return "Bar"; + case SENSOR_TYPE_TEMPERATURE: + return "Tmp"; + case SENSOR_TYPE_PROXIMITY: + return "Prx"; + case SENSOR_TYPE_GRAVITY: + return "Grv"; + case SENSOR_TYPE_LINEAR_ACCELERATION: + return "Lac"; + case SENSOR_TYPE_ROTATION_VECTOR: + return "Rot"; + case SENSOR_TYPE_RELATIVE_HUMIDITY: + return "Hum"; + case SENSOR_TYPE_AMBIENT_TEMPERATURE: + return "Tam"; + } + return "ukn"; +} + +int main(int /* argc */, char** /* argv */) +{ + int err; + struct sensors_poll_device_t* device; + struct sensors_module_t* module; + + err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); + if (err != 0) { + printf("hw_get_module() failed (%s)\n", strerror(-err)); + return 0; + } + + err = sensors_open(&module->common, &device); + if (err != 0) { + printf("sensors_open() failed (%s)\n", strerror(-err)); + return 0; + } + + struct sensor_t const* list; + int count = module->get_sensors_list(module, &list); + printf("%d sensors found:\n", count); + for (int i=0 ; i<count ; i++) { + printf("%s\n" + "\tvendor: %s\n" + "\tversion: %d\n" + "\thandle: %d\n" + "\ttype: %d\n" + "\tmaxRange: %f\n" + "\tresolution: %f\n" + "\tpower: %f mA\n", + list[i].name, + list[i].vendor, + list[i].version, + list[i].handle, + list[i].type, + list[i].maxRange, + list[i].resolution, + list[i].power); + } + + static const size_t numEvents = 16; + sensors_event_t buffer[numEvents]; + + for (int i=0 ; i<count ; i++) { + err = device->activate(device, list[i].handle, 0); + if (err != 0) { + printf("deactivate() for '%s'failed (%s)\n", + list[i].name, strerror(-err)); + return 0; + } + } + + for (int i=0 ; i<count ; i++) { + err = device->activate(device, list[i].handle, 1); + if (err != 0) { + printf("activate() for '%s'failed (%s)\n", + list[i].name, strerror(-err)); + return 0; + } + device->setDelay(device, list[i].handle, ms2ns(10)); + } + + do { + int n = device->poll(device, buffer, numEvents); + if (n < 0) { + printf("poll() failed (%s)\n", strerror(-err)); + break; + } + + printf("read %d events:\n", n); + for (int i=0 ; i<n ; i++) { + const sensors_event_t& data = buffer[i]; + + if (data.version != sizeof(sensors_event_t)) { + printf("incorrect event version (version=%d, expected=%zu", + data.version, sizeof(sensors_event_t)); + break; + } + + switch(data.type) { + case SENSOR_TYPE_ACCELEROMETER: + case SENSOR_TYPE_MAGNETIC_FIELD: + case SENSOR_TYPE_ORIENTATION: + case SENSOR_TYPE_GYROSCOPE: + case SENSOR_TYPE_GRAVITY: + case SENSOR_TYPE_LINEAR_ACCELERATION: + case SENSOR_TYPE_ROTATION_VECTOR: + printf("sensor=%s, time=%" PRId64 ", value=<%5.1f,%5.1f,%5.1f>\n", + getSensorName(data.type), + data.timestamp, + data.data[0], + data.data[1], + data.data[2]); + break; + + case SENSOR_TYPE_LIGHT: + case SENSOR_TYPE_PRESSURE: + case SENSOR_TYPE_TEMPERATURE: + case SENSOR_TYPE_PROXIMITY: + case SENSOR_TYPE_RELATIVE_HUMIDITY: + case SENSOR_TYPE_AMBIENT_TEMPERATURE: + printf("sensor=%s, time=%" PRId64 ", value=%f\n", + getSensorName(data.type), + data.timestamp, + data.data[0]); + break; + + default: + printf("sensor=%d, time=% " PRId64 ", value=<%f,%f,%f, ...>\n", + data.type, + data.timestamp, + data.data[0], + data.data[1], + data.data[2]); + break; + } + } + } while (1); // fix that + + + for (int i=0 ; i<count ; i++) { + err = device->activate(device, list[i].handle, 0); + if (err != 0) { + printf("deactivate() for '%s'failed (%s)\n", + list[i].name, strerror(-err)); + return 0; + } + } + + err = sensors_close(device); + if (err != 0) { + printf("sensors_close() failed (%s)\n", strerror(-err)); + } + return 0; +}