OSDN Git Service

Add guest mode functionality (1/3) am: 4e10135ef4 am: 6e98ba09a2 am: 4137555a77 am...
authorAjay Panicker <apanicke@google.com>
Tue, 24 May 2016 22:25:29 +0000 (22:25 +0000)
committerandroid-build-merger <android-build-merger@google.com>
Tue, 24 May 2016 22:25:29 +0000 (22:25 +0000)
am: 2fc4aebcdd

* commit '2fc4aebcdd48084125645340e5baeefc46f4c6a6':
  Add guest mode functionality (1/3)

Change-Id: I33613e8d89b198dbda2bc37bcbf25e355bedb201

99 files changed:
hardware.c
include/hardware/activity_recognition.h
include/hardware/audio.h
include/hardware/audio_policy.h
include/hardware/bluetooth.h
include/hardware/boot_control.h [new file with mode: 0644]
include/hardware/bt_av.h
include/hardware/bt_common_types.h
include/hardware/bt_gatt_client.h
include/hardware/bt_rc.h
include/hardware/bt_sock.h
include/hardware/camera2.h
include/hardware/camera3.h
include/hardware/camera_common.h
include/hardware/context_hub.h [new file with mode: 0644]
include/hardware/fingerprint.h
include/hardware/gps.h
include/hardware/gps_internal.h [new file with mode: 0644]
include/hardware/hwcomposer.h
include/hardware/hwcomposer2.h [new file with mode: 0644]
include/hardware/hwcomposer_defs.h
include/hardware/input.h
include/hardware/keymaster2.h [new file with mode: 0644]
include/hardware/keymaster_common.h
include/hardware/keymaster_defs.h
include/hardware/lights.h
include/hardware/nvram.h [new file with mode: 0644]
include/hardware/power.h
include/hardware/sensors.h
include/hardware/sound_trigger.h
include/hardware/thermal.h [new file with mode: 0644]
include/hardware/vehicle.h [new file with mode: 0644]
include/hardware/vehicle_camera.h [new file with mode: 0644]
include/hardware/vibrator.h
include/hardware/vr.h [new file with mode: 0644]
modules/Android.mk
modules/audio_remote_submix/audio_hw.cpp
modules/camera/Metadata.cpp
modules/gralloc/framebuffer.cpp
modules/gralloc/gralloc.cpp
modules/input/evdev/Android.mk
modules/input/evdev/BitUtils.cpp [new file with mode: 0644]
modules/input/evdev/BitUtils.h [new file with mode: 0644]
modules/input/evdev/EvdevModule.cpp
modules/input/evdev/InputDevice.cpp
modules/input/evdev/InputDevice.h
modules/input/evdev/InputDeviceManager.cpp
modules/input/evdev/InputDeviceManager.h
modules/input/evdev/InputHost.cpp
modules/input/evdev/InputHost.h
modules/input/evdev/InputHub.cpp
modules/input/evdev/InputHub.h
modules/input/evdev/InputMapper.cpp [new file with mode: 0644]
modules/input/evdev/InputMapper.h [new file with mode: 0644]
modules/input/evdev/MouseInputMapper.cpp [new file with mode: 0644]
modules/input/evdev/MouseInputMapper.h [new file with mode: 0644]
modules/input/evdev/SwitchInputMapper.cpp [new file with mode: 0644]
modules/input/evdev/SwitchInputMapper.h [new file with mode: 0644]
modules/radio/Android.mk
modules/radio/radio_hal_tool.c [new file with mode: 0644]
modules/radio/radio_hw.c
modules/sensors/Android.mk
modules/sensors/multihal.cpp
modules/soundtrigger/Android.mk
modules/soundtrigger/sound_trigger_hw.c
modules/thermal/Android.mk [new file with mode: 0644]
modules/thermal/thermal.c [new file with mode: 0644]
modules/usbaudio/audio_hal.c
modules/vehicle/Android.mk [new file with mode: 0644]
modules/vehicle/timeUtil.cpp [new file with mode: 0644]
modules/vehicle/vehicle.c [new file with mode: 0644]
modules/vr/Android.mk [new file with mode: 0644]
modules/vr/vr.c [new file with mode: 0644]
tests/camera2/CameraModuleFixture.h
tests/camera2/CameraMultiStreamTests.cpp
tests/camera2/CameraStreamFixture.h
tests/camera2/CameraStreamTests.cpp
tests/camera2/ForkedTests.cpp
tests/camera2/camera2_utils.cpp
tests/hardware/struct-size.cpp
tests/hwc/Android.mk
tests/hwc/cnativewindow.c
tests/input/evdev/Android.mk
tests/input/evdev/BitUtils_test.cpp [new file with mode: 0644]
tests/input/evdev/InputDevice_test.cpp
tests/input/evdev/InputHub_test.cpp
tests/input/evdev/InputMocks.cpp [new file with mode: 0644]
tests/input/evdev/InputMocks.h [new file with mode: 0644]
tests/input/evdev/MockInputHost.h [new file with mode: 0644]
tests/input/evdev/MouseInputMapper_test.cpp [new file with mode: 0644]
tests/input/evdev/SwitchInputMapper_test.cpp [new file with mode: 0644]
tests/input/evdev/TestHelpers.cpp
tests/keymaster/keymaster_test.cpp
tests/nusensors/nusensors.cpp
tests/vehicle/Android.mk [new file with mode: 0644]
tests/vehicle/README [new file with mode: 0644]
tests/vehicle/vehicle-hal-tool.c [new file with mode: 0755]
tests/vehicle/vehicle_test_fixtures.h [new file with mode: 0644]
tests/vehicle/vehicle_tests.cpp [new file with mode: 0644]

index 79d0a2f..5394787 100644 (file)
 #if defined(__LP64__)
 #define HAL_LIBRARY_PATH1 "/system/lib64/hw"
 #define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
+#define HAL_LIBRARY_PATH3 "/odm/lib64/hw"
 #else
 #define HAL_LIBRARY_PATH1 "/system/lib/hw"
 #define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
+#define HAL_LIBRARY_PATH3 "/odm/lib/hw"
 #endif
 
 /**
@@ -130,6 +132,11 @@ 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_PATH3, name, subname);
+    if (access(path, R_OK) == 0)
+        return 0;
+
+    snprintf(path, path_len, "%s/%s.%s.so",
              HAL_LIBRARY_PATH2, name, subname);
     if (access(path, R_OK) == 0)
         return 0;
index 8f99459..2200723 100644 (file)
@@ -179,9 +179,27 @@ typedef struct activity_recognition_device {
      * independently of the other. The HAL implementation needs to keep track of which pairs are
      * currently active and needs to detect only those pairs.
      *
+     * At the first detection after this function gets called, the hardware should know whether the
+     * user is in the activity.
+     * - If event_type is ACTIVITY_EVENT_ENTER and the user is in the activity, then an
+     *   (ACTIVITY_EVENT_ENTER, activity) event should be added to the FIFO.
+     * - If event_type is ACTIVITY_EVENT_EXIT and the user is not in the activity, then an
+     *   (ACTIVITY_EVENT_EXIT, activity) event should be added to the FIFO.
+     * For example, suppose get_supported_activities_list contains on_bicyle and running, and the
+     * user is biking. Consider the following four calls that could happen in any order.
+     * - When enable_activity_event(on_bicycle, ACTIVITY_EVENT_ENTER) is called,
+     *   (ACTIVITY_EVENT_ENTER, on_bicycle) should be added to the FIFO.
+     * - When enable_activity_event(on_bicycle, ACTIVITY_EVENT_EXIT) is called, nothing should be
+     *   added to the FIFO.
+     * - When enable_activity_event(running, ACTIVITY_EVENT_ENTER) is called, nothing should be
+     *   added to the FIFO.
+     * - When enable_activity_event(running, ACTIVITY_EVENT_EXIT) is called,
+     *   (ACTIVITY_EVENT_EXIT, running) should be added to the FIFO.
+     *
      * 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.
+     * event_type - Specific transition of the activity that needs to be detected. It should be
+     *              either ACTIVITY_EVENT_ENTER or ACTIVITY_EVENT_EXIT.
      * 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.
@@ -190,7 +208,8 @@ typedef struct activity_recognition_device {
             uint32_t activity_handle, uint32_t event_type, int64_t max_batch_report_latency_ns);
 
     /*
-     * Disables detection of a specific (activity, event_type) pair.
+     * Disables detection of a specific (activity, event_type) pair. All the (activity, event_type)
+     * events in the FIFO are discarded.
      */
     int (*disable_activity_event)(const struct activity_recognition_device* dev,
             uint32_t activity_handle, uint32_t event_type);
@@ -199,6 +218,7 @@ typedef struct activity_recognition_device {
      * 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.
+     * activity_callback should be called before this function returns successfully.
      * See ACTIVITY_EVENT_FLUSH_COMPLETE for more details.
      * Return 0 on success, negative errno code otherwise.
      */
index 2389c09..36bfa86 100644 (file)
@@ -144,6 +144,9 @@ __BEGIN_DECLS
 /* Set the HW synchronization source for an output stream. */
 #define AUDIO_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync"
 
+/* Enable mono audio playback if 1, else should be 0. */
+#define AUDIO_PARAMETER_MONO_OUTPUT "mono_output"
+
 /**
  * audio codec parameters
  */
@@ -428,6 +431,23 @@ struct audio_stream_in {
      * Unit: the number of input audio frames
      */
     uint32_t (*get_input_frames_lost)(struct audio_stream_in *stream);
+
+    /**
+     * Return a recent count of the number of audio frames received and
+     * the clock time associated with that frame count.
+     *
+     * frames is the total frame count received. This should be as early in
+     *     the capture pipeline as possible. In general,
+     *     frames should be non-negative and should not go "backwards".
+     *
+     * time is the clock MONOTONIC time when frames was measured. In general,
+     *     time should be a positive quantity and should not go "backwards".
+     *
+     * The status returned is 0 on success, -ENOSYS if the device is not
+     * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
+     */
+    int (*get_capture_position)(const struct audio_stream_in *stream,
+                                int64_t *frames, int64_t *time);
 };
 typedef struct audio_stream_in audio_stream_in_t;
 
@@ -442,7 +462,7 @@ 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)) {
+    if (audio_has_proportional_frames(format)) {
         chan_samp_sz = audio_bytes_per_sample(format);
         return popcount(s->get_channels(s)) * chan_samp_sz;
     }
@@ -458,7 +478,7 @@ static inline size_t audio_stream_out_frame_size(const struct audio_stream_out *
     size_t chan_samp_sz;
     audio_format_t format = s->common.get_format(&s->common);
 
-    if (audio_is_linear_pcm(format)) {
+    if (audio_has_proportional_frames(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;
     }
@@ -474,7 +494,7 @@ 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)) {
+    if (audio_has_proportional_frames(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;
     }
index 99cb044..bacb1e5 100644 (file)
@@ -141,14 +141,14 @@ struct audio_policy {
     int (*start_output)(struct audio_policy *pol,
                         audio_io_handle_t output,
                         audio_stream_type_t stream,
-                        int session);
+                        audio_session_t 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);
+                       audio_session_t session);
 
     /* releases the output. */
     void (*release_output)(struct audio_policy *pol, audio_io_handle_t output);
@@ -222,7 +222,7 @@ struct audio_policy {
                            const struct effect_descriptor_s *desc,
                            audio_io_handle_t output,
                            uint32_t strategy,
-                           int session,
+                           audio_session_t session,
                            int id);
 
     int (*unregister_effect)(struct audio_policy *pol, int id);
@@ -367,7 +367,7 @@ struct audio_policy_service_ops {
 
     /* move effect to the specified output */
     int (*move_effects)(void *service,
-                        int session,
+                        audio_session_t session,
                         audio_io_handle_t src_output,
                         audio_io_handle_t dst_output);
 
index 0f1a35b..b9b3b12 100644 (file)
@@ -89,8 +89,10 @@ typedef enum {
     BT_STATUS_UNHANDLED,
     BT_STATUS_AUTH_FAILURE,
     BT_STATUS_RMT_DEV_DOWN,
-    BT_STATUS_AUTH_REJECTED
-
+    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 */
@@ -107,6 +109,12 @@ typedef struct {
     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,
@@ -256,6 +264,19 @@ typedef struct
     void *val;
 } bt_property_t;
 
+/** Bluetooth Out Of Band data for bonding */
+typedef struct
+{
+   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 Random Value */
+   uint8_t le_sc_r[16]; /* LE Secure Connections Random Value */
+} bt_out_of_band_data_t;
+
+
 
 /** Bluetooth Device Type */
 typedef enum {
@@ -365,8 +386,12 @@ typedef void (*le_test_mode_callback)(bt_status_t status, uint16_t num_packets);
  * 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 */
-typedef void (*energy_info_callback)(bt_activity_energy_info *energy_info);
+ * 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 */
@@ -438,7 +463,7 @@ typedef struct {
     int (*init)(bt_callbacks_t* callbacks );
 
     /** Enable Bluetooth. */
-    int (*enable)(void);
+    int (*enable)(bool guest_mode);
 
     /** Disable Bluetooth. */
     int (*disable)(void);
@@ -485,6 +510,10 @@ typedef struct {
     /** 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);
 
@@ -540,8 +569,10 @@ typedef struct {
     /**
      * 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);
+    void (*dump)(int fd, const char **arguments);
 
     /**
      * Clear /data/misc/bt_config.conf and erase all stored connections
diff --git a/include/hardware/boot_control.h b/include/hardware/boot_control.h
new file mode 100644 (file)
index 0000000..36a867d
--- /dev/null
@@ -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
index 5252a17..9b32216 100644 (file)
@@ -38,13 +38,13 @@ typedef enum {
 /** 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, 
+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, 
+typedef void (* btav_audio_state_callback)(btav_audio_state_t state,
                                                bt_bdaddr_t *bd_addr);
 
 /** Callback for audio configuration change.
@@ -66,15 +66,15 @@ typedef struct {
     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 
+ *    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.
@@ -96,6 +96,12 @@ typedef struct {
 
     /** 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
index e30ac24..77c845b 100644 (file)
@@ -41,4 +41,35 @@ typedef struct
     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
+{
+    uint8_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;
+} btgatt_db_element_t;
+
 #endif  /* ANDROID_INCLUDE_BT_COMMON_TYPES_H */
index e7e8e82..e2c8a92 100644 (file)
@@ -40,9 +40,7 @@ typedef struct
 /** Parameters for GATT read operations */
 typedef struct
 {
-    btgatt_srvc_id_t    srvc_id;
-    btgatt_gatt_id_t    char_id;
-    btgatt_gatt_id_t    descr_id;
+    uint16_t           handle;
     btgatt_unformatted_value_t value;
     uint16_t            value_type;
     uint8_t             status;
@@ -62,8 +60,7 @@ typedef struct
 {
     uint8_t             value[BTGATT_MAX_ATTR_LEN];
     bt_bdaddr_t         bda;
-    btgatt_srvc_id_t    srvc_id;
-    btgatt_gatt_id_t    char_id;
+    uint16_t            handle;
     uint16_t            len;
     uint8_t             is_notify;
 } btgatt_notify_params_t;
@@ -137,27 +134,9 @@ typedef void (*disconnect_callback)(int conn_id, int status,
  */
 typedef void (*search_complete_callback)(int conn_id, int status);
 
-/** Reports GATT services on a remote device */
-typedef void (*search_result_callback)( int conn_id, btgatt_srvc_id_t *srvc_id);
-
-/** GATT characteristic enumeration result callback */
-typedef void (*get_characteristic_callback)(int conn_id, int status,
-                btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
-                int char_prop);
-
-/** GATT descriptor enumeration result callback */
-typedef void (*get_descriptor_callback)(int conn_id, int status,
-                btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
-                btgatt_gatt_id_t *descr_id);
-
-/** GATT included service enumeration result callback */
-typedef void (*get_included_service_callback)(int conn_id, int status,
-                btgatt_srvc_id_t *srvc_id, btgatt_srvc_id_t *incl_srvc_id);
-
 /** Callback invoked in response to [de]register_for_notification */
 typedef void (*register_for_notification_callback)(int conn_id,
-                int registered, int status, btgatt_srvc_id_t *srvc_id,
-                btgatt_gatt_id_t *char_id);
+                int registered, int status, uint16_t handle);
 
 /**
  * Remote device notification callback, invoked when a remote device sends
@@ -170,8 +149,7 @@ 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,
-                btgatt_write_params_t *p_data);
+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);
@@ -181,8 +159,7 @@ 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,
-                btgatt_write_params_t *p_data);
+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,
@@ -245,16 +222,21 @@ typedef void (*track_adv_event_callback)(btgatt_track_adv_info_t *p_track_adv_in
 typedef void (*scan_parameter_setup_completed_callback)(int client_if,
                                                         btgattc_error_t status);
 
+/** 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;
     scan_result_callback                scan_result_cb;
     connect_callback                    open_cb;
     disconnect_callback                 close_cb;
     search_complete_callback            search_complete_cb;
-    search_result_callback              search_result_cb;
-    get_characteristic_callback         get_characteristic_cb;
-    get_descriptor_callback             get_descriptor_cb;
-    get_included_service_callback       get_included_service_cb;
     register_for_notification_callback  register_for_notification_cb;
     notify_callback                     notify_cb;
     read_characteristic_callback        read_characteristic_cb;
@@ -279,6 +261,9 @@ typedef struct {
     batchscan_threshold_callback        batchscan_threshold_cb;
     track_adv_event_callback            track_adv_event_cb;
     scan_parameter_setup_completed_callback scan_parameter_setup_completed_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. */
@@ -313,48 +298,21 @@ typedef struct {
      */
     bt_status_t (*search_service)(int conn_id, bt_uuid_t *filter_uuid );
 
-    /**
-     * Enumerate included services for a given service.
-     * Set start_incl_srvc_id to NULL to get the first included service.
-     */
-    bt_status_t (*get_included_service)( int conn_id, btgatt_srvc_id_t *srvc_id,
-                                         btgatt_srvc_id_t *start_incl_srvc_id);
-
-    /**
-     * Enumerate characteristics for a given service.
-     * Set start_char_id to NULL to get the first characteristic.
-     */
-    bt_status_t (*get_characteristic)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id);
-
-    /**
-     * Enumerate descriptors for a given characteristic.
-     * Set start_descr_id to NULL to get the first descriptor.
-     */
-    bt_status_t (*get_descriptor)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
-                    btgatt_gatt_id_t *start_descr_id);
-
     /** Read a characteristic on a remote device */
-    bt_status_t (*read_characteristic)( int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+    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,
-                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+    bt_status_t (*write_characteristic)(int conn_id, uint16_t handle,
                     int write_type, int len, int auth_req,
                     char* p_value);
 
     /** Read the descriptor for a given characteristic */
-    bt_status_t (*read_descriptor)(int conn_id,
-                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
-                    btgatt_gatt_id_t *descr_id, int auth_req);
+    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,
-                    btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
-                    btgatt_gatt_id_t *descr_id, int write_type, int len,
+    bt_status_t (*write_descriptor)( int conn_id, uint16_t handle,
+                    int write_type, int len,
                     int auth_req, char* p_value);
 
     /** Execute a prepared write operation */
@@ -365,13 +323,11 @@ typedef struct {
      * characteristic
      */
     bt_status_t (*register_for_notification)( int client_if,
-                    const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
-                    btgatt_gatt_id_t *char_id);
+                    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, btgatt_srvc_id_t *srvc_id,
-                    btgatt_gatt_id_t *char_id);
+                    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);
@@ -448,6 +404,9 @@ typedef struct {
     /** 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
index c565c48..1e2c293 100644 (file)
@@ -103,6 +103,36 @@ typedef struct {
     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 union
 {
     btrc_play_status_t play_status;
@@ -264,14 +294,53 @@ typedef struct {
 
 typedef void (* btrc_passthrough_rsp_callback) (int id, int key_state);
 
+typedef void (* btrc_groupnavigation_rsp_callback) (int id, int key_state);
+
 typedef void (* btrc_connection_state_callback) (bool state, 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);
+
 /** BT-RC Controller callback structure. */
 typedef struct {
     /** set to sizeof(BtRcCallbacks) */
     size_t      size;
-    btrc_passthrough_rsp_callback               passthrough_rsp_cb;
-    btrc_connection_state_callback              connection_state_cb;
+    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_callbacks_t;
 
 /** Represents the standard BT-RC AVRCP Controller interface. */
@@ -285,7 +354,23 @@ typedef struct {
     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 );
+    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 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 );
index 5d206d7..8d1a9e0 100644 (file)
@@ -56,16 +56,20 @@ typedef struct {
      * 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);
+            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 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 channel, int* sock_fd, int flags, int callingUid);
 } btsock_interface_t;
 
 __END_DECLS
index d920d4b..2b7add0 100644 (file)
 /**
  * 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.
+ * NO LONGER SUPPORTED.  The camera service will no longer load HAL modules that
+ * contain HAL v2.0 or v2.1 devices.
+ *
+ * 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.
index 3ef6d6f..a7df0ee 100644 (file)
 #include "camera_common.h"
 
 /**
- * Camera device HAL 3.3 [ CAMERA_DEVICE_API_VERSION_3_3 ]
+ * Camera device HAL 3.4 [ CAMERA_DEVICE_API_VERSION_3_4 ]
  *
  * 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.
+ * android.hardware.camera2 API as LIMITED or above hardware level.
  *
  * 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_DEVICE_API_VERSION_3_4 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_3 and above:
+ *    Camera modules that may contain version 3.3 or above 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
  *
  *   - Addition of camera3 stream configuration operation mode to camera3_stream_configuration_t
  *
+ * 3.4: Minor additions to supported metadata and changes to data_space support
+ *
+ *   - Add ANDROID_SENSOR_OPAQUE_RAW_SIZE static metadata as mandatory if
+ *     RAW_OPAQUE format is supported.
+ *
+ *   - Add ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE static metadata as
+ *     mandatory if any RAW format is supported
+ *
+ *   - Switch camera3_stream_t data_space field to a more flexible definition,
+ *     using the version 0 definition of dataspace encoding.
+ *
+ *   - General metadata additions which are available to use for HALv3.2 or
+ *     newer:
+ *     - ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3
+ *     - ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST
+ *     - ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE
+ *     - ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL
+ *     - ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL
+ *     - ANDROID_SENSOR_OPAQUE_RAW_SIZE
+ *     - ANDROID_SENSOR_OPTICAL_BLACK_REGIONS
  */
 
 /**
@@ -1611,11 +1631,19 @@ typedef struct camera3_stream {
      *   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:
+     * = 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. The dataspace values are the
+     *   legacy definitions in graphics.h
+     *
+     * >= CAMERA_DEVICE_API_VERSION_3_4:
      *
      *   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.
+     *   color and depth outputs if supported. The dataspace values are set
+     *   using the V0 dataspace definitions in graphics.h
      */
     android_dataspace_t data_space;
 
@@ -1680,13 +1708,15 @@ typedef struct camera3_stream_configuration {
     /**
      * >= 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).
+     * 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;
@@ -1933,7 +1963,7 @@ typedef enum camera3_error_msg_code {
      * 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
+     * that dropped the frame.
      */
     CAMERA3_MSG_ERROR_BUFFER = 4,
 
index 7658dd4..c74d7bb 100644 (file)
@@ -140,17 +140,18 @@ __BEGIN_DECLS
  * 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_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) // DEPRECATED
+#define CAMERA_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) // NO LONGER SUPPORTED
+#define CAMERA_DEVICE_API_VERSION_2_1 HARDWARE_DEVICE_API_VERSION(2, 1) // NO LONGER SUPPORTED
 #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)
+#define CAMERA_DEVICE_API_VERSION_3_4 HARDWARE_DEVICE_API_VERSION(3, 4)
 
-// Device version 3.3 is current, older HAL camera device versions are not
+// Device version 3.4 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
+#define CAMERA_DEVICE_API_VERSION_CURRENT CAMERA_DEVICE_API_VERSION_3_4
 
 /**
  * Defined in /system/media/camera/include/system/camera_metadata.h
diff --git a/include/hardware/context_hub.h b/include/hardware/context_hub.h
new file mode 100644 (file)
index 0000000..99756cb
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * 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 CONTEXT_HUB_H
+#define CONTEXT_HUB_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <hardware/hardware.h>
+
+/**
+ * This header file defines the interface of a Context Hub Implementation to
+ * the Android service exposing Context hub capabilities to applications.
+ * The Context hub is expected to a low power compute domain with the following
+ * defining charecteristics -
+ *
+ *    1) Access to sensors like accelerometer, gyroscope, magenetometer.
+ *    2) Access to radios like GPS, Wifi, Bluetooth etc.
+ *    3) Access to low power audio sensing.
+ *
+ * Implementations of this HAL can add additional sensors not defined by the
+ * Android API. Such information sources shall be private to the implementation.
+ *
+ * The Context Hub HAL exposes the construct of code download. A piece of binary
+ * code can be pushed to the context hub through the supported APIs.
+ *
+ * This version of the HAL designs in the possibility of multiple context hubs.
+ */
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+#define CONTEXT_HUB_HEADER_MAJOR_VERSION          1
+#define CONTEXT_HUB_HEADER_MINOR_VERSION          0
+#define CONTEXT_HUB_DEVICE_API_VERSION \
+     HARDWARE_DEVICE_API_VERSION(CONTEXT_HUB_HEADER_MAJOR_VERSION, \
+                                 CONTEXT_HUB_HEADER_MINOR_VERSION)
+
+#define CONTEXT_HUB_DEVICE_API_VERSION_1_0  HARDWARE_DEVICE_API_VERSION(1, 0)
+
+/**
+ * The id of this module
+ */
+#define CONTEXT_HUB_MODULE_ID         "context_hub"
+
+/**
+ * Name of the device to open
+ */
+#define CONTEXT_HUB_HARDWARE_POLL     "ctxt_poll"
+
+/**
+ * Memory types for code upload. Device-specific. At least HUB_MEM_TYPE_MAIN must be supported
+ */
+#define HUB_MEM_TYPE_MAIN             0
+#define HUB_MEM_TYPE_SECONDARY        1
+#define HUB_MEM_TYPE_TCM              2
+
+
+#define HUB_MEM_TYPE_FIRST_VENDOR     0x80000000ul
+
+#define NANOAPP_VENDORS_ALL           0xFFFFFFFFFF000000ULL
+#define NANOAPP_VENDOR_ALL_APPS       0x0000000000FFFFFFULL
+
+#define NANOAPP_VENDOR(name) \
+    (((uint64_t)name[0] << 56) | \
+    ((uint64_t)name[1] << 48) | \
+    ((uint64_t)name[2] << 40) | \
+    ((uint64_t)name[3] << 32) | \
+    ((uint64_t)name[4] << 24))
+
+/*
+ * generates the NANOAPP ID from vendor id and app seq# id
+ */
+#define NANO_APP_ID(vendor, seq_id) \
+       (((uint64_t)vendor & NANOAPP_VENDORS_ALL) | ((uint64_t)seq_id & NANOAPP_VENDOR_ALL_APPS))
+
+struct hub_app_name_t {
+    uint64_t id;
+};
+
+/**
+ * Other memory types (likely not writeable, informational only)
+ */
+#define HUB_MEM_TYPE_BOOTLOADER       0xfffffffful
+#define HUB_MEM_TYPE_OS               0xfffffffeul
+#define HUB_MEM_TYPE_EEDATA           0xfffffffdul
+#define HUB_MEM_TYPE_RAM              0xfffffffcul
+
+/**
+ * Types of memory blocks on the context hub
+ * */
+#define MEM_FLAG_READ  0x1  // Memory can be written to
+#define MEM_FLAG_WRITE 0x2  // Memory can be written to
+#define MEM_FLAG_EXEC  0x4  // Memory can be executed from
+
+/**
+ * The following structure defines each memory block in detail
+ */
+struct mem_range_t {
+    uint32_t total_bytes;
+    uint32_t free_bytes;
+    uint32_t type;        // HUB_MEM_TYPE_*
+    uint32_t mem_flags;   // MEM_FLAG_*
+};
+
+#define NANOAPP_SIGNED_FLAG    0x1
+#define NANOAPP_ENCRYPTED_FLAG 0x2
+#define NANOAPP_MAGIC (((uint32_t)'N' <<  0) | ((uint32_t)'A' <<  8) | ((uint32_t)'N' << 16) | ((uint32_t)'O' << 24))
+
+// The binary format below is in little endian format
+struct nano_app_binary_t {
+    uint32_t header_version;       // 0x1 for this version
+    uint32_t magic;                // "NANO"
+    struct hub_app_name_t app_id;  // App Id contains vendor id
+    uint32_t app_version;          // Version of the app
+    uint32_t flags;                // Signed, encrypted
+    uint64_t hw_hub_type;          // which hub type is this compiled for
+    uint32_t reserved[2];          // Should be all zeroes
+    uint8_t  custom_binary[0];     // start of custom binary data
+};
+
+struct hub_app_info {
+    struct hub_app_name_t app_name;
+    uint32_t version;
+    uint32_t num_mem_ranges;
+    struct mem_range_t mem_usage[2]; // Apps could only have RAM and SHARED_DATA
+};
+
+/**
+ * Following enum defines the types of sensors that a hub may declare support
+ * for. Declaration for support would mean that the hub can access and process
+ * data from that particular sensor type.
+ */
+
+typedef enum {
+    CONTEXT_SENSOR_RESERVED,             // 0
+    CONTEXT_SENSOR_ACCELEROMETER,        // 1
+    CONTEXT_SENSOR_GYROSCOPE,            // 2
+    CONTEXT_SENSOR_MAGNETOMETER,         // 3
+    CONTEXT_SENSOR_BAROMETER,            // 4
+    CONTEXT_SENSOR_PROXIMITY_SENSOR,     // 5
+    CONTEXT_SENSOR_AMBIENT_LIGHT_SENSOR, // 6
+
+    CONTEXT_SENSOR_GPS = 0x100,          // 0x100
+    // Reserving this space for variants on GPS
+    CONTEXT_SENSOR_WIFI = 0x200,         // 0x200
+    // Reserving this space for variants on WIFI
+    CONTEXT_SENSOR_AUDIO = 0x300,        // 0x300
+    // Reserving this space for variants on Audio
+    CONTEXT_SENSOR_CAMERA = 0x400,       // 0x400
+    // Reserving this space for variants on Camera
+    CONTEXT_SENSOR_BLE = 0x500,          // 0x500
+
+    CONTEXT_SENSOR_MAX = 0xffffffff,     //make sure enum size is set
+} context_sensor_e;
+
+/**
+ * Sensor types beyond CONTEXT_HUB_TYPE_PRIVATE_SENSOR_BASE are custom types
+ */
+#define CONTEXT_HUB_TYPE_PRIVATE_SENSOR_BASE 0x10000
+
+/**
+ * The following structure describes a sensor
+ */
+struct physical_sensor_description_t {
+    uint32_t sensor_type;           // From the definitions above eg: 100
+    const char *type_string;        // Type as a string. eg: "GPS"
+    const char *name;               // Identifier eg: "Bosch BMI160"
+    const char *vendor;             // Vendor : eg "STM"
+    uint32_t version;               // Version : eg 0x1001
+    uint32_t fifo_reserved_count;   // Batching possible in hardware. Please
+                                    // note that here hardware does not include
+                                    // the context hub itself. Thus, this
+                                    // definition may be different from say the
+                                    // number advertised in the sensors HAL
+                                    // which allows for batching in a hub.
+    uint32_t fifo_max_count;        // maximum number of batchable events.
+    uint64_t min_delay_ms;          // in milliseconds, corresponding to highest
+                                    // sampling freq.
+    uint64_t max_delay_ms;          // in milliseconds, corresponds to minimum
+                                    // sampling frequency
+    float peak_power_mw;            // At max frequency & no batching, power
+                                    // in milliwatts
+};
+
+struct connected_sensor_t {
+    uint32_t sensor_id;             // identifier for this sensor
+
+    /* This union may be extended to other sensor types */
+    union {
+        struct physical_sensor_description_t physical_sensor;
+    };
+};
+
+struct hub_message_t {
+    struct hub_app_name_t app_name; /* To/From this nanoapp */
+    uint32_t message_type;
+    uint32_t message_len;
+    const void *message;
+};
+
+/**
+ * Definition of a context hub. A device may contain more than one low
+ * power domain. In that case, please add an entry for each hub. However,
+ * it is perfectly OK for a device to declare one context hub and manage
+ * them internally as several
+ */
+
+struct context_hub_t {
+    const char *name;                // descriptive name eg: "Awesome Hub #1"
+    const char *vendor;              // hub hardware vendor eg: "Qualcomm"
+    const char *toolchain;           // toolchain to make binaries eg:"gcc ARM"
+    uint32_t platform_version;       // Version of the hardware : eg 0x20
+    uint32_t toolchain_version;      // Version of the toolchain : eg: 0x484
+    uint32_t hub_id;                 // a device unique id for this hub
+
+    float peak_mips;                 // Peak MIPS platform can deliver
+    float stopped_power_draw_mw;     // if stopped, retention power, milliwatts
+    float sleep_power_draw_mw;       // if sleeping, retention power, milliwatts
+    float peak_power_draw_mw;        // for a busy CPUm power in milliwatts
+
+    const struct connected_sensor_t *connected_sensors; // array of connected sensors
+    uint32_t num_connected_sensors;  // number of connected sensors
+
+    const struct hub_app_name_t os_app_name; /* send msgs here for OS functions */
+    uint32_t max_supported_msg_len;  // This is the maximum size of the message that can
+                                     // be sent to the hub in one chunk (in bytes)
+};
+
+/**
+ * Definitions of message payloads, see hub_messages_e
+ */
+
+struct status_response_t {
+    int32_t result; // 0 on success, < 0 : error on failure. > 0 for any descriptive status
+};
+
+struct apps_enable_request_t {
+    struct hub_app_name_t app_name;
+};
+
+struct apps_disable_request_t {
+    struct hub_app_name_t app_name;
+};
+
+struct load_app_request_t {
+    struct nano_app_binary_t app_binary;
+};
+
+struct unload_app_request_t {
+    struct hub_app_name_t app_name;
+};
+
+struct query_apps_request_t {
+    struct hub_app_name_t app_name;
+};
+
+/**
+ * CONTEXT_HUB_APPS_ENABLE
+ * Enables the specified nano-app(s)
+ *
+ * Payload : apps_enable_request_t
+ *
+ * Response : status_response_t
+ *            On receipt of a successful response, it is
+ *               expected that
+ *
+ *               i) the app is executing and able to receive
+ *                  any messages.
+ *
+ *              ii) the system should be able to respond to an
+ *                  CONTEXT_HUB_QUERY_APPS request.
+ *
+ */
+
+/**
+ * CONTEXT_HUB_APPS_DISABLE
+ * Stops the specified nano-app(s)
+ *
+ * Payload : apps_disable_request_t
+ *
+ * Response : status_response_t
+ *            On receipt of a successful response,
+ *               i) No further events are delivered to the
+ *                  nanoapp.
+ *
+ *              ii) The app should not show up in a
+ *                  CONTEXT_HUB_QUERY_APPS request.
+ */
+
+/**
+ * CONTEXT_HUB_LOAD_APP
+ * Loads a nanoApp. Upon loading the nanoApp's init method is
+ * called.
+ *
+ *
+ * Payload : load_app_request_t
+ *
+ * Response : status_response_t On receipt of a successful
+ *               response, it is expected that
+ *               i) the app is executing and able to receive
+ *                  messages.
+ *
+ *              ii) the system should be able to respond to a
+ *                  CONTEXT_HUB_QUERY_APPS.
+ */
+
+/**
+ * CONTEXT_HUB_UNLOAD_APP
+ * Unloads a nanoApp. Before the unload, the app's deinit method
+ * is called.
+ *
+ * Payload : unload_app_request_t.
+ *
+ * Response : status_response_t On receipt of a
+ *            successful response, it is expected that
+ *               i) No further events are delivered to the
+ *                  nanoapp.
+ *
+ *              ii) the system does not list the app in a
+ *                  response to a CONTEXT_HUB_QUERY_APPS.
+ *
+ *             iii) Any resources used by the app should be
+ *                  freed up and available to the system.
+ */
+
+/**
+ * CONTEXT_HUB_QUERY_APPS Queries for status of apps
+ *
+ * Payload : query_apps_request_t
+ *
+ * Response : struct hub_app_info[]
+ */
+
+/**
+ * CONTEXT_HUB_QUERY_MEMORY Queries for memory regions on the
+ * hub
+ *
+ * Payload : NULL
+ *
+ * Response : struct mem_range_t[]
+ */
+
+/**
+ * All communication between the context hubs and the Context Hub Service is in
+ * the form of messages. Some message types are distinguished and their
+ * Semantics shall be well defined.
+ * Custom message types should be defined starting above
+ * CONTEXT_HUB_PRIVATE_MSG_BASE
+ */
+
+typedef enum {
+    CONTEXT_HUB_APPS_ENABLE  = 1, // Enables loaded nano-app(s)
+    CONTEXT_HUB_APPS_DISABLE = 2, // Disables loaded nano-app(s)
+    CONTEXT_HUB_LOAD_APP     = 3, // Load a supplied app
+    CONTEXT_HUB_UNLOAD_APP   = 4, // Unload a specified app
+    CONTEXT_HUB_QUERY_APPS   = 5, // Query for app(s) info on hub
+    CONTEXT_HUB_QUERY_MEMORY = 6, // Query for memory info
+} hub_messages_e;
+
+#define CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE 0x00400
+
+/**
+ * A callback registers with the context hub service to pass messages
+ * coming from the hub to the service/clients.
+ */
+typedef int context_hub_callback(uint32_t hub_id, const struct hub_message_t *rxed_msg, void *cookie);
+
+
+/**
+ * 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 context_hub_module_t {
+    struct hw_module_t common;
+
+    /**
+     * Enumerate all available hubs.The list is returned in "list".
+     * @return result : number of hubs in list or error  (negative)
+     *
+     * This method shall be called at device bootup.
+     */
+    int (*get_hubs)(struct context_hub_module_t* module, const struct context_hub_t ** list);
+
+    /**
+     * Registers a callback for the HAL implementation to communicate
+     * with the context hub service.
+     * @return result : 0 if successful, error code otherwise
+     */
+    int (*subscribe_messages)(uint32_t hub_id, context_hub_callback cbk, void *cookie);
+
+    /**
+     * Send a message to a hub
+     * @return result : 0 if successful, error code otherwise
+     */
+    int (*send_message)(uint32_t hub_id, const struct hub_message_t *msg);
+
+};
+
+__END_DECLS
+
+#endif  // CONTEXT_HUB_SENSORS_INTERFACE_H
index ac88c10..b567732 100644 (file)
@@ -21,6 +21,7 @@
 
 #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_MODULE_API_VERSION_2_1 HARDWARE_MODULE_API_VERSION(2, 1)
 #define FINGERPRINT_HARDWARE_MODULE_ID "fingerprint"
 
 typedef enum fingerprint_msg_type {
@@ -28,7 +29,8 @@ typedef enum fingerprint_msg_type {
     FINGERPRINT_ACQUIRED = 1,
     FINGERPRINT_TEMPLATE_ENROLLING = 3,
     FINGERPRINT_TEMPLATE_REMOVED = 4,
-    FINGERPRINT_AUTHENTICATED = 5
+    FINGERPRINT_AUTHENTICATED = 5,
+    FINGERPRINT_TEMPLATE_ENUMERATING = 6,
 } fingerprint_msg_type_t;
 
 /*
@@ -48,6 +50,7 @@ typedef enum fingerprint_error {
     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_LOCKOUT = 7, /* the functionality is temporarily locked out */
     FINGERPRINT_ERROR_VENDOR_BASE = 1000 /* vendor-specific error messages start here */
 } fingerprint_error_t;
 
@@ -82,6 +85,11 @@ typedef struct fingerprint_enroll {
     uint64_t msg; /* Vendor specific message. Used for user guidance */
 } fingerprint_enroll_t;
 
+typedef struct fingerprint_enumerated {
+    fingerprint_finger_id_t finger;
+    uint32_t remaining_templates;
+} fingerprint_enumerated_t;
+
 typedef struct fingerprint_removed {
     fingerprint_finger_id_t finger;
 } fingerprint_removed_t;
@@ -100,6 +108,7 @@ typedef struct fingerprint_msg {
     union {
         fingerprint_error_t error;
         fingerprint_enroll_t enroll;
+        fingerprint_enumerated_t enumerated;
         fingerprint_removed_t removed;
         fingerprint_acquired_t acquired;
         fingerprint_authenticated_t authenticated;
@@ -198,31 +207,24 @@ typedef struct fingerprint_device {
     /*
      * 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.
+     * For each template found notify() will be called with:
+     * fingerprint_msg.type == FINGERPRINT_TEMPLATE_ENUMERATED
+     * fingerprint_msg.data.enumerated.finger indicating a template id
+     * fingerprint_msg.data.enumerated.remaining_templates indicating how many more
+     * enumeration messages to expect.
      *
-     * Function return: Total number of fingerprint templates in the current storage directory.
+     * Function return: 0 if enumerate request is accepted
      *                  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);
+    int (*enumerate)(struct fingerprint_device *dev);
 
     /*
      * Fingerprint remove request:
      * Deletes a fingerprint template.
-     * Works only within a path set by set_active_group().
+     * Works only within the 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.
+     * fingerprint_msg.data.removed.finger 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.
@@ -249,8 +251,16 @@ typedef struct fingerprint_device {
      */
     int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid);
 
+    /*
+     * Resets a lockout by providing a valid hardware authentication token.
+     *
+     * Function return: 0 on success
+     *                  or a negative number in case of error, generally from the errno.h set.
+     */
+    int (*reset_lockout)(struct fingerprint_device *dev, const hw_auth_token_t *hat);
+
     /* Reserved for backward binary compatibility */
-    void *reserved[4];
+    void *reserved[3];
 } fingerprint_device_t;
 
 typedef struct fingerprint_module {
index 76b6cb7..acf601b 100644 (file)
@@ -39,28 +39,33 @@ typedef int64_t GpsUtcTime;
 
 /** Maximum number of SVs for gps_sv_status_callback(). */
 #define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
 
 /** Maximum number of Measurements in gps_measurement_callback(). */
 #define GPS_MAX_MEASUREMENT   32
 
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT   64
+
 /** Requested operational mode for GPS operation. */
 typedef uint32_t GpsPositionMode;
-// IMPORTANT: Note that the following values must match
-// constants in GpsLocationProvider.java.
+/* 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.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED 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.
+/* 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. */
@@ -68,8 +73,8 @@ typedef uint32_t GpsPositionRecurrence;
 
 /** GPS status event values. */
 typedef uint16_t GpsStatusValue;
-// IMPORTANT: Note that the following values must match
-// constants in GpsLocationProvider.java.
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
 /** GPS status unknown. */
 #define GPS_STATUS_NONE             0
 /** GPS has begun navigating. */
@@ -83,8 +88,8 @@ typedef uint16_t GpsStatusValue;
 
 /** 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.
+/* 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. */
@@ -98,31 +103,34 @@ typedef uint16_t GpsLocationFlags;
 
 /** 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.
+/**
+ * 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
+#define GPS_CAPABILITY_SCHEDULING       (1 << 0)
 /** GPS supports MS-Based AGPS mode */
-#define GPS_CAPABILITY_MSB              0x0000002
+#define GPS_CAPABILITY_MSB              (1 << 1)
 /** GPS supports MS-Assisted AGPS mode */
-#define GPS_CAPABILITY_MSA              0x0000004
+#define GPS_CAPABILITY_MSA              (1 << 2)
 /** GPS supports single-shot fixes */
-#define GPS_CAPABILITY_SINGLE_SHOT      0x0000008
+#define GPS_CAPABILITY_SINGLE_SHOT      (1 << 3)
 /** GPS supports on demand time injection */
-#define GPS_CAPABILITY_ON_DEMAND_TIME   0x0000010
+#define GPS_CAPABILITY_ON_DEMAND_TIME   (1 << 4)
 /** GPS supports Geofencing  */
-#define GPS_CAPABILITY_GEOFENCING       0x0000020
-/** GPS supports Measurements */
-#define GPS_CAPABILITY_MEASUREMENTS     0x0000040
+#define GPS_CAPABILITY_GEOFENCING       (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS     (1 << 6)
 /** GPS supports Navigation Messages */
-#define GPS_CAPABILITY_NAV_MESSAGES     0x0000080
+#define GPS_CAPABILITY_NAV_MESSAGES     (1 << 7)
 
-/** Flags used to specify which aiding data to delete
-    when calling delete_aiding_data(). */
+/**
+ * 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.
+/* 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
@@ -210,8 +218,13 @@ typedef uint16_t AGpsStatusValue;
 /** AGPS data connection failed */
 #define GPS_AGPS_DATA_CONN_FAILED   5
 
+typedef uint16_t AGpsRefLocationType;
 #define AGPS_REF_LOCATION_TYPE_GSM_CELLID   1
 #define AGPS_REF_LOCATION_TYPE_UMTS_CELLID  2
+#define AGPS_REF_LOCATION_TYPE_MAC          3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID   4
+
+/* Deprecated, to be removed in the next Android release. */
 #define AGPS_REG_LOCATION_TYPE_MAC          3
 
 /** Network types for update_network_state "type" parameter */
@@ -223,113 +236,110 @@ typedef uint16_t AGpsStatusValue;
 #define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
 #define AGPS_RIL_NETWORK_TTYPE_WIMAX        6
 
-/**
- * Flags to indicate what fields in GpsClock are valid.
- */
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 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.
+ * Flags to indicate what fields in GnssClock are valid.
  */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 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.
- */
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 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.
+ * Flags to indicate what fields in GnssMeasurement are valid.
  */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 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.
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
  */
 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).
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
  */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 typedef uint16_t GpsMeasurementState;
 #define GPS_MEASUREMENT_STATE_UNKNOWN                   0
 #define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
@@ -339,8 +349,38 @@ typedef uint16_t GpsMeasurementState;
 #define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
 
 /**
- * Flags indicating the Accumulated Delta Range's states.
+ * Flags indicating the GNSS 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:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ *         GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
  */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 typedef uint16_t GpsAccumulatedDeltaRangeState;
 #define GPS_ADR_STATE_UNKNOWN                       0
 #define GPS_ADR_STATE_VALID                     (1<<0)
@@ -348,21 +388,53 @@ typedef uint16_t GpsAccumulatedDeltaRangeState;
 #define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
 
 /**
- * Enumeration of available values to indicate the available GPS Navigation message types.
+ * Flags indicating the Accumulated Delta Range's states.
  */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN                       0
+#define GNSS_ADR_STATE_VALID                     (1<<0)
+#define GNSS_ADR_STATE_RESET                     (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
 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
 
 /**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+/**
  * 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
@@ -372,10 +444,34 @@ typedef uint8_t GpsNavigationMessageType;
  * corrected.
  */
 typedef uint16_t NavigationMessageStatus;
-#define NAV_MESSAGE_STATUS_UNKONW              0
+#define NAV_MESSAGE_STATUS_UNKNOWN              0
 #define NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
 #define NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
 
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW              0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t                                 GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE                      0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA        (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA          (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX               (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t                         GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN      0
+#define GNSS_CONSTELLATION_GPS          1
+#define GNSS_CONSTELLATION_SBAS         2
+#define GNSS_CONSTELLATION_GLONASS      3
+#define GNSS_CONSTELLATION_QZSS         4
+#define GNSS_CONSTELLATION_BEIDOU       5
+#define GNSS_CONSTELLATION_GALILEO      6
+
 /**
  * Name for the GPS XTRA interface.
  */
@@ -437,8 +533,9 @@ typedef struct {
     double          latitude;
     /** Represents longitude in degrees. */
     double          longitude;
-    /** Represents altitude in meters above the WGS 84 reference
-     * ellipsoid. */
+    /**
+     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     */
     double          altitude;
     /** Represents speed in meters per second. */
     float           speed;
@@ -457,7 +554,11 @@ typedef struct {
     GpsStatusValue status;
 } GpsStatus;
 
-/** Represents SV information. */
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
 typedef struct {
     /** set to sizeof(GpsSvInfo) */
     size_t          size;
@@ -471,43 +572,104 @@ typedef struct {
     float   azimuth;
 } GpsSvInfo;
 
-/** Represents SV status. */
 typedef struct {
-    /** set to sizeof(GpsSvStatus) */
-    size_t          size;
-
-    /** Number of SVs currently visible. */
-    int         num_svs;
+    /** set to sizeof(GnssSvInfo) */
+    size_t size;
 
-    /** Contains an array of SV information. */
-    GpsSvInfo   sv_list[GPS_MAX_SVS];
+    /**
+     * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+     * distinction is made by looking at constellation field. Values should be
+     * in the range of:
+     *
+     * - GPS:     1-32
+     * - SBAS:    120-151, 183-192
+     * - GLONASS: 1-24, the orbital slot number (OSN), if known.  Or, if not:
+     *            93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+     *            i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+     * - QZSS:    193-200
+     * - Galileo: 1-36
+     * - Beidou:  1-37
+     */
+    int16_t svid;
 
-    /** Represents a bit mask indicating which SVs
-     * have ephemeris data.
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
      */
-    uint32_t    ephemeris_mask;
+    GnssConstellationType constellation;
 
-    /** Represents a bit mask indicating which SVs
-     * have almanac data.
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
      */
-    uint32_t    almanac_mask;
+    float c_n0_dbhz;
+
+    /** Elevation of SV in degrees. */
+    float elevation;
+
+    /** Azimuth of SV in degrees. */
+    float azimuth;
 
     /**
-     * Represents a bit mask indicating which SVs
-     * were used for computing the most recent position fix.
+     * Contains additional data about the given SV. Value should be one of those
+     * GNSS_SV_FLAGS_* constants
      */
-    uint32_t    used_in_fix_mask;
+    GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvStatus) */
+    size_t size;
+    int num_svs;
+    GpsSvInfo sv_list[GPS_MAX_SVS];
+    uint32_t ephemeris_mask;
+    uint32_t almanac_mask;
+    uint32_t used_in_fix_mask;
 } GpsSvStatus;
 
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
 
-/* 2G and 3G */
-/* In 3G lac is discarded */
+/* CellID for 2G, 3G and LTE, used in AGPS. */
 typedef struct {
-    uint16_t type;
+    AGpsRefLocationType type;
+    /** Mobile Country Code. */
     uint16_t mcc;
+    /** Mobile Network Code .*/
     uint16_t mnc;
+    /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+     * lac is populated with tac, to ensure that we don't break old clients that
+     * might rely in the old (wrong) behavior.
+     */
     uint16_t lac;
+    /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
     uint32_t cid;
+    /** Tracking Area Code in LTE. */
+    uint16_t tac;
+    /** Physical Cell id in LTE (not used in 2G and 3G) */
+    uint16_t pcid;
 } AGpsRefLocationCellID;
 
 typedef struct {
@@ -516,41 +678,55 @@ typedef struct {
 
 /** Represents ref locations */
 typedef struct {
-    uint16_t type;
+    AGpsRefLocationType type;
     union {
         AGpsRefLocationCellID   cellID;
         AGpsRefLocationMac      mac;
     } u;
 } AGpsRefLocation;
 
-/** Callback with location information.
- *  Can only be called from a thread created by create_thread_cb.
+/**
+ * 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.
+/**
+ * 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.
+ * Legacy callback with SV status information.
  * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
  */
 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.
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* 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.
+/**
+ * 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.
+/**
+ * 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)();
 
@@ -560,12 +736,39 @@ 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.
+/**
+ * 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. */
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+    /** Set to sizeof(GnssSystemInfo) */
+    size_t   size;
+    /* year in which the last update was made to the underlying hardware/firmware
+     * used to capture GNSS signals, e.g. 2016 */
+    uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
 typedef struct {
     /** set to sizeof(GpsCallbacks) */
     size_t      size;
@@ -578,8 +781,10 @@ typedef struct {
     gps_release_wakelock release_wakelock_cb;
     gps_create_thread create_thread_cb;
     gps_request_utc_time request_utc_time_cb;
-} GpsCallbacks;
 
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
 
 /** Represents the standard GPS interface. */
 typedef struct {
@@ -604,10 +809,10 @@ typedef struct {
     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
+    /**
+     * 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);
 
@@ -623,10 +828,10 @@ typedef struct {
      * 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
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
      * 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 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,
@@ -636,9 +841,10 @@ typedef struct {
     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.
+/**
+ * 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)();
 
@@ -673,36 +879,11 @@ typedef struct {
     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. */
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
 typedef struct {
-    /** set to sizeof(AGpsStatus_v3) */
+    /** set to sizeof(AGpsStatus) */
     size_t                  size;
 
     AGpsType                type;
@@ -717,14 +898,13 @@ typedef struct {
     /**
      * 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;
+} AGpsStatus;
 
-typedef AGpsStatus_v3     AGpsStatus;
-
-/** Callback with AGPS status information.
- *  Can only be called from a thread created by create_thread_cb.
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
  */
 typedef void (* agps_status_callback)(AGpsStatus* status);
 
@@ -734,42 +914,12 @@ typedef struct {
     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) */
+    /** set to sizeof(AGpsInterface) */
     size_t size;
 
     /**
@@ -803,9 +953,7 @@ typedef struct {
     int (*data_conn_open_with_apn_ip_type)(
             const char* apn,
             ApnIpType apnIpType);
-} AGpsInterface_v2;
-
-typedef AGpsInterface_v2    AGpsInterface;
+} AGpsInterface;
 
 /** Error codes associated with certificate operations */
 #define AGPS_CERTIFICATE_OPERATION_SUCCESS               0
@@ -936,8 +1084,9 @@ typedef struct {
 
 } GpsNiNotification;
 
-/** Callback with NI notification.
- *  Can only be called from a thread created by create_thread_cb.
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
  */
 typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
 
@@ -1280,48 +1429,67 @@ typedef struct {
    void (*remove_geofence_area) (int32_t geofence_id);
 } GpsGeofencingInterface;
 
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsClock) */
+    size_t size;
+    GpsClockFlags flags;
+    int16_t leap_second;
+    GpsClockType type;
+    int64_t time_ns;
+    double time_uncertainty_ns;
+    int64_t full_bias_ns;
+    double bias_ns;
+    double bias_uncertainty_ns;
+    double drift_nsps;
+    double drift_uncertainty_nsps;
+} GpsClock;
 
 /**
  * Represents an estimate of the GPS clock time.
  */
 typedef struct {
-    /** set to sizeof(GpsClock) */
+    /** set to sizeof(GnssClock) */
     size_t size;
 
-    /** A set of flags indicating the validity of the fields in this data structure. */
-    GpsClockFlags flags;
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    GnssClockFlags 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
+     *      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.
+     * If the data is available 'flags' must contain GNSS_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.
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
      *
-     * 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 local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * 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.
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
      *
-     * Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
      * The value contains the 'time uncertainty' in it.
      *
-     * This is a Mandatory field.
+     * This field is mandatory.
      */
     int64_t time_ns;
 
@@ -1329,52 +1497,64 @@ typedef struct {
      * 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.
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
      */
     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 difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
      *
      * The sign of the value is defined by the following equation:
-     *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+     *      local estimate of 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.
-
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
      */
     int64_t full_bias_ns;
 
     /**
      * Sub-nanosecond bias.
-     * The value contains the 'bias uncertainty' in it.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
      *
-     * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
      */
     double bias_ns;
 
     /**
-     * 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
-     * The uncertainty is represented as an absolute (single sided) value.
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * 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.
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
      */
     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.
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
      *
      * The value contains the 'drift uncertainty' in it.
-     * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
      *
-     * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
-     * it is encouraged that this field is also provided.
+     * This value is mandatory if the receiver has estimated GNSS time
      */
     double drift_nsps;
 
@@ -1382,26 +1562,115 @@ typedef struct {
      * 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.
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
      */
     double drift_uncertainty_nsps;
-} GpsClock;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+    GpsMeasurementFlags flags;
+    int8_t prn;
+    double time_offset_ns;
+    GpsMeasurementState state;
+    int64_t received_gps_tow_ns;
+    int64_t received_gps_tow_uncertainty_ns;
+    double c_n0_dbhz;
+    double pseudorange_rate_mps;
+    double pseudorange_rate_uncertainty_mps;
+    GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+    double accumulated_delta_range_m;
+    double accumulated_delta_range_uncertainty_m;
+    double pseudorange_m;
+    double pseudorange_uncertainty_m;
+    double code_phase_chips;
+    double code_phase_uncertainty_chips;
+    float carrier_frequency_hz;
+    int64_t carrier_cycles;
+    double carrier_phase;
+    double carrier_phase_uncertainty;
+    GpsLossOfLock loss_of_lock;
+    int32_t bit_number;
+    int16_t time_from_last_bit_ms;
+    double doppler_shift_hz;
+    double doppler_shift_uncertainty_hz;
+    GpsMultipathIndicator multipath_indicator;
+    double snr_db;
+    double elevation_deg;
+    double elevation_uncertainty_deg;
+    double azimuth_deg;
+    double azimuth_uncertainty_deg;
+    bool used_in_fix;
+} GpsMeasurement;
 
 /**
- * Represents a GPS Measurement, it contains raw and computed information.
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
  */
 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;
+    GnssMeasurementFlags flags;
 
     /**
-     * Pseudo-random number in the range of [1, 32]
-     * This is a Mandatory value.
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
      */
-    int8_t prn;
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
 
     /**
      * Time offset at which the measurement was taken in nanoseconds.
@@ -1412,7 +1681,7 @@ typedef struct {
      *      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.
+     * This is a mandatory value.
      */
     double time_offset_ns;
 
@@ -1420,56 +1689,103 @@ typedef struct {
      * 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.
+     * This is a mandatory value.
      */
-    GpsMeasurementState state;
+    GnssMeasurementState state;
 
     /**
-     * Received GPS Time-of-Week at the measurement time, in nanoseconds.
-     * The value is relative to the beginning of the current GPS week.
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
      *
-     * 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
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
      *
-     * However, if there is any ambiguity in integer millisecond,
-     * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
      *
-     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
-     */
-    int64_t received_gps_tow_ns;
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_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;
+    int64_t received_sv_time_uncertainty_in_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.
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
      *
-     * This is a Mandatory value.
+     * 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.
+     * 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. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
      *
-     * It is encouraged to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
-     * 'drift' field as well.
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
      *
      * The value includes the 'pseudorange rate uncertainty' in it.
      * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
@@ -1478,15 +1794,21 @@ typedef struct {
      * shift' is given by the equation:
      *      pseudorange rate = -k * doppler shift   (where k is a constant)
      *
-     * This is a Mandatory value.
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
      */
     double pseudorange_rate_mps;
 
     /**
-     * 1-Sigma uncertainty of the pseudurange rate in m/s.
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
      * The uncertainty is represented as an absolute (single sided) value.
      *
-     * This is a Mandatory value.
+     * This is a mandatory value.
      */
     double pseudorange_rate_uncertainty_mps;
 
@@ -1494,9 +1816,9 @@ typedef struct {
      * 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.
+     * This is a mandatory value.
      */
-    GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+    GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
 
     /**
      * Accumulated delta range since the last channel reset in meters.
@@ -1519,54 +1841,22 @@ typedef struct {
     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.
+     * If the data is available, 'flags' must contain
+     * GNSS_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'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
      *
-     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
      */
     int64_t carrier_cycles;
 
@@ -1577,125 +1867,109 @@ typedef struct {
      * 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.
+     * If the data is available, 'flags' must contain
+     * GNSS_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.
+     * If the data is available, 'flags' must contain
+     * GNSS_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.
+     * An enumeration that indicates the 'multipath' state of the event.
      *
-     * The reference frequency is given by the field 'carrier_frequency_hz'.
-     * The value contains the 'doppler shift uncertainty' in it.
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
      *
-     * 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.
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
      */
-    GpsMultipathIndicator multipath_indicator;
+    GnssMultipathIndicator multipath_indicator;
 
     /**
-     * Signal-to-noise ratio in dB.
-     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR.
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
      */
     double snr_db;
+} GnssMeasurement;
 
-    /**
-     * 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;
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsData) */
+    size_t size;
+    size_t measurement_count;
+    GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
 
-    /**
-     * 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;
+    /** The GPS clock time reading. */
+    GpsClock clock;
+} GpsData;
 
-/** Represents a reading of GPS measurements. */
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
 typedef struct {
-    /** set to sizeof(GpsData) */
+    /** set to sizeof(GnssData) */
     size_t size;
 
     /** Number of measurements. */
     size_t measurement_count;
 
     /** The array of measurements. */
-    GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+    GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
 
     /** The GPS clock time reading. */
-    GpsClock clock;
-} GpsData;
+    GnssClock clock;
+} GnssData;
 
 /**
- * The callback for to report measurements from the HAL.
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
  *
  * Parameters:
  *    data - A data structure containing the measurements.
  */
 typedef void (*gps_measurement_callback) (GpsData* data);
 
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
 typedef struct {
     /** set to sizeof(GpsMeasurementCallbacks) */
     size_t size;
     gps_measurement_callback measurement_callback;
+    gnss_measurement_callback gnss_measurement_callback;
 } GpsMeasurementCallbacks;
 
 #define GPS_MEASUREMENT_OPERATION_SUCCESS          0
@@ -1732,23 +2006,39 @@ typedef struct {
 
 } GpsMeasurementInterface;
 
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsNavigationMessage) */
+    size_t size;
+    int8_t prn;
+    GpsNavigationMessageType type;
+    NavigationMessageStatus status;
+    int16_t message_id;
+    int16_t submessage_id;
+    size_t data_length;
+    uint8_t* data;
+} GpsNavigationMessage;
 
 /** Represents a GPS navigation message (or a fragment of it). */
 typedef struct {
-    /** set to sizeof(GpsNavigationMessage) */
+    /** set to sizeof(GnssNavigationMessage) */
     size_t size;
 
     /**
-     * Pseudo-random number in the range of [1, 32]
-     * This is a Mandatory value.
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
      */
-    int8_t prn;
+    int16_t svid;
 
     /**
      * The type of message contained in the structure.
-     * This is a Mandatory value.
+     * This is a mandatory value.
      */
-    GpsNavigationMessageType type;
+    GnssNavigationMessageType type;
 
     /**
      * The status of the received navigation message.
@@ -1758,18 +2048,41 @@ typedef struct {
     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.
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
      */
     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.
+     * 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.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
      */
     int16_t submessage_id;
 
@@ -1778,33 +2091,60 @@ typedef struct {
      * 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.
+     * 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).
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
      *
-     * 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.
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
      */
     uint8_t* data;
 
-} GpsNavigationMessage;
+} GnssNavigationMessage;
 
 /**
- * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
  *
  * Parameters:
  *      message - The GPS navigation submessage/subframe representation.
  */
 typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
 
+/**
+ * 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 (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
 typedef struct {
     /** set to sizeof(GpsNavigationMessageCallbacks) */
     size_t size;
     gps_navigation_message_callback navigation_message_callback;
+    gnss_navigation_message_callback gnss_navigation_message_callback;
 } GpsNavigationMessageCallbacks;
 
 #define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS             0
diff --git a/include/hardware/gps_internal.h b/include/hardware/gps_internal.h
new file mode 100644 (file)
index 0000000..6a3833b
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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_HARDWARE_GPS_INTERNAL_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+
+#include "hardware/gps.h"
+
+/****************************************************************************
+ * This file contains legacy structs that are deprecated/retired from gps.h *
+ ****************************************************************************/
+
+__BEGIN_DECLS
+
+/**
+ * Legacy GPS callback structure.
+ * Deprecated, to be removed in the next Android release.
+ * Use GpsCallbacks instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsCallbacks_v1) */
+    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_v1;
+
+#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.
+
+/**
+ * Legacy struct to represent the status of AGPS.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v1) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+} AGpsStatus_v1;
+
+#pragma pack(pop)
+
+/**
+ * Legacy struct to represent the status of AGPS augmented with a IPv4 address
+ * field.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v2) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+
+    /*-------------------- New fields in _v2 --------------------*/
+
+    uint32_t        ipaddr;
+} AGpsStatus_v2;
+
+/**
+ * Legacy extended interface for AGPS support.
+ * See AGpsInterface_v2 for more information.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface_v1) */
+    size_t          size;
+    void  (*init)( AGpsCallbacks* callbacks );
+    int  (*data_conn_open)( const char* apn );
+    int  (*data_conn_closed)();
+    int  (*data_conn_failed)();
+    int  (*set_server)( AGpsType type, const char* hostname, int port );
+} AGpsInterface_v1;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H */
index aa466b3..61218bb 100644 (file)
@@ -37,42 +37,6 @@ __BEGIN_DECLS
 
 /*****************************************************************************/
 
-/**
- * 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
diff --git a/include/hardware/hwcomposer2.h b/include/hardware/hwcomposer2.h
new file mode 100644 (file)
index 0000000..a51efd7
--- /dev/null
@@ -0,0 +1,1955 @@
+/*
+ * Copyright 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_HWCOMPOSER2_H
+#define ANDROID_HARDWARE_HWCOMPOSER2_H
+
+#include <hardware/hardware.h>
+
+#include "hwcomposer_defs.h"
+
+__BEGIN_DECLS
+
+/*
+ * Enums
+ *
+ * For most of these enums, there is an invalid value defined to be 0. This is
+ * an attempt to catch uninitialized fields, and these values should not be
+ * used.
+ */
+
+/* Display attributes queryable through getDisplayAttribute */
+typedef enum {
+    HWC2_ATTRIBUTE_INVALID = 0,
+
+    /* Dimensions in pixels */
+    HWC2_ATTRIBUTE_WIDTH = 1,
+    HWC2_ATTRIBUTE_HEIGHT = 2,
+
+    /* Vsync period in nanoseconds */
+    HWC2_ATTRIBUTE_VSYNC_PERIOD = 3,
+
+    /* Dots per thousand inches (DPI * 1000). Scaling by 1000 allows these
+     * numbers to be stored in an int32_t without losing too much precision. If
+     * the DPI for a configuration is unavailable or is considered unreliable,
+     * the device may return -1 instead */
+    HWC2_ATTRIBUTE_DPI_X = 4,
+    HWC2_ATTRIBUTE_DPI_Y = 5,
+} hwc2_attribute_t;
+
+/* Blend modes, settable per layer */
+typedef enum {
+    HWC2_BLEND_MODE_INVALID = 0,
+
+    /* colorOut = colorSrc */
+    HWC2_BLEND_MODE_NONE = 1,
+
+    /* colorOut = colorSrc + colorDst * (1 - alphaSrc) */
+    HWC2_BLEND_MODE_PREMULTIPLIED = 2,
+
+    /* colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */
+    HWC2_BLEND_MODE_COVERAGE = 3,
+} hwc2_blend_mode_t;
+
+/* See the 'Callbacks' section for more detailed descriptions of what these
+ * functions do */
+typedef enum {
+    HWC2_CALLBACK_INVALID = 0,
+    HWC2_CALLBACK_HOTPLUG = 1,
+    HWC2_CALLBACK_REFRESH = 2,
+    HWC2_CALLBACK_VSYNC = 3,
+} hwc2_callback_descriptor_t;
+
+/* Optional capabilities which may be supported by some devices. The particular
+ * set of supported capabilities for a given device may be retrieved using
+ * getCapabilities. */
+typedef enum {
+    HWC2_CAPABILITY_INVALID = 0,
+
+    /* Specifies that the device supports sideband stream layers, for which
+     * buffer content updates and other synchronization will not be provided
+     * through the usual validate/present cycle and must be handled by an
+     * external implementation-defined mechanism. Only changes to layer state
+     * (such as position, size, etc.) need to be performed through the
+     * validate/present cycle. */
+    HWC2_CAPABILITY_SIDEBAND_STREAM = 1,
+} hwc2_capability_t;
+
+/* Possible composition types for a given layer */
+typedef enum {
+    HWC2_COMPOSITION_INVALID = 0,
+
+    /* The client will composite this layer into the client target buffer
+     * (provided to the device through setClientTarget).
+     *
+     * The device must not request any composition type changes for layers of
+     * this type. */
+    HWC2_COMPOSITION_CLIENT = 1,
+
+    /* The device will handle the composition of this layer through a hardware
+     * overlay or other similar means.
+     *
+     * Upon validateDisplay, the device may request a change from this type to
+     * HWC2_COMPOSITION_CLIENT. */
+    HWC2_COMPOSITION_DEVICE = 2,
+
+    /* The device will render this layer using the color set through
+     * setLayerColor. If this functionality is not supported on a layer that the
+     * client sets to HWC2_COMPOSITION_SOLID_COLOR, the device must request that
+     * the composition type of that layer is changed to HWC2_COMPOSITION_CLIENT
+     * upon the next call to validateDisplay.
+     *
+     * Upon validateDisplay, the device may request a change from this type to
+     * HWC2_COMPOSITION_CLIENT. */
+    HWC2_COMPOSITION_SOLID_COLOR = 3,
+
+    /* Similar to DEVICE, but the position of this layer may also be set
+     * asynchronously through setCursorPosition. If this functionality is not
+     * supported on a layer that the client sets to HWC2_COMPOSITION_CURSOR, the
+     * device must request that the composition type of that layer is changed to
+     * HWC2_COMPOSITION_CLIENT upon the next call to validateDisplay.
+     *
+     * Upon validateDisplay, the device may request a change from this type to
+     * either HWC2_COMPOSITION_DEVICE or HWC2_COMPOSITION_CLIENT. Changing to
+     * HWC2_COMPOSITION_DEVICE will prevent the use of setCursorPosition but
+     * still permit the device to composite the layer. */
+    HWC2_COMPOSITION_CURSOR = 4,
+
+    /* The device will handle the composition of this layer, as well as its
+     * buffer updates and content synchronization. Only supported on devices
+     * which provide HWC2_CAPABILITY_SIDEBAND_STREAM.
+     *
+     * Upon validateDisplay, the device may request a change from this type to
+     * either HWC2_COMPOSITION_DEVICE or HWC2_COMPOSITION_CLIENT, but it is
+     * unlikely that content will display correctly in these cases. */
+    HWC2_COMPOSITION_SIDEBAND = 5,
+} hwc2_composition_t;
+
+/* Possible connection options from the hotplug callback */
+typedef enum {
+    HWC2_CONNECTION_INVALID = 0,
+
+    /* The display has been connected */
+    HWC2_CONNECTION_CONNECTED = 1,
+
+    /* The display has been disconnected */
+    HWC2_CONNECTION_DISCONNECTED = 2,
+} hwc2_connection_t;
+
+/* Display requests returned by getDisplayRequests */
+typedef enum {
+    /* Instructs the client to provide a new client target buffer, even if no
+     * layers are marked for client composition. */
+    HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET = 1 << 0,
+
+    /* Instructs the client to write the result of client composition directly
+     * into the virtual display output buffer. If any of the layers are not
+     * marked as HWC2_COMPOSITION_CLIENT or the given display is not a virtual
+     * display, this request has no effect. */
+    HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT = 1 << 1,
+} hwc2_display_request_t;
+
+/* Display types returned by getDisplayType */
+typedef enum {
+    HWC2_DISPLAY_TYPE_INVALID = 0,
+
+    /* All physical displays, including both internal displays and hotpluggable
+     * external displays */
+    HWC2_DISPLAY_TYPE_PHYSICAL = 1,
+
+    /* Virtual displays created by createVirtualDisplay */
+    HWC2_DISPLAY_TYPE_VIRTUAL = 2,
+} hwc2_display_type_t;
+
+/* Return codes from all functions */
+typedef enum {
+    HWC2_ERROR_NONE = 0,
+    HWC2_ERROR_BAD_CONFIG,
+    HWC2_ERROR_BAD_DISPLAY,
+    HWC2_ERROR_BAD_LAYER,
+    HWC2_ERROR_BAD_PARAMETER,
+    HWC2_ERROR_HAS_CHANGES,
+    HWC2_ERROR_NO_RESOURCES,
+    HWC2_ERROR_NOT_VALIDATED,
+    HWC2_ERROR_UNSUPPORTED,
+} hwc2_error_t;
+
+/* Function descriptors for use with getFunction */
+typedef enum {
+    HWC2_FUNCTION_INVALID = 0,
+    HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
+    HWC2_FUNCTION_CREATE_LAYER,
+    HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
+    HWC2_FUNCTION_DESTROY_LAYER,
+    HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+    HWC2_FUNCTION_DUMP,
+    HWC2_FUNCTION_GET_ACTIVE_CONFIG,
+    HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+    HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+    HWC2_FUNCTION_GET_COLOR_MODES,
+    HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
+    HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
+    HWC2_FUNCTION_GET_DISPLAY_NAME,
+    HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
+    HWC2_FUNCTION_GET_DISPLAY_TYPE,
+    HWC2_FUNCTION_GET_DOZE_SUPPORT,
+    HWC2_FUNCTION_GET_HDR_CAPABILITIES,
+    HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+    HWC2_FUNCTION_GET_RELEASE_FENCES,
+    HWC2_FUNCTION_PRESENT_DISPLAY,
+    HWC2_FUNCTION_REGISTER_CALLBACK,
+    HWC2_FUNCTION_SET_ACTIVE_CONFIG,
+    HWC2_FUNCTION_SET_CLIENT_TARGET,
+    HWC2_FUNCTION_SET_COLOR_MODE,
+    HWC2_FUNCTION_SET_COLOR_TRANSFORM,
+    HWC2_FUNCTION_SET_CURSOR_POSITION,
+    HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
+    HWC2_FUNCTION_SET_LAYER_BUFFER,
+    HWC2_FUNCTION_SET_LAYER_COLOR,
+    HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+    HWC2_FUNCTION_SET_LAYER_DATASPACE,
+    HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
+    HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
+    HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
+    HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
+    HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+    HWC2_FUNCTION_SET_LAYER_TRANSFORM,
+    HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+    HWC2_FUNCTION_SET_LAYER_Z_ORDER,
+    HWC2_FUNCTION_SET_OUTPUT_BUFFER,
+    HWC2_FUNCTION_SET_POWER_MODE,
+    HWC2_FUNCTION_SET_VSYNC_ENABLED,
+    HWC2_FUNCTION_VALIDATE_DISPLAY,
+} hwc2_function_descriptor_t;
+
+/* Layer requests returned from getDisplayRequests */
+typedef enum {
+    /* The client should clear its target with transparent pixels where this
+     * layer would be. The client may ignore this request if the layer must be
+     * blended. */
+    HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET = 1 << 0,
+} hwc2_layer_request_t;
+
+/* Power modes for use with setPowerMode */
+typedef enum {
+    /* The display is fully off (blanked) */
+    HWC2_POWER_MODE_OFF = 0,
+
+    /* These are optional low power modes. getDozeSupport may be called to
+     * determine whether a given display supports these modes. */
+
+    /* 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 HWC2_POWER_MODE_ON, but with greater efficiency. */
+    HWC2_POWER_MODE_DOZE = 1,
+
+    /* The display is configured as in HWC2_POWER_MODE_DOZE but may stop
+     * applying display updates from the client. This is effectively a hint to
+     * the device that drawing to the display has been suspended and that the
+     * the device should remain on in a low power state and continue displaying
+     * its current contents indefinitely until the power mode changes.
+     *
+     * This mode may also be used as a signal to enable hardware-based doze
+     * functionality. In this case, the device is free to take over the display
+     * and manage it autonomously to implement a low power always-on display. */
+    HWC2_POWER_MODE_DOZE_SUSPEND = 3,
+
+    /* The display is fully on */
+    HWC2_POWER_MODE_ON = 2,
+} hwc2_power_mode_t;
+
+/* Vsync values passed to setVsyncEnabled */
+typedef enum {
+    HWC2_VSYNC_INVALID = 0,
+
+    /* Enable vsync */
+    HWC2_VSYNC_ENABLE = 1,
+
+    /* Disable vsync */
+    HWC2_VSYNC_DISABLE = 2,
+} hwc2_vsync_t;
+
+/*
+ * Stringification Functions
+ */
+
+#ifdef HWC2_INCLUDE_STRINGIFICATION
+
+static inline const char* getAttributeName(hwc2_attribute_t attribute) {
+    switch (attribute) {
+        case HWC2_ATTRIBUTE_INVALID: return "Invalid";
+        case HWC2_ATTRIBUTE_WIDTH: return "Width";
+        case HWC2_ATTRIBUTE_HEIGHT: return "Height";
+        case HWC2_ATTRIBUTE_VSYNC_PERIOD: return "VsyncPeriod";
+        case HWC2_ATTRIBUTE_DPI_X: return "DpiX";
+        case HWC2_ATTRIBUTE_DPI_Y: return "DpiY";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getBlendModeName(hwc2_blend_mode_t mode) {
+    switch (mode) {
+        case HWC2_BLEND_MODE_INVALID: return "Invalid";
+        case HWC2_BLEND_MODE_NONE: return "None";
+        case HWC2_BLEND_MODE_PREMULTIPLIED: return "Premultiplied";
+        case HWC2_BLEND_MODE_COVERAGE: return "Coverage";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getCallbackDescriptorName(
+        hwc2_callback_descriptor_t desc) {
+    switch (desc) {
+        case HWC2_CALLBACK_INVALID: return "Invalid";
+        case HWC2_CALLBACK_HOTPLUG: return "Hotplug";
+        case HWC2_CALLBACK_REFRESH: return "Refresh";
+        case HWC2_CALLBACK_VSYNC: return "Vsync";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getCapabilityName(hwc2_capability_t capability) {
+    switch (capability) {
+        case HWC2_CAPABILITY_INVALID: return "Invalid";
+        case HWC2_CAPABILITY_SIDEBAND_STREAM: return "SidebandStream";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getCompositionName(hwc2_composition_t composition) {
+    switch (composition) {
+        case HWC2_COMPOSITION_INVALID: return "Invalid";
+        case HWC2_COMPOSITION_CLIENT: return "Client";
+        case HWC2_COMPOSITION_DEVICE: return "Device";
+        case HWC2_COMPOSITION_SOLID_COLOR: return "SolidColor";
+        case HWC2_COMPOSITION_CURSOR: return "Cursor";
+        case HWC2_COMPOSITION_SIDEBAND: return "Sideband";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getConnectionName(hwc2_connection_t connection) {
+    switch (connection) {
+        case HWC2_CONNECTION_INVALID: return "Invalid";
+        case HWC2_CONNECTION_CONNECTED: return "Connected";
+        case HWC2_CONNECTION_DISCONNECTED: return "Disconnected";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getDisplayRequestName(
+        hwc2_display_request_t request) {
+    switch (request) {
+        case 0: return "None";
+        case HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET: return "FlipClientTarget";
+        case HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT:
+            return "WriteClientTargetToOutput";
+        case HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET |
+                HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT:
+            return "FlipClientTarget|WriteClientTargetToOutput";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getDisplayTypeName(hwc2_display_type_t type) {
+    switch (type) {
+        case HWC2_DISPLAY_TYPE_INVALID: return "Invalid";
+        case HWC2_DISPLAY_TYPE_PHYSICAL: return "Physical";
+        case HWC2_DISPLAY_TYPE_VIRTUAL: return "Virtual";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getErrorName(hwc2_error_t error) {
+    switch (error) {
+        case HWC2_ERROR_NONE: return "None";
+        case HWC2_ERROR_BAD_CONFIG: return "BadConfig";
+        case HWC2_ERROR_BAD_DISPLAY: return "BadDisplay";
+        case HWC2_ERROR_BAD_LAYER: return "BadLayer";
+        case HWC2_ERROR_BAD_PARAMETER: return "BadParameter";
+        case HWC2_ERROR_HAS_CHANGES: return "HasChanges";
+        case HWC2_ERROR_NO_RESOURCES: return "NoResources";
+        case HWC2_ERROR_NOT_VALIDATED: return "NotValidated";
+        case HWC2_ERROR_UNSUPPORTED: return "Unsupported";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getFunctionDescriptorName(
+        hwc2_function_descriptor_t desc) {
+    switch (desc) {
+        case HWC2_FUNCTION_INVALID: return "Invalid";
+        case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES:
+            return "AcceptDisplayChanges";
+        case HWC2_FUNCTION_CREATE_LAYER: return "CreateLayer";
+        case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY:
+            return "CreateVirtualDisplay";
+        case HWC2_FUNCTION_DESTROY_LAYER: return "DestroyLayer";
+        case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY:
+            return "DestroyVirtualDisplay";
+        case HWC2_FUNCTION_DUMP: return "Dump";
+        case HWC2_FUNCTION_GET_ACTIVE_CONFIG: return "GetActiveConfig";
+        case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES:
+            return "GetChangedCompositionTypes";
+        case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT:
+            return "GetClientTargetSupport";
+        case HWC2_FUNCTION_GET_COLOR_MODES: return "GetColorModes";
+        case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE: return "GetDisplayAttribute";
+        case HWC2_FUNCTION_GET_DISPLAY_CONFIGS: return "GetDisplayConfigs";
+        case HWC2_FUNCTION_GET_DISPLAY_NAME: return "GetDisplayName";
+        case HWC2_FUNCTION_GET_DISPLAY_REQUESTS: return "GetDisplayRequests";
+        case HWC2_FUNCTION_GET_DISPLAY_TYPE: return "GetDisplayType";
+        case HWC2_FUNCTION_GET_DOZE_SUPPORT: return "GetDozeSupport";
+        case HWC2_FUNCTION_GET_HDR_CAPABILITIES: return "GetHdrCapabilities";
+        case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT:
+            return "GetMaxVirtualDisplayCount";
+        case HWC2_FUNCTION_GET_RELEASE_FENCES: return "GetReleaseFences";
+        case HWC2_FUNCTION_PRESENT_DISPLAY: return "PresentDisplay";
+        case HWC2_FUNCTION_REGISTER_CALLBACK: return "RegisterCallback";
+        case HWC2_FUNCTION_SET_ACTIVE_CONFIG: return "SetActiveConfig";
+        case HWC2_FUNCTION_SET_CLIENT_TARGET: return "SetClientTarget";
+        case HWC2_FUNCTION_SET_COLOR_MODE: return "SetColorMode";
+        case HWC2_FUNCTION_SET_COLOR_TRANSFORM: return "SetColorTransform";
+        case HWC2_FUNCTION_SET_CURSOR_POSITION: return "SetCursorPosition";
+        case HWC2_FUNCTION_SET_LAYER_BLEND_MODE: return "SetLayerBlendMode";
+        case HWC2_FUNCTION_SET_LAYER_BUFFER: return "SetLayerBuffer";
+        case HWC2_FUNCTION_SET_LAYER_COLOR: return "SetLayerColor";
+        case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE:
+            return "SetLayerCompositionType";
+        case HWC2_FUNCTION_SET_LAYER_DATASPACE: return "SetLayerDataspace";
+        case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME:
+            return "SetLayerDisplayFrame";
+        case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA: return "SetLayerPlaneAlpha";
+        case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM:
+            return "SetLayerSidebandStream";
+        case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP: return "SetLayerSourceCrop";
+        case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE:
+            return "SetLayerSurfaceDamage";
+        case HWC2_FUNCTION_SET_LAYER_TRANSFORM: return "SetLayerTransform";
+        case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION:
+            return "SetLayerVisibleRegion";
+        case HWC2_FUNCTION_SET_LAYER_Z_ORDER: return "SetLayerZOrder";
+        case HWC2_FUNCTION_SET_OUTPUT_BUFFER: return "SetOutputBuffer";
+        case HWC2_FUNCTION_SET_POWER_MODE: return "SetPowerMode";
+        case HWC2_FUNCTION_SET_VSYNC_ENABLED: return "SetVsyncEnabled";
+        case HWC2_FUNCTION_VALIDATE_DISPLAY: return "ValidateDisplay";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getLayerRequestName(hwc2_layer_request_t request) {
+    switch (request) {
+        case 0: return "None";
+        case HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET: return "ClearClientTarget";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getPowerModeName(hwc2_power_mode_t mode) {
+    switch (mode) {
+        case HWC2_POWER_MODE_OFF: return "Off";
+        case HWC2_POWER_MODE_DOZE_SUSPEND: return "DozeSuspend";
+        case HWC2_POWER_MODE_DOZE: return "Doze";
+        case HWC2_POWER_MODE_ON: return "On";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getTransformName(hwc_transform_t transform) {
+    switch (transform) {
+        case 0: return "None";
+        case HWC_TRANSFORM_FLIP_H: return "FlipH";
+        case HWC_TRANSFORM_FLIP_V: return "FlipV";
+        case HWC_TRANSFORM_ROT_90: return "Rotate90";
+        case HWC_TRANSFORM_ROT_180: return "Rotate180";
+        case HWC_TRANSFORM_ROT_270: return "Rotate270";
+        case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90";
+        case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90";
+        default: return "Unknown";
+    }
+}
+
+static inline const char* getVsyncName(hwc2_vsync_t vsync) {
+    switch (vsync) {
+        case HWC2_VSYNC_INVALID: return "Invalid";
+        case HWC2_VSYNC_ENABLE: return "Enable";
+        case HWC2_VSYNC_DISABLE: return "Disable";
+        default: return "Unknown";
+    }
+}
+
+#define TO_STRING(E, T, printer) \
+    inline std::string to_string(E value) { return printer(value); } \
+    inline std::string to_string(T value) { return to_string(static_cast<E>(value)); }
+#else // !HWC2_INCLUDE_STRINGIFICATION
+#define TO_STRING(name, printer)
+#endif // HWC2_INCLUDE_STRINGIFICATION
+
+/*
+ * C++11 features
+ */
+
+#ifdef HWC2_USE_CPP11
+__END_DECLS
+
+#ifdef HWC2_INCLUDE_STRINGIFICATION
+#include <string>
+#endif
+
+namespace HWC2 {
+
+enum class Attribute : int32_t {
+    Invalid = HWC2_ATTRIBUTE_INVALID,
+    Width = HWC2_ATTRIBUTE_WIDTH,
+    Height = HWC2_ATTRIBUTE_HEIGHT,
+    VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
+    DpiX = HWC2_ATTRIBUTE_DPI_X,
+    DpiY = HWC2_ATTRIBUTE_DPI_Y,
+};
+TO_STRING(hwc2_attribute_t, Attribute, getAttributeName)
+
+enum class BlendMode : int32_t {
+    Invalid = HWC2_BLEND_MODE_INVALID,
+    None = HWC2_BLEND_MODE_NONE,
+    Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED,
+    Coverage = HWC2_BLEND_MODE_COVERAGE,
+};
+TO_STRING(hwc2_blend_mode_t, BlendMode, getBlendModeName)
+
+enum class Callback : int32_t {
+    Invalid = HWC2_CALLBACK_INVALID,
+    Hotplug = HWC2_CALLBACK_HOTPLUG,
+    Refresh = HWC2_CALLBACK_REFRESH,
+    Vsync = HWC2_CALLBACK_VSYNC,
+};
+TO_STRING(hwc2_callback_descriptor_t, Callback, getCallbackDescriptorName)
+
+enum class Capability : int32_t {
+    Invalid = HWC2_CAPABILITY_INVALID,
+    SidebandStream = HWC2_CAPABILITY_SIDEBAND_STREAM,
+};
+TO_STRING(hwc2_capability_t, Capability, getCapabilityName)
+
+enum class Composition : int32_t {
+    Invalid = HWC2_COMPOSITION_INVALID,
+    Client = HWC2_COMPOSITION_CLIENT,
+    Device = HWC2_COMPOSITION_DEVICE,
+    SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
+    Cursor = HWC2_COMPOSITION_CURSOR,
+    Sideband = HWC2_COMPOSITION_SIDEBAND,
+};
+TO_STRING(hwc2_composition_t, Composition, getCompositionName)
+
+enum class Connection : int32_t {
+    Invalid = HWC2_CONNECTION_INVALID,
+    Connected = HWC2_CONNECTION_CONNECTED,
+    Disconnected = HWC2_CONNECTION_DISCONNECTED,
+};
+TO_STRING(hwc2_connection_t, Connection, getConnectionName)
+
+enum class DisplayRequest : int32_t {
+    FlipClientTarget = HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET,
+    WriteClientTargetToOutput =
+        HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT,
+};
+TO_STRING(hwc2_display_request_t, DisplayRequest, getDisplayRequestName)
+
+enum class DisplayType : int32_t {
+    Invalid = HWC2_DISPLAY_TYPE_INVALID,
+    Physical = HWC2_DISPLAY_TYPE_PHYSICAL,
+    Virtual = HWC2_DISPLAY_TYPE_VIRTUAL,
+};
+TO_STRING(hwc2_display_type_t, DisplayType, getDisplayTypeName)
+
+enum class Error : int32_t {
+    None = HWC2_ERROR_NONE,
+    BadConfig = HWC2_ERROR_BAD_CONFIG,
+    BadDisplay = HWC2_ERROR_BAD_DISPLAY,
+    BadLayer = HWC2_ERROR_BAD_LAYER,
+    BadParameter = HWC2_ERROR_BAD_PARAMETER,
+    HasChanges = HWC2_ERROR_HAS_CHANGES,
+    NoResources = HWC2_ERROR_NO_RESOURCES,
+    NotValidated = HWC2_ERROR_NOT_VALIDATED,
+    Unsupported = HWC2_ERROR_UNSUPPORTED,
+};
+TO_STRING(hwc2_error_t, Error, getErrorName)
+
+enum class FunctionDescriptor : int32_t {
+    Invalid = HWC2_FUNCTION_INVALID,
+    AcceptDisplayChanges = HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
+    CreateLayer = HWC2_FUNCTION_CREATE_LAYER,
+    CreateVirtualDisplay = HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
+    DestroyLayer = HWC2_FUNCTION_DESTROY_LAYER,
+    DestroyVirtualDisplay = HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+    Dump = HWC2_FUNCTION_DUMP,
+    GetActiveConfig = HWC2_FUNCTION_GET_ACTIVE_CONFIG,
+    GetChangedCompositionTypes = HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+    GetClientTargetSupport = HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+    GetColorModes = HWC2_FUNCTION_GET_COLOR_MODES,
+    GetDisplayAttribute = HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
+    GetDisplayConfigs = HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
+    GetDisplayName = HWC2_FUNCTION_GET_DISPLAY_NAME,
+    GetDisplayRequests = HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
+    GetDisplayType = HWC2_FUNCTION_GET_DISPLAY_TYPE,
+    GetDozeSupport = HWC2_FUNCTION_GET_DOZE_SUPPORT,
+    GetHdrCapabilities = HWC2_FUNCTION_GET_HDR_CAPABILITIES,
+    GetMaxVirtualDisplayCount = HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+    GetReleaseFences = HWC2_FUNCTION_GET_RELEASE_FENCES,
+    PresentDisplay = HWC2_FUNCTION_PRESENT_DISPLAY,
+    RegisterCallback = HWC2_FUNCTION_REGISTER_CALLBACK,
+    SetActiveConfig = HWC2_FUNCTION_SET_ACTIVE_CONFIG,
+    SetClientTarget = HWC2_FUNCTION_SET_CLIENT_TARGET,
+    SetColorMode = HWC2_FUNCTION_SET_COLOR_MODE,
+    SetColorTransform = HWC2_FUNCTION_SET_COLOR_TRANSFORM,
+    SetCursorPosition = HWC2_FUNCTION_SET_CURSOR_POSITION,
+    SetLayerBlendMode = HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
+    SetLayerBuffer = HWC2_FUNCTION_SET_LAYER_BUFFER,
+    SetLayerColor = HWC2_FUNCTION_SET_LAYER_COLOR,
+    SetLayerCompositionType = HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+    SetLayerDataspace = HWC2_FUNCTION_SET_LAYER_DATASPACE,
+    SetLayerDisplayFrame = HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
+    SetLayerPlaneAlpha = HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
+    SetLayerSidebandStream = HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
+    SetLayerSourceCrop = HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
+    SetLayerSurfaceDamage = HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+    SetLayerTransform = HWC2_FUNCTION_SET_LAYER_TRANSFORM,
+    SetLayerVisibleRegion = HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+    SetLayerZOrder = HWC2_FUNCTION_SET_LAYER_Z_ORDER,
+    SetOutputBuffer = HWC2_FUNCTION_SET_OUTPUT_BUFFER,
+    SetPowerMode = HWC2_FUNCTION_SET_POWER_MODE,
+    SetVsyncEnabled = HWC2_FUNCTION_SET_VSYNC_ENABLED,
+    ValidateDisplay = HWC2_FUNCTION_VALIDATE_DISPLAY,
+};
+TO_STRING(hwc2_function_descriptor_t, FunctionDescriptor,
+        getFunctionDescriptorName)
+
+enum class LayerRequest : int32_t {
+    ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET,
+};
+TO_STRING(hwc2_layer_request_t, LayerRequest, getLayerRequestName)
+
+enum class PowerMode : int32_t {
+    Off = HWC2_POWER_MODE_OFF,
+    DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND,
+    Doze = HWC2_POWER_MODE_DOZE,
+    On = HWC2_POWER_MODE_ON,
+};
+TO_STRING(hwc2_power_mode_t, PowerMode, getPowerModeName)
+
+enum class Transform : int32_t {
+    None = 0,
+    FlipH = HWC_TRANSFORM_FLIP_H,
+    FlipV = HWC_TRANSFORM_FLIP_V,
+    Rotate90 = HWC_TRANSFORM_ROT_90,
+    Rotate180 = HWC_TRANSFORM_ROT_180,
+    Rotate270 = HWC_TRANSFORM_ROT_270,
+    FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90,
+    FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90,
+};
+TO_STRING(hwc_transform_t, Transform, getTransformName)
+
+enum class Vsync : int32_t {
+    Invalid = HWC2_VSYNC_INVALID,
+    Enable = HWC2_VSYNC_ENABLE,
+    Disable = HWC2_VSYNC_DISABLE,
+};
+TO_STRING(hwc2_vsync_t, Vsync, getVsyncName)
+
+} // namespace HWC2
+
+__BEGIN_DECLS
+#endif // HWC2_USE_CPP11
+
+/*
+ * Typedefs
+ */
+
+typedef void (*hwc2_function_pointer_t)();
+
+typedef void* hwc2_callback_data_t;
+typedef uint32_t hwc2_config_t;
+typedef uint64_t hwc2_display_t;
+typedef uint64_t hwc2_layer_t;
+
+/*
+ * Device Struct
+ */
+
+typedef struct hwc2_device {
+    /* Must be the first member of this struct, since a pointer to this struct
+     * will be generated by casting from a hw_device_t* */
+    struct hw_device_t common;
+
+    /* getCapabilities(..., outCount, outCapabilities)
+     *
+     * Provides a list of capabilities (described in the definition of
+     * hwc2_capability_t above) supported by this device. This list must
+     * not change after the device has been loaded.
+     *
+     * Parameters:
+     *   outCount - if outCapabilities was NULL, the number of capabilities
+     *       which would have been returned; if outCapabilities was not NULL,
+     *       the number of capabilities returned, which must not exceed the
+     *       value stored in outCount prior to the call
+     *   outCapabilities - a list of capabilities supported by this device; may
+     *       be NULL, in which case this function must write into outCount the
+     *       number of capabilities which would have been written into
+     *       outCapabilities
+     */
+    void (*getCapabilities)(struct hwc2_device* device, uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities);
+
+    /* getFunction(..., descriptor)
+     *
+     * Returns a function pointer which implements the requested description.
+     *
+     * Parameters:
+     *   descriptor - the function to return
+     *
+     * Returns either a function pointer implementing the requested descriptor
+     *   or NULL if the described function is not supported by this device.
+     */
+    hwc2_function_pointer_t (*getFunction)(struct hwc2_device* device,
+            int32_t /*hwc2_function_descriptor_t*/ descriptor);
+} hwc2_device_t;
+
+static inline int hwc2_open(const struct hw_module_t* module,
+        hwc2_device_t** device) {
+    return module->methods->open(module, HWC_HARDWARE_COMPOSER,
+            (struct hw_device_t**) device);
+}
+
+static inline int hwc2_close(hwc2_device_t* device) {
+    return device->common.close(&device->common);
+}
+
+/*
+ * Callbacks
+ *
+ * All of these callbacks take as their first parameter the callbackData which
+ * was provided at the time of callback registration, so this parameter is
+ * omitted from the described parameter lists.
+ */
+
+/* hotplug(..., display, connected)
+ * Descriptor: HWC2_CALLBACK_HOTPLUG
+ * Will be provided to all HWC2 devices
+ *
+ * Notifies the client that the given display has either been connected or
+ * disconnected. Every active display (even a built-in physical display) must
+ * trigger at least one hotplug notification, even if it only occurs immediately
+ * after callback registration.
+ *
+ * The client may call back into the device on the same thread to query display
+ * properties (such as width, height, and vsync period), and other threads may
+ * call into the device while the callback is in progress. The device must
+ * serialize calls to this callback such that only one thread is calling it at a
+ * time.
+ *
+ * Displays which have been connected are assumed to be in HWC2_POWER_MODE_OFF,
+ * and the vsync callback should not be called for a display until vsync has
+ * been enabled with setVsyncEnabled.
+ *
+ * Parameters:
+ *   display - the display which has been hotplugged
+ *   connected - whether the display has been connected or disconnected
+ */
+typedef void (*HWC2_PFN_HOTPLUG)(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int32_t /*hwc2_connection_t*/ connected);
+
+/* refresh(..., display)
+ * Descriptor: HWC2_CALLBACK_REFRESH
+ * Will be provided to all HWC2 devices
+ *
+ * Notifies the client to trigger a screen refresh. This forces all layer state
+ * for this display to be resent, and the display to be validated and presented,
+ * even if there have been no changes.
+ *
+ * This refresh will occur some time after the callback is initiated, but not
+ * necessarily before it returns. This thread, however, is guaranteed not to
+ * call back into the device, thus it is safe to trigger this callback from
+ * other functions which call into the device.
+ *
+ * Parameters:
+ *   display - the display to refresh
+ */
+typedef void (*HWC2_PFN_REFRESH)(hwc2_callback_data_t callbackData,
+        hwc2_display_t display);
+
+/* vsync(..., display, timestamp)
+ * Descriptor: HWC2_CALLBACK_VSYNC
+ * Will be provided to all HWC2 devices
+ *
+ * Notifies the client that a vsync event has occurred. This callback must
+ * only be triggered when vsync is enabled for this display (through
+ * setVsyncEnabled).
+ *
+ * This callback should be triggered from a thread of at least
+ * HAL_PRIORITY_URGENT_DISPLAY with as little latency as possible, typically
+ * less than 0.5 ms. This thread is guaranteed not to call back into the device.
+ *
+ * Parameters:
+ *   display - the display which has received a vsync event
+ *   timestamp - the CLOCK_MONOTONIC time at which the vsync event occurred, in
+ *       nanoseconds
+ */
+typedef void (*HWC2_PFN_VSYNC)(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int64_t timestamp);
+
+/*
+ * Device Functions
+ *
+ * All of these functions take as their first parameter a device pointer, so
+ * this parameter is omitted from the described parameter lists.
+ */
+
+/* createVirtualDisplay(..., width, height, format, outDisplay)
+ * Descriptor: HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY
+ * Must be provided by all HWC2 devices
+ *
+ * Creates a new virtual display with the given width and height. The format
+ * passed into this function is the default format requested by the consumer of
+ * the virtual display output buffers. If a different format will be returned by
+ * the device, it should be returned in this parameter so it can be set properly
+ * when handing the buffers to the consumer.
+ *
+ * The display will be assumed to be on from the time the first frame is
+ * presented until the display is destroyed.
+ *
+ * Parameters:
+ *   width - width in pixels
+ *   height - height in pixels
+ *   format - prior to the call, the default output buffer format selected by
+ *       the consumer; after the call, the format the device will produce
+ *   outDisplay - the newly-created virtual display; pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_UNSUPPORTED - the width or height is too large for the device to
+ *       be able to create a virtual display
+ *   HWC2_ERROR_NO_RESOURCES - the device is unable to create a new virtual
+ *       display at this time
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_CREATE_VIRTUAL_DISPLAY)(
+        hwc2_device_t* device, uint32_t width, uint32_t height,
+        int32_t* /*android_pixel_format_t*/ format, hwc2_display_t* outDisplay);
+
+/* destroyVirtualDisplay(..., display)
+ * Descriptor: HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY
+ * Must be provided by all HWC2 devices
+ *
+ * Destroys a virtual display. After this call all resources consumed by this
+ * display may be freed by the device and any operations performed on this
+ * display should fail.
+ *
+ * Parameters:
+ *   display - the virtual display to destroy
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - the display handle which was passed in does not
+ *       refer to a virtual display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_DESTROY_VIRTUAL_DISPLAY)(
+        hwc2_device_t* device, hwc2_display_t display);
+
+/* dump(..., outSize, outBuffer)
+ * Descriptor: HWC2_FUNCTION_DUMP
+ * Must be provided by all HWC2 devices
+ *
+ * Retrieves implementation-defined debug information, which will be displayed
+ * during, for example, `dumpsys SurfaceFlinger`.
+ *
+ * If called with outBuffer == NULL, the device should store a copy of the
+ * desired output and return its length in bytes in outSize. If the device
+ * already has a stored copy, that copy should be purged and replaced with a
+ * fresh copy.
+ *
+ * If called with outBuffer != NULL, the device should copy its stored version
+ * of the output into outBuffer and store how many bytes of data it copied into
+ * outSize. Prior to this call, the client will have populated outSize with the
+ * maximum number of bytes outBuffer can hold. The device must not write more
+ * than this amount into outBuffer. If the device does not currently have a
+ * stored copy, then it should return 0 in outSize.
+ *
+ * Any data written into outBuffer need not be null-terminated.
+ *
+ * Parameters:
+ *   outSize - if outBuffer was NULL, the number of bytes needed to copy the
+ *       device's stored output; if outBuffer was not NULL, the number of bytes
+ *       written into it, which must not exceed the value stored in outSize
+ *       prior to the call; pointer will be non-NULL
+ *   outBuffer - the buffer to write the dump output into; may be NULL as
+ *       described above; data written into this buffer need not be
+ *       null-terminated
+ */
+typedef void (*HWC2_PFN_DUMP)(hwc2_device_t* device, uint32_t* outSize,
+        char* outBuffer);
+
+/* getMaxVirtualDisplayCount(...)
+ * Descriptor: HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT
+ * Must be provided by all HWC2 devices
+ *
+ * Returns the maximum number of virtual displays supported by this device
+ * (which may be 0). The client will not attempt to create more than this many
+ * virtual displays on this device. This number must not change for the lifetime
+ * of the device.
+ */
+typedef uint32_t (*HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT)(
+        hwc2_device_t* device);
+
+/* registerCallback(..., descriptor, callbackData, pointer)
+ * Descriptor: HWC2_FUNCTION_REGISTER_CALLBACK
+ * Must be provided by all HWC2 devices
+ *
+ * Provides a callback for the device to call. All callbacks take a callbackData
+ * item as the first parameter, so this value should be stored with the callback
+ * for later use. The callbackData may differ from one callback to another. If
+ * this function is called multiple times with the same descriptor, later
+ * callbacks replace earlier ones.
+ *
+ * Parameters:
+ *   descriptor - which callback should be set
+ *   callBackdata - opaque data which must be passed back through the callback
+ *   pointer - a non-NULL function pointer corresponding to the descriptor
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_PARAMETER - descriptor was invalid
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_REGISTER_CALLBACK)(
+        hwc2_device_t* device,
+        int32_t /*hwc2_callback_descriptor_t*/ descriptor,
+        hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+
+/*
+ * Display Functions
+ *
+ * All of these functions take as their first two parameters a device pointer
+ * and a display handle, so these parameters are omitted from the described
+ * parameter lists.
+ */
+
+/* acceptDisplayChanges(...)
+ * Descriptor: HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES
+ * Must be provided by all HWC2 devices
+ *
+ * Accepts the changes required by the device from the previous validateDisplay
+ * call (which may be queried using getChangedCompositionTypes) and revalidates
+ * the display. This function is equivalent to requesting the changed types from
+ * getChangedCompositionTypes, setting those types on the corresponding layers,
+ * and then calling validateDisplay again.
+ *
+ * After this call it must be valid to present this display. Calling this after
+ * validateDisplay returns 0 changes must succeed with HWC2_ERROR_NONE, but
+ * should have no other effect.
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_NOT_VALIDATED - validateDisplay has not been called
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_ACCEPT_DISPLAY_CHANGES)(
+        hwc2_device_t* device, hwc2_display_t display);
+
+/* createLayer(..., outLayer)
+ * Descriptor: HWC2_FUNCTION_CREATE_LAYER
+ * Must be provided by all HWC2 devices
+ *
+ * Creates a new layer on the given display.
+ *
+ * Parameters:
+ *   outLayer - the handle of the new layer; pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_NO_RESOURCES - the device was unable to create this layer
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_CREATE_LAYER)(hwc2_device_t* device,
+        hwc2_display_t display, hwc2_layer_t* outLayer);
+
+/* destroyLayer(..., layer)
+ * Descriptor: HWC2_FUNCTION_DESTROY_LAYER
+ * Must be provided by all HWC2 devices
+ *
+ * Destroys the given layer.
+ *
+ * Parameters:
+ *   layer - the handle of the layer to destroy
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_DESTROY_LAYER)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer);
+
+/* getActiveConfig(..., outConfig)
+ * Descriptor: HWC2_FUNCTION_GET_ACTIVE_CONFIG
+ * Must be provided by all HWC2 devices
+ *
+ * Retrieves which display configuration is currently active.
+ *
+ * If no display configuration is currently active, this function must return
+ * HWC2_ERROR_BAD_CONFIG and place no configuration handle in outConfig. It is
+ * the responsibility of the client to call setActiveConfig with a valid
+ * configuration before attempting to present anything on the display.
+ *
+ * Parameters:
+ *   outConfig - the currently active display configuration; pointer will be
+ *       non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_CONFIG - no configuration is currently active
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_ACTIVE_CONFIG)(
+        hwc2_device_t* device, hwc2_display_t display,
+        hwc2_config_t* outConfig);
+
+/* getChangedCompositionTypes(..., outNumElements, outLayers, outTypes)
+ * Descriptor: HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES
+ * Must be provided by all HWC2 devices
+ *
+ * Retrieves the layers for which the device requires a different composition
+ * type than had been set prior to the last call to validateDisplay. The client
+ * will either update its state with these types and call acceptDisplayChanges,
+ * or will set new types and attempt to validate the display again.
+ *
+ * outLayers and outTypes may be NULL to retrieve the number of elements which
+ * will be returned. The number of elements returned must be the same as the
+ * value returned in outNumTypes from the last call to validateDisplay.
+ *
+ * Parameters:
+ *   outNumElements - if outLayers or outTypes were NULL, the number of layers
+ *       and types which would have been returned; if both were non-NULL, the
+ *       number of elements returned in outLayers and outTypes, which must not
+ *       exceed the value stored in outNumElements prior to the call; pointer
+ *       will be non-NULL
+ *   outLayers - an array of layer handles
+ *   outTypes - an array of composition types, each corresponding to an element
+ *       of outLayers
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_NOT_VALIDATED - validateDisplay has not been called for this
+ *       display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES)(
+        hwc2_device_t* device, hwc2_display_t display,
+        uint32_t* outNumElements, hwc2_layer_t* outLayers,
+        int32_t* /*hwc2_composition_t*/ outTypes);
+
+/* getClientTargetSupport(..., width, height, format, dataspace)
+ * Descriptor: HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT
+ * Must be provided by all HWC2 devices
+ *
+ * Returns whether a client target with the given properties can be handled by
+ * the device.
+ *
+ * The valid formats can be found in android_pixel_format_t in
+ * <system/graphics.h>.
+ *
+ * For more about dataspaces, see setLayerDataspace.
+ *
+ * This function must return true for a client target with width and height
+ * equal to the active display configuration dimensions,
+ * HAL_PIXEL_FORMAT_RGBA_8888, and HAL_DATASPACE_UNKNOWN. It is not required to
+ * return true for any other configuration.
+ *
+ * Parameters:
+ *   width - client target width in pixels
+ *   height - client target height in pixels
+ *   format - client target format
+ *   dataspace - client target dataspace, as described in setLayerDataspace
+ *
+ * Returns HWC2_ERROR_NONE if the given configuration is supported or one of the
+ * following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_UNSUPPORTED - the given configuration is not supported
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_CLIENT_TARGET_SUPPORT)(
+        hwc2_device_t* device, hwc2_display_t display, uint32_t width,
+        uint32_t height, int32_t /*android_pixel_format_t*/ format,
+        int32_t /*android_dataspace_t*/ dataspace);
+
+/* getColorModes(..., outNumModes, outModes)
+ * Descriptor: HWC2_FUNCTION_GET_COLOR_MODES
+ * Must be provided by all HWC2 devices
+ *
+ * Returns the color modes supported on this display.
+ *
+ * The valid color modes can be found in android_color_mode_t in
+ * <system/graphics.h>. All HWC2 devices must support at least
+ * HAL_COLOR_MODE_NATIVE.
+ *
+ * outNumModes may be NULL to retrieve the number of modes which will be
+ * returned.
+ *
+ * Parameters:
+ *   outNumModes - if outModes was NULL, the number of modes which would have
+ *       been returned; if outModes was not NULL, the number of modes returned,
+ *       which must not exceed the value stored in outNumModes prior to the
+ *       call; pointer will be non-NULL
+ *   outModes - an array of color modes
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_COLOR_MODES)(
+        hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes,
+        int32_t* /*android_color_mode_t*/ outModes);
+
+/* getDisplayAttribute(..., config, attribute, outValue)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE
+ * Must be provided by all HWC2 devices
+ *
+ * Returns a display attribute value for a particular display configuration.
+ *
+ * Any attribute which is not supported or for which the value is unknown by the
+ * device must return a value of -1.
+ *
+ * Parameters:
+ *   config - the display configuration for which to return attribute values
+ *   attribute - the attribute to query
+ *   outValue - the value of the attribute; the pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_CONFIG - config does not name a valid configuration for this
+ *       display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_ATTRIBUTE)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+        int32_t /*hwc2_attribute_t*/ attribute, int32_t* outValue);
+
+/* getDisplayConfigs(..., outNumConfigs, outConfigs)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_CONFIGS
+ * Must be provided by all HWC2 devices
+ *
+ * Returns handles for all of the valid display configurations on this display.
+ *
+ * outConfigs may be NULL to retrieve the number of elements which will be
+ * returned.
+ *
+ * Parameters:
+ *   outNumConfigs - if outConfigs was NULL, the number of configurations which
+ *       would have been returned; if outConfigs was not NULL, the number of
+ *       configurations returned, which must not exceed the value stored in
+ *       outNumConfigs prior to the call; pointer will be non-NULL
+ *   outConfigs - an array of configuration handles
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_CONFIGS)(
+        hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumConfigs,
+        hwc2_config_t* outConfigs);
+
+/* getDisplayName(..., outSize, outName)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_NAME
+ * Must be provided by all HWC2 devices
+ *
+ * Returns a human-readable version of the display's name.
+ *
+ * outName may be NULL to retrieve the length of the name.
+ *
+ * Parameters:
+ *   outSize - if outName was NULL, the number of bytes needed to return the
+ *       name if outName was not NULL, the number of bytes written into it,
+ *       which must not exceed the value stored in outSize prior to the call;
+ *       pointer will be non-NULL
+ *   outName - the display's name
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_NAME)(
+        hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize,
+        char* outName);
+
+/* getDisplayRequests(..., outDisplayRequests, outNumElements, outLayers,
+ *     outLayerRequests)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_REQUESTS
+ * Must be provided by all HWC2 devices
+ *
+ * Returns the display requests and the layer requests required for the last
+ * validated configuration.
+ *
+ * Display requests provide information about how the client should handle the
+ * client target. Layer requests provide information about how the client
+ * should handle an individual layer.
+ *
+ * If outLayers or outLayerRequests is NULL, the required number of layers and
+ * requests must be returned in outNumElements, but this number may also be
+ * obtained from validateDisplay as outNumRequests (outNumElements must be equal
+ * to the value returned in outNumRequests from the last call to
+ * validateDisplay).
+ *
+ * Parameters:
+ *   outDisplayRequests - the display requests for the current validated state
+ *   outNumElements - if outLayers or outLayerRequests were NULL, the number of
+ *       elements which would have been returned, which must be equal to the
+ *       value returned in outNumRequests from the last validateDisplay call on
+ *       this display; if both were not NULL, the number of elements in
+ *       outLayers and outLayerRequests, which must not exceed the value stored
+ *       in outNumElements prior to the call; pointer will be non-NULL
+ *   outLayers - an array of layers which all have at least one request
+ *   outLayerRequests - the requests corresponding to each element of outLayers
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_NOT_VALIDATED - validateDisplay has not been called for this
+ *       display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_REQUESTS)(
+        hwc2_device_t* device, hwc2_display_t display,
+        int32_t* /*hwc2_display_request_t*/ outDisplayRequests,
+        uint32_t* outNumElements, hwc2_layer_t* outLayers,
+        int32_t* /*hwc2_layer_request_t*/ outLayerRequests);
+
+/* getDisplayType(..., outType)
+ * Descriptor: HWC2_FUNCTION_GET_DISPLAY_TYPE
+ * Must be provided by all HWC2 devices
+ *
+ * Returns whether the given display is a physical or virtual display.
+ *
+ * Parameters:
+ *   outType - the type of the display; pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DISPLAY_TYPE)(
+        hwc2_device_t* device, hwc2_display_t display,
+        int32_t* /*hwc2_display_type_t*/ outType);
+
+/* getDozeSupport(..., outSupport)
+ * Descriptor: HWC2_FUNCTION_GET_DOZE_SUPPORT
+ * Must be provided by all HWC2 devices
+ *
+ * Returns whether the given display supports HWC2_POWER_MODE_DOZE and
+ * HWC2_POWER_MODE_DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit over
+ * DOZE (see the definition of hwc2_power_mode_t for more information), but if
+ * both DOZE and DOZE_SUSPEND are no different from HWC2_POWER_MODE_ON, the
+ * device should not claim support.
+ *
+ * Parameters:
+ *   outSupport - whether the display supports doze modes (1 for yes, 0 for no);
+ *       pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_DOZE_SUPPORT)(
+        hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport);
+
+/* getHdrCapabilities(..., outNumTypes, outTypes, outMaxLuminance,
+ *     outMaxAverageLuminance, outMinLuminance)
+ * Descriptor: HWC2_FUNCTION_GET_HDR_CAPABILITIES
+ * Must be provided by all HWC2 devices
+ *
+ * Returns the high dynamic range (HDR) capabilities of the given display, which
+ * are invariant with regard to the active configuration.
+ *
+ * Displays which are not HDR-capable must return no types in outTypes and set
+ * outNumTypes to 0.
+ *
+ * If outTypes is NULL, the required number of HDR types must be returned in
+ * outNumTypes.
+ *
+ * Parameters:
+ *   outNumTypes - if outTypes was NULL, the number of types which would have
+ *       been returned; if it was not NULL, the number of types stored in
+ *       outTypes, which must not exceed the value stored in outNumTypes prior
+ *       to the call; pointer will be non-NULL
+ *   outTypes - an array of HDR types, may have 0 elements if the display is not
+ *       HDR-capable
+ *   outMaxLuminance - the desired content maximum luminance for this display in
+ *       cd/m^2; pointer will be non-NULL
+ *   outMaxAverageLuminance - the desired content maximum frame-average
+ *       luminance for this display in cd/m^2; pointer will be non-NULL
+ *   outMinLuminance - the desired content minimum luminance for this display in
+ *       cd/m^2; pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_HDR_CAPABILITIES)(
+        hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+        int32_t* /*android_hdr_t*/ outTypes, float* outMaxLuminance,
+        float* outMaxAverageLuminance, float* outMinLuminance);
+
+/* getReleaseFences(..., outNumElements, outLayers, outFences)
+ * Descriptor: HWC2_FUNCTION_GET_RELEASE_FENCES
+ * Must be provided by all HWC2 devices
+ *
+ * Retrieves the release fences for device layers on this display which will
+ * receive new buffer contents this frame.
+ *
+ * A release fence is a file descriptor referring to a sync fence object which
+ * will be signaled after the device has finished reading from the buffer
+ * presented in the prior frame. This indicates that it is safe to start writing
+ * to the buffer again. If a given layer's fence is not returned from this
+ * function, it will be assumed that the buffer presented on the previous frame
+ * is ready to be written.
+ *
+ * The fences returned by this function should be unique for each layer (even if
+ * they point to the same underlying sync object), and ownership of the fences
+ * is transferred to the client, which is responsible for closing them.
+ *
+ * If outLayers or outFences is NULL, the required number of layers and fences
+ * must be returned in outNumElements.
+ *
+ * Parameters:
+ *   outNumElements - if outLayers or outFences were NULL, the number of
+ *       elements which would have been returned; if both were not NULL, the
+ *       number of elements in outLayers and outFences, which must not exceed
+ *       the value stored in outNumElements prior to the call; pointer will be
+ *       non-NULL
+ *   outLayers - an array of layer handles
+ *   outFences - an array of sync fence file descriptors as described above,
+ *       each corresponding to an element of outLayers
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_GET_RELEASE_FENCES)(
+        hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumElements,
+        hwc2_layer_t* outLayers, int32_t* outFences);
+
+/* presentDisplay(..., outRetireFence)
+ * Descriptor: HWC2_FUNCTION_PRESENT_DISPLAY
+ * Must be provided by all HWC2 devices
+ *
+ * Presents the current display contents on the screen (or in the case of
+ * virtual displays, into the output buffer).
+ *
+ * Prior to calling this function, the display must be successfully validated
+ * with validateDisplay. Note that setLayerBuffer and setLayerSurfaceDamage
+ * specifically do not count as layer state, so if there are no other changes
+ * to the layer state (or to the buffer's properties as described in
+ * setLayerBuffer), then it is safe to call this function without first
+ * validating the display.
+ *
+ * If this call succeeds, outRetireFence will be populated with a file
+ * descriptor referring to a retire sync fence object. For physical displays,
+ * this fence will be signaled when the result of composition of the prior frame
+ * is no longer necessary (because it has been copied or replaced by this
+ * frame). For virtual displays, this fence will be signaled when writes to the
+ * output buffer have completed and it is safe to read from it.
+ *
+ * Parameters:
+ *   outRetireFence - a sync fence file descriptor as described above; pointer
+ *       will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_NO_RESOURCES - no valid output buffer has been set for a virtual
+ *       display
+ *   HWC2_ERROR_NOT_VALIDATED - validateDisplay has not successfully been called
+ *       for this display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_PRESENT_DISPLAY)(
+        hwc2_device_t* device, hwc2_display_t display, int32_t* outRetireFence);
+
+/* setActiveConfig(..., config)
+ * Descriptor: HWC2_FUNCTION_SET_ACTIVE_CONFIG
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the active configuration for this display. Upon returning, the given
+ * display configuration should be active and remain so until either this
+ * function is called again or the display is disconnected.
+ *
+ * Parameters:
+ *   config - the new display configuration
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_CONFIG - the configuration handle passed in is not valid for
+ *       this display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_ACTIVE_CONFIG)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config);
+
+/* setClientTarget(..., target, acquireFence, dataspace, damage)
+ * Descriptor: HWC2_FUNCTION_SET_CLIENT_TARGET
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the buffer handle which will receive the output of client composition.
+ * Layers marked as HWC2_COMPOSITION_CLIENT will be composited into this buffer
+ * prior to the call to presentDisplay, and layers not marked as
+ * HWC2_COMPOSITION_CLIENT should be composited with this buffer by the device.
+ *
+ * The buffer handle provided may be null if no layers are being composited by
+ * the client. This must not result in an error (unless an invalid display
+ * handle is also provided).
+ *
+ * Also provides a file descriptor referring to an acquire sync fence object,
+ * which will be signaled when it is safe to read from the client target buffer.
+ * If it is already safe to read from this buffer, -1 may be passed instead.
+ * The device must ensure that it is safe for the client to close this file
+ * descriptor at any point after this function is called.
+ *
+ * For more about dataspaces, see setLayerDataspace.
+ *
+ * The damage parameter describes a surface damage region as defined in the
+ * description of setLayerSurfaceDamage.
+ *
+ * Will be called before presentDisplay if any of the layers are marked as
+ * HWC2_COMPOSITION_CLIENT. If no layers are so marked, then it is not
+ * necessary to call this function. It is not necessary to call validateDisplay
+ * after changing the target through this function.
+ *
+ * Parameters:
+ *   target - the new target buffer
+ *   acquireFence - a sync fence file descriptor as described above
+ *   dataspace - the dataspace of the buffer, as described in setLayerDataspace
+ *   damage - the surface damage region
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - the new target handle was invalid
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_CLIENT_TARGET)(
+        hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target,
+        int32_t acquireFence, int32_t /*android_dataspace_t*/ dataspace,
+        hwc_region_t damage);
+
+/* setColorMode(..., mode)
+ * Descriptor: HWC2_FUNCTION_SET_COLOR_MODE
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the color mode of the given display.
+ *
+ * Upon returning from this function, the color mode change must have fully
+ * taken effect.
+ *
+ * The valid color modes can be found in android_color_mode_t in
+ * <system/graphics.h>. All HWC2 devices must support at least
+ * HAL_COLOR_MODE_NATIVE, and displays are assumed to be in this mode upon
+ * hotplug.
+ *
+ * Parameters:
+ *   mode - the mode to set
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - mode is not a valid color mode
+ *   HWC2_ERROR_UNSUPPORTED - mode is not supported on this display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_COLOR_MODE)(
+        hwc2_device_t* device, hwc2_display_t display,
+        int32_t /*android_color_mode_t*/ mode);
+
+/* setColorTransform(..., matrix, hint)
+ * Descriptor: HWC2_FUNCTION_SET_COLOR_TRANSFORM
+ * Must be provided by all HWC2 devices
+ *
+ * Sets a color transform which will be applied after composition.
+ *
+ * If hint is not HAL_COLOR_TRANSFORM_ARBITRARY, then the device may use the
+ * hint to apply the desired color transform instead of using the color matrix
+ * directly.
+ *
+ * If the device is not capable of either using the hint or the matrix to apply
+ * the desired color transform, it should force all layers to client composition
+ * during validateDisplay.
+ *
+ * The matrix provided is an affine color transformation of the following form:
+ *
+ * |r.r r.g r.b 0|
+ * |g.r g.g g.b 0|
+ * |b.r b.g b.b 0|
+ * |Tr  Tg  Tb  1|
+ *
+ * This matrix will be provided in row-major form: {r.r, r.g, r.b, 0, g.r, ...}.
+ *
+ * Given a matrix of this form and an input color [R_in, G_in, B_in], the output
+ * color [R_out, G_out, B_out] will be:
+ *
+ * R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr
+ * G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg
+ * B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb
+ *
+ * Parameters:
+ *   matrix - a 4x4 transform matrix (16 floats) as described above
+ *   hint - a hint value which may be used instead of the given matrix unless it
+ *       is HAL_COLOR_TRANSFORM_ARBITRARY
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - hint is not a valid color transform hint
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_COLOR_TRANSFORM)(
+        hwc2_device_t* device, hwc2_display_t display, const float* matrix,
+        int32_t /*android_color_transform_t*/ hint);
+
+/* setOutputBuffer(..., buffer, releaseFence)
+ * Descriptor: HWC2_FUNCTION_SET_OUTPUT_BUFFER
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the output buffer for a virtual display. That is, the buffer to which
+ * the composition result will be written.
+ *
+ * Also provides a file descriptor referring to a release sync fence object,
+ * which will be signaled when it is safe to write to the output buffer. If it
+ * is already safe to write to the output buffer, -1 may be passed instead. The
+ * device must ensure that it is safe for the client to close this file
+ * descriptor at any point after this function is called.
+ *
+ * Must be called at least once before presentDisplay, but does not have any
+ * interaction with layer state or display validation.
+ *
+ * Parameters:
+ *   buffer - the new output buffer
+ *   releaseFence - a sync fence file descriptor as described above
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - the new output buffer handle was invalid
+ *   HWC2_ERROR_UNSUPPORTED - display does not refer to a virtual display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_OUTPUT_BUFFER)(
+        hwc2_device_t* device, hwc2_display_t display, buffer_handle_t buffer,
+        int32_t releaseFence);
+
+/* setPowerMode(..., mode)
+ * Descriptor: HWC2_FUNCTION_SET_POWER_MODE
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the power mode of the given display. The transition must be complete
+ * when this function returns. It is valid to call this function multiple times
+ * with the same power mode.
+ *
+ * All displays must support HWC2_POWER_MODE_ON and HWC2_POWER_MODE_OFF. Whether
+ * a display supports HWC2_POWER_MODE_DOZE or HWC2_POWER_MODE_DOZE_SUSPEND may
+ * be queried using getDozeSupport.
+ *
+ * Parameters:
+ *   mode - the new power mode
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - mode was not a valid power mode
+ *   HWC2_ERROR_UNSUPPORTED - mode was a valid power mode, but is not supported
+ *       on this display
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_POWER_MODE)(
+        hwc2_device_t* device, hwc2_display_t display,
+        int32_t /*hwc2_power_mode_t*/ mode);
+
+/* setVsyncEnabled(..., enabled)
+ * Descriptor: HWC2_FUNCTION_SET_VSYNC_ENABLED
+ * Must be provided by all HWC2 devices
+ *
+ * Enables or disables the vsync signal for the given display. Virtual displays
+ * never generate vsync callbacks, and any attempt to enable vsync for a virtual
+ * display though this function must return HWC2_ERROR_NONE and have no other
+ * effect.
+ *
+ * Parameters:
+ *   enabled - whether to enable or disable vsync
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - enabled was an invalid value
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_VSYNC_ENABLED)(
+        hwc2_device_t* device, hwc2_display_t display,
+        int32_t /*hwc2_vsync_t*/ enabled);
+
+/* validateDisplay(..., outNumTypes, outNumRequests)
+ * Descriptor: HWC2_FUNCTION_VALIDATE_DISPLAY
+ * Must be provided by all HWC2 devices
+ *
+ * Instructs the device to inspect all of the layer state and determine if
+ * there are any composition type changes necessary before presenting the
+ * display. Permitted changes are described in the definition of
+ * hwc2_composition_t above.
+ *
+ * Also returns the number of layer requests required
+ * by the given layer configuration.
+ *
+ * Parameters:
+ *   outNumTypes - the number of composition type changes required by the
+ *       device; if greater than 0, the client must either set and validate new
+ *       types, or call acceptDisplayChanges to accept the changes returned by
+ *       getChangedCompositionTypes; must be the same as the number of changes
+ *       returned by getChangedCompositionTypes (see the declaration of that
+ *       function for more information); pointer will be non-NULL
+ *   outNumRequests - the number of layer requests required by this layer
+ *       configuration; must be equal to the number of layer requests returned
+ *       by getDisplayRequests (see the declaration of that function for
+ *       more information); pointer will be non-NULL
+ *
+ * Returns HWC2_ERROR_NONE if no changes are necessary and it is safe to present
+ * the display using the current layer state. Otherwise returns one of the
+ * following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_HAS_CHANGES - outNumTypes was greater than 0 (see parameter list
+ *       for more information)
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_VALIDATE_DISPLAY)(
+        hwc2_device_t* device, hwc2_display_t display,
+        uint32_t* outNumTypes, uint32_t* outNumRequests);
+
+/*
+ * Layer Functions
+ *
+ * These are functions which operate on layers, but which do not modify state
+ * that must be validated before use. See also 'Layer State Functions' below.
+ *
+ * All of these functions take as their first three parameters a device pointer,
+ * a display handle for the display which contains the layer, and a layer
+ * handle, so these parameters are omitted from the described parameter lists.
+ */
+
+/* setCursorPosition(..., x, y)
+ * Descriptor: HWC2_FUNCTION_SET_CURSOR_POSITION
+ * Must be provided by all HWC2 devices
+ *
+ * Asynchonously sets the position of a cursor layer.
+ *
+ * Prior to validateDisplay, a layer may be marked as HWC2_COMPOSITION_CURSOR.
+ * If validation succeeds (i.e., the device does not request a composition
+ * change for that layer), then once a buffer has been set for the layer and it
+ * has been presented, its position may be set by this function at any time
+ * between presentDisplay and any subsequent validateDisplay calls for this
+ * display.
+ *
+ * Once validateDisplay is called, this function will not be called again until
+ * the validate/present sequence is completed.
+ *
+ * May be called from any thread so long as it is not interleaved with the
+ * validate/present sequence as described above.
+ *
+ * Parameters:
+ *   x - the new x coordinate (in pixels from the left of the screen)
+ *   y - the new y coordinate (in pixels from the top of the screen)
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ *   HWC2_ERROR_BAD_LAYER - the layer is invalid or is not currently marked as
+ *       HWC2_COMPOSITION_CURSOR
+ *   HWC2_ERROR_NOT_VALIDATED - the device is currently in the middle of the
+ *       validate/present sequence
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_CURSOR_POSITION)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        int32_t x, int32_t y);
+
+/* setLayerBuffer(..., buffer, acquireFence)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_BUFFER
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the buffer handle to be displayed for this layer. If the buffer
+ * properties set at allocation time (width, height, format, and usage) have not
+ * changed since the previous frame, it is not necessary to call validateDisplay
+ * before calling presentDisplay unless new state needs to be validated in the
+ * interim.
+ *
+ * Also provides a file descriptor referring to an acquire sync fence object,
+ * which will be signaled when it is safe to read from the given buffer. If it
+ * is already safe to read from the buffer, -1 may be passed instead. The
+ * device must ensure that it is safe for the client to close this file
+ * descriptor at any point after this function is called.
+ *
+ * This function must return HWC2_ERROR_NONE and have no other effect if called
+ * for a layer with a composition type of HWC2_COMPOSITION_SOLID_COLOR (because
+ * it has no buffer) or HWC2_COMPOSITION_SIDEBAND or HWC2_COMPOSITION_CLIENT
+ * (because synchronization and buffer updates for these layers are handled
+ * elsewhere).
+ *
+ * Parameters:
+ *   buffer - the buffer handle to set
+ *   acquireFence - a sync fence file descriptor as described above
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - the buffer handle passed in was invalid
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_BUFFER)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        buffer_handle_t buffer, int32_t acquireFence);
+
+/* setLayerSurfaceDamage(..., damage)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE
+ * Must be provided by all HWC2 devices
+ *
+ * Provides the region of the source buffer which has been modified since the
+ * last frame. This region does not need to be validated before calling
+ * presentDisplay.
+ *
+ * Once set through this function, the damage region remains the same until a
+ * subsequent call to this function.
+ *
+ * If damage.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
+ * damage.numRects == 0, then the whole source buffer must be treated as if it
+ * has been modified.
+ *
+ * If the layer's contents are not modified relative to the prior frame, damage
+ * 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. They will not exceed the dimensions of the latched
+ * buffer.
+ *
+ * Parameters:
+ *   damage - the new surface damage region
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_SURFACE_DAMAGE)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        hwc_region_t damage);
+
+/*
+ * Layer State Functions
+ *
+ * These functions modify the state of a given layer. They do not take effect
+ * until the display configuration is successfully validated with
+ * validateDisplay and the display contents are presented with presentDisplay.
+ *
+ * All of these functions take as their first three parameters a device pointer,
+ * a display handle for the display which contains the layer, and a layer
+ * handle, so these parameters are omitted from the described parameter lists.
+ */
+
+/* setLayerBlendMode(..., mode)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_BLEND_MODE
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the blend mode of the given layer.
+ *
+ * Parameters:
+ *   mode - the new blend mode
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - an invalid blend mode was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_BLEND_MODE)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        int32_t /*hwc2_blend_mode_t*/ mode);
+
+/* setLayerColor(..., color)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_COLOR
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the color of the given layer. If the composition type of the layer is
+ * not HWC2_COMPOSITION_SOLID_COLOR, this call must return HWC2_ERROR_NONE and
+ * have no other effect.
+ *
+ * Parameters:
+ *   color - the new color
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_COLOR)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        hwc_color_t color);
+
+/* setLayerCompositionType(..., type)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the desired composition type of the given layer. During validateDisplay,
+ * the device may request changes to the composition types of any of the layers
+ * as described in the definition of hwc2_composition_t above.
+ *
+ * Parameters:
+ *   type - the new composition type
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - an invalid composition type was passed in
+ *   HWC2_ERROR_UNSUPPORTED - a valid composition type was passed in, but it is
+ *       not supported by this device
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_COMPOSITION_TYPE)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        int32_t /*hwc2_composition_t*/ type);
+
+/* setLayerDataspace(..., dataspace)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_DATASPACE
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the dataspace that the current buffer on this layer is in.
+ *
+ * The dataspace provides more information about how to interpret the buffer
+ * contents, such as the encoding standard and color transform.
+ *
+ * See the values of android_dataspace_t in <system/graphics.h> for more
+ * information.
+ *
+ * Parameters:
+ *   dataspace - the new dataspace
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_DATASPACE)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        int32_t /*android_dataspace_t*/ dataspace);
+
+/* setLayerDisplayFrame(..., frame)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the display frame (the portion of the display covered by a layer) of the
+ * given layer. This frame will not exceed the display dimensions.
+ *
+ * Parameters:
+ *   frame - the new display frame
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_DISPLAY_FRAME)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        hwc_rect_t frame);
+
+/* setLayerPlaneAlpha(..., alpha)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA
+ * Must be provided by all HWC2 devices
+ *
+ * Sets an alpha value (a floating point value in the range [0.0, 1.0]) which
+ * will be applied to the whole layer. It can be conceptualized as a
+ * preprocessing step which applies the following function:
+ *   if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED)
+ *       out.rgb = in.rgb * planeAlpha
+ *   out.a = in.a * planeAlpha
+ *
+ * If the device does not support this operation on a layer which is marked
+ * HWC2_COMPOSITION_DEVICE, it must request a composition type change to
+ * HWC2_COMPOSITION_CLIENT upon the next validateDisplay call.
+ *
+ * Parameters:
+ *   alpha - the plane alpha value to apply
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_PLANE_ALPHA)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        float alpha);
+
+/* setLayerSidebandStream(..., stream)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM
+ * Provided by HWC2 devices which support HWC2_CAPABILITY_SIDEBAND_STREAM
+ *
+ * Sets the sideband stream for this layer. If the composition type of the given
+ * layer is not HWC2_COMPOSITION_SIDEBAND, this call must return HWC2_ERROR_NONE
+ * and have no other effect.
+ *
+ * Parameters:
+ *   stream - the new sideband stream
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - an invalid sideband stream was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_SIDEBAND_STREAM)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        const native_handle_t* stream);
+
+/* setLayerSourceCrop(..., crop)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_SOURCE_CROP
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the source crop (the portion of the source buffer which will fill the
+ * display frame) of the given layer. This crop rectangle will not exceed the
+ * dimensions of the latched buffer.
+ *
+ * If the device is not capable of supporting a true float source crop (i.e., it
+ * will truncate or round the floats to integers), it should set this layer to
+ * HWC2_COMPOSITION_CLIENT when crop is non-integral for the most accurate
+ * rendering.
+ *
+ * If the device cannot support float source crops, but still wants to handle
+ * the layer, it should use the following code (or similar) to convert to
+ * an integer crop:
+ *   intCrop.left = (int) ceilf(crop.left);
+ *   intCrop.top = (int) ceilf(crop.top);
+ *   intCrop.right = (int) floorf(crop.right);
+ *   intCrop.bottom = (int) floorf(crop.bottom);
+ *
+ * Parameters:
+ *   crop - the new source crop
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_SOURCE_CROP)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        hwc_frect_t crop);
+
+/* setLayerTransform(..., transform)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_TRANSFORM
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the transform (rotation/flip) of the given layer.
+ *
+ * Parameters:
+ *   transform - the new transform
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ *   HWC2_ERROR_BAD_PARAMETER - an invalid transform was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_TRANSFORM)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        int32_t /*hwc_transform_t*/ transform);
+
+/* setLayerVisibleRegion(..., visible)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION
+ * Must be provided by all HWC2 devices
+ *
+ * Specifies the portion of the layer that is visible, including portions under
+ * translucent areas of other layers. The region is in screen space, and will
+ * not exceed the dimensions of the screen.
+ *
+ * Parameters:
+ *   visible - the new visible region, in screen space
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_VISIBLE_REGION)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        hwc_region_t visible);
+
+/* setLayerZOrder(..., z)
+ * Descriptor: HWC2_FUNCTION_SET_LAYER_Z_ORDER
+ * Must be provided by all HWC2 devices
+ *
+ * Sets the desired Z order (height) of the given layer. A layer with a greater
+ * Z value occludes a layer with a lesser Z value.
+ *
+ * Parameters:
+ *   z - the new Z order
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ *   HWC2_ERROR_BAD_LAYER - an invalid layer handle was passed in
+ */
+typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_LAYER_Z_ORDER)(
+        hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+        uint32_t z);
+
+__END_DECLS
+
+#endif
index a19a26c..18b30bc 100644 (file)
@@ -26,7 +26,7 @@
 
 __BEGIN_DECLS
 
-/*****************************************************************************/
+/* Shared by HWC1 and HWC2 */
 
 #define HWC_HEADER_VERSION          1
 
@@ -39,6 +39,69 @@ __BEGIN_DECLS
 #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)
 
+#define HWC_DEVICE_API_VERSION_2_0  HARDWARE_DEVICE_API_VERSION_2(2, 0, HWC_HEADER_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_color {
+    uint8_t r;
+    uint8_t g;
+    uint8_t b;
+    uint8_t a;
+} hwc_color_t;
+
+typedef struct hwc_frect {
+    float left;
+    float top;
+    float right;
+    float bottom;
+} hwc_frect_t;
+
+typedef struct hwc_rect {
+    int left;
+    int top;
+    int right;
+    int bottom;
+} hwc_rect_t;
+
+typedef struct hwc_region {
+    size_t numRects;
+    hwc_rect_t const* rects;
+} hwc_region_t;
+
+/*
+ * hwc_layer_t::transform values
+ */
+typedef 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,
+    /* flip source image horizontally, the rotate 90 degrees clock-wise */
+    HWC_TRANSFORM_FLIP_H_ROT_90 = HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90,
+    /* flip source image vertically, the rotate 90 degrees clock-wise */
+    HWC_TRANSFORM_FLIP_V_ROT_90 = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90,
+} hwc_transform_t;
+
+/*******************************************************************************
+ * Beyond this point are things only used by HWC1, which should be ignored when
+ * implementing a HWC2 device
+ ******************************************************************************/
+
 enum {
     /* hwc_composer_device_t::set failed in EGL */
     HWC_EGL_ERROR = -1
@@ -132,22 +195,6 @@ enum {
     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 {
     /*
index 969b8ce..c4a4cb5 100644 (file)
@@ -318,6 +318,12 @@ typedef enum {
     // axes
     INPUT_USAGE_AXIS_X,
     INPUT_USAGE_AXIS_Y,
+    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_PRESSURE,
     INPUT_USAGE_AXIS_SIZE,
     INPUT_USAGE_AXIS_TOUCH_MAJOR,
@@ -327,12 +333,6 @@ typedef enum {
     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,
@@ -375,13 +375,32 @@ typedef enum {
     INPUT_USAGE_LED_CONTROLLER_2,
     INPUT_USAGE_LED_CONTROLLER_3,
     INPUT_USAGE_LED_CONTROLLER_4,
+
+    // switches
+    INPUT_USAGE_SWITCH_UNKNOWN,
+    INPUT_USAGE_SWITCH_LID,
+    INPUT_USAGE_SWITCH_KEYPAD_SLIDE,
+    INPUT_USAGE_SWITCH_HEADPHONE_INSERT,
+    INPUT_USAGE_SWITCH_MICROPHONE_INSERT,
+    INPUT_USAGE_SWITCH_LINEOUT_INSERT,
+    INPUT_USAGE_SWITCH_CAMERA_LENS_COVER,
+
+    // mouse buttons
+    // (see android.view.MotionEvent)
+    INPUT_USAGE_BUTTON_UNKNOWN,
+    INPUT_USAGE_BUTTON_PRIMARY,   // left
+    INPUT_USAGE_BUTTON_SECONDARY, // right
+    INPUT_USAGE_BUTTON_TERTIARY,  // middle
+    INPUT_USAGE_BUTTON_FORWARD,
+    INPUT_USAGE_BUTTON_BACK,
 } input_usage_t;
 
-typedef enum {
+typedef enum input_collection_id {
     INPUT_COLLECTION_ID_TOUCH,
     INPUT_COLLECTION_ID_KEYBOARD,
     INPUT_COLLECTION_ID_MOUSE,
     INPUT_COLLECTION_ID_TOUCHPAD,
+    INPUT_COLLECTION_ID_SWITCH,
     // etc
 } input_collection_id_t;
 
@@ -413,6 +432,11 @@ typedef struct input_host_callbacks {
     input_report_definition_t* (*create_output_report_definition)(input_host_t* host);
 
     /**
+     * Frees the report definition.
+     */
+    void (*free_report_definition)(input_host_t* host, input_report_definition_t* report_def);
+
+    /**
      * Append the report to the given input device.
      */
     void (*input_device_definition_add_report)(input_host_t* host,
diff --git a/include/hardware/keymaster2.h b/include/hardware/keymaster2.h
new file mode 100644 (file)
index 0000000..565ad2e
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * 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;
+
+    /**
+     * Configures keymaster.  This method must be called once after the device is opened and before
+     * it is used.  It's used to provide KM_TAG_OS_VERSION and KM_TAG_OS_PATCHLEVEL to keymaster.
+     * Until this method is called, all other methods will return KM_ERROR_KEYMASTER_NOT_CONFIGURED.
+     * The values provided by this method are only accepted by keymaster once per boot.  Subsequent
+     * calls will return KM_ERROR_OK, but do nothing.
+     *
+     * If the keymaster implementation is in secure hardware and the OS version and patch level
+     * values provided do not match the values provided to the secure hardware by the bootloader (or
+     * if the bootloader did not provide values), then this method will return
+     * KM_ERROR_INVALID_ARGUMENT, and all other methods will continue returning
+     * KM_ERROR_KEYMASTER_NOT_CONFIGURED.
+     */
+    keymaster_error_t (*configure)(const struct keymaster2_device* dev,
+                                   const keymaster_key_param_set_t* params);
+
+    /**
+     * 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);
+
+    /**
+     * 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
index 772d7e4..c79c122 100644 (file)
@@ -54,6 +54,12 @@ __BEGIN_DECLS
 #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
index 5be956d..b45e785 100644 (file)
@@ -52,18 +52,25 @@ typedef enum {
      */
 
     /* 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_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 */
@@ -102,20 +109,32 @@ typedef enum {
                                                    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, /* Reserved for future use -- ignore */
-    KM_TAG_APPLICATION_ID = KM_BYTES | 601,  /* Reserved for fugure use -- ignore */
+    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_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 */
+    KM_TAG_ATTESTATION_CHALLENGE = KM_BYTES | 708, /* Used to provide challenge 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. */
@@ -123,7 +142,12 @@ typedef enum {
     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_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;
 
 /**
@@ -187,6 +211,34 @@ typedef enum {
     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
@@ -194,8 +246,9 @@ typedef enum {
  * hardware-enforced list is guaranteed never to have existed outide the secure hardware.
  */
 typedef enum {
-    KM_ORIGIN_GENERATED = 0, /* Generated in keymaster */
-    KM_ORIGIN_IMPORTED = 2,  /* Imported, origin unknown */
+    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
@@ -207,7 +260,7 @@ typedef enum {
  * 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.  This type is new in 0_4.
+ * as needed for implementations.
  */
 typedef enum {
     KM_BLOB_STANDALONE = 0,
@@ -215,13 +268,14 @@ typedef enum {
 } keymaster_key_blob_usage_requirements_t;
 
 /**
- * Possible purposes of a key (or pair). This type is new in 0_4.
+ * Possible purposes of a key (or pair).
  */
 typedef enum {
-    KM_PURPOSE_ENCRYPT = 0,
-    KM_PURPOSE_DECRYPT = 1,
-    KM_PURPOSE_SIGN = 2,
-    KM_PURPOSE_VERIFY = 3,
+    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 {
@@ -263,14 +317,42 @@ typedef struct {
     size_t key_material_size;
 } keymaster_key_blob_t;
 
+typedef struct {
+    keymaster_blob_t* entries;
+    size_t entry_count;
+} keymaster_cert_chain_t;
+
+typedef enum {
+    KM_VERIFIED_BOOT_VERIFIED = 0,    /* Full chain of trust extending from the bootloader to
+                                       * verified partitions, including the bootloader, boot
+                                       * partition, and all verified partitions*/
+    KM_VERIFIED_BOOT_SELF_SIGNED = 1, /* The boot partition has been verified using the embedded
+                                       * certificate, and the signature is valid. The bootloader
+                                       * displays a warning and the fingerprint of the public
+                                       * key before allowing the boot process to continue.*/
+    KM_VERIFIED_BOOT_UNVERIFIED = 2,  /* The device may be freely modified. Device integrity is left
+                                       * to the user to verify out-of-band. The bootloader
+                                       * displays a warning to the user before allowing the boot
+                                       * process to continue */
+    KM_VERIFIED_BOOT_FAILED = 3,      /* The device failed verification. The bootloader displays a
+                                       * warning and stops the boot process, so no keymaster
+                                       * implementation should ever actually return this value,
+                                       * since it should not run.  Included here only for
+                                       * completeness. */
+} keymaster_verified_boot_t;
+
+typedef enum {
+    KM_SECURITY_LEVEL_SOFTWARE = 0,
+    KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 1,
+} keymaster_security_level_t;
+
 /**
- * Formats for key import and export.  At present, only asymmetric key import/export is supported.
- * In the future this list will expand greatly to accommodate asymmetric key import/export.
+ * 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 */
+    KM_KEY_FORMAT_RAW = 3,   /* for symmetric key import and export*/
 } keymaster_key_format_t;
 
 /**
@@ -340,12 +422,15 @@ typedef enum {
     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_ATTESTATION_CHALLENGE_MISSING = -63,
+    KM_ERROR_KEYMASTER_NOT_CONFIGURED = -64,
 
     KM_ERROR_UNIMPLEMENTED = -100,
     KM_ERROR_VERSION_MISMATCH = -101,
 
-    /* Additional error codes may be added by implementations, but implementers should coordinate
-     * with Google to avoid code collision. */
     KM_ERROR_UNKNOWN_ERROR = -1000,
 } keymaster_error_t;
 
@@ -481,7 +566,8 @@ inline int keymaster_param_compare(const keymaster_key_param_t* a, const keymast
 #undef KEYMASTER_SIMPLE_COMPARE
 
 inline void keymaster_free_param_values(keymaster_key_param_t* param, size_t param_count) {
-    while (param_count-- > 0) {
+    while (param_count > 0) {
+        param_count--;
         switch (keymaster_tag_get_type(param->tag)) {
         case KM_BIGNUM:
         case KM_BYTES:
@@ -501,6 +587,7 @@ inline void keymaster_free_param_set(keymaster_key_param_set_t* set) {
         keymaster_free_param_values(set->params, set->length);
         free(set->params);
         set->params = NULL;
+        set->length = 0;
     }
 }
 
@@ -511,6 +598,19 @@ inline void keymaster_free_characteristics(keymaster_key_characteristics_t* char
     }
 }
 
+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
index 2cf5519..b3d28b0 100644 (file)
@@ -30,6 +30,28 @@ __BEGIN_DECLS
  */
 #define LIGHTS_HARDWARE_MODULE_ID "lights"
 
+/**
+ * Header file version.
+ */
+#define LIGHTS_HEADER_VERSION   1
+
+/**
+ * Device API version 0.0-1.0
+ *
+ * Base version for the device API in the lights HAL: all versions less than
+ * 2.0 are treated as being this version.
+ */
+#define LIGHTS_DEVICE_API_VERSION_1_0   HARDWARE_DEVICE_API_VERSION_2(1, 0, LIGHTS_HEADER_VERSION)
+
+/**
+ * Device API version 2.0
+ *
+ * Devices reporting this version or higher may additionally support the
+ * following modes:
+ * - BRIGHTNESS_MODE_LOW_PERSISTENCE
+ */
+#define LIGHTS_DEVICE_API_VERSION_2_0   HARDWARE_DEVICE_API_VERSION_2(2, 0, LIGHTS_HEADER_VERSION)
+
 /*
  * These light IDs correspond to logical lights, not physical.
  * So for example, if your INDICATOR light is in line with your
@@ -82,6 +104,39 @@ __BEGIN_DECLS
 #define BRIGHTNESS_MODE_SENSOR      1
 
 /**
+ * Use a low-persistence mode for display backlights.
+ *
+ * When set, the device driver must switch to a mode optimized for low display
+ * persistence that is intended to be used when the device is being treated as a
+ * head mounted display (HMD).  The actual display brightness in this mode is
+ * implementation dependent, and any value set for color in light_state may be
+ * overridden by the HAL implementation.
+ *
+ * For an optimal HMD viewing experience, the display must meet the following
+ * criteria in this mode:
+ * - Gray-to-Gray, White-to-Black, and Black-to-White switching time must be ≤ 3 ms.
+ * - The display must support low-persistence with ≤ 3.5 ms persistence.
+ *   Persistence is defined as the amount of time for which a pixel is
+ *   emitting light for a single frame.
+ * - Any "smart panel" or other frame buffering options that increase display
+ *   latency are disabled.
+ * - Display brightness is set so that the display is still visible to the user
+ *   under normal indoor lighting.
+ * - The display must update at 60 Hz at least, but higher refresh rates are
+ *   recommended for low latency.
+ *
+ * This mode will only be used with light devices of type LIGHT_ID_BACKLIGHT,
+ * and will only be called by the Android framework for light_device_t
+ * implementations that report a version >= 2.0 in their hw_device_t common
+ * fields.  If the device version is >= 2.0 and this mode is unsupported, calling
+ * set_light with this mode must return the negative error code -ENOSYS (-38)
+ * without altering any settings.
+ *
+ * Available only for version >= LIGHTS_DEVICE_API_VERSION_2_0
+ */
+#define BRIGHTNESS_MODE_LOW_PERSISTENCE 2
+
+/**
  * The parameters that can be set for a given light.
  *
  * Not all lights must support all parameters.  If you
diff --git a/include/hardware/nvram.h b/include/hardware/nvram.h
new file mode 100644 (file)
index 0000000..a1868b5
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * 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>
+
+__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_0_1 HARDWARE_DEVICE_API_VERSION(0, 1)
+
+/* 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;
+
+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 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
index 10612f3..c451d67 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef ANDROID_INCLUDE_HARDWARE_POWER_H
 #define ANDROID_INCLUDE_HARDWARE_POWER_H
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
@@ -28,6 +29,8 @@ __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)
+#define POWER_MODULE_API_VERSION_0_4  HARDWARE_MODULE_API_VERSION(0, 4)
+#define POWER_MODULE_API_VERSION_0_5  HARDWARE_MODULE_API_VERSION(0, 5)
 
 /**
  * The id of this module
@@ -35,6 +38,18 @@ __BEGIN_DECLS
 #define POWER_HARDWARE_MODULE_ID "power"
 
 /*
+ * Platform-level sleep state stats.
+ * Maximum length of Platform-level sleep state name.
+ */
+#define POWER_STATE_NAME_MAX_LENGTH 100
+
+/*
+ * Platform-level sleep state stats.
+ * Maximum length of Platform-level sleep state voter name.
+ */
+#define POWER_STATE_VOTER_NAME_MAX_LENGTH 100
+
+/*
  * Power hint identifiers passed to (*powerHint)
  */
 
@@ -46,13 +61,100 @@ typedef enum {
      */
     POWER_HINT_VIDEO_ENCODE = 0x00000003,
     POWER_HINT_VIDEO_DECODE = 0x00000004,
-    POWER_HINT_LOW_POWER = 0x00000005
+    POWER_HINT_LOW_POWER = 0x00000005,
+    POWER_HINT_SUSTAINED_PERFORMANCE = 0x00000006,
+    POWER_HINT_VR_MODE = 0x00000007
 } power_hint_t;
 
 typedef enum {
     POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 0x00000001
 } feature_t;
 
+/*
+ * Platform-level sleep state stats:
+ * power_state_voter_t struct is useful for describing the individual voters when a
+ * Platform-level sleep state is chosen by aggregation of votes from multiple
+ * clients/system conditions.
+ *
+ * This helps in attirbuting what in the device is blocking the device from
+ * entering the lowest Platform-level sleep state.
+ */
+typedef struct {
+    /*
+     * Name of the voter.
+     */
+     char name[POWER_STATE_VOTER_NAME_MAX_LENGTH];
+
+    /*
+     * Total time in msec the voter voted for the platform sleep state since boot.
+     */
+     uint64_t total_time_in_msec_voted_for_since_boot;
+
+    /*
+     * Number of times the voter voted for the platform sleep state since boot.
+     */
+     uint64_t total_number_of_times_voted_since_boot;
+} power_state_voter_t;
+
+/*
+ * Platform-level sleep state stats:
+ * power_state_platform_sleep_state_t represents the Platform-level sleep state the
+ * device is capable of getting into.
+ *
+ * SoCs usually have more than one Platform-level sleep state.
+ *
+ * The caller calls the get_number_of_platform_modes function to figure out the size
+ * of power_state_platform_sleep_state_t array where each array element represents
+ * a specific Platform-level sleep state.
+ *
+ * Higher the index deeper the state is i.e. lesser steady-state power is consumed
+ * by the platform to be resident in that state.
+ *
+ * Caller allocates power_state_voter_t *voters for each Platform-level sleep state by
+ * calling get_voter_list.
+ */
+typedef struct {
+    /*
+     * Platform-level Sleep state name.
+     */
+    char name[POWER_STATE_NAME_MAX_LENGTH];
+
+    /*
+     * Time spent in msec at this platform-level sleep state since boot.
+     */
+    uint64_t residency_in_msec_since_boot;
+
+    /*
+     * Total number of times system entered this state.
+     */
+    uint64_t total_transitions;
+
+    /*
+     * This platform-level sleep state can only be reached during system suspend.
+     */
+    bool supported_only_in_suspend;
+
+    /*
+     * The following fields are useful if the Platform-level sleep state
+     * is chosen by aggregation votes from multiple clients/system conditions.
+     * All the voters have to say yes or all the system conditions need to be
+     * met to enter a platform-level sleep state.
+     *
+     * Setting number_of_voters to zero implies either the info is not available
+     * or the system does not follow a voting mechanism to choose this
+     * Platform-level sleep state.
+     */
+    uint32_t number_of_voters;
+
+    /*
+     * Voter list - Has to be allocated by the caller.
+     *
+     * Caller allocates power_state_voter_t *voters for each Platform-level sleep state
+     * by calling get_voter_list.
+     */
+    power_state_voter_t *voters;
+} power_state_platform_sleep_state_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
@@ -66,6 +168,10 @@ typedef struct power_module {
      * startup, such as to set default cpufreq parameters.  This is
      * called only by the Power HAL instance loaded by
      * PowerManagerService.
+     *
+     * Platform-level sleep state stats:
+     * Can Also be used to initiate device specific Platform-level
+     * Sleep state nodes from version 0.5 onwards.
      */
     void (*init)(struct power_module *module);
 
@@ -126,6 +232,21 @@ typedef struct power_module {
      *     parameter is non-zero when low power mode is activated, and zero
      *     when deactivated.
      *
+     * POWER_HINT_SUSTAINED_PERFORMANCE
+     *
+     *     Sustained Performance mode is actived or deactivated. Sustained
+     *     performance mode is intended to provide a consistent level of
+     *     performance for a prolonged amount of time. The data parameter is
+     *     non-zero when sustained performance mode is activated, and zero
+     *     when deactivated.
+     *
+     * POWER_HINT_VR_MODE
+     *
+     *     VR Mode is activated or deactivated. VR mode is intended to
+     *     provide minimum guarantee for performance for the amount of time the
+     *     device can sustain it. The data parameter is non-zero when the mode
+     *     is activated and zero when deactivated.
+     *
      * A particular platform may choose to ignore any hint.
      *
      * availability: version 0.2
@@ -148,6 +269,62 @@ typedef struct power_module {
      */
     void (*setFeature)(struct power_module *module, feature_t feature, int state);
 
+    /*
+     * Platform-level sleep state stats:
+     * Report cumulative info on the statistics on platform-level sleep states since boot.
+     *
+     * Caller of the function queries the get_number_of_sleep_states and allocates the
+     * memory for the power_state_platform_sleep_state_t *list before calling this function.
+     *
+     * power_stats module is responsible to assign values to all the fields as
+     * necessary.
+     *
+     * Higher the index deeper the state is i.e. lesser steady-state power is consumed
+     * by the platform to be resident in that state.
+     *
+     * The function returns 0 on success or negative value -errno on error.
+     * EINVAL - *list is NULL.
+     * EIO - filesystem nodes access error.
+     *
+     * availability: version 0.5
+     */
+    int (*get_platform_low_power_stats)(struct power_module *module,
+        power_state_platform_sleep_state_t *list);
+
+    /*
+     * Platform-level sleep state stats:
+     * This function is called to determine the number of platform-level sleep states
+     * for get_platform_low_power_stats.
+     *
+     * The value returned by this function is used to allocate memory for
+     * power_state_platform_sleep_state_t *list for get_platform_low_power_stats.
+     *
+     * The number of parameters must not change for successive calls.
+     *
+     * Return number of parameters on success or negative value -errno on error.
+     * EIO - filesystem nodes access error.
+     *
+     * availability: version 0.5
+     */
+    ssize_t (*get_number_of_platform_modes)(struct power_module *module);
+
+    /*
+     * Platform-level sleep state stats:
+     * Provides the number of voters for each of the Platform-level sleep state.
+     *
+     * Caller uses this function to allocate memory for the power_state_voter_t list.
+     *
+     * Caller has to allocate the space for the *voter array which is
+     * get_number_of_platform_modes() long.
+     *
+     * Return 0 on success or negative value -errno on error.
+     * EINVAL - *voter is NULL.
+     * EIO - filesystem nodes access error.
+     *
+     * availability: version 0.5
+     */
+    int (*get_voter_list)(struct power_module *module, size_t *voter);
+
 } power_module_t;
 
 
index 51bffe1..1d73c31 100644 (file)
@@ -116,6 +116,35 @@ enum {
     SENSOR_HAL_DATA_INJECTION_MODE      = 0x1
 };
 
+#define SENSOR_FLAG_MASK(nbit, shift)   (((1<<(nbit))-1)<<(shift))
+#define SENSOR_FLAG_MASK_1(shift)       SENSOR_FLAG_MASK(1, shift)
+
+/*
+ * Mask and shift for reporting mode sensor flags defined above.
+ */
+#define REPORTING_MODE_SHIFT            (1)
+#define REPORTING_MODE_NBIT             (3)
+#define REPORTING_MODE_MASK             SENSOR_FLAG_MASK(REPORTING_MODE_NBIT, REPORTING_MODE_SHIFT)
+                                        // 0xE
+
+/*
+ * Mask and shift for data_injection mode sensor flags defined above.
+ */
+#define DATA_INJECTION_SHIFT            (4)
+#define DATA_INJECTION_MASK             SENSOR_FLAG_MASK_1(DATA_INJECTION_SHIFT) //0x10
+
+/*
+ * Mask and shift for dynamic sensor flag.
+ */
+#define DYNAMIC_SENSOR_SHIFT            (5)
+#define DYNAMIC_SENSOR_MASK             SENSOR_FLAG_MASK_1(DYNAMIC_SENSOR_SHIFT) //0x20
+
+/*
+ * Mask and shift for sensor additional information support.
+ */
+#define ADDITIONAL_INFO_SHIFT           (6)
+#define ADDITIONAL_INFO_MASK            SENSOR_FLAG_MASK_1(ADDITIONAL_INFO_SHIFT) //0x40
+
 /*
  * Availability: SENSORS_DEVICE_API_VERSION_1_3
  * Sensor flags used in sensor_t.flags.
@@ -147,20 +176,21 @@ enum {
      * 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
-};
+    SENSOR_FLAG_SUPPORTS_DATA_INJECTION = DATA_INJECTION_MASK, // 1 0000
 
-/*
- * Mask and shift for reporting mode sensor flags defined above.
- */
-#define REPORTING_MODE_MASK              (0xE)
-#define REPORTING_MODE_SHIFT             (1)
+    /*
+     * Set this flag if the sensor is a dynamically connected sensor. See
+     * dynamic_sensor_meta_event_t and SENSOR_TYPE_DYNAMIC_SENSOR_META for details.
+     */
+    SENSOR_FLAG_DYNAMIC_SENSOR = DYNAMIC_SENSOR_MASK,
+
+    /*
+     * Set this flag if sensor additional information is supported. See SENSOR_TYPE_ADDITIONAL_INFO
+     * and additional_info_event_t for details.
+     */
+    SENSOR_FLAG_ADDITIONAL_INFO = ADDITIONAL_INFO_MASK
+};
 
-/*
- * Mask and shift for data_injection mode sensor flags defined above.
- */
-#define DATA_INJECTION_MASK              (0x10)
-#define DATA_INJECTION_SHIFT             (4)
 
 /*
  * Sensor type
@@ -657,6 +687,182 @@ enum {
 #define SENSOR_TYPE_WRIST_TILT_GESTURE                         (26)
 #define SENSOR_STRING_TYPE_WRIST_TILT_GESTURE                  "android.sensor.wrist_tilt_gesture"
 
+/*
+ * SENSOR_TYPE_DEVICE_ORIENTATION
+ * reporting-mode: on-change
+ *
+ * The current orientation of the device. The value should be reported in the
+ * first element of the 'data' member variable in sensors_event_t. The only
+ * values that can be reported are (please refer to Android Sensor Coordinate
+ * System to understand the X and Y axis direction with respect to default
+ * orientation):
+ *  - 0: device is in default orientation (Y axis is vertical and points up)
+ *  - 1: device is rotated 90 degrees counter-clockwise from default
+ *       orientation (X axis is vertical and points up)
+ *  - 2: device is rotated 180 degrees from default orientation (Y axis is
+ *       vertical and points down)
+ *  - 3: device is rotated 90 degrees clockwise from default orientation (X axis
+ *       is vertical and points down)
+ *
+ * Moving the device to an orientation where the Z axis is vertical (either up
+ * or down) should not cause a new event to be reported.
+ *
+ * To improve the user experience of this sensor, it is recommended to implement
+ * some physical (i.e., rotation angle) and temporal (i.e., delay) hysteresis.
+ * In other words, minor or transient rotations should not cause a new event to
+ * be reported.
+ *
+ * This sensor should only be implemented with the help of an accelerometer.
+ * This is a low power sensor that should reduce the number of interrupts of the
+ * AP. Do not emulate this sensor in the HAL.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+#define SENSOR_TYPE_DEVICE_ORIENTATION                 (27)
+#define SENSOR_STRING_TYPE_DEVICE_ORIENTATION          "android.sensor.device_orientation"
+
+/*
+ * SENSOR_TYPE_POSE_6DOF
+ * trigger-mode: continuous
+ *
+ * A sensor of this type returns the pose of the device.
+ * Pose of the device is defined as the orientation of the device from a
+ * Earth Centered Earth Fixed frame and the translation from an arbitrary
+ * point at subscription.
+ *
+ * This sensor can be high power. It can use any and all of the following
+ *           . Accelerometer
+ *           . Gyroscope
+ *           . Camera
+ *           . Depth Camera
+ *
+ */
+#define SENSOR_TYPE_POSE_6DOF                         (28)
+#define SENSOR_STRING_TYPE_POSE_6DOF                  "android.sensor.pose_6dof"
+
+/*
+ * SENSOR_TYPE_STATIONARY_DETECT
+ * trigger mode: one shot
+ *
+ * A sensor of this type returns an event if the device is still/stationary for
+ * a while. The period of time to monitor for statinarity should be greater than
+ * 5 seconds, and less than 10 seconds.
+ *
+ * Stationarity here refers to absolute stationarity. eg: device on desk.
+ *
+ * The only allowed value to return is 1.0.
+ */
+#define SENSOR_TYPE_STATIONARY_DETECT                   (29)
+#define SENSOR_STRING_TYPE_STATIONARY_DETECT            "android.sensor.stationary_detect"
+
+/*
+ * SENSOR_TYPE_MOTION_DETECT
+ * trigger mode: one shot
+ *
+ * A sensor of this type returns an event if the device is not still for
+ * a while. The period of time to monitor for statinarity should be greater than
+ * 5 seconds, and less than 10 seconds.
+ *
+ * Motion here refers to any mechanism in which the device is causes to be
+ * moved in its inertial frame. eg: Pickin up the device and walking with it
+ * to a nearby room may trigger motion wherewas keeping the device on a table
+ * on a smooth train moving at constant velocity may not trigger motion.
+ *
+ * The only allowed value to return is 1.0.
+ */
+#define SENSOR_TYPE_MOTION_DETECT                       (30)
+#define SENSOR_STRING_TYPE_MOTION_DETECT                "android.sensor.motion_detect"
+
+/*
+ * SENSOR_TYPE_HEART_BEAT
+ * trigger mode: continuous
+ *
+ * A sensor of this type returns an event everytime a hear beat peak is
+ * detected.
+ *
+ * Peak here ideally corresponds to the positive peak in the QRS complex of
+ * and ECG signal.
+ *
+ * The sensor is not expected to be optimized for latency. As a guide, a
+ * latency of up to 10 seconds is acceptable. However the timestamp attached
+ * to the event should be accurate and should correspond to the time the peak
+ * occured.
+ *
+ * The sensor event contains a parameter for the confidence in the detection
+ * of the peak where 0.0 represent no information at all, and 1.0 represents
+ * certainty.
+ */
+#define SENSOR_TYPE_HEART_BEAT                          (31)
+#define SENSOR_STRING_TYPE_HEART_BEAT                   "android.sensor.heart_beat"
+
+/**
+ * SENSOR_TYPE_DYNAMIC_SENSOR_META
+ * trigger-mode: special
+ *
+ * A sensor event of this type is received when a dynamic sensor is added to or removed from the
+ * system. At most one sensor of this type can be present in one sensor HAL implementation and
+ * presence of a sensor of this type in sensor HAL implementation indicates that this sensor HAL
+ * supports dynamic sensor feature. Operations, such as batch, activate and setDelay, to this
+ * special purpose sensor should be treated as no-op and return successful.
+ *
+ * A dynamic sensor connection indicates connection of a physical device or instantiation of a
+ * virtual sensor backed by algorithm; and a dynamic sensor disconnection indicates the the
+ * opposite. A sensor event of SENSOR_TYPE_DYNAMIC_SENSOR_META type should be delivered regardless
+ * of the activation status of the sensor in the event of dynamic sensor connection and
+ * disconnection. In the sensor event, besides the common data entries, "dynamic_sensor_meta", which
+ * includes fields for connection status, handle of the sensor involved, pointer to sensor_t
+ * structure and a uuid field, should be populated.
+ *
+ * At a dynamic sensor connection event, fields of sensor_t structure referenced by a pointer in
+ * dynamic_sensor_meta should be filled as if it was regular sensors. Sensor HAL is responsible for
+ * recovery of memory if the corresponding data is dynamicially allocated. However, the the pointer
+ * must be valid until the first activate call to the sensor reported in this connection event. At a
+ * dynamic sensor disconnection, the sensor_t pointer should be NULL.
+ *
+ * The sensor handle assigned to dynamic sensors should never be the same as that of any regular
+ * static sensors, and should be unique until next boot. In another word, if a handle h is used for
+ * a dynamic sensor A, that same number cannot be used for the same dynamic sensor A or another
+ * dynamic sensor B even after disconnection of A until reboot.
+ *
+ * The UUID field will be used for identifying the sensor in addition to name, vendor and version
+ * and type. For physical sensors of the same model, all sensors will have the same values in
+ * sensor_t, but the UUID should be unique and persistent for each individual unit. An all zero UUID
+ * indicates it is not possible to differentiate individual sensor unit.
+ *
+ */
+#define SENSOR_TYPE_DYNAMIC_SENSOR_META                         (32)
+#define SENSOR_STRING_TYPE_DYNAMIC_SENSOR_META                  "android.sensor.dynamic_sensor_meta"
+
+/**
+ * SENSOR_TYPE_ADDITIONAL_INFO
+ * reporting-mode: N/A
+ *
+ * This sensor type is for delivering additional sensor information aside from sensor event data.
+ * Additional information may include sensor front-end group delay, internal calibration parameters,
+ * noise level metrics, device internal temperature, etc.
+ *
+ * This type will never bind to a sensor. In other words, no sensor in the sensor list should be of
+ * the type SENSOR_TYPE_ADDITIONAL_INFO. If a sensor HAL supports sensor additional information
+ * feature, it reports sensor_event_t with "sensor" field set to handle of the reporting sensor and
+ * "type" field set to SENSOR_TYPE_ADDITIONAL_INFO. Delivery of additional information events is
+ * triggered under two conditions: an enable activate() call or a flush() call to the corresponding
+ * sensor.
+ *
+ * A single additional information report consists of multiple frames. Sequences of these frames are
+ * ordered using timestamps, which means the timestamps of sequential frames have to be at least 1
+ * nanosecond apart from each other. Each frame is a sensor_event_t delivered through the HAL
+ * interface, with related data stored in the "additional_info" field, which is of type
+ * additional_info_event_t.  The "type" field of additional_info_event_t denotes the nature of the
+ * payload data (see additional_info_type_t).  The "serial" field is used to keep the sequence of
+ * payload data that spans multiple frames. The first frame of the entire report is always of type
+ * AINFO_BEGIN, and the last frame is always AINFO_END.
+ *
+ * All additional information frames have to be delivered after flush complete event if flush() was
+ * triggering the report.
+ */
+#define SENSOR_TYPE_ADDITIONAL_INFO                       (33)
+#define SENSOR_STRING_TYPE_ADDITIONAL_INFO                "android.sensor.additional_info"
+
 /**
  * Values returned by the accelerometer in various locations in the universe.
  * all values are in SI units (m/s^2)
@@ -679,6 +885,9 @@ enum {
 #define SENSOR_STATUS_ACCURACY_MEDIUM   2
 #define SENSOR_STATUS_ACCURACY_HIGH     3
 
+
+struct sensor_t;
+
 /**
  * sensor event data
  */
@@ -731,6 +940,20 @@ typedef struct meta_data_event {
 } meta_data_event_t;
 
 /**
+ * Dynamic sensor meta event. See the description of SENSOR_TYPE_DYNAMIC_SENSOR_META type for
+ * details.
+ */
+typedef struct dynamic_sensor_meta_event {
+    int32_t  connected;
+    int32_t  handle;
+    const struct sensor_t * sensor; // should be NULL if connected == false
+    uint8_t uuid[16];               // UUID of a dynamic sensor (using RFC 4122 byte order)
+                                    // For UUID 12345678-90AB-CDEF-1122-334455667788 the uuid field
+                                    // should be initialized as:
+                                    // {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x11, ...}
+} dynamic_sensor_meta_event_t;
+
+/**
  * Heart rate event data
  */
 typedef struct {
@@ -744,6 +967,85 @@ typedef struct {
   int8_t status;
 } heart_rate_event_t;
 
+typedef struct {
+    int32_t type;                           // type of payload data, see additional_info_type_t
+    int32_t serial;                         // sequence number of this frame for this type
+    union {
+        // for each frame, a single data type, either int32_t or float, should be used.
+        int32_t data_int32[14];
+        float   data_float[14];
+    };
+} additional_info_event_t;
+
+typedef enum additional_info_type {
+    //
+    AINFO_BEGIN = 0x0,                      // Marks the beginning of additional information frames
+    AINFO_END   = 0x1,                      // Marks the end of additional information frames
+    // Basic information
+    AINFO_UNTRACKED_DELAY =  0x10000,       // Estimation of the delay that is not tracked by sensor
+                                            // timestamps. This includes delay introduced by
+                                            // sensor front-end filtering, data transport, etc.
+                                            // float[2]: delay in seconds
+                                            //           standard deviation of estimated value
+                                            //
+    AINFO_INTERNAL_TEMPERATURE,             // float: Celsius temperature.
+                                            //
+    AINFO_VEC3_CALIBRATION,                 // First three rows of a homogeneous matrix, which
+                                            // represents calibration to a three-element vector
+                                            // raw sensor reading.
+                                            // float[12]: 3x4 matrix in row major order
+                                            //
+    AINFO_SENSOR_PLACEMENT,                 // Location and orientation of sensor element in the
+                                            // device frame: origin is the geometric center of the
+                                            // mobile device screen surface; the axis definition
+                                            // corresponds to Android sensor definitions.
+                                            // float[12]: 3x4 matrix in row major order
+                                            //
+    AINFO_SAMPLING,                         // float[2]: raw sample period in seconds,
+                                            //           standard deviation of sampling period
+
+    // Sampling channel modeling information
+    AINFO_CHANNEL_NOISE = 0x20000,          // int32_t: noise type
+                                            // float[n]: parameters
+                                            //
+    AINFO_CHANNEL_SAMPLER,                  // float[3]: sample period
+                                            //           standard deviation of sample period,
+                                            //           quantization unit
+                                            //
+    AINFO_CHANNEL_FILTER,                   // Represents a filter:
+                                            //      \sum_j a_j y[n-j] == \sum_i b_i x[n-i]
+                                            //
+                                            // int32_t[3]: number of feedforward coefficients, M,
+                                            //             number of feedback coefficients, N, for
+                                            //               FIR filter, N=1.
+                                            //             bit mask that represents which element to
+                                            //               which the filter is applied, bit 0 == 1
+                                            //               means this filter applies to vector
+                                            //               element 0.
+                                            // float[M+N]: filter coefficients (b0, b1, ..., BM-1),
+                                            //             then (a0, a1, ..., aN-1), a0 is always 1.
+                                            //             Multiple frames may be needed for higher
+                                            //             number of taps.
+                                            //
+    AINFO_CHANNEL_LINEAR_TRANSFORM,         // int32_t[2]: size in (row, column) ... 1st frame
+                                            // float[n]: matrix element values in row major order.
+                                            //
+    AINFO_CHANNEL_NONLINEAR_MAP,            // int32_t[2]: extrapolate method
+                                            //             interpolate method
+                                            // float[n]: mapping key points in pairs, (in, out)...
+                                            //           (may be used to model saturation)
+                                            //
+    AINFO_CHANNEL_RESAMPLER,                // int32_t:  resample method (0-th order, 1st order...)
+                                            // float[1]: resample ratio (upsampling if < 1.0;
+                                            //           downsampling if > 1.0).
+                                            //
+
+    // Custom information
+    AINFO_CUSTOM_START =    0x10000000,     //
+    // Debugging
+    AINFO_DEBUGGING_START = 0x40000000,     //
+} additional_info_type_t;
+
 /**
  * Union of the various types of sensor data
  * that can be returned.
@@ -809,6 +1111,15 @@ typedef struct sensors_event_t {
              * SENSOR_TYPE_META_DATA. The handle is ignored and must be zero.
              */
             meta_data_event_t meta_data;
+
+            /* dynamic sensor meta event. See SENSOR_TYPE_DYNAMIC_SENSOR_META type for details */
+            dynamic_sensor_meta_event_t dynamic_sensor_meta;
+
+            /*
+             * special additional sensor information frame, see
+             * SENSOR_TYPE_ADDITIONAL_INFO for details.
+             */
+            additional_info_event_t additional_info;
         };
 
         union {
@@ -830,8 +1141,6 @@ typedef struct sensors_event_t {
 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
@@ -851,7 +1160,7 @@ struct sensors_module_t {
      *  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
+     *  1 - Loopback mode. Data is injected for the supported
      *      sensors by the sensor service in this mode.
      * @return 0 on success
      *         -EINVAL if requested mode is not supported
index 2a8db87..e1abbc9 100644 (file)
@@ -39,7 +39,8 @@ __BEGIN_DECLS
 
 
 #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
+#define SOUND_TRIGGER_DEVICE_API_VERSION_1_1 HARDWARE_DEVICE_API_VERSION(1, 1)
+#define SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT SOUND_TRIGGER_DEVICE_API_VERSION_1_1
 
 /**
  * List of known sound trigger HAL modules. This is the base name of the sound_trigger HAL
@@ -106,7 +107,13 @@ struct sound_trigger_hw_device {
      * 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);
+                            sound_model_handle_t sound_model_handle);
+
+    /* Stop recognition on all models.
+     * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_1 or above.
+     * If no implementation is provided, stop_recognition will be called for each running model.
+     */
+    int (*stop_all_recognitions)(const struct sound_trigger_hw_device* dev);
 };
 
 typedef struct sound_trigger_hw_device sound_trigger_hw_device_t;
diff --git a/include/hardware/thermal.h b/include/hardware/thermal.h
new file mode 100644 (file)
index 0000000..b5b6e1d
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * 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_HARDWARE_THERMAL_H
+#define ANDROID_INCLUDE_HARDWARE_THERMAL_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+#define THERMAL_HARDWARE_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1)
+
+#define THERMAL_HARDWARE_MODULE_ID "thermal"
+
+// This value is returned if a desired temperature is not available.
+#define UNKNOWN_TEMPERATURE -FLT_MAX
+
+/** Device temperature types. Must be kept in sync with
+ * framework/base/core/java/android/os/HardwarePropertiesManager.java
+ */
+enum temperature_type {
+    DEVICE_TEMPERATURE_UNKNOWN  = -1,
+    DEVICE_TEMPERATURE_CPU      = 0,
+    DEVICE_TEMPERATURE_GPU      = 1,
+    DEVICE_TEMPERATURE_BATTERY  = 2,
+    DEVICE_TEMPERATURE_SKIN     = 3
+};
+
+enum cooling_type {
+    /** Fan cooling device speed in RPM. */
+    FAN_RPM                     = 0,
+};
+
+typedef struct {
+  /**
+   * This temperature's type.
+   */
+  enum temperature_type type;
+
+  /**
+   * Name of this temperature.
+   * All temperatures of the same "type" must have a different "name".
+   */
+  const char *name;
+
+  /**
+   * Current temperature in Celsius. If not available set by HAL to
+   * UNKNOWN_TEMPERATURE.
+   * Current temperature can be in any units if
+   * type=DEVICE_TEMPERATURE_UNKNOWN.
+   */
+  float current_value;
+
+  /**
+   * Throttling temperature constant for this temperature.
+   * If not available, set by HAL to UNKNOWN_TEMPERATURE.
+   */
+  float throttling_threshold;
+
+  /**
+   * Shutdown temperature constant for this temperature.
+   * If not available, set by HAL to UNKNOWN_TEMPERATURE.
+   */
+  float shutdown_threshold;
+
+  /**
+   * Threshold temperature above which the VR mode clockrate minimums cannot
+   * be maintained for this device.
+   * If not available, set by HAL to UNKNOWN_TEMPERATURE.
+   */
+  float vr_throttling_threshold;
+} temperature_t;
+
+typedef struct {
+    /**
+     * This cooling device type.
+     */
+    enum cooling_type type;
+
+    /**
+     * Name of this cooling device.
+     * All cooling devices of the same "type" must have a different "name".
+     */
+    const char *name;
+
+    /**
+     * Current cooling device value. Units depend on cooling device "type".
+     */
+    float current_value;
+} cooling_device_t;
+
+typedef struct {
+    /**
+     * Name of this CPU.
+     * All CPUs must have a different "name".
+     */
+    const char *name;
+
+    /**
+     * Active time since the last boot in ms.
+     */
+    uint64_t active;
+
+    /**
+     * Total time since the last boot in ms.
+     */
+    uint64_t total;
+
+    /**
+     * Is set to true when a core is online.
+     * If the core is offline, all other members except |name| should be ignored.
+     */
+    bool is_online;
+} cpu_usage_t;
+
+typedef struct thermal_module {
+    struct hw_module_t common;
+
+    /*
+     * (*getTemperatures) is called to get temperatures in Celsius.
+     *
+     * @param list If NULL, this method only returns number of temperatures
+     *     and caller should allocate a temperature_t array with that number
+     *     of elements.
+     *     Caller is responsible for allocating temperature_t array |list| of
+     *     large enough size (not less than returned number of temperatures).
+     *     If |list| is not NULL and this method returns non-negative value,
+     *     it's filled with the current temperatures. If the resulting
+     *     temperature list is longer than |size| elements, the remaining
+     *     temperatures are discarded and not stored, but counted for the value
+     *     returned by this method.
+     *     The order of temperatures of built-in devices (such as CPUs, GPUs and
+     *     etc.) in the |list| is kept the same regardless the number of calls
+     *     to this method even if they go offline, if these devices exist on
+     *     boot. The method always returns and never removes such temperatures.
+     * @param size The capacity of |list|, in elements, if |list| is not NULL.
+     *
+     * @return number of temperatures or negative value -errno on error.
+     *
+     */
+    ssize_t (*getTemperatures)(struct thermal_module *module, temperature_t *list, size_t size);
+
+    /*
+     * (*getCpuUsages) is called to get CPU usage information of each core:
+     *     active and total times in ms since first boot.
+     *
+     * @param list If NULL, this method only returns number of cores and caller
+     *     should allocate a cpu_usage_t array with that number of elements.
+     *     Caller is responsible for allocating cpu_usage_t array |list| of
+     *     large enough size (not less than returned number of CPUs).
+     *     If |list| is not NULL and this method returns non-negative value,
+     *     it's filled with the current CPU usages.
+     *     The order of CPUs in the |list| is kept the same regardless the
+     *     number of calls to this method.
+     *
+     * @return constant number of CPUs or negative value -errno on error.
+     *
+     */
+    ssize_t (*getCpuUsages)(struct thermal_module *module, cpu_usage_t *list);
+
+    /*
+     * (*getCoolingDevices) is called to get the cooling devices information.
+     *
+     * @param list If NULL, this method only returns number of cooling devices
+     *     and caller should allocate a cooling_device_t array with that number
+     *     of elements.
+     *     Caller is responsible for allocating cooling_device_t array |list| of
+     *     large enough size (not less than returned number of cooling devices).
+     *     If |list| is not NULL and this method returns non-negative value,
+     *     it's filled with the current cooling device information. If the
+     *     resulting cooling device list is longer than |size| elements, the
+     *     remaining cooling device informations are discarded and not stored,
+     *     but counted for the value returned by this method.
+     *     The order of built-in coolling devices in the |list| is kept the same
+     *     regardless the number of calls to this method even if they go
+     *     offline, if these devices exist on boot. The method always returns
+     *     and never removes from the list such coolling devices.
+     * @param size The capacity of |list|, in elements, if |list| is not NULL.
+     *
+     * @return number of cooling devices or negative value -errno on error.
+     *
+     */
+    ssize_t (*getCoolingDevices)(struct thermal_module *module, cooling_device_t *list,
+                                 size_t size);
+
+} thermal_module_t;
+
+__END_DECLS
+
+#endif  // ANDROID_INCLUDE_HARDWARE_THERMAL_H
diff --git a/include/hardware/vehicle.h b/include/hardware/vehicle.h
new file mode 100644 (file)
index 0000000..a590fbd
--- /dev/null
@@ -0,0 +1,1750 @@
+/*
+ * 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_VEHICLE_INTERFACE_H
+#define ANDROID_VEHICLE_INTERFACE_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <math.h>
+#include <errno.h>
+
+#include <hardware/hardware.h>
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+#define VEHICLE_HEADER_VERSION          1
+#define VEHICLE_MODULE_API_VERSION_1_0  HARDWARE_MODULE_API_VERSION(1, 0)
+#define VEHICLE_DEVICE_API_VERSION_1_0  HARDWARE_DEVICE_API_VERSION_2(1, 0, VEHICLE_HEADER_VERSION)
+
+/**
+ * Vehicle HAL to provide interfaces to various Car related sensors. The HAL is
+ * designed in a property, value maping where each property has a value which
+ * can be "get", "set" and "(un)subscribed" to. Subscribing will require the
+ * user of this HAL to provide parameters such as sampling rate.
+ */
+
+
+/*
+ * The id of this module
+ */
+#define VEHICLE_HARDWARE_MODULE_ID  "vehicle"
+
+/**
+ *  Name of the vehicle device to open
+ */
+#define VEHICLE_HARDWARE_DEVICE     "vehicle_hw_device"
+
+/**
+ * Each vehicle property is defined with various annotations to specify the type of information.
+ * Annotations will be used by scripts to run some type check or generate some boiler-plate codes.
+ * Also the annotations are the specification for each property, and each HAL implementation should
+ * follow what is specified as annotations.
+ * Here is the list of annotations with explanation on what it does:
+ * @value_type: Type of data for this property. One of the value from vehicle_value_type should be
+ *              set here.
+ * @change_mode: How this property changes. Value set is from vehicle_prop_change_mode. Some
+ *               properties can allow either on change or continuous mode and it is up to HAL
+ *               implementation to choose which mode to use.
+ * @access: Define how this property can be accessed. read only, write only or R/W from
+ *          vehicle_prop_access
+ * @data_member: Name of member from vehicle_value union to access this data.
+ * @data_enum: enum type that should be used for the data.
+ * @unit: Unit of data. Should be from vehicle_unit_type.
+ * @config_flags: Usage of config_flags in vehicle_prop_config
+ * @config_array: Usage of config_array in vehicle_prop_config. When this is specified,
+ *                @config_flags will not be used.
+ * @config_string: Explains the usage of config_string in vehicle_prop_config. Property with
+ *                 this annotation is expected to have additional information in config_string
+ *                 for that property to work.
+ * @zone_type type of zoned used. defined for zoned property
+ * @range_start, @range_end : define range of specific property values.
+ * @allow_out_of_range_value : This property allows out of range value to deliver additional
+ *                             information. Check VEHICLE_*_OUT_OF_RANGE_* for applicable values.
+ */
+//===== Vehicle Information ====
+
+/**
+ * Invalid property value used for argument where invalid property gives different result.
+ * @range_start
+ */
+#define VEHICLE_PROPERTY_INVALID (0x0)
+
+/**
+ * VIN of vehicle
+ * @value_type VEHICLE_VALUE_TYPE_STRING
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member info_vin
+ */
+#define VEHICLE_PROPERTY_INFO_VIN                                   (0x00000100)
+
+/**
+ * Maker name of vehicle
+ * @value_type VEHICLE_VALUE_TYPE_STRING
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member info_make
+ */
+#define VEHICLE_PROPERTY_INFO_MAKE                                  (0x00000101)
+
+/**
+ * Model of vehicle
+ * @value_type VEHICLE_VALUE_TYPE_STRING
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member info_model
+ */
+#define VEHICLE_PROPERTY_INFO_MODEL                                 (0x00000102)
+
+/**
+ * Model year of vehicle.
+ * @value_type VEHICLE_VALUE_TYPE_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member info_model_year
+ * @unit VEHICLE_UNIT_TYPE_YEAR
+ */
+#define VEHICLE_PROPERTY_INFO_MODEL_YEAR                           (0x00000103)
+
+/**
+ * Fuel capacity of the vehicle
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member info_fuel_capacity
+ * @unit VEHICLE_UNIT_TYPE_VEHICLE_UNIT_TYPE_MILLILITER
+ */
+#define VEHICLE_PROPERTY_INFO_FUEL_CAPACITY                         (0x00000104)
+
+
+//==== Vehicle Performance Sensors ====
+
+/**
+ * Current odometer value of the vehicle
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member odometer
+ * @unit VEHICLE_UNIT_TYPE_KILOMETER
+ */
+#define VEHICLE_PROPERTY_PERF_ODOMETER                              (0x00000204)
+
+/**
+ * Speed of the vehicle
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member vehicle_speed
+ * @unit VEHICLE_UNIT_TYPE_METER_PER_SEC
+ */
+#define VEHICLE_PROPERTY_PERF_VEHICLE_SPEED                         (0x00000207)
+
+
+//==== Engine Sensors ====
+
+/**
+ * Temperature of engine coolant
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member engine_coolant_temperature
+ * @unit VEHICLE_UNIT_TYPE_CELCIUS
+ */
+#define VEHICLE_PROPERTY_ENGINE_COOLANT_TEMP                        (0x00000301)
+
+/**
+ * Temperature of engine oil
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member engine_oil_temperature
+ * @unit VEHICLE_UNIT_TYPE_CELCIUS
+ */
+#define VEHICLE_PROPERTY_ENGINE_OIL_TEMP                            (0x00000304)
+/**
+ * Engine rpm
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member engine_rpm
+ * @unit VEHICLE_UNIT_TYPE_RPM
+ */
+#define VEHICLE_PROPERTY_ENGINE_RPM                                 (0x00000305)
+
+//==== Event Sensors ====
+
+/**
+ * Currently selected gear
+ * @value_type VEHICLE_VALUE_TYPE_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member gear_selection
+ * @data_enum vehicle_gear
+ */
+#define VEHICLE_PROPERTY_GEAR_SELECTION                             (0x00000400)
+
+/**
+ * Current gear. In non-manual case, selected gear does not necessarily match the current gear
+ * @value_type VEHICLE_VALUE_TYPE_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member gear_current_gear
+ * @data_enum vehicle_gear
+ */
+#define VEHICLE_PROPERTY_CURRENT_GEAR                               (0x00000401)
+
+/**
+ * Parking brake state.
+ * @value_type VEHICLE_VALUE_TYPE_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member parking_brake
+ * @data_enum vehicle_boolean
+ */
+#define VEHICLE_PROPERTY_PARKING_BRAKE_ON                           (0x00000402)
+
+/**
+ * Driving status policy.
+ * @value_type VEHICLE_VALUE_TYPE_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member driving_status
+ * @data_enum vehicle_driving_status
+ */
+#define VEHICLE_PROPERTY_DRIVING_STATUS                             (0x00000404)
+
+/**
+ * Warning for fuel low level.
+ * @value_type VEHICLE_VALUE_TYPE_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member is_fuel_level_low
+ * @data_enum vehicle_boolean
+ */
+#define VEHICLE_PROPERTY_FUEL_LEVEL_LOW                             (0x00000405)
+
+/**
+ * Night mode or not.
+ * @value_type VEHICLE_VALUE_TYPE_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member night_mode
+ * @data_enum vehicle_boolean
+ */
+#define VEHICLE_PROPERTY_NIGHT_MODE                                 (0x00000407)
+
+
+
+ //==== HVAC Properties ====
+
+/**
+ * Fan speed setting
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @data_member hvac.fan_speed
+ * @zone_type VEHICLE_ZONE
+ * @data_enum TODO
+ * @allow_out_of_range_value : OFF
+ */
+#define VEHICLE_PROPERTY_HVAC_FAN_SPEED                             (0x00000500)
+
+/**
+ * Fan direction setting
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @data_member hvac.fan_direction
+ * @zone_type VEHICLE_ZONE
+ * @data_enum TODO
+ * @allow_out_of_range_value : OFF
+ */
+#define VEHICLE_PROPERTY_HVAC_FAN_DIRECTION                         (0x00000501)
+
+/*
+ * Bit flags for fan direction
+ */
+enum vehicle_hvac_fan_direction {
+    VEHICLE_HVAC_FAN_DIRECTION_FACE                 = 0x1,
+    VEHICLE_HVAC_FAN_DIRECTION_FLOOR                = 0x2,
+    VEHICLE_HVAC_FAN_DIRECTION_FACE_AND_FLOOR       = 0x3,
+    VEHICLE_HVAC_FAN_DIRECTION_DEFROST              = 0x4,
+    VEHICLE_HVAC_FAN_DIRECTION_DEFROST_AND_FLOOR    = 0x5
+};
+
+/**
+ * HVAC current temperature.
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.temperature_current
+ */
+#define VEHICLE_PROPERTY_HVAC_TEMPERATURE_CURRENT                   (0x00000502)
+
+/**
+ * HVAC, target temperature set.
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.temperature_set
+ * @allow_out_of_range_value : MIN / MAX / OFF
+ */
+#define VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET                       (0x00000503)
+
+/**
+ * On/off defrost
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_WINDOW
+ * @data_member hvac.defrost_on
+ */
+#define VEHICLE_PROPERTY_HVAC_DEFROSTER                             (0x00000504)
+
+/**
+ * On/off AC
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_flags Supported zones
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.ac_on
+ */
+#define VEHICLE_PROPERTY_HVAC_AC_ON                                 (0x00000505)
+
+/**
+ * On/off max AC
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.max_ac_on
+ */
+#define VEHICLE_PROPERTY_HVAC_MAX_AC_ON                             (0x00000506)
+
+/**
+ * On/off max defrost
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.max_defrost_on
+ */
+#define VEHICLE_PROPERTY_HVAC_MAX_DEFROST_ON                        (0x00000507)
+
+/**
+ * On/off re-circulation
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.max_recirc_on
+ */
+#define VEHICLE_PROPERTY_HVAC_RECIRC_ON                             (0x00000508)
+
+/**
+ * On/off dual. This will be defined per each row.
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.dual_on
+ */
+#define VEHICLE_PROPERTY_HVAC_DUAL_ON                               (0x00000509)
+
+/**
+ * Represents power state for HVAC. Some HVAC properties will require matching power to be turned on
+ * to get out of OFF state. For non-zoned HVAC properties, VEHICLE_ALL_ZONE corresponds to
+ * global power state.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_ZONED_BOOLEAN
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_string list of HVAC properties whose power is controlled by this property. Format is
+ *                hexa-decimal number (0x...) separated by comma like "0x500,0x503". All zones
+ *                defined in these affected properties should be available in the property.
+ * @zone_type VEHICLE_ZONE
+ * @data_member hvac.power_on
+ */
+#define VEHICLE_PROPERTY_HVAC_POWER_ON                              (0x00000510)
+
+/**
+ * Outside temperature
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member outside_temperature
+ * @unit VEHICLE_UNIT_TYPE_CELCIUS
+ */
+
+#define VEHICLE_PROPERTY_ENV_OUTSIDE_TEMPERATURE                   (0x00000703)
+
+
+/**
+ * Cabin temperature
+ * @value_type VEHICLE_VALUE_TYPE_FLOAT
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE|VEHICLE_PROP_CHANGE_MODE_CONTINUOUS
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @data_member cabin_temperature
+ * @unit VEHICLE_UNIT_TYPE_CELCIUS
+ */
+#define VEHICLE_PROPERTY_ENV_CABIN_TEMPERATURE                  (0x00000704)
+
+
+/*
+ * Radio features.
+ */
+/**
+ * Radio presets stored on the Car radio module. The data type used is int32
+ * array with the following fields:
+ * <ul>
+ *    <li> int32_array[0]: Preset number </li>
+ *    <li> int32_array[1]: Band type (see #RADIO_BAND_FM in
+ *    system/core/include/system/radio.h).
+ *    <li> int32_array[2]: Channel number </li>
+ *    <li> int32_array[3]: Sub channel number </li>
+ * </ul>
+ *
+ * NOTE: When getting a current preset config ONLY set preset number (i.e.
+ * int32_array[0]). For setting a preset other fields are required.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC4
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_flags Number of presets supported
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_RADIO_PRESET                               (0x0000801)
+
+/**
+ * Constants relevant to radio.
+ */
+enum vehicle_radio_consts {
+    /** Minimum value for the radio preset */
+    VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
+};
+
+/**
+ * Represents audio focus state of Android side. Note that car's audio module will own audio
+ * focus and grant audio focus to Android side when requested by Android side. The focus has both
+ * per stream characteristics and global characteristics.
+ *
+ * Focus request (get of this property) will take the following form in int32_vec4:
+ *   int32_array[0]: vehicle_audio_focus_request type
+ *   int32_array[1]: bit flags of streams requested by this focus request. There can be up to
+ *                   32 streams.
+ *   int32_array[2]: External focus state flags. For request, only flag like
+ *                   VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG or
+ *                   VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG can be used.
+ *                   VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG is for case like radio where android
+ *                   side app still needs to hold focus but playback is done outside Android.
+ *                   VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG is for muting media channel
+ *                   including radio. VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG can be set even
+ *                   if android side releases focus (request type REQUEST_RELEASE). In that case,
+ *                   audio module should maintain mute state until user's explicit action to
+ *                   play some media.
+ *   int32_array[3]: Currently active audio contexts. Use combination of flags from
+ *                   vehicle_audio_context_flag.
+ *                   This can be used as a hint to adjust audio policy or other policy decision.
+ *                   Note that there can be multiple context active at the same time. And android
+ *                   can send the same focus request type gain due to change in audio contexts.
+ * Note that each focus request can request multiple streams that is expected to be used for
+ * the current request. But focus request itself is global behavior as GAIN or GAIN_TRANSIENT
+ * expects all sounds played by car's audio module to stop. Note that stream already allocated to
+ * android before this focus request should not be affected by focus request.
+ *
+ * Focus response (set and subscription callback for this property) will take the following form:
+ *   int32_array[0]: vehicle_audio_focus_state type
+ *   int32_array[1]: bit flags of streams allowed.
+ *   int32_array[2]: External focus state: bit flags of currently active audio focus in car
+ *                   side (outside Android). Active audio focus does not necessarily mean currently
+ *                   playing, but represents the state of having focus or waiting for focus
+ *                   (pause state).
+ *                   One or combination of flags from vehicle_audio_ext_focus_flag.
+ *                   0 means no active audio focus holder outside Android.
+ *                   The state will have following values for each vehicle_audio_focus_state_type:
+ *                   GAIN: 0 or VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY when radio is active in
+ *                       Android side.
+ *                   GAIN_TRANSIENT: 0. Can be VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT or
+ *                       VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT if android side has requested
+ *                       GAIN_TRANSIENT_MAY_DUCK and car side is ducking.
+ *                   LOSS: 0 when no focus is audio is active in car side.
+ *                       VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT when car side is playing something
+ *                       permanent.
+ *                   LOSS_TRANSIENT: always should be VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT
+ *   int32_array[3]: should be zero.
+ *
+ * If car does not support VEHICLE_PROPERTY_AUDIO_FOCUS, focus is assumed to be granted always.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC4
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_AUDIO_FOCUS                                  (0x00000900)
+
+enum vehicle_audio_focus_request {
+    VEHICLE_AUDIO_FOCUS_REQUEST_GAIN = 0x1,
+    VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT = 0x2,
+    VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
+    /**
+     * This is for the case where android side plays sound like UI feedback
+     * and car side does not need to duck existing playback as long as
+     * requested stream is available.
+     */
+    VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_NO_DUCK  = 0x4,
+    VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE = 0x5,
+};
+
+enum vehicle_audio_focus_state {
+    /**
+     * Android side has permanent focus and can play allowed streams.
+     */
+    VEHICLE_AUDIO_FOCUS_STATE_GAIN = 0x1,
+    /**
+     * Android side has transient focus and can play allowed streams.
+     */
+    VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT = 0x2,
+    /**
+     * Car audio module is playing guidance kind of sound outside Android. Android side can
+     * still play through allowed streams with ducking.
+     */
+    VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
+    /**
+     * Car audio module is playing transient sound outside Android. Android side should stop
+     * playing any sounds.
+     */
+    VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT = 0x4,
+    /**
+     * Android side has lost focus and cannot play any sound.
+     */
+    VEHICLE_AUDIO_FOCUS_STATE_LOSS = 0x5,
+    /**
+     * car audio module is playing safety critical sound, and Android side cannot request focus
+     * until the current state is finished. car audio module should restore it to the previous
+     * state when it can allow Android to play.
+     */
+    VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
+};
+
+/**
+ * Flags to represent multiple streams by combining these.
+ */
+enum vehicle_audio_stream_flag {
+    VEHICLE_AUDIO_STREAM_STREAM0_FLAG = (0x1<<0),
+    VEHICLE_AUDIO_STREAM_STREAM1_FLAG = (0x1<<1),
+    VEHICLE_AUDIO_STREAM_STREAM2_FLAG = (0x1<<2),
+};
+
+/**
+ * Represents stream number (always 0 to N -1 where N is max number of streams).
+ * Can be used for audio related property expecting one stream.
+ */
+enum vehicle_audio_stream {
+    VEHICLE_AUDIO_STREAM0 = 0,
+    VEHICLE_AUDIO_STREAM1 = 1,
+};
+
+/**
+ * Flag to represent external focus state (outside Android).
+ */
+enum vehicle_audio_ext_focus_flag {
+    /**
+     * No external focus holder.
+     */
+    VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG = 0x0,
+    /**
+     * Car side (outside Android) has component holding GAIN kind of focus state.
+     */
+    VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG = 0x1,
+    /**
+     * Car side (outside Android) has component holding GAIN_TRANSIENT kind of focus state.
+     */
+    VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT_FLAG = 0x2,
+    /**
+     * Car side is expected to play something while focus is held by Android side. One example
+     * can be radio attached in car side. But Android's radio app still should have focus,
+     * and Android side should be in GAIN state, but media stream will not be allocated to Android
+     * side and car side can play radio any time while this flag is active.
+     */
+    VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG = 0x4,
+    /**
+     * Car side should mute any media including radio. This can be used with any focus request
+     * including GAIN* and RELEASE.
+     */
+    VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG = 0x8,
+};
+
+/**
+ * Index in int32_array for VEHICLE_PROPERTY_AUDIO_FOCUS property.
+ */
+enum vehicle_audio_focus_index {
+    VEHICLE_AUDIO_FOCUS_INDEX_FOCUS = 0,
+    VEHICLE_AUDIO_FOCUS_INDEX_STREAMS = 1,
+    VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE = 2,
+    VEHICLE_AUDIO_FOCUS_INDEX_AUDIO_CONTEXTS = 3,
+};
+
+/**
+ * Flags to tell the current audio context.
+ */
+enum vehicle_audio_context_flag {
+    /** Music playback is currently active. */
+    VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG                      = 0x1,
+    /** Navigation is currently running. */
+    VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG                 = 0x2,
+    /** Voice command session is currently running. */
+    VEHICLE_AUDIO_CONTEXT_VOICE_COMMAND_FLAG              = 0x4,
+    /** Voice call is currently active. */
+    VEHICLE_AUDIO_CONTEXT_CALL_FLAG                       = 0x8,
+    /** Alarm is active. This may be only used in VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY. */
+    VEHICLE_AUDIO_CONTEXT_ALARM_FLAG                      = 0x10,
+    /**
+     * Notification sound is active. This may be only used in VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY.
+     */
+    VEHICLE_AUDIO_CONTEXT_NOTIFICATION_FLAG               = 0x20,
+    /**
+     * Context unknown. Only used for VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY to represent default
+     * stream for unknown contents.
+     */
+    VEHICLE_AUDIO_CONTEXT_UNKNOWN_FLAG                    = 0x40,
+    /** Safety alert / warning is played. */
+    VEHICLE_AUDIO_CONTEXT_SAFETY_ALERT_FLAG               = 0x80,
+    /** CD / DVD kind of audio is played */
+    VEHICLE_AUDIO_CONTEXT_CD_ROM_FLAG                     = 0x100,
+    /** Aux audio input is played */
+    VEHICLE_AUDIO_CONTEXT_AUX_AUDIO_FLAG                  = 0x200,
+    /** system sound like UI feedback */
+    VEHICLE_AUDIO_CONTEXT_SYSTEM_SOUND_FLAG               = 0x400,
+    /** Radio is played */
+    VEHICLE_AUDIO_CONTEXT_RADIO_FLAG                      = 0x800,
+};
+
+/**
+ * Property to control audio volume of each audio context.
+ *
+ * Data type looks like:
+ *   int32_array[0] : stream context as defined in vehicle_audio_context_flag.
+ *   int32_array[1] : volume level, valid range is 0 to int32_max_value defined in config.
+ *                    0 will be mute state. int32_min_value in config should be always 0.
+ *   int32_array[2] : One of vehicle_audio_volume_state.
+ *
+ * This property requires per stream based get. HAL implementation should check stream number
+ * in get call to return the right volume.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC3
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_flags all audio contexts supported.
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_AUDIO_VOLUME                                 (0x00000901)
+
+/**
+ * enum to represent audio volume state.
+ */
+enum vehicle_audio_volume_state {
+    VEHICLE_AUDIO_VOLUME_STATE_OK            = 0,
+    /**
+     * Audio volume has reached volume limit set in VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT
+     * and user's request to increase volume further is not allowed.
+     */
+    VEHICLE_AUDIO_VOLUME_STATE_LIMIT_REACHED = 1,
+};
+
+/**
+ * Index in int32_array for VEHICLE_PROPERTY_AUDIO_VOLUME property.
+ */
+enum vehicle_audio_volume_index {
+    VEHICLE_AUDIO_VOLUME_INDEX_STREAM = 0,
+    VEHICLE_AUDIO_VOLUME_INDEX_VOLUME = 1,
+    VEHICLE_AUDIO_VOLUME_INDEX_STATE = 2,
+};
+
+/**
+ * Property for handling volume limit set by user. This limits maximum volume that can be set
+ * per each context.
+ *   int32_array[0] : stream context as defined in vehicle_audio_context_flag.
+ *   int32_array[1] : maximum volume set to the stream. If there is no restriction, this value
+ *                    will be  bigger than VEHICLE_PROPERTY_AUDIO_VOLUME's max value.
+ *
+ * If car does not support this feature, this property should not be populated by HAL.
+ * This property requires per stream based get. HAL implementation should check stream number
+ * in get call to return the right volume.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC2
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_flags all audio contexts supported.
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT                           (0x00000902)
+
+/**
+ * Index in int32_array for VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT property.
+ */
+enum vehicle_audio_volume_limit_index {
+    VEHICLE_AUDIO_VOLUME_LIMIT_INDEX_STREAM = 0,
+    VEHICLE_AUDIO_VOLUME_LIMIT_INDEX_MAX_VOLUME = 1,
+};
+
+/**
+ * Property to share audio routing policy of android side. This property is set at the beginning
+ * to pass audio policy in android side down to vehicle HAL and car audio module.
+ * This can be used as a hint to adjust audio policy or other policy decision.
+ *
+ *   int32_array[0] : audio stream where the audio for the application context will be routed
+ *                    by default. Note that this is the default setting from system, but each app
+ *                    may still use different audio stream for whatever reason.
+ *   int32_array[1] : All audio contexts that will be sent through the physical stream. Flag
+ *                    is defined in vehicle_audio_context_flag.
+
+ * Setting of this property will be done for all available physical streams based on audio H/W
+ * variant information acquired from VEHICLE_PROPERTY_AUDIO_HW_VARIANT property.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC2
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_WRITE
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY                         (0x00000903)
+
+/**
+ * Index in int32_array for VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY property.
+ */
+enum vehicle_audio_routing_policy_index {
+    VEHICLE_AUDIO_ROUTING_POLICY_INDEX_STREAM = 0,
+    VEHICLE_AUDIO_ROUTING_POLICY_INDEX_CONTEXTS = 1,
+};
+
+/**
+* Property to return audio H/W variant type used in this car. This allows android side to
+* support different audio policy based on H/W variant used. Note that other components like
+* CarService may need overlay update to support additional variants. If this property does not
+* exist, default audio policy will be used.
+*
+* @value_type VEHICLE_VALUE_TYPE_INT32
+* @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+* @access VEHICLE_PROP_ACCESS_READ
+* @config_flags Additional info on audio H/W. Should use vehicle_audio_hw_variant_config_flag for
+*               this.
+* @data_member int32_value
+*/
+#define VEHICLE_PROPERTY_AUDIO_HW_VARIANT                             (0x00000904)
+
+/**
+ * Flag to be used in vehicle_prop_config.config_flags for VEHICLE_PROPERTY_AUDIO_HW_VARIANT.
+ */
+enum vehicle_audio_hw_variant_config_flag {
+    /**
+     * Flag to tell that radio is internal to android and radio should
+     * be treated like other android stream like media.
+     * When this flag is not set or AUDIO_HW_VARIANT does not exist,
+     * radio is treated as external module. This brins some delta in audio focus
+     * handling as well.
+     */
+    VEHICLE_AUDIO_HW_VARIANT_FLAG_INTERNAL_RADIO_FLAG = 0x1,
+};
+
+
+/**
+ * Property to control power state of application processor.
+ *
+ * It is assumed that AP's power state is controller by separate power controller.
+ *
+ * For configuration information, vehicle_prop_config.config_flags can have bit flag combining
+ * values in vehicle_ap_power_state_config_type.
+ *
+ * For get / notification, data type looks like this:
+ *   int32_array[0] : vehicle_ap_power_state_type
+ *   int32_array[1] : additional parameter relevant for each state. should be 0 if not used.
+ * For set, data type looks like this:
+ *   int32_array[0] : vehicle_ap_power_state_set_type
+ *   int32_array[1] : additional parameter relevant for each request. should be 0 if not used.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC2
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_flags Additional info on power state. Should use vehicle_ap_power_state_config_flag.
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_AP_POWER_STATE                               (0x00000A00)
+
+enum vehicle_ap_power_state_config_flag {
+    /**
+     * AP can enter deep sleep state. If not set, AP will always shutdown from
+     * VEHICLE_AP_POWER_STATE_SHUTDOWN_PREPARE power state.
+     */
+    VEHICLE_AP_POWER_STATE_CONFIG_ENABLE_DEEP_SLEEP_FLAG = 0x1,
+
+    /**
+     * The power controller can power on AP from off state after timeout specified in
+     * VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
+     */
+    VEHICLE_AP_POWER_STATE_CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
+};
+
+enum vehicle_ap_power_state {
+    /** vehicle HAL will never publish this state to AP */
+    VEHICLE_AP_POWER_STATE_OFF = 0,
+    /** vehicle HAL will never publish this state to AP */
+    VEHICLE_AP_POWER_STATE_DEEP_SLEEP = 1,
+    /** AP is on but display should be off. */
+    VEHICLE_AP_POWER_STATE_ON_DISP_OFF = 2,
+    /** AP is on with display on. This state allows full user interaction. */
+    VEHICLE_AP_POWER_STATE_ON_FULL = 3,
+    /**
+     * The power controller has requested AP to shutdown. AP can either enter sleep state or start
+     * full shutdown. AP can also request postponing shutdown by sending
+     * VEHICLE_AP_POWER_SET_SHUTDOWN_POSTPONE message. The power controller should change power
+     * state to this state to shutdown system.
+     *
+     * int32_array[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
+     */
+    VEHICLE_AP_POWER_STATE_SHUTDOWN_PREPARE = 4,
+};
+
+enum vehicle_ap_power_state_shutdown_param {
+    /** AP should shutdown immediately. Postponing is not allowed. */
+    VEHICLE_AP_POWER_SHUTDOWN_PARAM_SHUTDOWN_IMMEDIATELY = 1,
+    /** AP can enter deep sleep instead of shutting down completely. */
+    VEHICLE_AP_POWER_SHUTDOWN_PARAM_CAN_SLEEP = 2,
+    /** AP can only shutdown with postponing allowed. */
+    VEHICLE_AP_POWER_SHUTDOWN_PARAM_SHUTDOWN_ONLY = 3,
+};
+
+enum vehicle_ap_power_set_state {
+    /**
+     * AP has finished boot up, and can start shutdown if requested by power controller.
+     */
+    VEHICLE_AP_POWER_SET_BOOT_COMPLETE = 0x1,
+    /**
+     * AP is entering deep sleep state. How this state is implemented may vary depending on
+     * each H/W, but AP's power should be kept in this state.
+     */
+    VEHICLE_AP_POWER_SET_DEEP_SLEEP_ENTRY = 0x2,
+    /**
+     * AP is exiting from deep sleep state, and is in VEHICLE_AP_POWER_STATE_SHUTDOWN_PREPARE state.
+     * The power controller may change state to other ON states based on the current state.
+     */
+    VEHICLE_AP_POWER_SET_DEEP_SLEEP_EXIT = 0x3,
+    /**
+     * int32_array[1]: Time to postpone shutdown in ms. Maximum value can be 5000 ms.
+     *                 If AP needs more time, it will send another POSTPONE message before
+     *                 the previous one expires.
+     */
+    VEHICLE_AP_POWER_SET_SHUTDOWN_POSTPONE = 0x4,
+    /**
+     * AP is starting shutting down. When system completes shutdown, everything will stop in AP
+     * as kernel will stop all other contexts. It is responsibility of vehicle HAL or lower level
+     * to synchronize that state with external power controller. As an example, some kind of ping
+     * with timeout in power controller can be a solution.
+     *
+     * int32_array[1]: Time to turn on AP in secs. Power controller may turn on AP after specified
+     *                 time so that AP can run tasks like update. If it is set to 0, there is no
+     *                 wake up, and power controller may not necessarily support wake-up.
+     *                 If power controller turns on AP due to timer, it should start with
+     *                 VEHICLE_AP_POWER_STATE_ON_DISP_OFF state, and after receiving
+     *                 VEHICLE_AP_POWER_SET_BOOT_COMPLETE, it shall do state transition to
+     *                 VEHICLE_AP_POWER_STATE_SHUTDOWN_PREPARE.
+     */
+    VEHICLE_AP_POWER_SET_SHUTDOWN_START = 0x5,
+    /**
+     * User has requested to turn off headunit's display, which is detected in android side.
+     * The power controller may change the power state to VEHICLE_AP_POWER_STATE_ON_DISP_OFF.
+     */
+    VEHICLE_AP_POWER_SET_DISPLAY_OFF = 0x6,
+    /**
+     * User has requested to turn on headunit's display, most probably from power key input which
+     * is attached to headunit. The power controller may change the power state to
+     * VEHICLE_AP_POWER_STATE_ON_FULL.
+     */
+    VEHICLE_AP_POWER_SET_DISPLAY_ON = 0x7,
+};
+
+/**
+ * Property to represent brightness of the display. Some cars have single control for
+ * the brightness of all displays and this property is to share change in that control.
+ *
+ * If this is writable, android side can set this value when user changes display brightness
+ * from Settings. If this is read only, user may still change display brightness from Settings,
+ * but that will not be reflected to other displays.
+ *
+ * @value_type VEHICLE_VALUE_TYPE_INT32
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ|VEHICLE_PROP_ACCESS_READ_WRITE
+ * @data_member int32
+ */
+#define VEHICLE_PROPERTY_DISPLAY_BRIGHTNESS                        (0x00000A01)
+
+
+/**
+ * Index in int32_array for VEHICLE_PROPERTY_AP_POWER_STATE property.
+ */
+enum vehicle_ap_power_state_index {
+    VEHICLE_AP_POWER_STATE_INDEX_STATE = 0,
+    VEHICLE_AP_POWER_STATE_INDEX_ADDITIONAL = 1,
+};
+
+/**
+* Property to report bootup reason for the current power on. This is a static property that will
+* not change for the whole duration until power off. For example, even if user presses power on
+* button after automatic power on with door unlock, bootup reason should stay with
+* VEHICLE_AP_POWER_BOOTUP_REASON_USER_UNLOCK.
+*
+* int32_value should be vehicle_ap_power_bootup_reason.
+*
+* @value_type VEHICLE_VALUE_TYPE_INT32
+* @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+* @access VEHICLE_PROP_ACCESS_READ
+* @data_member int32_value
+*/
+#define VEHICLE_PROPERTY_AP_POWER_BOOTUP_REASON                     (0x00000A02)
+
+/**
+ * Enum to represent bootup reason.
+ */
+enum vehicle_ap_power_bootup_reason {
+    /**
+     * Power on due to user's pressing of power key or rotating of ignition switch.
+     */
+    VEHICLE_AP_POWER_BOOTUP_REASON_USER_POWER_ON = 0,
+    /**
+     * Automatic power on triggered by door unlock or any other kind of automatic user detection.
+     */
+    VEHICLE_AP_POWER_BOOTUP_REASON_USER_UNLOCK   = 1,
+    /**
+     * Automatic power on triggered by timer. This only happens when AP has asked wake-up after
+     * certain time through time specified in VEHICLE_AP_POWER_SET_SHUTDOWN_START.
+     */
+    VEHICLE_AP_POWER_BOOTUP_REASON_TIMER         = 2,
+};
+
+
+/**
+ * Property to feed H/W input events to android
+ *
+ * int32_array[0] : action defined by vehicle_hw_key_input_action
+ * int32_array[1] : key code, should use standard android key code
+ * int32_array[2] : target display defined in vehicle_display. Events not tied
+ *                  to specific display should be sent to DISPLAY_MAIN.
+ * int32_array[3] : reserved for now. should be zero
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC4
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ
+ * @config_flags
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_HW_KEY_INPUT                               (0x00000A10)
+
+enum vehicle_hw_key_input_action {
+    /** Key down */
+    VEHICLE_HW_KEY_INPUT_ACTION_DOWN = 0,
+    /** Key up */
+    VEHICLE_HW_KEY_INPUT_ACTION_UP = 1,
+};
+
+enum vehicle_display {
+    /** center console */
+    VEHICLE_DISPLAY_MAIN               = 0,
+    VEHICLE_DISPLAY_INSTRUMENT_CLUSTER = 1,
+};
+
+/**
+ * Property to define instrument cluster information.
+ * For CLUSTER_TYPE_EXTERNAL_DISPLAY:
+ *  READ:
+ *   int32_array[0] : The current screen mode index. Screen mode is defined
+ *                     as a configuration in car service and represents which
+ *                     area of screen is renderable.
+ *   int32_array[1] : Android can render to instrument cluster (=1) or not(=0). When this is 0,
+ *                    instrument cluster may be rendering some information in the area
+ *                    allocated for android and android side rendering is invisible. *
+ *   int32_array[2..3] : should be zero
+ *  WRITE from android:
+ *   int32_array[0] : Preferred mode for android side. Depending on the app rendering to instrument
+ *                    cluster, preferred mode can change. Instrument cluster still needs to send
+ *                    event with new mode to trigger actual mode change.
+ *   int32_array[1] : The current app context relevant for instrument cluster. Use the same flag
+ *                    with vehicle_audio_context_flag but this context represents active apps, not
+ *                    active audio. Instrument cluster side may change mode depending on the
+ *                    currently active contexts.
+ *   int32_array[2..3] : should be zero
+ *  When system boots up, Android side will write {0, 0, 0, 0} when it is ready to render to
+ *  instrument cluster. Before this message, rendering from android should not be visible in the
+ *  cluster.
+ * @value_type VEHICLE_VALUE_TYPE_INT32_VEC4
+ * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+ * @access VEHICLE_PROP_ACCESS_READ_WRITE
+ * @config_array 0:vehicle_instument_cluster_type 1:hw type
+ * @data_member int32_array
+ */
+#define VEHICLE_PROPERTY_INSTRUMENT_CLUSTER_INFO                     (0x00000A20)
+
+/**
+ * Represents instrument cluster type available in system
+ */
+enum vehicle_instument_cluster_type {
+    /** Android has no access to instument cluster */
+    VEHICLE_INSTRUMENT_CLUSTER_TYPE_NONE = 0,
+    /**
+     * Instrument cluster can communicate through vehicle hal with additional
+     * properties to exchange meta-data
+     */
+    VEHICLE_INSTRUMENT_CLUSTER_TYPE_HAL_INTERFACE = 1,
+    /**
+     * Instrument cluster is external display where android can render contents
+     */
+    VEHICLE_INSTRUMENT_CLUSTER_TYPE_EXTERNAL_DISPLAY = 2,
+};
+
+/**
+ *  H/W specific, non-standard property can be added as necessary. Such property should use
+ *  property number in range of [VEHICLE_PROPERTY_CUSTOM_START, VEHICLE_PROPERTY_CUSTOM_END].
+ *  Definition of property in this range is completely up to each HAL implementation.
+ *  For such property, it is recommended to fill vehicle_prop_config.config_string with some
+ *  additional information to help debugging. For example, company XYZ's custom extension may
+ *  include config_string of "com.XYZ.some_further_details".
+ *  @range_start
+ */
+#define VEHICLE_PROPERTY_CUSTOM_START                       (0x70000000)
+/** @range_end */
+#define VEHICLE_PROPERTY_CUSTOM_END                         (0x73ffffff)
+
+/**
+ * Property range allocated for system's internal usage like testing. HAL should never declare
+ * property in this range.
+ * @range_start
+ */
+#define VEHICLE_PROPERTY_INTERNAL_START                     (0x74000000)
+/**
+ * @range_end
+ */
+#define VEHICLE_PROPERTY_INTERNAL_END                       (0x74ffffff)
+
+/**
+ * Value types for various properties.
+ */
+enum vehicle_value_type {
+    VEHICLE_VALUE_TYPE_SHOUD_NOT_USE            = 0x00, // value_type should never set to 0.
+    VEHICLE_VALUE_TYPE_STRING                   = 0x01,
+    VEHICLE_VALUE_TYPE_BYTES                    = 0x02,
+    VEHICLE_VALUE_TYPE_BOOLEAN                  = 0x03,
+    VEHICLE_VALUE_TYPE_ZONED_BOOLEAN            = 0x04,
+    VEHICLE_VALUE_TYPE_INT64                    = 0x05,
+    VEHICLE_VALUE_TYPE_FLOAT                    = 0x10,
+    VEHICLE_VALUE_TYPE_FLOAT_VEC2               = 0x11,
+    VEHICLE_VALUE_TYPE_FLOAT_VEC3               = 0x12,
+    VEHICLE_VALUE_TYPE_FLOAT_VEC4               = 0x13,
+    VEHICLE_VALUE_TYPE_INT32                    = 0x20,
+    VEHICLE_VALUE_TYPE_INT32_VEC2               = 0x21,
+    VEHICLE_VALUE_TYPE_INT32_VEC3               = 0x22,
+    VEHICLE_VALUE_TYPE_INT32_VEC4               = 0x23,
+    VEHICLE_VALUE_TYPE_ZONED_FLOAT              = 0x30,
+    VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2         = 0x31,
+    VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3         = 0x32,
+    VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4         = 0x33,
+    VEHICLE_VALUE_TYPE_ZONED_INT32              = 0x40,
+    VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2         = 0x41,
+    VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3         = 0x42,
+    VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4         = 0x43,
+};
+
+/**
+ * Units used for int or float type with no attached enum types.
+ */
+enum vehicle_unit_type {
+    VEHICLE_UNIT_TYPE_SHOULD_NOT_USE        = 0x00000000,
+    // speed related items
+    VEHICLE_UNIT_TYPE_METER_PER_SEC         = 0x00000001,
+    VEHICLE_UNIT_TYPE_RPM                   = 0x00000002,
+    VEHICLE_UNIT_TYPE_HZ                    = 0x00000003,
+    // kind of ratio
+    VEHICLE_UNIT_TYPE_PERCENTILE            = 0x00000010,
+    // length
+    VEHICLE_UNIT_TYPE_MILLIMETER            = 0x00000020,
+    VEHICLE_UNIT_TYPE_METER                 = 0x00000021,
+    VEHICLE_UNIT_TYPE_KILOMETER             = 0x00000023,
+    // temperature
+    VEHICLE_UNIT_TYPE_CELCIUS               = 0x00000030,
+    // volume
+    VEHICLE_UNIT_TYPE_MILLILITER            = 0x00000040,
+    // time
+    VEHICLE_UNIT_TYPE_NANO_SECS             = 0x00000050,
+    VEHICLE_UNOT_TYPE_SECS                  = 0x00000053,
+    VEHICLE_UNIT_TYPE_YEAR                  = 0x00000059,
+};
+
+/**
+ * This describes how value of property can change.
+ */
+enum vehicle_prop_change_mode {
+    /**
+     * Property of this type will *never* change. This property will not support subscription, but
+     * will support get
+     */
+    VEHICLE_PROP_CHANGE_MODE_STATIC         = 0x00,
+    /**
+     * Property of this type will be reported when there is a change. get should return the
+     * current value.
+     */
+    VEHICLE_PROP_CHANGE_MODE_ON_CHANGE      = 0x01,
+    /**
+     * Property of this type change continuously and requires fixed rate of sampling to retrieve
+     * the data.
+     */
+    VEHICLE_PROP_CHANGE_MODE_CONTINUOUS     = 0x02,
+};
+
+/**
+ * Property config defines the capabilities of it. User of the API
+ * should first get the property config to understand the output from get()
+ * commands and also to ensure that set() or events commands are in sync with
+ * the expected output.
+ */
+enum vehicle_prop_access {
+    VEHICLE_PROP_ACCESS_READ  = 0x01,
+    VEHICLE_PROP_ACCESS_WRITE = 0x02,
+    VEHICLE_PROP_ACCESS_READ_WRITE = 0x03
+};
+
+/**
+ * These permissions define how the OEMs want to distribute their information and security they
+ * want to apply. On top of these restrictions, android will have additional
+ * 'app-level' permissions that the apps will need to ask the user before the apps have the
+ * information.
+ * This information should be kept in vehicle_prop_config.permission_model.
+ */
+enum vehicle_permission_model {
+    /**
+     * No special restriction, but each property can still require specific android app-level
+     * permission.
+     */
+    VEHICLE_PERMISSION_NO_RESTRICTION = 0,
+    /** Signature only. Only APKs signed with OEM keys are allowed. */
+    VEHICLE_PERMISSION_OEM_ONLY = 0x1,
+    /** System only. APKs built-in to system  can access the property. */
+    VEHICLE_PERMISSION_SYSTEM_APP_ONLY = 0x2,
+    /** Equivalent to “system|signature” */
+    VEHICLE_PERMISSION_OEM_OR_SYSTEM_APP = 0x3
+};
+
+
+/**
+ *  Special values for INT32/FLOAT (including ZONED types)
+ *  These values represent special state, which is outside MIN/MAX range but can happen.
+ *  For example, HVAC temperature may use out of range min / max to represent that
+ *  it is working in full power although target temperature has separate min / max.
+ *  OUT_OF_RANGE_OFF can represent a state where the property is powered off.
+ *  Usually such property will have separate property to control power.
+ */
+
+#define VEHICLE_INT_OUT_OF_RANGE_MAX (INT32_MAX)
+#define VEHICLE_INT_OUT_OF_RANGE_MIN (INT32_MIN)
+#define VEHICLE_INT_OUT_OF_RANGE_OFF (INT32_MIN + 1)
+
+#define VEHICLE_FLOAT_OUT_OF_RANGE_MAX (INFINITY)
+#define VEHICLE_FLOAT_OUT_OF_RANGE_MIN (-INFINITY)
+#define VEHICLE_FLOAT_OUT_OF_RANGE_OFF (NAN)
+
+/**
+ * Car states.
+ *
+ * The driving states determine what features of the UI will be accessible.
+ */
+enum vehicle_driving_status {
+    VEHICLE_DRIVING_STATUS_UNRESTRICTED      = 0x00,
+    VEHICLE_DRIVING_STATUS_NO_VIDEO          = 0x01,
+    VEHICLE_DRIVING_STATUS_NO_KEYBOARD_INPUT = 0x02,
+    VEHICLE_DRIVING_STATUS_NO_VOICE_INPUT    = 0x04,
+    VEHICLE_DRIVING_STATUS_NO_CONFIG         = 0x08,
+    VEHICLE_DRIVING_STATUS_LIMIT_MESSAGE_LEN = 0x10
+};
+
+/**
+ * Various gears which can be selected by user and chosen in system.
+ */
+enum vehicle_gear {
+    // Gear selections present in both automatic and manual cars.
+    VEHICLE_GEAR_NEUTRAL    = 0x0001,
+    VEHICLE_GEAR_REVERSE    = 0x0002,
+
+    // Gear selections (mostly) present only in automatic cars.
+    VEHICLE_GEAR_PARK       = 0x0004,
+    VEHICLE_GEAR_DRIVE      = 0x0008,
+    VEHICLE_GEAR_LOW        = 0x0010,
+
+    // Other possible gear selections (maybe present in manual or automatic
+    // cars).
+    VEHICLE_GEAR_1          = 0x0010,
+    VEHICLE_GEAR_2          = 0x0020,
+    VEHICLE_GEAR_3          = 0x0040,
+    VEHICLE_GEAR_4          = 0x0080,
+    VEHICLE_GEAR_5          = 0x0100,
+    VEHICLE_GEAR_6          = 0x0200,
+    VEHICLE_GEAR_7          = 0x0400,
+    VEHICLE_GEAR_8          = 0x0800,
+    VEHICLE_GEAR_9          = 0x1000
+};
+
+
+/**
+ * Various zones in the car.
+ *
+ * Zones are used for Air Conditioning purposes and divide the car into physical
+ * area zones.
+ */
+enum vehicle_zone {
+    VEHICLE_ZONE_ROW_1_LEFT    = 0x00000001,
+    VEHICLE_ZONE_ROW_1_CENTER  = 0x00000002,
+    VEHICLE_ZONE_ROW_1_RIGHT   = 0x00000004,
+    VEHICLE_ZONE_ROW_1_ALL     = 0x00000008,
+    VEHICLE_ZONE_ROW_2_LEFT    = 0x00000010,
+    VEHICLE_ZONE_ROW_2_CENTER  = 0x00000020,
+    VEHICLE_ZONE_ROW_2_RIGHT   = 0x00000040,
+    VEHICLE_ZONE_ROW_2_ALL     = 0x00000080,
+    VEHICLE_ZONE_ROW_3_LEFT    = 0x00000100,
+    VEHICLE_ZONE_ROW_3_CENTER  = 0x00000200,
+    VEHICLE_ZONE_ROW_3_RIGHT   = 0x00000400,
+    VEHICLE_ZONE_ROW_3_ALL     = 0x00000800,
+    VEHICLE_ZONE_ROW_4_LEFT    = 0x00001000,
+    VEHICLE_ZONE_ROW_4_CENTER  = 0x00002000,
+    VEHICLE_ZONE_ROW_4_RIGHT   = 0x00004000,
+    VEHICLE_ZONE_ROW_4_ALL     = 0x00008000,
+    VEHICLE_ZONE_ALL           = 0x80000000,
+};
+
+/**
+ * Various Seats in the car.
+ */
+enum vehicle_seat {
+    VEHICLE_SEAT_DRIVER_LHD             = 0x0001,
+    VEHICLE_SEAT_DRIVER_RHD             = 0x0002,
+    VEHICLE_SEAT_ROW_1_PASSENGER_LEFT   = 0x0010,
+    VEHICLE_SEAT_ROW_1_PASSENGER_CENTER = 0x0020,
+    VEHICLE_SEAT_ROW_1_PASSENGER_RIGHT  = 0x0040,
+    VEHICLE_SEAT_ROW_2_PASSENGER_LEFT   = 0x0100,
+    VEHICLE_SEAT_ROW_2_PASSENGER_CENTER = 0x0200,
+    VEHICLE_SEAT_ROW_2_PASSENGER_RIGHT  = 0x0400,
+    VEHICLE_SEAT_ROW_3_PASSENGER_LEFT   = 0x1000,
+    VEHICLE_SEAT_ROW_3_PASSENGER_CENTER = 0x2000,
+    VEHICLE_SEAT_ROW_3_PASSENGER_RIGHT  = 0x4000
+};
+
+/**
+ * Various windshields/windows in the car.
+ */
+enum vehicle_window {
+    VEHICLE_WINDOW_FRONT_WINDSHIELD = 0x0001,
+    VEHICLE_WINDOW_REAR_WINDSHIELD  = 0x0002,
+    VEHICLE_WINDOW_ROOF_TOP         = 0x0004,
+    VEHICLE_WINDOW_ROW_1_LEFT       = 0x0010,
+    VEHICLE_WINDOW_ROW_1_RIGHT      = 0x0020,
+    VEHICLE_WINDOW_ROW_2_LEFT       = 0x0100,
+    VEHICLE_WINDOW_ROW_2_RIGHT      = 0x0200,
+    VEHICLE_WINDOW_ROW_3_LEFT       = 0x1000,
+    VEHICLE_WINDOW_ROW_3_RIGHT      = 0x2000,
+};
+
+enum vehicle_door {
+    VEHICLE_DOOR_ROW_1_LEFT    = 0x00000001,
+    VEHICLE_DOOR_ROW_1_RIGHT   = 0x00000004,
+    VEHICLE_DOOR_ROW_2_LEFT    = 0x00000010,
+    VEHICLE_DOOR_ROW_2_RIGHT   = 0x00000040,
+    VEHICLE_DOOR_ROW_3_LEFT    = 0x00000100,
+    VEHICLE_DOOR_ROW_3_RIGHT   = 0x00000400,
+    VEHICLE_DOOR_HOOD          = 0x10000000,
+    VEHICLE_DOOR_REAR          = 0x20000000,
+};
+
+enum vehicle_mirror {
+    VEHICLE_MIRROR_DRIVER_LEFT   = 0x00000001,
+    VEHICLE_MIRROR_DRIVER_RIGHT  = 0x00000002,
+    VEHICLE_MIRROR_DRIVER_CENTER = 0x00000004,
+};
+enum vehicle_turn_signal {
+    VEHICLE_SIGNAL_NONE         = 0x00,
+    VEHICLE_SIGNAL_RIGHT        = 0x01,
+    VEHICLE_SIGNAL_LEFT         = 0x02,
+    VEHICLE_SIGNAL_EMERGENCY    = 0x04
+};
+
+/*
+ * Boolean type.
+ */
+enum vehicle_boolean {
+    VEHICLE_FALSE = 0x00,
+    VEHICLE_TRUE  = 0x01
+};
+
+typedef int32_t vehicle_boolean_t;
+
+/**
+ * Vehicle string.
+ *
+ * Defines a UTF8 encoded sequence of bytes that should be used for string
+ * representation throughout.
+ */
+typedef struct vehicle_str {
+    uint8_t* data;
+    int32_t len;
+} vehicle_str_t;
+
+/**
+ * Vehicle byte array.
+ * This is for passing generic raw data.
+ */
+typedef vehicle_str_t vehicle_bytes_t;
+
+typedef struct vehicle_prop_config {
+    int32_t prop;
+
+    /**
+     * Defines if the property is read or write. Value should be one of
+     * enum vehicle_prop_access.
+     */
+    int32_t access;
+
+    /**
+     * Defines if the property is continuous or on-change. Value should be one
+     * of enum vehicle_prop_change_mode.
+     */
+    int32_t change_mode;
+
+    /**
+     * Type of data used for this property. This type is fixed per each property.
+     * Check vehicle_value_type for allowed value.
+     */
+    int32_t value_type;
+
+    /**
+     * Define necessary permission model to access the data.
+     */
+    int32_t permission_model;
+
+    /**
+     * Some of the properties may have associated zones (such as hvac), in these
+     * cases the config should contain an ORed value for the associated zone.
+     */
+    union {
+        /**
+         * The value is derived by ORing one or more of enum vehicle_zone members.
+         */
+        int32_t vehicle_zone_flags;
+        /** The value is derived by ORing one or more of enum vehicle_seat members. */
+        int32_t vehicle_seat_flags;
+        /** The value is derived by ORing one or more of enum vehicle_window members. */
+        int32_t vehicle_window_flags;
+    };
+
+    /**
+     * Property specific configuration information. Usage of this will be defined per each property.
+     */
+    union {
+        /**
+         * For generic configuration information
+         */
+        int32_t config_flags;
+        /** The number of presets that are stored by the radio module. Pass 0 if
+         * there are no presets available. The range of presets is defined to be
+         * from 1 (see VEHICLE_RADIO_PRESET_MIN_VALUE) to vehicle_radio_num_presets.
+         */
+        int32_t vehicle_radio_num_presets;
+        int32_t config_array[4];
+    };
+
+    /**
+     * Some properties may require additional information passed over this string. Most properties
+     * do not need to set this and in that case, config_string.data should be NULL and
+     * config_string.len should be 0.
+     */
+    vehicle_str_t config_string;
+
+    /**
+     * Specify minimum allowed value for the property. This is necessary for property which does
+     * not have specified enum.
+     */
+    union {
+        float float_min_value;
+        int32_t int32_min_value;
+        int64_t int64_min_value;
+    };
+
+    /**
+     * Specify maximum allowed value for the property. This is necessary for property which does
+     * not have specified enum.
+     */
+    union {
+        float float_max_value;
+        int32_t int32_max_value;
+        int64_t int64_max_value;
+    };
+
+    /**
+     * Array of min values for zoned properties. Zoned property can specify min / max value in two
+     * different ways:
+     *   1. All zones having the same min / max value: *_min/max_value should be set and this
+     *      array should be set to NULL.
+     *   2. All zones having separate min / max value: *_min/max_values array should be populated
+     *      and its length should be the same as number of active zones specified by *_zone_flags.
+     *
+     * Should be NULL if each zone does not have separate max values.
+     */
+    union {
+        float* float_min_values;
+        int32_t* int32_min_values;
+        int64_t* int64_min_values;
+    };
+
+    /**
+     * Array of max values for zoned properties. See above for its usage.
+     * Should be NULL if each zone does not have separate max values.
+     * If not NULL, length of array should match that of min_values.
+     */
+    union {
+        float* float_max_values;
+        int32_t* int32_max_values;
+        int64_t* int64_max_values;
+    };
+
+    /**
+     * Min sample rate in Hz. Should be 0 for sensor type of VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+     */
+    float min_sample_rate;
+    /**
+     * Max sample rate in Hz. Should be 0 for sensor type of VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+     */
+    float max_sample_rate;
+    /**
+     * Place holder for putting HAL implementation specific data. Usage is wholly up to HAL
+     * implementation.
+     */
+    void* hal_data;
+} vehicle_prop_config_t;
+
+/**
+ * HVAC property fields.
+ *
+ * Defines various HVAC properties which are packed into vehicle_hvac_t (see
+ * below). We define these properties outside in global scope so that HAL
+ * implementation and HAL users (JNI) can typecast vehicle_hvac correctly.
+ */
+typedef struct vehicle_hvac {
+    /**
+     * Define one structure for each possible HVAC property.
+     * NOTES:
+     * a) Fan speed is a number from (0 - 6) where 6 is the highest speed. (TODO define enum)
+     * b) Temperature is a floating point Celcius scale.
+     * c) Direction is defined in enum vehicle_fan_direction.
+     *
+     * The HAL should create #entries number of vehicle_hvac_properties and
+     * assign it to "properties" variable below.
+     */
+    union {
+        int32_t fan_speed;
+        int32_t fan_direction;
+        vehicle_boolean_t ac_on;
+        vehicle_boolean_t max_ac_on;
+        vehicle_boolean_t max_defrost_on;
+        vehicle_boolean_t recirc_on;
+        vehicle_boolean_t dual_on;
+        vehicle_boolean_t power_on;
+
+        float temperature_current;
+        float temperature_set;
+
+        vehicle_boolean_t defrost_on;
+    };
+} vehicle_hvac_t;
+
+/*
+ * Defines how the values for various properties are represented.
+ *
+ * There are two ways to populate and access the fields:
+ * a) Using the individual fields. Use this mechanism (see
+ * info_manufacture_date, fuel_capacity fields etc).
+ * b) Using the union accessors (see uint32_value, float_value etc).
+ *
+ * To add a new field make sure that it does not exceed the total union size
+ * (defined in int_array) and it is one of the vehicle_value_type. Then add the
+ * field name with its unit to union. If the field type is not yet defined (as
+ * of this draft, we don't use int64_t) then add that type to vehicle_value_type
+ * and have an accessor (so for int64_t it will be int64_t int64_value).
+ */
+typedef union vehicle_value {
+    /** Define the max size of this structure. */
+    int32_t int32_array[4];
+    float float_array[4];
+
+    // Easy accessors for union members (HAL implementation SHOULD NOT USE these
+    // fields while populating, use the property specific fields below instead).
+    int32_t int32_value;
+    int64_t int64_value;
+    float float_value;
+    vehicle_str_t str_value;
+    vehicle_bytes_t bytes_value;
+    vehicle_boolean_t boolean_value;
+
+    // Vehicle Information.
+    vehicle_str_t info_vin;
+    vehicle_str_t info_make;
+    vehicle_str_t info_model;
+    int32_t info_model_year;
+
+    // Represented in milliliters.
+    float info_fuel_capacity;
+
+    float vehicle_speed;
+    float odometer;
+
+    // Engine sensors.
+
+    // Represented in milliliters.
+    //float engine_coolant_level;
+    // Represented in celcius.
+    float engine_coolant_temperature;
+    // Represented in a percentage value.
+    //float engine_oil_level;
+    // Represented in celcius.
+    float engine_oil_temperature;
+    float engine_rpm;
+
+    // Event sensors.
+    // Value should be one of enum vehicle_gear_selection.
+    int32_t gear_selection;
+    // Value should be one of enum vehicle_gear.
+    int32_t gear_current_gear;
+    // Value should be one of enum vehicle_boolean.
+    int32_t parking_brake;
+    // If cruise_set_speed > 0 then cruise is ON otherwise cruise is OFF.
+    // Unit: meters / second (m/s).
+    //int32_t cruise_set_speed;
+    // Value should be one of enum vehicle_boolean.
+    int32_t is_fuel_level_low;
+    // Value should be one of enum vehicle_driving_status.
+    int32_t driving_status;
+    int32_t night_mode;
+    // Value should be one of emum vehicle_turn_signal.
+    int32_t turn_signals;
+    // Value should be one of enum vehicle_boolean.
+    //int32_t engine_on;
+
+    // HVAC properties.
+    vehicle_hvac_t hvac;
+
+    float outside_temperature;
+    float cabin_temperature;
+
+} vehicle_value_t;
+
+/*
+ * Encapsulates the property name and the associated value. It
+ * is used across various API calls to set values, get values or to register for
+ * events.
+ */
+typedef struct vehicle_prop_value {
+    /* property identifier */
+    int32_t prop;
+
+    /* value type of property for quick conversion from union to appropriate
+     * value. The value must be one of enum vehicle_value_type.
+     */
+    int32_t value_type;
+
+    /** time is elapsed nanoseconds since boot */
+    int64_t timestamp;
+
+    /**
+     * Zone information for zoned property. For non-zoned property, this should be ignored.
+     */
+    union {
+        int32_t zone;
+        int32_t seat;
+        int32_t window;
+    };
+
+    vehicle_value_t value;
+} vehicle_prop_value_t;
+
+/*
+ * Event callback happens whenever a variable that the API user has subscribed
+ * to needs to be reported. This may be based purely on threshold and frequency
+ * (a regular subscription, see subscribe call's arguments) or when the set()
+ * command is executed and the actual change needs to be reported.
+ *
+ * event_data is OWNED by the HAL and should be copied before the callback
+ * finishes.
+ */
+typedef int (*vehicle_event_callback_fn)(const vehicle_prop_value_t *event_data);
+
+
+/**
+ * Represent the operation where the current error has happened.
+ */
+enum vehicle_property_operation {
+    /** Generic error to this property which is not tied to any operation. */
+    VEHICLE_OPERATION_GENERIC = 0,
+    /** Error happened while handling property set. */
+    VEHICLE_OPERATION_SET = 1,
+    /** Error happened while handling property get. */
+    VEHICLE_OPERATION_GET = 2,
+    /** Error happened while handling property subscription. */
+    VEHICLE_OPERATION_SUBSCRIBE = 3,
+};
+
+/*
+ * Suggests that an error condition has occurred.
+ *
+ * @param error_code Error code. error_code should be standard error code with
+ *                negative value like -EINVAL.
+ * @parm property Note a property where error has happened. If this is generic error, property
+ *                should be VEHICLE_PROPERTY_INVALID.
+ * @param operation Represent the operation where the error has happened. Should be one of
+ *                  vehicle_property_operation.
+ */
+typedef int (*vehicle_error_callback_fn)(int32_t error_code, int32_t property, int32_t operation);
+
+/************************************************************************************/
+
+/*
+ * 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 vehicle_module {
+    struct hw_module_t common;
+} vehicle_module_t;
+
+
+typedef struct vehicle_hw_device {
+    struct hw_device_t common;
+
+    /**
+     * After calling open on device the user should register callbacks for event and error
+     * functions.
+     */
+    int (*init)(struct vehicle_hw_device* device,
+                vehicle_event_callback_fn event_fn, vehicle_error_callback_fn err_fn);
+    /**
+     * Before calling close the user should destroy the registered callback
+     * functions.
+     * In case the unsubscribe() call is not called on all properties before
+     * release() then release() will unsubscribe the properties itself.
+     */
+    int (*release)(struct vehicle_hw_device* device);
+
+    /**
+     * Enumerate all available properties. The list is returned in "list".
+     * @param num_properties number of properties contained in the retuned array.
+     * @return array of property configs supported by this car. Note that returned data is const
+     *         and caller cannot modify it. HAL implementation should keep this memory until HAL
+     *         is released to avoid copying this again.
+     */
+    vehicle_prop_config_t const *(*list_properties)(struct vehicle_hw_device* device,
+            int* num_properties);
+
+    /**
+     * Get a vehicle property value immediately. data should be allocated
+     * properly.
+     * The caller of the API OWNS the data field.
+     * Caller will set data->prop, data->value_type, and optionally zone value for zoned property.
+     * But HAL implementation needs to fill all entries properly when returning.
+     * For pointer type, HAL implementation should allocate necessary memory and caller is
+     * responsible for calling release_memory_from_get, which allows HAL to release allocated
+     * memory.
+     * For VEHICLE_PROP_CHANGE_MODE_STATIC type of property, get should return the same value
+     * always.
+     * For VEHICLE_PROP_CHANGE_MODE_ON_CHANGE type of property, it should return the latest value.
+     * If there is no data available yet, which can happen during initial stage, this call should
+     * return immediately with error code of -EAGAIN.
+     */
+    int (*get)(struct vehicle_hw_device* device, vehicle_prop_value_t *data);
+
+    /**
+     * Release memory allocated to data in previous get call. get call for byte or string involves
+     * allocating necessary memory from vehicle hal.
+     * To be safe, memory allocated by vehicle hal should be released by vehicle hal and vehicle
+     * network service will call this when data from vehicle hal is no longer necessary.
+     * vehicle hal implementation should only release member of vehicle_prop_value_t like
+     * data->str_value.data or data->bytes_value.data but not data itself as data itself is
+     * allocated from vehicle network service. Once memory is freed, corresponding pointer should
+     * be set to NULL bu vehicle hal.
+     */
+    void (*release_memory_from_get)(struct vehicle_hw_device* device, vehicle_prop_value_t *data);
+
+    /**
+     * Set a vehicle property value.  data should be allocated properly and not
+     * NULL.
+     * The caller of the API OWNS the data field.
+     * timestamp of data will be ignored for set operation.
+     * Setting some properties require having initial state available. Depending on the vehicle hal,
+     * such initial data may not be available for short time after init. In such case, set call
+     * can return -EAGAIN like get call.
+     * For a property with separate power control, set can fail if the property is not powered on.
+     * In such case, hal should return -ESHUTDOWN error.
+     */
+    int (*set)(struct vehicle_hw_device* device, const vehicle_prop_value_t *data);
+
+    /**
+     * Subscribe to events.
+     * Depending on output of list_properties if the property is:
+     * a) on-change: sample_rate should be set to 0.
+     * b) supports frequency: sample_rate should be set from min_sample_rate to
+     * max_sample_rate.
+     * For on-change type of properties, vehicle network service will make another get call to check
+     * the initial state. Due to this, vehicle hal implementation does not need to send initial
+     * state for on-change type of properties.
+     * @param device
+     * @param prop
+     * @param sample_rate
+     * @param zones All subscribed zones for zoned property. can be ignored for non-zoned property.
+     *              0 means all zones supported instead of no zone.
+     */
+    int (*subscribe)(struct vehicle_hw_device* device, int32_t prop, float sample_rate,
+            int32_t zones);
+
+    /** Cancel subscription on a property. */
+    int (*unsubscribe)(struct vehicle_hw_device* device, int32_t prop);
+
+    /**
+     * Print out debugging state for the vehicle hal. This will be called by
+     * the vehicle network service and will be included into the service' dump.
+     *
+     * 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 of operation.
+     * Any synchronization primitives used (such as mutex locks or semaphores)
+     * should be acquired with a timeout.
+     */
+    int (*dump)(struct vehicle_hw_device* device, int fd);
+
+} vehicle_hw_device_t;
+
+__END_DECLS
+
+#endif  // ANDROID_VEHICLE_INTERFACE_H
diff --git a/include/hardware/vehicle_camera.h b/include/hardware/vehicle_camera.h
new file mode 100644 (file)
index 0000000..8075aee
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * 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_VEHICLE_CAMERA_INTERFACE_H
+#define ANDROID_VEHICLE_CAMERA_INTERFACE_H
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <hardware/hardware.h>
+#include <cutils/native_handle.h>
+#include <system/window.h>
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+#define VEHICLE_CAMERA_HEADER_VERSION          1
+#define VEHICLE_CAMERA_MODULE_API_VERSION_1_0  HARDWARE_MODULE_API_VERSION(1, 0)
+#define VEHICLE_CAMERA_DEVICE_API_VERSION_1_0  HARDWARE_DEVICE_API_VERSION_2(1, 0, VEHICLE_CAMERA_HEADER_VERSION)
+
+/**
+ * Vehicle Camera to provide interfaces for controlling cameras
+ */
+
+/**
+ * The id of this module
+ */
+#define VEHICLE_CAMERA_HARDWARE_MODULE_ID  "vehicle_camera"
+
+/**
+ *  Name of the vehicle device to open.  Extend this list as
+ *  more cameras are added.  Each camera defined in vehicle_camera_type_t
+ *  shall have a string defined for it.
+ */
+#define VEHICLE_CAMERA_RVC_DEVICE       "vehicle_camera_rvc_device"
+
+/**
+ * Each camera on the car shall be enumerated
+ */
+typedef enum {
+    VEHICLE_CAMERA_RVC = 1,
+} vehicle_camera_type_t;
+
+/**
+ * Describes the current state of camera device
+ */
+typedef struct {
+    uint32_t overlay_on;
+    uint32_t camera_on;
+} vehicle_camera_state_t;
+
+/**
+ * Bitmask of features supported by a camera module
+ */
+enum {
+    VEHICLE_CAMERA_CONFIG_FLAG_ANDROID_OVERLAY_SUPPORT      = 0x1,
+    VEHICLE_CAMERA_CONFIG_FLAG_CAMERA_CROP_SUPPORT          = 0x2,
+    VEHICLE_CAMERA_CONFIG_FLAG_CAMERA_POSITIONING_SUPPORT   = 0x4
+} vehicle_camera_config_flag;
+
+typedef struct {
+    uint32_t capabilites_flags;
+    uint32_t camera_width;
+    uint32_t camera_height;
+    uint32_t display_width;
+    uint32_t display_height;
+} vehicle_camera_cap_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 {
+    struct hw_module_t common;
+    /**
+     * Queries the HW for the cameras installed on the vehicle
+     * @param num_cameras - number of camera devices available.  If
+     *                    0 is returned, an error has occurred and
+     *                    the return pointer shall be NULL.
+     * @return pointer to an array of vehicle_camera_type_t to
+     *         denote which cameras are installed.  This pointer is
+     *         only valid while the vehicle hal is loaded.  If the
+     *         pointer is NULL, then an error has occurred and
+     *         num_cameras shall be 0.
+     */
+    const uint32_t * (*get_camera_device_list)(uint32_t *num_cameras);
+} vehicle_camera_module_t;
+
+
+typedef struct vehicle_camera_device_t {
+    struct hw_device_t common;
+
+    const uint32_t camera_type;
+
+    /**
+     * Returns the capabilities of this camera.
+     * @param device - device handle
+     * @param cap - pointer to capabilities flags being returned
+     * @return 0 on success
+     *          -EPERM if device is invalid or not initialized
+     */
+    int (*get_capabilities)(struct vehicle_camera_device_t *device, vehicle_camera_cap_t *cap);
+
+    /**
+     * Gets the current camera crop settings.
+     * @param device - device handle
+     * @param rect - current camera crop settings
+     * @return 0 on success
+     *          -EPERM if device is not initialized
+     *          -errno on error
+     */
+    int (*get_camera_crop)(struct vehicle_camera_device_t *device, android_native_rect_t *rect);
+
+    /**
+     * Sets the camera crop.
+     * @param device - device handle
+     * @param rect - area of camera input to crop.  Must fit within
+     *             camera width and height from camera capabilities.
+     * @return 0 on success
+     *          -EPERM if device is not initialized
+     *          -errno on error
+     */
+    int (*set_camera_crop)(struct vehicle_camera_device_t *device, const android_native_rect_t *rect);
+
+    /**
+     * Gets position of the camera on the display.
+     * @param device - device handle
+     * @param rect - area of display the camera will appear when on
+     * @return 0 on success
+     *          -EPERM if device is not initialized
+     *          -errno on error
+     */
+    int (*get_camera_position)(struct vehicle_camera_device_t *device, android_native_rect_t *rect);
+
+    /**
+     * Sets position of the camera on the display.
+     * @param device - device handle
+     * @param rect - area of display the camera will appear when on.
+     *             Must fit within display width and height from
+     *             camera capabilities.
+     * @return 0 on success
+     *          -EPERM if device is not initialized
+     *          -errno on error
+     */
+    int (*set_camera_position)(struct vehicle_camera_device_t *device, const android_native_rect_t *rect);
+
+    /**
+     * Gets the current camera state.
+     * @param device - device handle
+     * @param state - last setting for the camera
+     * @return 0 on success
+     *          -EPERM if device is not initialized
+     */
+    int (*get_camera_state)(struct vehicle_camera_device_t *device, vehicle_camera_state_t *state);
+
+    /**
+     * Sets the camera state.
+     * @param device - device handle
+     * @param state - desired setting for the camera
+     * @return 0 on success
+     *          -EPERM if device is not initialized
+     *          -errno on error
+     */
+    int (*set_camera_state)(struct vehicle_camera_device_t *device, const vehicle_camera_state_t *state);
+} vehicle_camera_device_t;
+
+__END_DECLS
+
+#endif  // ANDROID_VEHICLE_CAMERA_INTERFACE_H
index 92b1fd0..200adf0 100644 (file)
@@ -45,8 +45,8 @@ typedef struct vibrator_device {
 
     /** Turn on vibrator
      *
-     * What happens when this function is called while the the timeout of a
-     * previous call has not expired is implementation dependent.
+     * 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
      *
@@ -56,8 +56,7 @@ typedef struct vibrator_device {
 
     /** Turn off vibrator
      *
-     * It is not guaranteed that the vibrator will be immediately stopped: the
-     * behaviour is implementation dependent.
+     * Cancel a previously-started vibration, if any.
      *
      * @return 0 in case of success, negative errno code else
      */
diff --git a/include/hardware/vr.h b/include/hardware/vr.h
new file mode 100644 (file)
index 0000000..69f8654
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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_HARDWARE_VR_H
+#define ANDROID_INCLUDE_HARDWARE_VR_H
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+#define VR_HARDWARE_MODULE_ID "vr"
+
+#define VR_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0)
+
+/**
+ * Implement this HAL to receive callbacks when a virtual reality (VR)
+ * application is being used.  VR applications characteristically have a number
+ * of special display and performance requirements, including:
+ * - Low sensor latency - Total end-to-end latency from the IMU, accelerometer,
+ *   and gyro to an application-visible callback must be extremely low (<5ms
+ *   typically).  This is required for HIFI sensor support.
+ * - Low display latency - Total end-to-end latency from the GPU draw calls to
+ *   the actual display update must be as low as possible.  This is achieved by
+ *   using SurfaceFlinger in a single-buffered mode, and assuring that draw calls
+ *   are synchronized with the display scanout correctly.  This behavior is
+ *   exposed via an EGL extension to applications.  See below for the EGL
+ *   extensions needed for this.
+ * - Low-persistence display - Display persistence settings must be set as low as
+ *   possible while still maintaining a reasonable brightness.  For a typical
+ *   display running at 60Hz, pixels should be illuminated for <=3.5ms to be
+ *   considered low-persistence.  This avoids ghosting during movements in a VR
+ *   setting, and should be enabled from the lights.h HAL when
+ *   BRIGHTNESS_MODE_LOW_PERSISTENCE is set.
+ * - Consistent performance of the GPU and CPU - When given a mixed GPU/CPU
+ *   workload for a VR application with bursts of work at regular intervals
+ *   several times a frame, the CPU scheduling should ensure that the application
+ *   render thread work is run consistently within 1ms of when scheduled, and
+ *   completed before the end of the draw window.  To this end, a single CPU core
+ *   must be reserved for solely for the currently running VR application's render
+ *   thread while in VR mode, and made available in the "top-app" cpuset.
+ *   Likewise, an appropriate CPU, GPU, and bus clockrate must be maintained to
+ *   ensure that the rendering workload finishes within the time allotted to
+ *   render each frame when the POWER_HINT_SUSTAINED_PERFORMANCE flag has been
+ *   set in the power.h HAL while in VR mode when the device is not being
+ *   thermally throttled.
+ * - Required EGL extensions must be present - Any GPU settings required to allow
+ *   the above capabilities are required, including the EGL extensions:
+ *   EGL_ANDROID_create_native_client_buffer, EGL_ANDROID_front_buffer_auto_refresh,
+ *   EGL_EXT_protected_content, EGL_KHR_mutable_render_buffer,
+ *   EGL_KHR_reusable_sync, and EGL_KHR_wait_sync.
+ * - Accurate thermal reporting - Accurate thermal temperatures and limits must be
+ *   reported in the thermal.h HAL.  Specifically, the current skin temperature
+ *   must accurately be reported for DEVICE_TEMPERATURE_SKIN and the
+ *   vr_throttling_threshold reported for this device must accurately report the
+ *   temperature limit above which the device's thermal governor throttles the
+ *   CPU, GPU, and/or bus clockrates below the minimum necessary for consistent
+ *   performance (see previous bullet point).
+ *
+ * In general, vendors implementing this HAL are expected to use set_vr_mode as a
+ * hint to enable VR-specific performance tuning needed for any of the above
+ * requirements, and to turn on any device features optimal for VR display
+ * modes.  The set_vr_mode call may simply do nothing if no optimizations are
+ * available or necessary to meet the above requirements.
+ *
+ * No methods in this HAL will be called concurrently from the Android framework.
+ */
+typedef struct vr_module {
+    /**
+     * Common methods of the  module.  This *must* be the first member of
+     * vr_module as users of this structure may cast a hw_module_t to a
+     * vr_module pointer in contexts where it's known that the hw_module_t
+     * references a vr_module.
+     */
+    struct hw_module_t common;
+
+    /**
+     * Convenience method for the HAL implementation to set up any state needed
+     * at runtime startup.  This is called once from the VrManagerService during
+     * its boot phase.  No methods from this HAL will be called before init.
+     */
+    void (*init)(struct vr_module *module);
+
+    /**
+     * Set the VR mode state.  Possible states of the enabled parameter are:
+     * false - VR mode is disabled, turn off all VR-specific settings.
+     * true - VR mode is enabled, turn on all VR-specific settings.
+     *
+     * This is called whenever the the Android system enters or leaves VR mode.
+     * This will typically occur when the user switches to or from a VR application
+     * that is doing stereoscopic rendering.
+     */
+    void (*set_vr_mode)(struct vr_module *module, bool enabled);
+
+    /* Reserved for future use. Must be NULL. */
+    void* reserved[8 - 2];
+} vr_module_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_VR_H */
index 9f7e5f0..3bd0943 100644 (file)
@@ -1,4 +1,4 @@
 hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
        power usbaudio audio_remote_submix camera usbcamera consumerir sensors vibrator \
-       tv_input fingerprint input
+       tv_input fingerprint input vehicle thermal vr
 include $(call all-named-subdir-makefiles,$(hardware_modules))
index ed3d311..d47cfba 100644 (file)
@@ -89,7 +89,7 @@ namespace android {
 #define ENABLE_RESAMPLING            1
 #if LOG_STREAMS_TO_FILES
 // Folder to save stream log files to.
-#define LOG_STREAM_FOLDER "/data/misc/media"
+#define LOG_STREAM_FOLDER "/data/misc/audioserver"
 // 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"
@@ -823,7 +823,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
                 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);
+                source->read(flush_buffer, flush_size);
             }
         }
     }
@@ -1192,7 +1192,7 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
 
             SUBMIX_ALOGV("in_read(): frames available to read %zd", source->availableToRead());
 
-            frames_read = source->read(buff, read_frames, AudioBufferProvider::kInvalidPTS);
+            frames_read = source->read(buff, read_frames);
 
             SUBMIX_ALOGV("in_read(): frames read %zd", frames_read);
 
@@ -1573,7 +1573,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
 
     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);
+        ALOGE("Error %d looking for address=%s in adev_open_input_stream", res, address);
         pthread_mutex_unlock(&rsxadev->lock);
         return res;
     }
index f195534..18e5239 100644 (file)
@@ -52,7 +52,7 @@ int Metadata::init(const camera_metadata_t *metadata)
 {
     camera_metadata_t* tmp;
 
-    if (!validate_camera_metadata_structure(metadata, NULL))
+    if (validate_camera_metadata_structure(metadata, NULL))
         return -EINVAL;
 
     tmp = clone_camera_metadata(metadata);
@@ -130,16 +130,23 @@ bool Metadata::validate(uint32_t tag, int tag_type, int count)
 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);
-    size_t entry_capacity = get_camera_metadata_entry_count(mData) + 1;
-    size_t data_capacity = get_camera_metadata_data_count(mData) + size;
 
-    // Opportunistically attempt to add if metadata has room for it
-    if (!add_camera_metadata_entry(mData, tag, tag_data, count))
-        return 0;
+    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) {
@@ -147,22 +154,24 @@ int Metadata::add(uint32_t tag, int count, const void *tag_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;
+    // 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
+    // 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;
 }
 
index 486e27a..eadcdaa 100644 (file)
@@ -33,7 +33,7 @@
 #include <cutils/log.h>
 #include <cutils/atomic.h>
 
-#if HAVE_ANDROID_OS
+#ifdef __ANDROID__
 #include <linux/fb.h>
 #endif
 
index a9fbc80..e9559e9 100644 (file)
@@ -196,36 +196,41 @@ static int gralloc_alloc_buffer(alloc_device_t* dev,
 
 /*****************************************************************************/
 
+inline size_t align(size_t value, size_t alignment)
+{
+    return ((value + alignment - 1) / alignment) * alignment;
+}
+
 static int gralloc_alloc(alloc_device_t* dev,
-        int w, int h, int format, int usage,
+        int width, int height, 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;
+    int bytesPerPixel = 0;
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_BGRA_8888:
-            bpp = 4;
+            bytesPerPixel = 4;
             break;
         case HAL_PIXEL_FORMAT_RGB_888:
-            bpp = 3;
+            bytesPerPixel = 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
         case HAL_PIXEL_FORMAT_RAW16:
-            bpp = 2;
+            bytesPerPixel = 2;
             break;
         default:
             return -EINVAL;
     }
-    size_t bpr = (w*bpp + (align-1)) & ~(align-1);
-    size = bpr * h;
-    stride = bpr / bpp;
+
+    const size_t tileWidth = 2;
+    const size_t tileHeight = 2;
+
+    size_t stride = align(width, tileWidth);
+    size_t size = align(height, tileHeight) * stride * bytesPerPixel + 4;
 
     int err;
     if (usage & GRALLOC_USAGE_HW_FB) {
index d3c49e7..9a5d092 100644 (file)
@@ -18,10 +18,14 @@ LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
+    BitUtils.cpp \
     InputHub.cpp \
     InputDevice.cpp \
     InputDeviceManager.cpp \
-    InputHost.cpp
+    InputHost.cpp \
+    InputMapper.cpp \
+    MouseInputMapper.cpp \
+    SwitchInputMapper.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libhardware_legacy \
diff --git a/modules/input/evdev/BitUtils.cpp b/modules/input/evdev/BitUtils.cpp
new file mode 100644 (file)
index 0000000..3434c31
--- /dev/null
@@ -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.
+ */
+
+#define LOG_TAG "BitUtils"
+//#define LOG_NDEBUG 0
+
+#include "BitUtils.h"
+
+#include <utils/Log.h>
+
+// Enables debug output for hasKeyInRange
+#define DEBUG_KEY_RANGE 0
+
+namespace android {
+
+#if DEBUG_KEY_RANGE
+static const char* bitstrings[16] = {
+    "0000", "0001", "0010", "0011",
+    "0100", "0101", "0110", "0111",
+    "1000", "1001", "1010", "1011",
+    "1100", "1101", "1110", "1111",
+};
+#endif
+
+bool testBitInRange(const uint8_t arr[], size_t start, size_t end) {
+#if DEBUG_KEY_RANGE
+    ALOGD("testBitInRange(%d, %d)", start, end);
+#endif
+    // Invalid range! This is nonsense; just say no.
+    if (end <= start) return false;
+
+    // Find byte array indices. The end is not included in the range, nor is
+    // endIndex. Round up for endIndex.
+    size_t startIndex = start / 8;
+    size_t endIndex = (end + 7) / 8;
+#if DEBUG_KEY_RANGE
+    ALOGD("startIndex=%d, endIndex=%d", startIndex, endIndex);
+#endif
+    for (size_t i = startIndex; i < endIndex; ++i) {
+        uint8_t bits = arr[i];
+        uint8_t mask = 0xff;
+#if DEBUG_KEY_RANGE
+        ALOGD("block %04d: %s%s", i, bitstrings[bits >> 4], bitstrings[bits & 0x0f]);
+#endif
+        if (bits) {
+            // Mask off bits before our start bit
+            if (i == startIndex) {
+                mask &= 0xff << (start % 8);
+            }
+            // Mask off bits after our end bit
+            if (i == endIndex - 1 && (end % 8)) {
+                mask &= 0xff >> (8 - (end % 8));
+            }
+#if DEBUG_KEY_RANGE
+            ALOGD("mask: %s%s", bitstrings[mask >> 4], bitstrings[mask & 0x0f]);
+#endif
+            // Test the index against the mask
+            if (bits & mask) return true;
+        }
+    }
+    return false;
+}
+}  // namespace android
diff --git a/modules/input/evdev/BitUtils.h b/modules/input/evdev/BitUtils.h
new file mode 100644 (file)
index 0000000..1aa1f6a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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_BIT_UTILS_H_
+#define ANDROID_BIT_UTILS_H_
+
+#include <cstdint>
+
+namespace android {
+
+/** Test whether any bits in the interval [start, end) are set in the array. */
+bool testBitInRange(const uint8_t arr[], size_t start, size_t end);
+
+}  // namespace android
+
+#endif  // ANDROID_BIT_UTILS_H_
index e9c8222..b37eba1 100644 (file)
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#define LOG_NDEBUG 0
 #define LOG_TAG "EvdevModule"
+//#define LOG_NDEBUG 0
 
 #include <memory>
 #include <string>
@@ -37,7 +37,8 @@ static const char kDevInput[] = "/dev/input";
 
 class EvdevModule {
 public:
-    explicit EvdevModule(InputHost inputHost);
+    // Takes ownership of the InputHostInterface
+    explicit EvdevModule(InputHostInterface* inputHost);
 
     void init();
     void notifyReport(input_report_t* r);
@@ -45,18 +46,18 @@ public:
 private:
     void loop();
 
-    InputHost mInputHost;
+    std::unique_ptr<InputHostInterface> mInputHost;
     std::shared_ptr<InputDeviceManager> mDeviceManager;
-    std::shared_ptr<InputHub> mInputHub;
+    std::unique_ptr<InputHub> mInputHub;
     std::thread mPollThread;
 };
 
-static std::shared_ptr<EvdevModule> gEvdevModule;
+static std::unique_ptr<EvdevModule> gEvdevModule;
 
-EvdevModule::EvdevModule(InputHost inputHost) :
+EvdevModule::EvdevModule(InputHostInterface* inputHost) :
     mInputHost(inputHost),
-    mDeviceManager(std::make_shared<InputDeviceManager>()),
-    mInputHub(std::make_shared<InputHub>(mDeviceManager)) {}
+    mDeviceManager(std::make_shared<InputDeviceManager>(mInputHost.get())),
+    mInputHub(std::make_unique<InputHub>(mDeviceManager)) {}
 
 void EvdevModule::init() {
     ALOGV("%s", __func__);
@@ -97,8 +98,8 @@ static int dummy_open(const hw_module_t __unused *module, const char __unused *i
 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);
+    auto inputHost = new InputHost(host, cb);
+    gEvdevModule = std::make_unique<EvdevModule>(inputHost);
     gEvdevModule->init();
 }
 
index c0b59d7..5f90982 100644 (file)
  */
 
 #define LOG_TAG "InputDevice"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
+
+// Enables debug output for processing input events
+#define DEBUG_INPUT_EVENTS 0
+
+#include "InputDevice.h"
 
 #include <linux/input.h>
 
 #define __STDC_FORMAT_MACROS
 #include <cinttypes>
+#include <cstdlib>
 #include <string>
 
 #include <utils/Log.h>
 #include <utils/Timers.h>
 
+#include "InputHost.h"
 #include "InputHub.h"
-#include "InputDevice.h"
+#include "MouseInputMapper.h"
+#include "SwitchInputMapper.h"
 
 #define MSC_ANDROID_TIME_SEC  0x6
 #define MSC_ANDROID_TIME_USEC 0x7
 
 namespace android {
 
-EvdevDevice::EvdevDevice(std::shared_ptr<InputDeviceNode> node) :
-    mDeviceNode(node) {}
+static InputBus getInputBus(const std::shared_ptr<InputDeviceNode>& node) {
+    switch (node->getBusType()) {
+        case BUS_USB:
+            return INPUT_BUS_USB;
+        case BUS_BLUETOOTH:
+            return INPUT_BUS_BT;
+        case BUS_RS232:
+            return INPUT_BUS_SERIAL;
+        default:
+            // TODO: check for other linux bus types that might not be built-in
+            return INPUT_BUS_BUILTIN;
+    }
+}
+
+static uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
+    // Touch devices get dibs on touch-related axes.
+    if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
+        switch (axis) {
+            case ABS_X:
+            case ABS_Y:
+            case ABS_PRESSURE:
+            case ABS_TOOL_WIDTH:
+            case ABS_DISTANCE:
+            case ABS_TILT_X:
+            case ABS_TILT_Y:
+            case ABS_MT_SLOT:
+            case ABS_MT_TOUCH_MAJOR:
+            case ABS_MT_TOUCH_MINOR:
+            case ABS_MT_WIDTH_MAJOR:
+            case ABS_MT_WIDTH_MINOR:
+            case ABS_MT_ORIENTATION:
+            case ABS_MT_POSITION_X:
+            case ABS_MT_POSITION_Y:
+            case ABS_MT_TOOL_TYPE:
+            case ABS_MT_BLOB_ID:
+            case ABS_MT_TRACKING_ID:
+            case ABS_MT_PRESSURE:
+            case ABS_MT_DISTANCE:
+                return INPUT_DEVICE_CLASS_TOUCH;
+        }
+    }
+
+    // External stylus gets the pressure axis
+    if (deviceClasses & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+        if (axis == ABS_PRESSURE) {
+            return INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+        }
+    }
+
+    // Joystick devices get the rest.
+    return INPUT_DEVICE_CLASS_JOYSTICK;
+}
+
+static bool getBooleanProperty(const InputProperty& prop) {
+    const char* propValue = prop.getValue();
+    if (propValue == nullptr) return false;
+
+    char* end;
+    int value = std::strtol(propValue, &end, 10);
+    if (*end != '\0') {
+        ALOGW("Expected boolean for property %s; value=%s", prop.getKey(), propValue);
+        return false;
+    }
+    return value;
+}
+
+EvdevDevice::EvdevDevice(InputHostInterface* host, const std::shared_ptr<InputDeviceNode>& node) :
+    mHost(host), mDeviceNode(node), mDeviceDefinition(mHost->createDeviceDefinition()) {
+
+    InputBus bus = getInputBus(node);
+    mInputId = mHost->createDeviceIdentifier(
+            node->getName().c_str(),
+            node->getProductId(),
+            node->getVendorId(),
+            bus,
+            node->getUniqueId().c_str());
+
+    createMappers();
+    configureDevice();
+
+    // If we found a need for at least one mapper, register the device with the
+    // host. If there were no mappers, this device is effectively ignored, as
+    // the host won't know about it.
+    if (mMappers.size() > 0) {
+        mDeviceHandle = mHost->registerDevice(mInputId, mDeviceDefinition);
+        for (const auto& mapper : mMappers) {
+            mapper->setDeviceHandle(mDeviceHandle);
+        }
+    }
+}
+
+void EvdevDevice::createMappers() {
+    // See if this is a cursor device such as a trackball or mouse.
+    if (mDeviceNode->hasKey(BTN_MOUSE)
+            && mDeviceNode->hasRelativeAxis(REL_X)
+            && mDeviceNode->hasRelativeAxis(REL_Y)) {
+        mClasses |= INPUT_DEVICE_CLASS_CURSOR;
+        mMappers.push_back(std::make_unique<MouseInputMapper>());
+    }
+
+    bool isStylus = false;
+    bool haveGamepadButtons = mDeviceNode->hasKeyInRange(BTN_MISC, BTN_MOUSE) ||
+            mDeviceNode->hasKeyInRange(BTN_JOYSTICK, BTN_DIGI);
+
+    // See if this is a touch pad or stylus.
+    // Is this a new modern multi-touch driver?
+    if (mDeviceNode->hasAbsoluteAxis(ABS_MT_POSITION_X)
+            && mDeviceNode->hasAbsoluteAxis(ABS_MT_POSITION_Y)) {
+        // Some joysticks such as the PS3 controller report axes that conflict
+        // with the ABS_MT range. Try to confirm that the device really is a
+        // touch screen.
+        if (mDeviceNode->hasKey(BTN_TOUCH) || !haveGamepadButtons) {
+            mClasses |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
+            //mMappers.push_back(std::make_unique<MultiTouchInputMapper>());
+        }
+    // Is this an old style single-touch driver?
+    } else if (mDeviceNode->hasKey(BTN_TOUCH)
+            && mDeviceNode->hasAbsoluteAxis(ABS_X)
+            && mDeviceNode->hasAbsoluteAxis(ABS_Y)) {
+        mClasses |= INPUT_DEVICE_CLASS_TOUCH;
+        //mMappers.push_back(std::make_unique<SingleTouchInputMapper>());
+    // Is this a BT stylus?
+    } else if ((mDeviceNode->hasAbsoluteAxis(ABS_PRESSURE) || mDeviceNode->hasKey(BTN_TOUCH))
+            && !mDeviceNode->hasAbsoluteAxis(ABS_X) && !mDeviceNode->hasAbsoluteAxis(ABS_Y)) {
+        mClasses |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+        //mMappers.push_back(std::make_unique<ExternalStylusInputMapper>());
+        isStylus = true;
+        mClasses &= ~INPUT_DEVICE_CLASS_KEYBOARD;
+    }
+
+    // See if this is a keyboard. Ignore everything in the button range except
+    // for joystick and gamepad buttons which are handled like keyboards for the
+    // most part.
+    // Keyboard will try to claim some of the stylus buttons but we really want
+    // to reserve those so we can fuse it with the touch screen data. Note this
+    // means an external stylus cannot also be a keyboard device.
+    if (!isStylus) {
+        bool haveKeyboardKeys = mDeviceNode->hasKeyInRange(0, BTN_MISC) ||
+            mDeviceNode->hasKeyInRange(KEY_OK, KEY_CNT);
+        if (haveKeyboardKeys || haveGamepadButtons) {
+            mClasses |= INPUT_DEVICE_CLASS_KEYBOARD;
+            //mMappers.push_back(std::make_unique<KeyboardInputMapper>());
+        }
+    }
+
+    // See if this device is a joystick.
+    // Assumes that joysticks always have gamepad buttons in order to
+    // distinguish them from other devices such as accelerometers that also have
+    // absolute axes.
+    if (haveGamepadButtons) {
+        uint32_t assumedClasses = mClasses | INPUT_DEVICE_CLASS_JOYSTICK;
+        for (int i = 0; i < ABS_CNT; ++i) {
+            if (mDeviceNode->hasAbsoluteAxis(i)
+                    && getAbsAxisUsage(i, assumedClasses) == INPUT_DEVICE_CLASS_JOYSTICK) {
+                mClasses = assumedClasses;
+                //mMappers.push_back(std::make_unique<JoystickInputMapper>());
+                break;
+            }
+        }
+    }
+
+    // Check whether this device has switches.
+    for (int i = 0; i < SW_CNT; ++i) {
+        if (mDeviceNode->hasSwitch(i)) {
+            mClasses |= INPUT_DEVICE_CLASS_SWITCH;
+            mMappers.push_back(std::make_unique<SwitchInputMapper>());
+            break;
+        }
+    }
+
+    // Check whether this device supports the vibrator.
+    // TODO: decide if this is necessary.
+    if (mDeviceNode->hasForceFeedback(FF_RUMBLE)) {
+        mClasses |= INPUT_DEVICE_CLASS_VIBRATOR;
+        //mMappers.push_back(std::make_unique<VibratorInputMapper>());
+    }
+
+    ALOGD("device %s classes=0x%x %zu mappers", mDeviceNode->getPath().c_str(), mClasses,
+            mMappers.size());
+}
+
+void EvdevDevice::configureDevice() {
+    for (const auto& mapper : mMappers) {
+        auto reportDef = mHost->createInputReportDefinition();
+        if (mapper->configureInputReport(mDeviceNode.get(), reportDef)) {
+            mDeviceDefinition->addReport(reportDef);
+        } else {
+            mHost->freeReportDefinition(reportDef);
+        }
+
+        reportDef = mHost->createOutputReportDefinition();
+        if (mapper->configureOutputReport(mDeviceNode.get(), reportDef)) {
+            mDeviceDefinition->addReport(reportDef);
+        } else {
+            mHost->freeReportDefinition(reportDef);
+        }
+    }
+}
 
 void EvdevDevice::processInput(InputEvent& event, nsecs_t currentTime) {
+#if DEBUG_INPUT_EVENTS
     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,
+    ALOGD(log.c_str(), mDeviceNode->getPath().c_str(), event.when, event.type, event.code,
             event.value);
+#endif
 
     if (event.type == EV_MSC) {
         if (event.code == MSC_ANDROID_TIME_SEC) {
@@ -97,6 +303,10 @@ void EvdevDevice::processInput(InputEvent& event, nsecs_t currentTime) {
                     ", call time %" PRId64 ".", event.when, time, currentTime);
         }
     }
+
+    for (size_t i = 0; i < mMappers.size(); ++i) {
+        mMappers[i]->process(event);
+    }
 }
 
 }  // namespace android
index 3aa16cc..6892778 100644 (file)
 #define ANDROID_INPUT_DEVICE_H_
 
 #include <memory>
+#include <vector>
 
 #include <utils/Timers.h>
 
-#include "InputHub.h"
+#include "InputMapper.h"
+
+struct input_device_handle;
+struct input_device_identifier;
 
 namespace android {
 
+class InputDeviceDefinition;
+class InputDeviceNode;
+class InputHostInterface;
+struct InputEvent;
+using InputDeviceHandle = struct input_device_handle;
+using InputDeviceIdentifier = struct input_device_identifier;
+
 /**
  * InputDeviceInterface represents an input device in the HAL. It processes
  * input events before passing them to the input host.
@@ -33,6 +44,7 @@ class InputDeviceInterface {
 public:
     virtual void processInput(InputEvent& event, nsecs_t currentTime) = 0;
 
+    virtual uint32_t getInputClasses() = 0;
 protected:
     InputDeviceInterface() = default;
     virtual ~InputDeviceInterface() = default;
@@ -43,18 +55,75 @@ protected:
  */
 class EvdevDevice : public InputDeviceInterface {
 public:
-    explicit EvdevDevice(std::shared_ptr<InputDeviceNode> node);
+    EvdevDevice(InputHostInterface* host, const std::shared_ptr<InputDeviceNode>& node);
     virtual ~EvdevDevice() override = default;
 
     virtual void processInput(InputEvent& event, nsecs_t currentTime) override;
 
+    virtual uint32_t getInputClasses() override { return mClasses; }
 private:
+    void createMappers();
+    void configureDevice();
+
+    InputHostInterface* mHost = nullptr;
     std::shared_ptr<InputDeviceNode> mDeviceNode;
+    InputDeviceIdentifier* mInputId = nullptr;
+    InputDeviceDefinition* mDeviceDefinition = nullptr;
+    InputDeviceHandle* mDeviceHandle = nullptr;
+    std::vector<std::unique_ptr<InputMapper>> mMappers;
+    uint32_t mClasses = 0;
 
     int32_t mOverrideSec = 0;
     int32_t mOverrideUsec = 0;
 };
 
+/* Input device classes. */
+enum {
+    /* The input device is a keyboard or has buttons. */
+    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
+
+    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
+    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
+
+    /* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
+    INPUT_DEVICE_CLASS_TOUCH         = 0x00000004,
+
+    /* The input device is a cursor device such as a trackball or mouse. */
+    INPUT_DEVICE_CLASS_CURSOR        = 0x00000008,
+
+    /* The input device is a multi-touch touchscreen. */
+    INPUT_DEVICE_CLASS_TOUCH_MT      = 0x00000010,
+
+    /* The input device is a directional pad (implies keyboard, has DPAD keys). */
+    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
+
+    /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
+    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
+
+    /* The input device has switches. */
+    INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
+
+    /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
+    INPUT_DEVICE_CLASS_JOYSTICK      = 0x00000100,
+
+    /* The input device has a vibrator (supports FF_RUMBLE). */
+    INPUT_DEVICE_CLASS_VIBRATOR      = 0x00000200,
+
+    /* The input device has a microphone. */
+    // TODO: remove this and let the host take care of it
+    INPUT_DEVICE_CLASS_MIC           = 0x00000400,
+
+    /* The input device is an external stylus (has data we want to fuse with touch data). */
+    INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
+
+    /* The input device is virtual (not a real device, not part of UI configuration). */
+    /* not used - INPUT_DEVICE_CLASS_VIRTUAL       = 0x40000000, */
+
+    /* The input device is external (not built-in). */
+    // TODO: remove this and let the host take care of it?
+    INPUT_DEVICE_CLASS_EXTERNAL      = 0x80000000,
+};
+
 }  // namespace android
 
 #endif  // ANDROID_INPUT_DEVICE_H_
index ceddd90..d50c1ae 100644 (file)
 #define LOG_TAG "InputDeviceManager"
 //#define LOG_NDEBUG 0
 
+#include "InputDeviceManager.h"
+
 #include <utils/Log.h>
 
 #include "InputDevice.h"
-#include "InputDeviceManager.h"
 
 namespace android {
 
-void InputDeviceManager::onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event,
+void InputDeviceManager::onInputEvent(const 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());
@@ -33,17 +34,18 @@ void InputDeviceManager::onInputEvent(std::shared_ptr<InputDeviceNode> node, Inp
     mDevices[node]->processInput(event, event_time);
 }
 
-void InputDeviceManager::onDeviceAdded(std::shared_ptr<InputDeviceNode> node) {
-    mDevices[node] = std::make_shared<EvdevDevice>(node);
+void InputDeviceManager::onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) {
+    mDevices[node] = std::make_shared<EvdevDevice>(mHost, node);
 }
 
-void InputDeviceManager::onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) {
+void InputDeviceManager::onDeviceRemoved(const 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.
+    // removed so they can run any cleanup, including unregistering from the
+    // host.
     mDevices.erase(node);
 }
 
index b652155..8fbf3ca 100644 (file)
 
 #include <utils/Timers.h>
 
-#include "InputDevice.h"
 #include "InputHub.h"
 
 namespace android {
 
+class InputDeviceInterface;
+class InputHostInterface;
+
 /**
  * InputDeviceManager keeps the mapping of InputDeviceNodes to
  * InputDeviceInterfaces and handles the callbacks from the InputHub, delegating
@@ -34,14 +36,18 @@ namespace android {
  */
 class InputDeviceManager : public InputCallbackInterface {
 public:
+    explicit InputDeviceManager(InputHostInterface* host) :
+        mHost(host) {}
     virtual ~InputDeviceManager() override = default;
 
-    virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event,
+    virtual void onInputEvent(const 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;
+    virtual void onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) override;
+    virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) override;
 
 private:
+    InputHostInterface* mHost;
+
     template<class T, class U>
     using DeviceMap = std::unordered_map<std::shared_ptr<T>, std::shared_ptr<U>>;
 
index 6a65fcd..5be4a79 100644 (file)
 
 namespace android {
 
-void InputReport::reportEvent(InputDeviceHandle d) {
+void InputReport::setIntUsage(InputCollectionId id, InputUsage usage, int32_t value,
+        int32_t arityIndex) {
+    mCallbacks.input_report_set_usage_int(mHost, mReport, id, usage, value, arityIndex);
+}
+
+void InputReport::setBoolUsage(InputCollectionId id, InputUsage usage, bool value,
+        int32_t arityIndex) {
+    mCallbacks.input_report_set_usage_bool(mHost, mReport, id, usage, value, arityIndex);
+}
+
+void InputReport::reportEvent(InputDeviceHandle* d) {
     mCallbacks.report_event(mHost, d, mReport);
 }
 
@@ -32,73 +42,78 @@ void InputReportDefinition::declareUsage(InputCollectionId id, InputUsage usage,
             id, usage, min, max, resolution);
 }
 
-void InputReportDefinition::declareUsage(InputCollectionId id, InputUsage* usage,
+void InputReportDefinition::declareUsages(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,
+InputReport* InputReportDefinition::allocateReport() {
+    return new 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);
+void InputDeviceDefinition::addReport(InputReportDefinition* r) {
+    mCallbacks.input_device_definition_add_report(mHost, mDeviceDefinition, *r);
 }
 
-const char* InputProperty::getKey() {
+const char* InputProperty::getKey() const {
     return mCallbacks.input_get_property_key(mHost, mProperty);
 }
 
-const char* InputProperty::getValue() {
+const char* InputProperty::getValue() const {
     return mCallbacks.input_get_property_value(mHost, mProperty);
 }
 
-InputPropertyMap::~InputPropertyMap() {
-    mCallbacks.input_free_device_property_map(mHost, mMap);
+InputProperty* InputPropertyMap::getDeviceProperty(const char* key) const {
+    return new InputProperty(mHost, mCallbacks,
+            mCallbacks.input_get_device_property(mHost, mMap, key));
 }
 
-InputProperty InputPropertyMap::getDeviceProperty(const char* key) {
-    return InputProperty(mHost, mCallbacks,
-            mCallbacks.input_get_device_property(mHost, mMap, key));
+void InputPropertyMap::freeDeviceProperty(InputProperty* property) const {
+    mCallbacks.input_free_device_property(mHost, *property);
 }
 
-InputDeviceIdentifier InputHost::createDeviceIdentifier(const char* name, int32_t productId,
+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);
+    return mCallbacks.create_device_identifier(
+                mHost, name, productId, vendorId, bus, uniqueId);
 }
 
-InputDeviceDefinition InputHost::createDeviceDefinition() {
-    return InputDeviceDefinition(mHost, mCallbacks, mCallbacks.create_device_definition(mHost));
+InputDeviceDefinition* InputHost::createDeviceDefinition() {
+    return new InputDeviceDefinition(mHost, mCallbacks, mCallbacks.create_device_definition(mHost));
 }
 
-InputReportDefinition InputHost::createInputReportDefinition() {
-    return InputReportDefinition(mHost, mCallbacks,
+InputReportDefinition* InputHost::createInputReportDefinition() {
+    return new InputReportDefinition(mHost, mCallbacks,
             mCallbacks.create_input_report_definition(mHost));
 }
 
-InputReportDefinition InputHost::createOutputReportDefinition() {
-    return InputReportDefinition(mHost, mCallbacks,
+InputReportDefinition* InputHost::createOutputReportDefinition() {
+    return new 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::freeReportDefinition(InputReportDefinition* reportDef) {
+    mCallbacks.free_report_definition(mHost, *reportDef);
+}
+
+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);
+void InputHost::unregisterDevice(InputDeviceHandle* handle) {
+    mCallbacks.unregister_device(mHost, handle);
 }
 
-InputPropertyMap InputHost::getDevicePropertyMap(InputDeviceIdentifier id) {
-    return InputPropertyMap(mHost, mCallbacks,
+InputPropertyMap* InputHost::getDevicePropertyMap(InputDeviceIdentifier* id) {
+    return new InputPropertyMap(mHost, mCallbacks,
             mCallbacks.input_get_device_property_map(mHost, id));
 }
 
+void InputHost::freeDevicePropertyMap(InputPropertyMap* propertyMap) {
+    mCallbacks.input_free_device_property_map(mHost, *propertyMap);
+}
+
 }  // namespace android
index 98ce26f..d6573d2 100644 (file)
@@ -25,17 +25,17 @@ 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.
+ * are intended to be lightweight, as they primarily wrap pointers to callbacks.
+ * 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 InputDeviceHandle = input_device_handle_t;
+using InputDeviceIdentifier = input_device_identifier_t;
 using InputUsage = input_usage_t;
 
 class InputHostBase {
@@ -43,148 +43,148 @@ protected:
     InputHostBase(input_host_t* host, input_host_callbacks_t cb) : mHost(host), mCallbacks(cb) {}
     virtual ~InputHostBase() = default;
 
+    InputHostBase(const InputHostBase& rhs) = delete;
+    InputHostBase(InputHostBase&& rhs) = delete;
+
     input_host_t* mHost;
     input_host_callbacks_t mCallbacks;
 };
 
 class InputReport : private InputHostBase {
 public:
+    InputReport(input_host_t* host, input_host_callbacks_t cb, input_report_t* r) :
+        InputHostBase(host, cb), mReport(r) {}
     virtual ~InputReport() = default;
 
-    InputReport(const InputReport& rhs) = default;
-    InputReport& operator=(const InputReport& rhs) = default;
-    operator input_report_t*() const { return mReport; }
+    virtual void setIntUsage(InputCollectionId id, InputUsage usage, int32_t value,
+            int32_t arityIndex);
+    virtual void setBoolUsage(InputCollectionId id, InputUsage usage, bool value,
+            int32_t arityIndex);
+    virtual void reportEvent(InputDeviceHandle* d);
 
-    void reportEvent(InputDeviceHandle d);
+    operator input_report_t*() const { return mReport; }
 
+    InputReport(const InputReport& rhs) = delete;
+    InputReport& operator=(const InputReport& rhs) = delete;
 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:
+    InputReportDefinition(input_host_t* host, input_host_callbacks_t cb,
+            input_report_definition_t* r) : InputHostBase(host, cb), mReportDefinition(r) {}
     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,
+    virtual void addCollection(InputCollectionId id, int32_t arity);
+    virtual 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();
+    virtual void declareUsages(InputCollectionId id, InputUsage* usage, size_t usageCount);
 
-private:
-    friend class InputHost;
+    virtual InputReport* allocateReport();
 
-    InputReportDefinition(
-            input_host_t* host, input_host_callbacks_t cb, input_report_definition_t* r) :
-        InputHostBase(host, cb), mReportDefinition(r) {}
+    operator input_report_definition_t*() { return mReportDefinition; }
 
+    InputReportDefinition(const InputReportDefinition& rhs) = delete;
+    InputReportDefinition& operator=(const InputReportDefinition& rhs) = delete;
+private:
     input_report_definition_t* mReportDefinition;
 };
 
 class InputDeviceDefinition : private InputHostBase {
 public:
+    InputDeviceDefinition(input_host_t* host, input_host_callbacks_t cb,
+            input_device_definition_t* d) :
+        InputHostBase(host, cb), mDeviceDefinition(d) {}
     virtual ~InputDeviceDefinition() = default;
 
-    InputDeviceDefinition(const InputDeviceDefinition& rhs) = default;
-    InputDeviceDefinition& operator=(const InputDeviceDefinition& rhs) = default;
-    operator input_device_definition_t*() { return mDeviceDefinition; }
+    virtual void addReport(InputReportDefinition* r);
 
-    void addReport(InputReportDefinition r);
+    operator input_device_definition_t*() { return mDeviceDefinition; }
 
+    InputDeviceDefinition(const InputDeviceDefinition& rhs) = delete;
+    InputDeviceDefinition& operator=(const InputDeviceDefinition& rhs) = delete;
 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();
+    virtual ~InputProperty() = default;
 
-    operator input_property_t*() { return mProperty; }
+    InputProperty(input_host_t* host, input_host_callbacks_t cb, input_property_t* p) :
+        InputHostBase(host, cb), mProperty(p) {}
 
-    const char* getKey();
-    const char* getValue();
+    virtual const char* getKey() const;
+    virtual const char* getValue() const;
 
-    // Default move constructor transfers ownership of the input_property_t
-    // pointer.
-    InputProperty(InputProperty&& rhs) = default;
+    operator input_property_t*() { return mProperty; }
 
-    // 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();
+    virtual ~InputPropertyMap() = default;
 
-    operator input_property_map_t*() { return mMap; }
+    InputPropertyMap(input_host_t* host, input_host_callbacks_t cb, input_property_map_t* m) :
+        InputHostBase(host, cb), mMap(m) {}
 
-    InputProperty getDeviceProperty(const char* key);
+    virtual InputProperty* getDeviceProperty(const char* key) const;
+    virtual void freeDeviceProperty(InputProperty* property) const;
 
-    // Default move constructor transfers ownership of the input_property_map_t
-    // pointer.
-    InputPropertyMap(InputPropertyMap&& rhs) = default;
+    operator input_property_map_t*() { return mMap; }
 
-    // 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;
+    input_property_map_t* mMap;
+};
 
-    InputPropertyMap(
-            input_host_t* host, input_host_callbacks_t cb, input_property_map_t* m) :
-        InputHostBase(host, cb), mMap(m) {}
+class InputHostInterface {
+public:
+    virtual ~InputHostInterface() = default;
 
-    input_property_map_t* mMap;
+    virtual InputDeviceIdentifier* createDeviceIdentifier(const char* name, int32_t productId,
+            int32_t vendorId, InputBus bus, const char* uniqueId) = 0;
+
+    virtual InputDeviceDefinition* createDeviceDefinition() = 0;
+    virtual InputReportDefinition* createInputReportDefinition() = 0;
+    virtual InputReportDefinition* createOutputReportDefinition() = 0;
+    virtual void freeReportDefinition(InputReportDefinition* reportDef) = 0;
+
+    virtual InputDeviceHandle* registerDevice(InputDeviceIdentifier* id,
+            InputDeviceDefinition* d) = 0;
+    virtual void unregisterDevice(InputDeviceHandle* handle) = 0;
+
+    virtual InputPropertyMap* getDevicePropertyMap(InputDeviceIdentifier* id) = 0;
+    virtual void freeDevicePropertyMap(InputPropertyMap* propertyMap) = 0;
 };
 
-class InputHost : private InputHostBase {
+class InputHost : public InputHostInterface, 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) override;
 
-    InputDeviceIdentifier createDeviceIdentifier(const char* name, int32_t productId,
-            int32_t vendorId, InputBus bus, const char* uniqueId);
+    InputDeviceDefinition* createDeviceDefinition() override;
+    InputReportDefinition* createInputReportDefinition() override;
+    InputReportDefinition* createOutputReportDefinition() override;
+    virtual void freeReportDefinition(InputReportDefinition* reportDef) override;
 
-    InputDeviceDefinition createDeviceDefinition();
-    InputReportDefinition createInputReportDefinition();
-    InputReportDefinition createOutputReportDefinition();
+    InputDeviceHandle* registerDevice(InputDeviceIdentifier* id, InputDeviceDefinition* d) override;
+    void unregisterDevice(InputDeviceHandle* handle) override;
 
-    InputDeviceHandle registerDevice(InputDeviceIdentifier id, InputDeviceDefinition d);
-    void unregisterDevice(InputDeviceHandle handle);
+    InputPropertyMap* getDevicePropertyMap(InputDeviceIdentifier* id) override;
+    void freeDevicePropertyMap(InputPropertyMap* propertyMap) override;
 
-    InputPropertyMap getDevicePropertyMap(InputDeviceIdentifier id);
+    InputHost(const InputHost& rhs) = delete;
+    InputHost& operator=(const InputHost& rhs) = delete;
 };
 
 }  // namespace android
index e72ac2e..389955d 100644 (file)
@@ -15,7 +15,9 @@
  */
 
 #define LOG_TAG "InputHub"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
+
+#include "InputHub.h"
 
 #include <dirent.h>
 #include <errno.h>
 
 #include <vector>
 
-#include "InputHub.h"
-
 #include <android/input.h>
 #include <hardware_legacy/power.h>
 #include <linux/input.h>
 
 #include <utils/Log.h>
 
+#include "BitUtils.h"
+
 namespace android {
 
 static const char WAKE_LOCK_ID[] = "KeyEvents";
@@ -74,7 +76,6 @@ static bool processHasCapability(int capability) {
     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);
 }
@@ -102,16 +103,20 @@ public:
     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 hasKeyInRange(int32_t start, int32_t end) const override;
+    virtual bool hasRelativeAxis(int32_t axis) const override;
+    virtual bool hasAbsoluteAxis(int32_t axis) const override;
+    virtual bool hasSwitch(int32_t sw) const override;
+    virtual bool hasForceFeedback(int32_t ff) 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 const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) 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 cancelVibrate() override;
 
     virtual void disableDriverKeyRepeat() override;
 
@@ -272,6 +277,10 @@ bool EvdevDeviceNode::hasKey(int32_t key) const {
     return false;
 }
 
+bool EvdevDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
+    return testBitInRange(mKeyBitmask, startKey, endKey);
+}
+
 bool EvdevDeviceNode::hasRelativeAxis(int axis) const {
     if (axis >= 0 && axis <= REL_MAX) {
         return testBit(axis, mRelBitmask);
@@ -279,6 +288,13 @@ bool EvdevDeviceNode::hasRelativeAxis(int axis) const {
     return false;
 }
 
+bool EvdevDeviceNode::hasAbsoluteAxis(int axis) const {
+    if (axis >= 0 && axis <= ABS_MAX) {
+        return getAbsoluteAxisInfo(axis) != nullptr;
+    }
+    return false;
+}
+
 const AbsoluteAxisInfo* EvdevDeviceNode::getAbsoluteAxisInfo(int32_t axis) const {
     if (axis < 0 || axis > ABS_MAX) {
         return nullptr;
@@ -291,6 +307,20 @@ const AbsoluteAxisInfo* EvdevDeviceNode::getAbsoluteAxisInfo(int32_t axis) const
     return nullptr;
 }
 
+bool EvdevDeviceNode::hasSwitch(int32_t sw) const {
+    if (sw >= 0 && sw <= SW_MAX) {
+        return testBit(sw, mSwBitmask);
+    }
+    return false;
+}
+
+bool EvdevDeviceNode::hasForceFeedback(int32_t ff) const {
+    if (ff >= 0 && ff <= FF_MAX) {
+        return testBit(ff, mFfBitmask);
+    }
+    return false;
+}
+
 bool EvdevDeviceNode::hasInputProperty(int property) const {
     if (property >= 0 && property <= INPUT_PROP_MAX) {
         return testBit(property, mPropBitmask);
@@ -371,7 +401,7 @@ void EvdevDeviceNode::vibrate(nsecs_t duration) {
     mFfEffectPlaying = true;
 }
 
-void EvdevDeviceNode::cancelVibrate(int32_t deviceId) {
+void EvdevDeviceNode::cancelVibrate() {
     if (mFfEffectPlaying) {
         mFfEffectPlaying = false;
 
@@ -396,7 +426,7 @@ void EvdevDeviceNode::disableDriverKeyRepeat() {
     }
 }
 
-InputHub::InputHub(std::shared_ptr<InputCallbackInterface> cb) :
+InputHub::InputHub(const 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:
@@ -670,9 +700,8 @@ status_t InputHub::readNotify() {
             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) {
+                auto deviceNode = openNode(path);
+                if (deviceNode == nullptr) {
                     ALOGE("could not open device node %s. err=%d", path.c_str(), res);
                 } else {
                     mInputCallback->onDeviceAdded(deviceNode);
@@ -680,7 +709,7 @@ status_t InputHub::readNotify() {
             } else {
                 auto deviceNode = findNodeByPath(path);
                 if (deviceNode != nullptr) {
-                    status_t ret = closeNode(deviceNode);
+                    status_t ret = closeNode(deviceNode.get());
                     if (ret != OK) {
                         ALOGW("Could not close device %s. errno=%d", path.c_str(), ret);
                     } else {
@@ -712,8 +741,8 @@ status_t InputHub::scanDir(const std::string& path) {
             continue;
         }
         std::string filename = path + "/" + dirent->d_name;
-        std::shared_ptr<InputDeviceNode> node;
-        if (openNode(filename, &node) != OK) {
+        auto node = openNode(filename);
+        if (node == nullptr) {
             ALOGE("could not open device node %s", filename.c_str());
         } else {
             mInputCallback->onDeviceAdded(node);
@@ -723,18 +752,16 @@ status_t InputHub::scanDir(const std::string& path) {
     return OK;
 }
 
-status_t InputHub::openNode(const std::string& path,
-        std::shared_ptr<InputDeviceNode>* outNode) {
+std::shared_ptr<InputDeviceNode> InputHub::openNode(const std::string& path) {
     ALOGV("opening %s...", path.c_str());
     auto evdevNode = std::shared_ptr<EvdevDeviceNode>(EvdevDeviceNode::openDeviceNode(path));
     if (evdevNode == nullptr) {
-        return UNKNOWN_ERROR;
+        return nullptr;
     }
 
     auto fd = evdevNode->getFd();
     ALOGV("opened %s with fd %d", path.c_str(), fd);
-    *outNode = std::static_pointer_cast<InputDeviceNode>(evdevNode);
-    mDeviceNodes[fd] = *outNode;
+    mDeviceNodes[fd] = evdevNode;
     struct epoll_event eventItem{};
     eventItem.events = EPOLLIN;
     if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) {
@@ -743,7 +770,7 @@ status_t InputHub::openNode(const std::string& path,
     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;
+        return nullptr;
     }
 
     if (mNeedToCheckSuspendBlockIoctl) {
@@ -765,12 +792,12 @@ status_t InputHub::openNode(const std::string& path,
         mNeedToCheckSuspendBlockIoctl = false;
     }
 
-    return OK;
+    return evdevNode;
 }
 
-status_t InputHub::closeNode(const std::shared_ptr<InputDeviceNode>& node) {
+status_t InputHub::closeNode(const InputDeviceNode* node) {
     for (auto pair : mDeviceNodes) {
-        if (pair.second.get() == node.get()) {
+        if (pair.second.get() == node) {
             return closeNodeByFd(pair.first);
         }
     }
index bec327a..1abdc09 100644 (file)
@@ -56,29 +56,55 @@ struct AbsoluteAxisInfo {
  */
 class InputDeviceNode {
 public:
+    /** Get the Linux device path for the node. */
     virtual const std::string& getPath() const = 0;
 
+    /** Get the name of the device returned by the driver. */
     virtual const std::string& getName() const = 0;
+    /** Get the location of the device returned by the driver. */
     virtual const std::string& getLocation() const = 0;
+    /** Get the unique id of the device returned by the driver. */
     virtual const std::string& getUniqueId() const = 0;
 
+    /** Get the bus type of the device returned by the driver. */
     virtual uint16_t getBusType() const = 0;
+    /** Get the vendor id of the device returned by the driver. */
     virtual uint16_t getVendorId() const = 0;
+    /** Get the product id of the device returned by the driver. */
     virtual uint16_t getProductId() const = 0;
+    /** Get the version of the device driver. */
     virtual uint16_t getVersion() const = 0;
 
+    /** Returns true if the device has the key. */
     virtual bool hasKey(int32_t key) const = 0;
-    virtual bool hasRelativeAxis(int axis) const = 0;
-    virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
+    /** Returns true if the device has a key in the range [startKey, endKey). */
+    virtual bool hasKeyInRange(int32_t startKey, int32_t endKey) const = 0;
+    /** Returns true if the device has the relative axis. */
+    virtual bool hasRelativeAxis(int32_t axis) const = 0;
+    /** Returns true if the device has the absolute axis. */
+    virtual bool hasAbsoluteAxis(int32_t axis) const = 0;
+    /** Returns true if the device has the switch. */
+    virtual bool hasSwitch(int32_t sw) const = 0;
+    /** Returns true if the device has the force feedback method. */
+    virtual bool hasForceFeedback(int32_t ff) const = 0;
+    /** Returns true if the device has the input property. */
     virtual bool hasInputProperty(int property) const = 0;
 
+    /** Returns the state of the key. */
     virtual int32_t getKeyState(int32_t key) const = 0;
+    /** Returns the state of the switch. */
     virtual int32_t getSwitchState(int32_t sw) const = 0;
+    /** Returns information about the absolute axis. */
+    virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
+    /** Returns the value of the absolute axis. */
     virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0;
 
+    /** Vibrate the device for duration ns. */
     virtual void vibrate(nsecs_t duration) = 0;
-    virtual void cancelVibrate(int32_t deviceId) = 0;
+    /** Stop vibration on the device. */
+    virtual void cancelVibrate() = 0;
 
+    /** Disable key repeat for the device in the driver. */
     virtual void disableDriverKeyRepeat() = 0;
 
 protected:
@@ -89,10 +115,10 @@ protected:
 /** Callback interface for receiving input events, including device changes. */
 class InputCallbackInterface {
 public:
-    virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event,
+    virtual void onInputEvent(const 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;
+    virtual void onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) = 0;
+    virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) = 0;
 
 protected:
     InputCallbackInterface() = default;
@@ -129,7 +155,7 @@ protected:
  */
 class InputHub : public InputHubInterface {
 public:
-    explicit InputHub(std::shared_ptr<InputCallbackInterface> cb);
+    explicit InputHub(const std::shared_ptr<InputCallbackInterface>& cb);
     virtual ~InputHub() override;
 
     virtual status_t registerDevicePath(const std::string& path) override;
@@ -143,8 +169,8 @@ public:
 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);
+    std::shared_ptr<InputDeviceNode> openNode(const std::string& path);
+    status_t closeNode(const InputDeviceNode* node);
     status_t closeNodeByFd(int fd);
     std::shared_ptr<InputDeviceNode> findNodeByPath(const std::string& path);
 
diff --git a/modules/input/evdev/InputMapper.cpp b/modules/input/evdev/InputMapper.cpp
new file mode 100644 (file)
index 0000000..3893125
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 "InputMapper.h"
+
+#include "InputHost.h"
+
+namespace android {
+
+InputReport* InputMapper::getInputReport() {
+    if (mReport) return mReport;
+    if (mInputReportDef == nullptr) return nullptr;
+    mReport = mInputReportDef->allocateReport();
+    return mReport;
+}
+
+}  // namespace android
diff --git a/modules/input/evdev/InputMapper.h b/modules/input/evdev/InputMapper.h
new file mode 100644 (file)
index 0000000..5e88d06
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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_MAPPER_H_
+#define ANDROID_INPUT_MAPPER_H_
+
+struct input_device_handle;
+
+namespace android {
+
+class InputDeviceNode;
+class InputReport;
+class InputReportDefinition;
+struct InputEvent;
+using InputDeviceHandle = struct input_device_handle;
+
+/**
+ * An InputMapper processes raw evdev input events and combines them into
+ * Android input HAL reports. A given InputMapper will focus on a particular
+ * type of input, like key presses or touch events. A single InputDevice may
+ * have multiple InputMappers, corresponding to the different types of inputs it
+ * supports.
+ */
+class InputMapper {
+public:
+    InputMapper() = default;
+    virtual ~InputMapper() {}
+
+    /**
+     * If the mapper supports input events from the InputDevice,
+     * configureInputReport will populate the InputReportDefinition and return
+     * true. If input is not supported, false is returned, and the InputDevice
+     * may free or re-use the InputReportDefinition.
+     */
+    virtual bool configureInputReport(InputDeviceNode* devNode, InputReportDefinition* report) {
+        return false;
+    }
+
+    /**
+     * If the mapper supports output events from the InputDevice,
+     * configureOutputReport will populate the InputReportDefinition and return
+     * true. If output is not supported, false is returned, and the InputDevice
+     * may free or re-use the InputReportDefinition.
+     */
+    virtual bool configureOutputReport(InputDeviceNode* devNode, InputReportDefinition* report) {
+        return false;
+    }
+
+    // Set the InputDeviceHandle after registering the device with the host.
+    virtual void setDeviceHandle(InputDeviceHandle* handle) { mDeviceHandle = handle; }
+    // Process the InputEvent.
+    virtual void process(const InputEvent& event) = 0;
+
+protected:
+    virtual void setInputReportDefinition(InputReportDefinition* reportDef) final {
+        mInputReportDef = reportDef;
+    }
+    virtual void setOutputReportDefinition(InputReportDefinition* reportDef) final {
+        mOutputReportDef = reportDef;
+    }
+    virtual InputReportDefinition* getInputReportDefinition() final { return mInputReportDef; }
+    virtual InputReportDefinition* getOutputReportDefinition() final { return mOutputReportDef; }
+    virtual InputDeviceHandle* getDeviceHandle() final { return mDeviceHandle; }
+    virtual InputReport* getInputReport() final;
+
+private:
+    InputReportDefinition* mInputReportDef = nullptr;
+    InputReportDefinition* mOutputReportDef = nullptr;
+    InputDeviceHandle* mDeviceHandle = nullptr;
+    InputReport* mReport = nullptr;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_INPUT_MAPPER_H_
diff --git a/modules/input/evdev/MouseInputMapper.cpp b/modules/input/evdev/MouseInputMapper.cpp
new file mode 100644 (file)
index 0000000..8fba5ca
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * 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 "MouseInputMapper"
+//#define LOG_NDEBUG 0
+
+#include "MouseInputMapper.h"
+
+#include <linux/input.h>
+#include <hardware/input.h>
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include "InputHost.h"
+#include "InputHub.h"
+
+
+namespace android {
+
+// Map scancodes to input HAL usages.
+// The order of these definitions MUST remain in sync with the order they are
+// defined in linux/input.h.
+static struct {
+    int32_t scancode;
+    InputUsage usage;
+} codeMap[] = {
+    {BTN_LEFT, INPUT_USAGE_BUTTON_PRIMARY},
+    {BTN_RIGHT, INPUT_USAGE_BUTTON_SECONDARY},
+    {BTN_MIDDLE, INPUT_USAGE_BUTTON_TERTIARY},
+    {BTN_SIDE, INPUT_USAGE_BUTTON_UNKNOWN},
+    {BTN_EXTRA, INPUT_USAGE_BUTTON_UNKNOWN},
+    {BTN_FORWARD, INPUT_USAGE_BUTTON_FORWARD},
+    {BTN_BACK, INPUT_USAGE_BUTTON_BACK},
+    {BTN_TASK, INPUT_USAGE_BUTTON_UNKNOWN},
+};
+
+
+bool MouseInputMapper::configureInputReport(InputDeviceNode* devNode,
+        InputReportDefinition* report) {
+    setInputReportDefinition(report);
+    getInputReportDefinition()->addCollection(INPUT_COLLECTION_ID_MOUSE, 1);
+
+    // Configure mouse axes
+    if (!devNode->hasRelativeAxis(REL_X) || !devNode->hasRelativeAxis(REL_Y)) {
+        ALOGE("Device %s is missing a relative x or y axis. Device cannot be configured.",
+                devNode->getPath().c_str());
+        return false;
+    }
+    getInputReportDefinition()->declareUsage(INPUT_COLLECTION_ID_MOUSE, INPUT_USAGE_AXIS_X,
+            INT32_MIN, INT32_MAX, 1.0f);
+    getInputReportDefinition()->declareUsage(INPUT_COLLECTION_ID_MOUSE, INPUT_USAGE_AXIS_Y,
+            INT32_MIN, INT32_MAX, 1.0f);
+    if (devNode->hasRelativeAxis(REL_WHEEL)) {
+        getInputReportDefinition()->declareUsage(INPUT_COLLECTION_ID_MOUSE,
+                INPUT_USAGE_AXIS_VSCROLL, -1, 1, 0.0f);
+    }
+    if (devNode->hasRelativeAxis(REL_HWHEEL)) {
+        getInputReportDefinition()->declareUsage(INPUT_COLLECTION_ID_MOUSE,
+                INPUT_USAGE_AXIS_HSCROLL, -1, 1, 0.0f);
+    }
+
+    // Configure mouse buttons
+    InputUsage usages[NELEM(codeMap)];
+    int numUsages = 0;
+    for (int32_t i = 0; i < NELEM(codeMap); ++i) {
+        if (devNode->hasKey(codeMap[i].scancode)) {
+            usages[numUsages++] = codeMap[i].usage;
+        }
+    }
+    if (numUsages == 0) {
+        ALOGW("MouseInputMapper found no buttons for %s", devNode->getPath().c_str());
+    }
+    getInputReportDefinition()->declareUsages(INPUT_COLLECTION_ID_MOUSE, usages, numUsages);
+    return true;
+}
+
+void MouseInputMapper::process(const InputEvent& event) {
+    ALOGV("processing mouse event. type=%d code=%d value=%d",
+            event.type, event.code, event.value);
+    switch (event.type) {
+        case EV_KEY:
+            processButton(event.code, event.value);
+            break;
+        case EV_REL:
+            processMotion(event.code, event.value);
+            break;
+        case EV_SYN:
+            if (event.code == SYN_REPORT) {
+                sync(event.when);
+            }
+            break;
+        default:
+            ALOGV("unknown mouse event type: %d", event.type);
+    }
+}
+
+void MouseInputMapper::processMotion(int32_t code, int32_t value) {
+    switch (code) {
+        case REL_X:
+            mRelX = value;
+            break;
+        case REL_Y:
+            mRelY = value;
+            break;
+        case REL_WHEEL:
+            mRelWheel = value;
+            break;
+        case REL_HWHEEL:
+            mRelHWheel = value;
+            break;
+        default:
+            // Unknown code. Ignore.
+            break;
+    }
+}
+
+// Map evdev button codes to bit indices. This function assumes code >=
+// BTN_MOUSE.
+uint32_t buttonToBit(int32_t code) {
+    return static_cast<uint32_t>(code - BTN_MOUSE);
+}
+
+void MouseInputMapper::processButton(int32_t code, int32_t value) {
+    // Mouse buttons start at BTN_MOUSE and end before BTN_JOYSTICK. There isn't
+    // really enough room after the mouse buttons for another button class, so
+    // the risk of a button type being inserted after mouse is low.
+    if (code >= BTN_MOUSE && code < BTN_JOYSTICK) {
+        if (value) {
+            mButtonValues.markBit(buttonToBit(code));
+        } else {
+            mButtonValues.clearBit(buttonToBit(code));
+        }
+        mUpdatedButtonMask.markBit(buttonToBit(code));
+    }
+}
+
+void MouseInputMapper::sync(nsecs_t when) {
+    // Process updated button states.
+    while (!mUpdatedButtonMask.isEmpty()) {
+        auto bit = mUpdatedButtonMask.clearFirstMarkedBit();
+        getInputReport()->setBoolUsage(INPUT_COLLECTION_ID_MOUSE, codeMap[bit].usage,
+                mButtonValues.hasBit(bit), 0);
+    }
+
+    // Process motion and scroll changes.
+    if (mRelX != 0) {
+        getInputReport()->setIntUsage(INPUT_COLLECTION_ID_MOUSE, INPUT_USAGE_AXIS_X, mRelX, 0);
+    }
+    if (mRelY != 0) {
+        getInputReport()->setIntUsage(INPUT_COLLECTION_ID_MOUSE, INPUT_USAGE_AXIS_Y, mRelY, 0);
+    }
+    if (mRelWheel != 0) {
+        getInputReport()->setIntUsage(INPUT_COLLECTION_ID_MOUSE, INPUT_USAGE_AXIS_VSCROLL,
+                mRelWheel, 0);
+    }
+    if (mRelHWheel != 0) {
+        getInputReport()->setIntUsage(INPUT_COLLECTION_ID_MOUSE, INPUT_USAGE_AXIS_HSCROLL,
+                mRelHWheel, 0);
+    }
+
+    // Report and reset.
+    getInputReport()->reportEvent(getDeviceHandle());
+    mUpdatedButtonMask.clear();
+    mButtonValues.clear();
+    mRelX = 0;
+    mRelY = 0;
+    mRelWheel = 0;
+    mRelHWheel = 0;
+}
+
+}  // namespace android
diff --git a/modules/input/evdev/MouseInputMapper.h b/modules/input/evdev/MouseInputMapper.h
new file mode 100644 (file)
index 0000000..1f8bc06
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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_MOUSE_INPUT_MAPPER_H_
+#define ANDROID_MOUSE_INPUT_MAPPER_H_
+
+#include <cstdint>
+
+#include <utils/BitSet.h>
+#include <utils/Timers.h>
+
+#include "InputMapper.h"
+
+namespace android {
+
+class MouseInputMapper : public InputMapper {
+public:
+    virtual ~MouseInputMapper() = default;
+
+    virtual bool configureInputReport(InputDeviceNode* devNode,
+            InputReportDefinition* report) override;
+    virtual void process(const InputEvent& event) override;
+
+private:
+    void processMotion(int32_t code, int32_t value);
+    void processButton(int32_t code, int32_t value);
+    void sync(nsecs_t when);
+
+    BitSet32 mButtonValues;
+    BitSet32 mUpdatedButtonMask;
+
+    int32_t mRelX = 0;
+    int32_t mRelY = 0;
+
+    bool mHaveRelWheel = false;
+    bool mHaveRelHWheel = false;
+    int32_t mRelWheel = 0;
+    int32_t mRelHWheel = 0;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_MOUSE_INPUT_MAPPER_H_
diff --git a/modules/input/evdev/SwitchInputMapper.cpp b/modules/input/evdev/SwitchInputMapper.cpp
new file mode 100644 (file)
index 0000000..bb79d01
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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 "SwitchInputMapper"
+//#define LOG_NDEBUG 0
+
+#include "SwitchInputMapper.h"
+
+#include <inttypes.h>
+#include <linux/input.h>
+#include <hardware/input.h>
+#include <utils/Log.h>
+
+#include "InputHost.h"
+#include "InputHub.h"
+
+namespace android {
+
+static struct {
+    int32_t scancode;
+    InputUsage usage;
+} codeMap[] = {
+    {SW_LID, INPUT_USAGE_SWITCH_LID},
+    {SW_TABLET_MODE, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_HEADPHONE_INSERT, INPUT_USAGE_SWITCH_HEADPHONE_INSERT},
+    {SW_RFKILL_ALL, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_MICROPHONE_INSERT, INPUT_USAGE_SWITCH_MICROPHONE_INSERT},
+    {SW_DOCK, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_LINEOUT_INSERT, INPUT_USAGE_SWITCH_LINEOUT_INSERT},
+    {SW_JACK_PHYSICAL_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_VIDEOOUT_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_CAMERA_LENS_COVER, INPUT_USAGE_SWITCH_CAMERA_LENS_COVER},
+    {SW_KEYPAD_SLIDE, INPUT_USAGE_SWITCH_KEYPAD_SLIDE},
+    {SW_FRONT_PROXIMITY, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_ROTATE_LOCK, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_LINEIN_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
+    {0x0e /* unused */, INPUT_USAGE_SWITCH_UNKNOWN},
+    {SW_MAX, INPUT_USAGE_SWITCH_UNKNOWN},
+};
+
+SwitchInputMapper::SwitchInputMapper()
+    : InputMapper() {
+    static_assert(SW_CNT <= 32, "More than 32 switches defined in linux/input.h");
+}
+
+bool SwitchInputMapper::configureInputReport(InputDeviceNode* devNode,
+        InputReportDefinition* report) {
+    InputUsage usages[SW_CNT];
+    int numUsages = 0;
+    for (int32_t i = 0; i < SW_CNT; ++i) {
+        if (devNode->hasSwitch(codeMap[i].scancode)) {
+            usages[numUsages++] = codeMap[i].usage;
+        }
+    }
+    if (numUsages == 0) {
+        ALOGE("SwitchInputMapper found no switches for %s!", devNode->getPath().c_str());
+        return false;
+    }
+    setInputReportDefinition(report);
+    getInputReportDefinition()->addCollection(INPUT_COLLECTION_ID_SWITCH, 1);
+    getInputReportDefinition()->declareUsages(INPUT_COLLECTION_ID_SWITCH, usages, numUsages);
+    return true;
+}
+
+void SwitchInputMapper::process(const InputEvent& event) {
+    switch (event.type) {
+        case EV_SW:
+            processSwitch(event.code, event.value);
+            break;
+        case EV_SYN:
+            if (event.code == SYN_REPORT) {
+                sync(event.when);
+            }
+            break;
+        default:
+            ALOGV("unknown switch event type: %d", event.type);
+    }
+}
+
+void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
+    ALOGV("processing switch event. code=%" PRId32 ", value=%" PRId32, switchCode, switchValue);
+    if (switchCode >= 0 && switchCode < SW_CNT) {
+        if (switchValue) {
+            mSwitchValues.markBit(switchCode);
+        } else {
+            mSwitchValues.clearBit(switchCode);
+        }
+        mUpdatedSwitchMask.markBit(switchCode);
+    }
+}
+
+void SwitchInputMapper::sync(nsecs_t when) {
+    if (mUpdatedSwitchMask.isEmpty()) {
+        // Clear the values just in case.
+        mSwitchValues.clear();
+        return;
+    }
+
+    while (!mUpdatedSwitchMask.isEmpty()) {
+        auto bit = mUpdatedSwitchMask.firstMarkedBit();
+        getInputReport()->setBoolUsage(INPUT_COLLECTION_ID_SWITCH, codeMap[bit].usage,
+                mSwitchValues.hasBit(bit), 0);
+        mUpdatedSwitchMask.clearBit(bit);
+    }
+    getInputReport()->reportEvent(getDeviceHandle());
+    mUpdatedSwitchMask.clear();
+    mSwitchValues.clear();
+}
+
+}  // namespace android
diff --git a/modules/input/evdev/SwitchInputMapper.h b/modules/input/evdev/SwitchInputMapper.h
new file mode 100644 (file)
index 0000000..e25c3a5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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_SWITCH_INPUT_MAPPER_H_
+#define ANDROID_SWITCH_INPUT_MAPPER_H_
+
+#include <cstdint>
+
+#include <utils/BitSet.h>
+#include <utils/Timers.h>
+
+#include "InputMapper.h"
+
+namespace android {
+
+class SwitchInputMapper : public InputMapper {
+public:
+    SwitchInputMapper();
+    virtual ~SwitchInputMapper() = default;
+
+    virtual bool configureInputReport(InputDeviceNode* devNode,
+            InputReportDefinition* report) override;
+    virtual void process(const InputEvent& event) override;
+
+private:
+    void processSwitch(int32_t switchCode, int32_t switchValue);
+    void sync(nsecs_t when);
+
+    BitSet32 mSwitchValues;
+    BitSet32 mUpdatedSwitchMask;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_SWITCH_INPUT_MAPPER_H_
index f433c85..221424f 100644 (file)
@@ -17,11 +17,24 @@ LOCAL_PATH := $(call my-dir)
 # Stub radio HAL module, used for tests
 include $(CLEAR_VARS)
 
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+
 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)
+
+# Stub radio tool that can be run in native.
+include $(CLEAR_VARS)
+
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+
+LOCAL_MODULE := radio_hal_tool
+LOCAL_SRC_FILES := radio_hal_tool.c
+LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
+LOCAL_SHARED_LIBRARIES := libcutils libhardware liblog libradio_metadata
+
+include $(BUILD_EXECUTABLE)
diff --git a/modules/radio/radio_hal_tool.c b/modules/radio/radio_hal_tool.c
new file mode 100644 (file)
index 0000000..05d872e
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 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_hal_tool"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/log.h>
+#include <hardware/hardware.h>
+#include <hardware/radio.h>
+#include <system/radio.h>
+#include <system/radio_metadata.h>
+
+
+// Global state variables.
+const struct radio_tuner *hal_tuner = NULL;
+
+void usage() {
+    printf("Usage: "
+            "./radio_hal_tool -l\n"
+            "-l: List properties global to the Radio.\n"
+    );
+}
+
+void list_all_properties(radio_hw_device_t *device) {
+    radio_hal_properties_t hal_properties;
+    device->get_properties(device, &hal_properties);
+    printf("Class: %d\n"
+           "Impl: %s\n"
+           "Tuners: %d\n"
+           "Bands: %d\n\n",
+           hal_properties.class_id, hal_properties.implementor, hal_properties.num_tuners,
+           hal_properties.num_bands);
+
+    uint32_t i;
+    for (i = 0; i < hal_properties.num_bands; i++) {
+        printf("Band Information\n"
+               "Type: %d\n"
+               "Connected: %d\n"
+               "Lower limit: %d\n"
+               "Upper limit: %d\n"
+               "Spacing: %d\n\n",
+               hal_properties.bands[i].type,
+               hal_properties.bands[i].antenna_connected,
+               hal_properties.bands[i].lower_limit,
+               hal_properties.bands[i].upper_limit,
+               hal_properties.bands[i].num_spacings);
+    }
+}
+
+void callback(radio_hal_event_t *event, void *cookie) {
+    printf("\nEvent detected\n"
+           "Type: %d\n", event->type);
+}
+
+void tune(radio_hw_device_t *device, int band_number) {
+    int ret;
+    radio_hal_properties_t hal_properties;
+    ret = device->get_properties(device, &hal_properties);
+    if (ret != 0) {
+        printf("Err: get_properties returned: %d\n", ret);
+        return;
+    }
+
+    if ((uint32_t) band_number >= hal_properties.num_bands) {
+        printf("Tuner number range should be: [0, %d]\n", hal_properties.num_bands);
+    }
+    printf("Setting band config as:\n"
+           "Type: %d\n"
+           "Connected: %d\n"
+           "Lower limit: %d\n"
+           "Upper limit: %d\n"
+           "Spacing: %d\n\n",
+           hal_properties.bands[band_number].type,
+           hal_properties.bands[band_number].antenna_connected,
+           hal_properties.bands[band_number].lower_limit,
+           hal_properties.bands[band_number].upper_limit,
+           hal_properties.bands[band_number].num_spacings);
+    int cookie = 0;
+    ret = device->open_tuner(
+        device, (const radio_hal_band_config_t *) (&(hal_properties.bands[band_number])), false,
+        callback, &cookie, &hal_tuner);
+    if (ret != 0) {
+        printf("Err: open_tuner returned: %d\n", ret);
+        return;
+    }
+    // It takes some time to apply the config which is currently set as 500ms in
+    // the stub implementation.
+    sleep(1);
+
+    // Stub tuner implementation will regard this magic channel as a valid channel to tune.
+    ret = hal_tuner->tune(hal_tuner, 87916, 0);
+    if (ret != 0) {
+        printf("Err: tune returned: %d\n", ret);
+        return;
+    }
+    // In the stub implementation it takes ~100ms to tune to the channel and the
+    // data is set rightafter.
+    sleep(1);
+}
+
+void get_tuner_metadata(radio_hw_device_t *device) {
+    // Get the metadata and print it.
+    radio_program_info_t info;
+    radio_metadata_allocate(&info.metadata, 87916, 0);
+    int ret;
+    ret = hal_tuner->get_program_information(hal_tuner, &info);
+    if (ret != 0) {
+        printf("Err: Get program info ret code: %d\n", ret);
+        return;
+    }
+
+    // Print the info.
+    printf("Metadata from the band\n");
+    int i;
+    for (i = 0; i < radio_metadata_get_count(info.metadata); i++) {
+        radio_metadata_key_t key;
+        radio_metadata_type_t type;
+        void *value;
+        uint32_t size;
+
+        radio_metadata_get_at_index(info.metadata, i, &key, &type, &value, &size);
+
+        printf("\nMetadata key: %d\n"
+               "Type: %d\n", key, type);
+
+        switch (type) {
+            case RADIO_METADATA_TYPE_INT:
+                printf("Int value: %d\n", *((int *) value));
+                break;
+            case RADIO_METADATA_TYPE_TEXT:
+                printf("Text value: %s\n", (char *) value);
+                break;
+            case RADIO_METADATA_TYPE_RAW:
+                printf("Raw value, skipping\n");
+                break;
+            case RADIO_METADATA_TYPE_CLOCK:
+                printf("UTC Epoch: %lld\n"
+                       "UTC Offset: %d\n",
+                       (long long)((radio_metadata_clock_t *) value)->utc_seconds_since_epoch,
+                       ((radio_metadata_clock_t *) value)->timezone_offset_in_minutes);
+        }
+    }
+
+    // Close the tuner when we are done.
+    ret = device->close_tuner(device, hal_tuner);
+    if (ret != 0) {
+        printf("Err: close_tuner returned: %d\n", ret);
+    }
+}
+
+int main(int argc, char** argv) {
+    // Open the radio module and just ask for the list of properties.
+    const hw_module_t *hw_module = NULL;
+    int rc;
+    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &hw_module);
+    if (rc != 0) {
+        printf("Cannot open the hw module. Does the HAL exist? %d\n", rc);
+        return -1;
+    }
+
+    radio_hw_device_t *dev;
+    rc = radio_hw_device_open(hw_module, &dev);
+    if (rc != 0) {
+        printf("Cannot open the device. Check that HAL implementation. %d\n", rc);
+        return -1;
+    }
+    printf("HAL Loaded!\n");
+
+    // If this is a list properties command - we check for -l command.
+    int list_properties = 0;
+    // Get metadata.
+    int get_metadata = 0;
+    // Tune. Takes a tuner number (see bands obtainaed by list_properties).
+    int should_tune = 0;
+    int band_number = -1;
+
+    int opt;
+    while ((opt = getopt(argc, argv, "lmt:")) != -1) {
+        switch (opt) {
+            case 'l':
+                list_properties = 1;
+                break;
+            case 't':
+                should_tune = 1;
+                band_number = atoi(optarg);
+                break;
+            case 'm':
+                get_metadata = 1;
+                break;
+        }
+    }
+
+    if (list_properties) {
+        printf("Listing properties...\n");
+        list_all_properties(dev);
+    } else {
+        if (should_tune) {
+            if (band_number < 0) {
+                printf("Tuner number should be positive");
+                return -1;
+            }
+            printf("Tuning to a station...\n");
+            tune(dev, band_number);
+        }
+        if (get_metadata) {
+            if (!hal_tuner) {
+                printf("Please pass -t <band_number> to tune to a valid station to get metadata.");
+                exit(1);
+            }
+            get_tuner_metadata(dev);
+        }
+    }
+    return 0;
+}
index 9c0f22c..fbf8c94 100644 (file)
@@ -58,6 +58,7 @@ static const radio_hal_properties_t hw_properties = {
                 .rds = RADIO_RDS_US,
                 .ta = false,
                 .af = false,
+                .ea = true,
             }
         },
         {
@@ -74,6 +75,11 @@ static const radio_hal_properties_t hw_properties = {
     }
 };
 
+static const radio_metadata_clock_t hw_clock = {
+    .utc_seconds_since_epoch = 1234567890,
+    .timezone_offset_in_minutes = (-8 * 60),
+};
+
 struct stub_radio_tuner {
     struct radio_tuner interface;
     struct stub_radio_device *dev;
@@ -103,6 +109,7 @@ typedef enum {
     CMD_TUNE,
     CMD_CANCEL,
     CMD_METADATA,
+    CMD_ANNOUNCEMENTS,
 } thread_cmd_type_t;
 
 struct thread_command {
@@ -152,7 +159,7 @@ static int send_command_l(struct stub_radio_tuner *tuner,
     return 0;
 }
 
-#define BITMAP_FILE_PATH "/data/misc/media/android.png"
+#define BITMAP_FILE_PATH "/data/misc/audioserver/android.png"
 
 static int add_bitmap_metadata(radio_metadata_t **metadata, radio_metadata_key_t key,
                                const char *source)
@@ -215,6 +222,9 @@ static int prepare_metadata(struct stub_radio_tuner *tuner,
         ret = add_bitmap_metadata(metadata, RADIO_METADATA_KEY_ICON, BITMAP_FILE_PATH);
         if (ret != 0)
             goto exit;
+        ret = radio_metadata_add_clock(metadata, RADIO_METADATA_KEY_CLOCK, &hw_clock);
+        if (ret != 0)
+            goto exit;
     } else {
         ret = add_bitmap_metadata(metadata, RADIO_METADATA_KEY_ART, BITMAP_FILE_PATH);
         if (ret != 0)
@@ -251,6 +261,10 @@ static void *callback_thread_loop(void *context)
 
     pthread_mutex_lock(&tuner->lock);
 
+    // Fields which are used to toggle the state of traffic announcements and
+    // ea announcements at random. They are access protected by tuner->lock.
+    bool ea_state = false;
+
     while (true) {
         struct thread_command *cmd = NULL;
         struct listnode *item;
@@ -278,7 +292,8 @@ static void *callback_thread_loop(void *context)
             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)) {
+                    cmd->type == CMD_TUNE || cmd->type == CMD_METADATA ||
+                    cmd->type == CMD_ANNOUNCEMENTS)) {
                  list_remove(item);
                  free(cmd);
                  continue;
@@ -309,9 +324,11 @@ static void *callback_thread_loop(void *context)
                           __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",
+                        ALOGV("  - stereo %d\n  - rds %d\n  - ta %d\n  - af %d\n"
+                              "  - ea %d\n",
                               tuner->config.fm.stereo, tuner->config.fm.rds,
-                              tuner->config.fm.ta, tuner->config.fm.af);
+                              tuner->config.fm.ta, tuner->config.fm.af,
+                              tuner->config.fm.ea);
                     } else {
                         ALOGV("  - stereo %d", tuner->config.am.stereo);
                     }
@@ -377,7 +394,7 @@ static void *callback_thread_loop(void *context)
 
                     if (tuner->program.tuned) {
                         prepare_metadata(tuner, &tuner->program.metadata, true);
-                        send_command_l(tuner, CMD_METADATA, 5000, NULL);
+                        send_command_l(tuner, CMD_ANNOUNCEMENTS, 1000, NULL);
                     } else {
                         if (tuner->program.metadata != NULL)
                             radio_metadata_deallocate(tuner->program.metadata);
@@ -408,6 +425,28 @@ static void *callback_thread_loop(void *context)
                     got_cancel = true;
                 } break;
 
+                // Fire emergency announcements if they are enabled in the config. Stub
+                // implementation simply fires an announcement for 5 second
+                // duration with a gap of 5 seconds.
+                case CMD_ANNOUNCEMENTS: {
+                    ALOGV("In annoucements. %d %d %d\n",
+                          ea_state, tuner->config.type, tuner->config.fm.ea);
+                    if (tuner->config.type == RADIO_BAND_FM ||
+                        tuner->config.type == RADIO_BAND_FM_HD) {
+                        if (ea_state) {
+                            ea_state = false;
+                            event.type = RADIO_EVENT_EA;
+                        } else if (tuner->config.fm.ea) {
+                            ea_state = true;
+                            event.type = RADIO_EVENT_EA;
+                        }
+                        event.on = ea_state;
+
+                        if (tuner->config.fm.ea) {
+                            send_command_l(tuner, CMD_ANNOUNCEMENTS, 5000, NULL);
+                        }
+                    }
+                } break;
                 }
                 if (event.type != RADIO_EVENT_HW_FAILURE && tuner->callback != NULL) {
                     pthread_mutex_unlock(&tuner->lock);
@@ -438,7 +477,7 @@ static void *callback_thread_loop(void *context)
                     free(cmd);
                 }
             }
-            send_command_l(tuner, CMD_METADATA, 100, NULL);
+            send_command_l(tuner, CMD_METADATA, 1000, NULL);
         }
     }
 
@@ -472,7 +511,7 @@ exit:
 }
 
 static int tuner_get_configuration(const struct radio_tuner *tuner,
-                         radio_hal_band_config_t *config)
+                                   radio_hal_band_config_t *config)
 {
     struct stub_radio_tuner *stub_tuner = (struct stub_radio_tuner *)tuner;
     int status = 0;
index 445f69e..534e6e9 100644 (file)
@@ -22,13 +22,12 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE := sensors.$(TARGET_DEVICE)
 
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
 
 LOCAL_CFLAGS := -DLOG_TAG=\"MultiHal\"
 
 LOCAL_SRC_FILES := \
     multihal.cpp \
-    SensorEventQueue.h \
     SensorEventQueue.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
index d1536f4..0edbc2d 100644 (file)
@@ -27,6 +27,8 @@
 #include <cutils/log.h>
 
 #include <vector>
+#include <string>
+#include <fstream>
 #include <map>
 #include <string>
 
@@ -38,8 +40,6 @@
 #include <stdlib.h>
 
 static const char* CONFIG_FILENAME = "/system/etc/sensors/hals.conf";
-static const char* LEGAL_SUBHAL_PATH_PREFIX = "/system/lib/hw/";
-static const char* LEGAL_SUBHAL_ALTERNATE_PATH_PREFIX = "/system/vendor/lib/";
 static const int MAX_CONF_LINE_LENGTH = 1024;
 
 static pthread_mutex_t init_modules_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -228,7 +228,7 @@ void sensors_poll_context_t::addSubHwDevice(struct hw_device_t* sub_hw_device) {
 // 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()) {
+    if (sub_index < 0 || sub_index >= (int) this->sub_hw_devices.size()) {
         return NULL;
     }
     return (sensors_poll_device_t*) this->sub_hw_devices[sub_index];
@@ -237,7 +237,7 @@ sensors_poll_device_t* sensors_poll_context_t::get_v0_device_by_handle(int globa
 // 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()) {
+    if (sub_index < 0 || sub_index >= (int) this->sub_hw_devices.size()) {
         return NULL;
     }
     return (sensors_poll_device_1_t*) this->sub_hw_devices[sub_index];
@@ -465,39 +465,19 @@ static bool starts_with(const char* s, const char* prefix) {
  * 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<char*> *so_paths) {
-    FILE *conf_file = fopen(CONFIG_FILENAME, "r");
-    if (conf_file == 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);
-    char *line = NULL;
-    size_t len = 0;
-    int line_count = 0;
-    while (getline(&line, &len, conf_file) != -1) {
-        // overwrite trailing eoln with null char
-        char* pch = strchr(line, '\n');
-        if (pch != NULL) {
-            *pch = '\0';
-        }
-        ALOGV("config file line #%d: '%s'", ++line_count, line);
-        char *real_path = realpath(line, NULL);
-        if (starts_with(real_path, LEGAL_SUBHAL_PATH_PREFIX) ||
-               starts_with(real_path, LEGAL_SUBHAL_ALTERNATE_PATH_PREFIX)) {
-            ALOGV("accepting valid path '%s'", real_path);
-            char* compact_line = new char[strlen(real_path) + 1];
-            strcpy(compact_line, real_path);
-            so_paths->push_back(compact_line);
-        } else {
-            ALOGW("rejecting path '%s' because it does not start with '%s' or '%s'",
-                    real_path, LEGAL_SUBHAL_PATH_PREFIX, LEGAL_SUBHAL_ALTERNATE_PATH_PREFIX);
-        }
-        free(real_path);
+    while (std::getline(conf_file, line)) {
+        ALOGV("config file line: '%s'", line.c_str());
+        so_paths->push_back(line);
     }
-    free(line);
-    fclose(conf_file);
-    ALOGV("hals.conf contained %d lines", line_count);
 }
 
 /*
@@ -510,15 +490,15 @@ static void lazy_init_modules() {
         pthread_mutex_unlock(&init_modules_mutex);
         return;
     }
-    std::vector<char*> *so_paths = new std::vector<char*>();
+    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<char*>::iterator it = so_paths->begin(); it != so_paths->end(); it++) {
-        char* path = *it;
+    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());
@@ -625,22 +605,22 @@ static int module__get_sensors_list(__unused struct sensors_module_t* module,
 }
 
 static struct hw_module_methods_t sensors_module_methods = {
-    open : open_sensors
+    .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},
+    .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
+    .get_sensors_list = module__get_sensors_list
 };
 
 static int open_sensors(const struct hw_module_t* hw_module, const char* name,
index 325980c..bb58053 100644 (file)
@@ -22,6 +22,5 @@ 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)
index e7f9baf..20d97f2 100644 (file)
  * limitations under the License.
  */
 
+
+/* This HAL simulates triggers from the DSP.
+ * To send a trigger from the command line you can type:
+ *
+ * adb forward tcp:14035 tcp:14035
+ *
+ * telnet localhost 14035
+ *
+ * Commands include:
+ * ls : Lists all models that have been loaded.
+ * trig <uuid> : Sends a recognition event for the model at the given uuid
+ * update <uuid> : Sends a model update event for the model at the given uuid.
+ * close : Closes the network connection.
+ *
+ * To enable this file, you can make with command line parameter
+ * SOUND_TRIGGER_USE_STUB_MODULE=1
+ */
+
 #define LOG_TAG "sound_trigger_hw_default"
-/*#define LOG_NDEBUG 0*/
+#define LOG_NDEBUG 1
+#define PARSE_BUF_LEN 1024  // Length of the parsing buffer.S
+
+#define EVENT_RECOGNITION 1
+#define EVENT_SOUND_MODEL 2
+
+// The following commands work with the network port:
+#define COMMAND_LS "ls"
+#define COMMAND_RECOGNITION_TRIGGER "trig"  // Argument: model index.
+#define COMMAND_RECOGNITION_ABORT "abort"  // Argument: model index.
+#define COMMAND_RECOGNITION_FAILURE "fail"  // Argument: model index.
+#define COMMAND_UPDATE "update"  // Argument: model index.
+#define COMMAND_CLEAR "clear" // Removes all models from the list.
+#define COMMAND_CLOSE "close" // Close just closes the network port, keeps thread running.
+#define COMMAND_END "end" // Closes connection and stops the thread.
+
+#define ERROR_BAD_COMMAND "Bad command"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
 
 #include <errno.h>
 #include <pthread.h>
@@ -31,79 +76,526 @@ static const struct sound_trigger_properties hw_properties = {
         "Sound Trigger stub HAL", // description
         1, // version
         { 0xed7a7d60, 0xc65e, 0x11e3, 0x9be4, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
-        1, // max_sound_models
+        4, // 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
+        true, // concurrent_capture
         false, // trigger_in_event
         0 // power_consumption_mw
 };
 
-struct stub_sound_trigger_device {
-    struct sound_trigger_hw_device device;
+struct recognition_context {
+    // Sound Model information, added in method load_sound_model
     sound_model_handle_t model_handle;
+    sound_trigger_uuid_t model_uuid;
+    sound_trigger_sound_model_type_t model_type;
+    sound_model_callback_t model_callback;
+    void *model_cookie;
+
+    // Sound Model information, added in start_recognition
+    struct sound_trigger_recognition_config *config;
     recognition_callback_t recognition_callback;
     void *recognition_cookie;
-    sound_model_callback_t sound_model_callback;
-    void *sound_model_cookie;
-    pthread_t callback_thread;
+
+    bool model_started;
+
+    // Next recognition_context in the linked list
+    struct recognition_context *next;
+};
+
+char tmp_write_buffer[PARSE_BUF_LEN];
+
+struct stub_sound_trigger_device {
+    struct sound_trigger_hw_device device;
     pthread_mutex_t lock;
-    pthread_cond_t  cond;
+
+    // This thread opens a port that can be used to monitor and inject events
+    // into the stub HAL.
+    pthread_t control_thread;
+
+    // Recognition contexts are stored as a linked list
+    struct recognition_context *root_model_context;
+
+    int next_sound_model_id;
 };
 
+static bool check_uuid_equality(sound_trigger_uuid_t uuid1, sound_trigger_uuid_t uuid2) {
+    if (uuid1.timeLow != uuid2.timeLow ||
+        uuid1.timeMid != uuid2.timeMid ||
+        uuid1.timeHiAndVersion != uuid2.timeHiAndVersion ||
+        uuid1.clockSeq != uuid2.clockSeq) {
+        return false;
+    }
+    for (int i = 0; i < 6; i++) {
+        if(uuid1.node[i] != uuid2.node[i]) {
+            return false;
+        }
+    }
+    return true;
+}
 
-static void *callback_thread_loop(void *context)
-{
-    struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)context;
+bool str_to_uuid(char* uuid_str, sound_trigger_uuid_t* uuid) {
+    if (uuid_str == NULL) {
+        ALOGI("Invalid str_to_uuid input.");
+        return false;
+    }
+
+    int tmp[10];
+    if (sscanf(uuid_str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+               tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+        ALOGI("Invalid UUID, got: %s", uuid_str);
+        return false;
+    }
+    uuid->timeLow = (unsigned int)tmp[0];
+    uuid->timeMid = (unsigned short)tmp[1];
+    uuid->timeHiAndVersion = (unsigned short)tmp[2];
+    uuid->clockSeq = (unsigned short)tmp[3];
+    uuid->node[0] = (unsigned char)tmp[4];
+    uuid->node[1] = (unsigned char)tmp[5];
+    uuid->node[2] = (unsigned char)tmp[6];
+    uuid->node[3] = (unsigned char)tmp[7];
+    uuid->node[4] = (unsigned char)tmp[8];
+    uuid->node[5] = (unsigned char)tmp[9];
+    return true;
+}
+
+void write_bad_command_error(int conn_socket, char* command) {
+    int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "Bad command received: %s", command);
+    tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';  // Just to be sure.
+    tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
+    write(conn_socket, tmp_write_buffer, num);
+}
+
+void write_string(int conn_socket, char* str) {
+    int num = snprintf(tmp_write_buffer, PARSE_BUF_LEN, "%s", str);
+    tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
+    tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
+    write(conn_socket, tmp_write_buffer, num);
+}
+
+void write_vastr(int conn_socket, char* format, ...) {
+    va_list argptr;
+    va_start(argptr, format);
+    int num = vsnprintf(tmp_write_buffer, PARSE_BUF_LEN, format, argptr);
+    va_end(argptr);
+    tmp_write_buffer[PARSE_BUF_LEN - 1] = '\0';
+    tmp_write_buffer[PARSE_BUF_LEN - 2] = '\n';
+    write(conn_socket, tmp_write_buffer, num);
+}
+
+static void print_uuid(sound_trigger_uuid_t uuid) {
+    ALOGI("%s %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", __func__, uuid.timeLow, uuid.timeMid,
+          uuid.timeHiAndVersion, uuid.clockSeq, uuid.node[0], uuid.node[1], uuid.node[2],
+          uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
+static void write_uuid(int conn_socket, sound_trigger_uuid_t uuid) {
+    write_vastr(conn_socket, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", uuid.timeLow, uuid.timeMid,
+                uuid.timeHiAndVersion, uuid.clockSeq, uuid.node[0], uuid.node[1], uuid.node[2],
+                uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
+// Returns model at the given index, null otherwise (error, doesn't exist, etc).
+// Note that here index starts from zero.
+struct recognition_context* fetch_model_with_handle(
+        struct stub_sound_trigger_device* stdev, sound_model_handle_t* model_handle) {
     ALOGI("%s", __func__);
+    struct recognition_context *model_context = NULL;
+    struct recognition_context *last_model_context = stdev->root_model_context;
+    while(last_model_context) {
+        if (last_model_context->model_handle == *model_handle) {
+            model_context = last_model_context;
+            break;
+        }
+        last_model_context = last_model_context->next;
+    }
+    return model_context;
+}
 
-    prctl(PR_SET_NAME, (unsigned long)"sound trigger callback", 0, 0, 0);
+// Returns the first model that matches the sound model UUID.
+static sound_model_handle_t* get_model_handle_with_uuid(struct stub_sound_trigger_device* stdev,
+                                                        sound_trigger_uuid_t uuid) {
+    sound_model_handle_t* model_handle_str = NULL;
+    struct recognition_context *last_model_context = stdev->root_model_context;
+    while(last_model_context) {
+        if (check_uuid_equality(last_model_context->model_uuid, uuid)) {
+            model_handle_str = &last_model_context->model_handle;
+            break;
+        }
+        last_model_context = last_model_context->next;
+    }
+    return model_handle_str;
+}
 
-    pthread_mutex_lock(&stdev->lock);
-    if (stdev->recognition_callback == NULL) {
-        goto exit;
+/* Will reuse ids when overflow occurs */
+static sound_model_handle_t generate_sound_model_handle(const struct sound_trigger_hw_device *dev) {
+    struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
+    int new_id = stdev->next_sound_model_id;
+    ++stdev->next_sound_model_id;
+    if (stdev->next_sound_model_id == 0) {
+        stdev->next_sound_model_id = 1;
+    }
+    return (sound_model_handle_t) new_id;
+}
+
+bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev);
+static void unload_all_sound_models(struct stub_sound_trigger_device *stdev);
+
+static char *sound_trigger_keyphrase_event_alloc(sound_model_handle_t handle,
+                                                 struct sound_trigger_recognition_config *config,
+                                                 int recognition_status) {
+    char *data;
+    struct sound_trigger_phrase_recognition_event *event;
+    data = (char *)calloc(1, sizeof(struct sound_trigger_phrase_recognition_event));
+    if (!data)
+        return NULL;
+    event = (struct sound_trigger_phrase_recognition_event *)data;
+    event->common.status = recognition_status;
+    event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
+    event->common.model = handle;
+
+    if (config) {
+        unsigned int i;
+
+        event->num_phrases = config->num_phrases;
+        if (event->num_phrases > SOUND_TRIGGER_MAX_PHRASES)
+            event->num_phrases = SOUND_TRIGGER_MAX_PHRASES;
+        for (i=0; i < event->num_phrases; i++)
+            memcpy(&event->phrase_extras[i],
+                   &config->phrases[i],
+                   sizeof(struct sound_trigger_phrase_recognition_extra));
+    }
+
+    event->num_phrases = 1;
+    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;
+    // Signify that all the data is comming through streaming, not through the buffer.
+    event->common.capture_available = true;
+    event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
+    event->common.audio_config.sample_rate = 16000;
+    event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
+    event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
+    return data;
+}
+
+static char *sound_trigger_generic_event_alloc(sound_model_handle_t handle,
+                                               struct sound_trigger_recognition_config *config,
+                                               int recognition_status) {
+    char *data;
+    struct sound_trigger_generic_recognition_event *event;
+    data = (char *)calloc(1, sizeof(struct sound_trigger_generic_recognition_event));
+    if (!data)
+        return NULL;
+    event = (struct sound_trigger_generic_recognition_event *)data;
+    event->common.status = recognition_status;
+    event->common.type = SOUND_MODEL_TYPE_GENERIC;
+    event->common.model = handle;
+
+    // Signify that all the data is comming through streaming, not through the buffer.
+    event->common.capture_available = true;
+    event->common.audio_config = AUDIO_CONFIG_INITIALIZER;
+    event->common.audio_config.sample_rate = 16000;
+    event->common.audio_config.channel_mask = AUDIO_CHANNEL_IN_MONO;
+    event->common.audio_config.format = AUDIO_FORMAT_PCM_16_BIT;
+    return data;
+}
+
+void send_event_with_handle(sound_model_handle_t* model_handle_str,
+                            struct stub_sound_trigger_device* stdev, int event_type,
+                            int status) {
+    ALOGI("%s", __func__);
+    struct recognition_context *model_context = fetch_model_with_handle(stdev, model_handle_str);
+    if (model_context) {
+        if (event_type == EVENT_RECOGNITION) {
+            if (model_context->recognition_callback == NULL) {
+                ALOGI("%s No matching callback", __func__);
+                return;
+            }
+
+            if (model_context->model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
+                struct sound_trigger_phrase_recognition_event *event;
+                event = (struct sound_trigger_phrase_recognition_event *)
+                        sound_trigger_keyphrase_event_alloc(model_context->model_handle,
+                                                            model_context->config, status);
+                if (event) {
+                    model_context->recognition_callback(event, model_context->recognition_cookie);
+                    free(event);
+                }
+            } else if (model_context->model_type == SOUND_MODEL_TYPE_GENERIC) {
+                struct sound_trigger_generic_recognition_event *event;
+                event = (struct sound_trigger_generic_recognition_event *)
+                        sound_trigger_generic_event_alloc(model_context->model_handle,
+                                                          model_context->config, status);
+                if (event) {
+                    model_context->recognition_callback(event, model_context->recognition_cookie);
+                    free(event);
+                }
+            } else {
+                ALOGI("Unknown Sound Model Type, No Event to Send");
+            }
+        } else if (event_type == EVENT_SOUND_MODEL) {
+            char *data;
+            data = (char *)calloc(1, sizeof(struct sound_trigger_model_event));
+            if (!data) {
+                ALOGW("%s Could not allocate event", __func__);
+                return;
+            }
+
+            struct sound_trigger_model_event *event;
+            event = (struct sound_trigger_model_event *)data;
+            event->status = SOUND_MODEL_STATUS_UPDATED;
+            event->model = model_context->model_handle;
+            if (event) {
+                model_context->model_callback(&event, model_context->model_cookie);
+                free(event);
+            }
+        }
+    } else {
+        ALOGI("No model for this handle");
     }
-    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);
+}
+
+static void send_event(int conn_socket, struct stub_sound_trigger_device* stdev, int event_type,
+                       int status) {
+    char* model_uuid_str = strtok(NULL, " \r\n");
+    sound_trigger_uuid_t model_uuid;
+    if (str_to_uuid(model_uuid_str, &model_uuid)) {
+        sound_model_handle_t* model_handle_str = get_model_handle_with_uuid(stdev, model_uuid);
+        if (model_handle_str == NULL) {
+            ALOGI("%s Bad sound model handle.", __func__);
+            write_string(conn_socket, "Bad sound model handle.\n");
+            return;
+        }
+        send_event_with_handle(model_handle_str, stdev, event_type, status);
     } else {
-        ALOGI("%s abort recognition model %d", __func__, stdev->model_handle);
+        ALOGI("%s Not a valid UUID", __func__);
+        write_string(conn_socket, "Not a valid UUID.\n");
     }
-    stdev->recognition_callback = NULL;
+}
 
-exit:
-    pthread_mutex_unlock(&stdev->lock);
+static bool recognition_callback_exists(struct stub_sound_trigger_device *stdev) {
+    bool callback_found = false;
+    if (stdev->root_model_context) {
+        struct recognition_context *current_model_context = stdev->root_model_context;
+        while(current_model_context) {
+            if (current_model_context->recognition_callback != NULL) {
+                callback_found = true;
+                break;
+            }
+            current_model_context = current_model_context->next;
+        }
+    }
+    return callback_found;
+}
+
+static struct recognition_context * get_model_context(struct stub_sound_trigger_device *stdev,
+            sound_model_handle_t handle) {
+    struct recognition_context *model_context = NULL;
+    if (stdev->root_model_context) {
+        struct recognition_context *current_model_context = stdev->root_model_context;
+        while(current_model_context) {
+            if (current_model_context->model_handle == handle) {
+                model_context = current_model_context;
+                break;
+            }
+            current_model_context = current_model_context->next;
+        }
+    }
+    return model_context;
+}
+
+static void *control_thread_loop(void *context) {
+    struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)context;
+    struct sockaddr_in incoming_info;
+    struct sockaddr_in self_info;
+    int self_socket;
+    socklen_t sock_size = sizeof(struct sockaddr_in);
+    memset(&self_info, 0, sizeof(self_info));
+    self_info.sin_family = AF_INET;
+    self_info.sin_addr.s_addr = htonl(INADDR_ANY);
+    self_info.sin_port = htons(14035);
+
+    bool exit = false;
+    while(!exit) {
+        int received_count;
+        int requested_count = 2;
+        char buffer[requested_count];
+        ALOGE("Opening socket");
+        self_socket = socket(AF_INET, SOCK_STREAM, 0);
+        if (self_socket < 0) {
+            ALOGE("Error on socket creation: %s", strerror(errno));
+            exit = true;
+        } else {
+            ALOGI("Socket created");
+        }
+
+        int reuse = 1;
+        if (setsockopt(self_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) {
+            ALOGE("setsockopt(SO_REUSEADDR) failed");
+        }
+
+        int bind_result = bind(self_socket, (struct sockaddr *)&self_info, sizeof(struct sockaddr));
+        if (bind_result < 0) {
+            ALOGE("Error on bind");
+            exit = true;
+        }
+
+        int listen_result = listen(self_socket, 1);
+        if (listen_result < 0) {
+            ALOGE("Error on Listen");
+            exit = true;
+        }
+
+        while(!exit) {
+            int con_socket = accept(self_socket, (struct sockaddr *)&incoming_info, &sock_size);
+            if (!con_socket) {
+                ALOGE("Lost socket, cannot send trigger");
+                break;
+            }
+            ALOGI("Connection from %s", inet_ntoa(incoming_info.sin_addr));
+            if (!parse_socket_data(con_socket, stdev)) {
+                ALOGI("Done processing commands over network. Stopping thread.");
+                exit = true;
+            }
+            close(con_socket);
+        }
+        ALOGE("Closing socket");
+        close(self_socket);
+    }
 
     return NULL;
 }
 
+void list_models(int conn_socket, char* buffer,
+                 struct stub_sound_trigger_device* stdev) {
+    ALOGI("%s", __func__);
+    struct recognition_context *last_model_context = stdev->root_model_context;
+    unsigned int model_index = 0;
+    write_string(conn_socket, "-----------------------\n");
+    if (!last_model_context) {
+        ALOGI("ZERO Models exist.");
+        write_string(conn_socket, "Zero models exist.\n");
+    }
+    while (last_model_context) {
+        write_vastr(conn_socket, "Model Index: %d\n", model_index);
+        ALOGI("Model Index: %d", model_index);
+        write_vastr(conn_socket, "Model handle: %d\n", last_model_context->model_handle);
+        ALOGI("Model handle: %d", last_model_context->model_handle);
+        write_uuid(conn_socket, last_model_context->model_uuid);
+        print_uuid(last_model_context->model_uuid);
+        sound_trigger_sound_model_type_t model_type = last_model_context->model_type;
+
+        if (model_type == SOUND_MODEL_TYPE_KEYPHRASE) {
+            write_string(conn_socket, "Keyphrase sound Model.\n");
+            ALOGI("Keyphrase sound Model.");
+        } else if (model_type == SOUND_MODEL_TYPE_GENERIC) {
+            write_string(conn_socket, "Generic sound Model.\n");
+            ALOGI("Generic sound Model.");
+        } else {
+            write_vastr(conn_socket, "Unknown sound model type: %d\n", model_type);
+            ALOGI("Unknown sound model type: %d", model_type);
+        }
+        if (last_model_context->model_started) {
+            write_string(conn_socket, "Model started.\n");
+            ALOGI("Model started.\n");
+        } else {
+            write_string(conn_socket, "Model stopped.\n");
+            ALOGI("Model stopped.\n");
+        }
+        write_string(conn_socket, "-----------------------\n\n");
+        ALOGI("----\n\n");
+        last_model_context = last_model_context->next;
+        model_index++;
+    }
+}
+
+// Gets the next word from buffer, replaces '\n' or ' ' with '\0'.
+char* get_command(char* buffer) {
+    char* command = strtok(buffer, " ");
+    char* newline = strchr(command, '\n');
+    if (newline != NULL) {
+        *newline = '\0';
+    }
+    return command;
+}
+
+// Parses data coming in from the local socket, executes commands. Returns when
+// done. Return code indicates whether the server should continue listening or
+// abort (true if continue listening).
+bool parse_socket_data(int conn_socket, struct stub_sound_trigger_device* stdev) {
+    ALOGI("Calling parse_socket_data");
+    bool input_done = false;
+    char buffer[PARSE_BUF_LEN];
+    FILE* input_fp = fdopen(conn_socket, "r");
+    bool continue_listening = true;
+
+    // Note: Since we acquire a lock inside this loop, do not use break or other
+    // exit methods without releasing this lock.
+    write_string(conn_socket, "\n>>> ");
+    while(!input_done) {
+        if (fgets(buffer, PARSE_BUF_LEN, input_fp) != NULL) {
+            pthread_mutex_lock(&stdev->lock);
+            char* command = strtok(buffer, " \r\n");
+            if (command == NULL) {
+                write_bad_command_error(conn_socket, command);
+            } else if (strncmp(command, COMMAND_LS, 2) == 0) {
+                list_models(conn_socket, buffer, stdev);
+            } else if (strcmp(command, COMMAND_RECOGNITION_TRIGGER) == 0) {
+                send_event(conn_socket, stdev, EVENT_RECOGNITION, RECOGNITION_STATUS_SUCCESS);
+            } else if (strcmp(command, COMMAND_RECOGNITION_ABORT) == 0) {
+                send_event(conn_socket, stdev, EVENT_RECOGNITION, RECOGNITION_STATUS_ABORT);
+            } else if (strcmp(command, COMMAND_RECOGNITION_FAILURE) == 0) {
+                send_event(conn_socket, stdev, EVENT_RECOGNITION, RECOGNITION_STATUS_FAILURE);
+            } else if (strcmp(command, COMMAND_UPDATE) == 0) {
+                send_event(conn_socket, stdev, EVENT_SOUND_MODEL, SOUND_MODEL_STATUS_UPDATED);
+            } else if (strncmp(command, COMMAND_CLEAR, 5) == 0) {
+                unload_all_sound_models(stdev);
+            } else if (strncmp(command, COMMAND_CLOSE, 5) == 0) {
+                ALOGI("Closing this connection.");
+                write_string(conn_socket, "Closing this connection.");
+                input_done = true;
+            } else if (strncmp(command, COMMAND_END, 3) == 0) {
+                ALOGI("End command received.");
+                write_string(conn_socket, "End command received. Stopping connection.");
+                continue_listening = false;
+                input_done = true;
+            } else {
+                write_vastr(conn_socket, "\nBad command %s.\n\n", command);
+            }
+            pthread_mutex_unlock(&stdev->lock);
+        } else {
+            ALOGI("parse_socket_data done (got null)");
+            input_done = true;  // break.
+        }
+        write_string(conn_socket, "\n>>> ");
+    }
+    return continue_listening;
+}
+
+static void send_loop_kill_signal() {
+    ALOGI("Sending loop thread kill signal");
+    int self_socket = socket(AF_INET, SOCK_STREAM, 0);
+    struct sockaddr_in remote_info;
+    memset(&remote_info, 0, sizeof(remote_info));
+    remote_info.sin_family = AF_INET;
+    remote_info.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    remote_info.sin_port = htons(14035);
+    if (connect(self_socket, (struct sockaddr *)&remote_info, sizeof(struct sockaddr)) == 0) {
+        send(self_socket, COMMAND_END, 3, 0);
+    } else {
+        ALOGI("Could not connect");
+    }
+    close(self_socket);
+    ALOGI("Sent loop thread kill signal");
+}
+
 static int stdev_get_properties(const struct sound_trigger_hw_device *dev,
-                                struct sound_trigger_properties *properties)
-{
+                                struct sound_trigger_properties *properties) {
     struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
 
     ALOGI("%s", __func__);
@@ -117,140 +609,238 @@ 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)
-{
+                                  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);
+    int status = 0;
     pthread_mutex_lock(&stdev->lock);
+
     if (handle == NULL || sound_model == NULL) {
-        status = -EINVAL;
-        goto exit;
+        pthread_mutex_unlock(&stdev->lock);
+        return -EINVAL;
     }
     if (sound_model->data_size == 0 ||
             sound_model->data_offset < sizeof(struct sound_trigger_sound_model)) {
-        status = -EINVAL;
-        goto exit;
+        pthread_mutex_unlock(&stdev->lock);
+        return -EINVAL;
     }
 
-    if (stdev->model_handle == 1) {
-        status = -ENOSYS;
-        goto exit;
+    struct recognition_context *model_context;
+    model_context = malloc(sizeof(struct recognition_context));
+    if(!model_context) {
+        ALOGW("Could not allocate recognition_context");
+        pthread_mutex_unlock(&stdev->lock);
+        return -ENOSYS;
     }
+
+    // Add the new model context to the recognition_context linked list
+    if (stdev->root_model_context) {
+        // Find the tail
+        struct recognition_context *current_model_context = stdev->root_model_context;
+        unsigned int model_count = 0;
+        while(current_model_context->next) {
+            current_model_context = current_model_context->next;
+            model_count++;
+            if (model_count >= hw_properties.max_sound_models) {
+                ALOGW("Can't load model: reached max sound model limit");
+                free(model_context);
+                pthread_mutex_unlock(&stdev->lock);
+                return -ENOSYS;
+            }
+        }
+        current_model_context->next = model_context;
+    } else {
+        stdev->root_model_context = model_context;
+    }
+
+    model_context->model_handle = generate_sound_model_handle(dev);
+    *handle = model_context->model_handle;
+    model_context->model_type = sound_model->type;
+
     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;
+    model_context->model_uuid = sound_model->uuid;
+    model_context->model_callback = callback;
+    model_context->model_cookie = cookie;
+    model_context->config = NULL;
+    model_context->recognition_callback = NULL;
+    model_context->recognition_cookie = NULL;
+    model_context->next = NULL;
+    model_context->model_started = false;
+    ALOGI("Sound model loaded: Handle %d ", *handle);
 
-exit:
     pthread_mutex_unlock(&stdev->lock);
     return status;
 }
 
+static void unload_all_sound_models(struct stub_sound_trigger_device *stdev) {
+    ALOGI("%s", __func__);
+    struct recognition_context *model_context = stdev->root_model_context;
+    stdev->root_model_context = NULL;
+    pthread_mutex_lock(&stdev->lock);
+    while (model_context) {
+        ALOGI("Deleting model with handle: %d", model_context->model_handle);
+        struct recognition_context *temp = model_context;
+        model_context = model_context->next;
+        free(temp->config);
+        free(temp);
+    }
+    pthread_mutex_unlock(&stdev->lock);
+}
+
 static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev,
-                                    sound_model_handle_t handle)
-{
+                                    sound_model_handle_t handle) {
+    // If recognizing, stop_recognition must be called for a sound model before unload_sound_model
+    ALOGI("%s", __func__);
     struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
     int status = 0;
-
-    ALOGI("%s handle %d", __func__, handle);
+    ALOGI("unload_sound_model:%d", handle);
     pthread_mutex_lock(&stdev->lock);
-    if (handle != 1) {
-        status = -EINVAL;
-        goto exit;
-    }
-    if (stdev->model_handle == 0) {
-        status = -ENOSYS;
-        goto exit;
+
+    struct recognition_context *model_context = NULL;
+    struct recognition_context *previous_model_context = NULL;
+    if (stdev->root_model_context) {
+        struct recognition_context *current_model_context = stdev->root_model_context;
+        while(current_model_context) {
+            if (current_model_context->model_handle == handle) {
+                model_context = current_model_context;
+                break;
+            }
+            previous_model_context = current_model_context;
+            current_model_context = current_model_context->next;
+        }
     }
-    stdev->model_handle = 0;
-    if (stdev->recognition_callback != NULL) {
-        stdev->recognition_callback = NULL;
-        pthread_cond_signal(&stdev->cond);
+    if (!model_context) {
+        ALOGW("Can't find sound model handle %d in registered list", handle);
         pthread_mutex_unlock(&stdev->lock);
-        pthread_join(stdev->callback_thread, (void **) NULL);
-        pthread_mutex_lock(&stdev->lock);
+        return -ENOSYS;
     }
-
-exit:
+    if (previous_model_context) {
+        previous_model_context->next = model_context->next;
+    } else {
+        stdev->root_model_context = model_context->next;
+    }
+    free(model_context->config);
+    free(model_context);
     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,
+                                   sound_model_handle_t handle,
                                    const struct sound_trigger_recognition_config *config,
                                    recognition_callback_t callback,
-                                   void *cookie)
-{
+                                   void *cookie) {
+    ALOGI("%s", __func__);
     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 other models running with callbacks, don't start trigger thread */
+    bool other_callbacks_found = recognition_callback_exists(stdev);
+
+    struct recognition_context *model_context = get_model_context(stdev, handle);
+    if (!model_context) {
+        ALOGW("Can't find sound model handle %d in registered list", handle);
+        pthread_mutex_unlock(&stdev->lock);
+        return -ENOSYS;
     }
-    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]);
+
+    free(model_context->config);
+    model_context->config = NULL;
+    if (config) {
+        model_context->config = malloc(sizeof(*config));
+        if (!model_context->config) {
+            pthread_mutex_unlock(&stdev->lock);
+            return -ENOMEM;
+        }
+        memcpy(model_context->config, config, sizeof(*config));
     }
+    model_context->recognition_callback = callback;
+    model_context->recognition_cookie = cookie;
+    model_context->model_started = true;
 
-    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;
+    ALOGI("%s done for handle %d", __func__, handle);
+    return 0;
 }
 
 static int stdev_stop_recognition(const struct sound_trigger_hw_device *dev,
-                                 sound_model_handle_t sound_model_handle)
-{
+            sound_model_handle_t 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);
+    ALOGI("%s", __func__);
     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;
+
+    struct recognition_context *model_context = get_model_context(stdev, handle);
+    if (!model_context) {
+        ALOGW("Can't find sound model handle %d in registered list", handle);
+        pthread_mutex_unlock(&stdev->lock);
+        return -ENOSYS;
     }
-    stdev->recognition_callback = NULL;
-    pthread_cond_signal(&stdev->cond);
+
+    free(model_context->config);
+    model_context->config = NULL;
+    model_context->recognition_callback = NULL;
+    model_context->recognition_cookie = NULL;
+    model_context->model_started = false;
+
     pthread_mutex_unlock(&stdev->lock);
-    pthread_join(stdev->callback_thread, (void **) NULL);
+    ALOGI("%s done for handle %d", __func__, handle);
+
+    return 0;
+}
+
+static int stdev_stop_all_recognitions(const struct sound_trigger_hw_device *dev) {
+    struct stub_sound_trigger_device *stdev = (struct stub_sound_trigger_device *)dev;
+    ALOGI("%s", __func__);
     pthread_mutex_lock(&stdev->lock);
 
-exit:
+    struct recognition_context *model_context = stdev->root_model_context;
+    while (model_context) {
+        free(model_context->config);
+        model_context->config = NULL;
+        model_context->recognition_callback = NULL;
+        model_context->recognition_cookie = NULL;
+        model_context->model_started = false;
+        ALOGI("%s stopped handle %d", __func__, model_context->model_handle);
+
+        model_context = model_context->next;
+    }
+
     pthread_mutex_unlock(&stdev->lock);
-    return status;
+
+    return 0;
 }
 
+__attribute__ ((visibility ("default")))
+int sound_trigger_open_for_streaming() {
+    int ret = 0;
+    return ret;
+}
+
+__attribute__ ((visibility ("default")))
+size_t sound_trigger_read_samples(int audio_handle, void *buffer, size_t  buffer_len) {
+    size_t ret = 0;
+    return ret;
+}
 
-static int stdev_close(hw_device_t *device)
-{
+__attribute__ ((visibility ("default")))
+int sound_trigger_close_for_streaming(int audio_handle __unused) {
+    return 0;
+}
+
+static int stdev_close(hw_device_t *device) {
+    // TODO: Implement the ability to stop the control thread. Since this is a
+    // test hal, we have skipped implementing this for now. A possible method
+    // would register a signal handler for the control thread so that any
+    // blocking socket calls can be interrupted. We would send that signal here
+    // to interrupt and quit the thread.
     free(device);
     return 0;
 }
 
 static int stdev_open(const hw_module_t* module, const char* name,
-                     hw_device_t** device)
-{
+                     hw_device_t** device) {
     struct stub_sound_trigger_device *stdev;
     int ret;
 
@@ -261,8 +851,11 @@ static int stdev_open(const hw_module_t* module, const char* name,
     if (!stdev)
         return -ENOMEM;
 
+    stdev->next_sound_model_id = 1;
+    stdev->root_model_context = NULL;
+
     stdev->device.common.tag = HARDWARE_DEVICE_TAG;
-    stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_0;
+    stdev->device.common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_1;
     stdev->device.common.module = (struct hw_module_t *) module;
     stdev->device.common.close = stdev_close;
     stdev->device.get_properties = stdev_get_properties;
@@ -270,12 +863,16 @@ static int stdev_open(const hw_module_t* module, const char* name,
     stdev->device.unload_sound_model = stdev_unload_sound_model;
     stdev->device.start_recognition = stdev_start_recognition;
     stdev->device.stop_recognition = stdev_stop_recognition;
+    stdev->device.stop_all_recognitions = stdev_stop_all_recognitions;
 
     pthread_mutex_init(&stdev->lock, (const pthread_mutexattr_t *) NULL);
-    pthread_cond_init(&stdev->cond, (const pthread_condattr_t *) NULL);
 
     *device = &stdev->device.common;
 
+    pthread_create(&stdev->control_thread, (const pthread_attr_t *) NULL,
+                control_thread_loop, stdev);
+    ALOGI("Starting control thread for the stub hal.");
+
     return 0;
 }
 
@@ -294,3 +891,4 @@ struct sound_trigger_module HAL_MODULE_INFO_SYM = {
         .methods = &hal_module_methods,
     },
 };
+
diff --git a/modules/thermal/Android.mk b/modules/thermal/Android.mk
new file mode 100644 (file)
index 0000000..80ad78a
--- /dev/null
@@ -0,0 +1,26 @@
+# 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 := thermal.default
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := thermal.c
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Wno-unused-parameter
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/thermal/thermal.c b/modules/thermal/thermal.c
new file mode 100644 (file)
index 0000000..6ba5845
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define LOG_TAG "ThermalHAL"
+#include <utils/Log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/thermal.h>
+
+#define CPU_LABEL               "CPU"
+#define MAX_LENGTH              50
+
+#define CPU_USAGE_FILE          "/proc/stat"
+#define TEMPERATURE_DIR         "/sys/class/thermal"
+#define THERMAL_DIR             "thermal_zone"
+#define CPU_ONLINE_FILE_FORMAT  "/sys/devices/system/cpu/cpu%d/online"
+#define UNKNOWN_LABEL           "UNKNOWN"
+
+static ssize_t get_temperatures(thermal_module_t *module, temperature_t *list, size_t size) {
+    char file_name[MAX_LENGTH];
+    FILE *file;
+    float temp;
+    size_t idx = 0;
+    DIR *dir;
+    struct dirent *de;
+
+    /** Read all available temperatures from
+     * /sys/class/thermal/thermal_zone[0-9]+/temp files.
+     * Don't guarantee that all temperatures are in Celsius. */
+    dir = opendir(TEMPERATURE_DIR);
+    if (dir == 0) {
+        ALOGE("%s: failed to open directory %s: %s", __func__, TEMPERATURE_DIR, strerror(-errno));
+        return -errno;
+    }
+
+    while ((de = readdir(dir))) {
+        if (!strncmp(de->d_name, THERMAL_DIR, strlen(THERMAL_DIR))) {
+            snprintf(file_name, MAX_LENGTH, "%s/%s/temp", TEMPERATURE_DIR, de->d_name);
+            file = fopen(file_name, "r");
+            if (file == NULL) {
+                continue;
+            }
+            if (1 != fscanf(file, "%f", &temp)) {
+                fclose(file);
+                continue;
+            }
+
+            if (list != NULL && idx < size) {
+                list[idx] = (temperature_t) {
+                    .name = UNKNOWN_LABEL,
+                    .type = DEVICE_TEMPERATURE_UNKNOWN,
+                    .current_value = temp,
+                    .throttling_threshold = UNKNOWN_TEMPERATURE,
+                    .shutdown_threshold = UNKNOWN_TEMPERATURE,
+                    .vr_throttling_threshold = UNKNOWN_TEMPERATURE,
+                };
+            }
+            fclose(file);
+            idx++;
+        }
+    }
+    closedir(dir);
+    return idx;
+}
+
+static ssize_t get_cpu_usages(thermal_module_t *module, cpu_usage_t *list) {
+    int vals, cpu_num, online;
+    ssize_t read;
+    uint64_t user, nice, system, idle, active, total;
+    char *line = NULL;
+    size_t len = 0;
+    size_t size = 0;
+    char file_name[MAX_LENGTH];
+    FILE *cpu_file;
+    FILE *file = fopen(CPU_USAGE_FILE, "r");
+
+    if (file == NULL) {
+        ALOGE("%s: failed to open: %s", __func__, strerror(errno));
+        return -errno;
+    }
+
+    while ((read = getline(&line, &len, file)) != -1) {
+        // Skip non "cpu[0-9]" lines.
+        if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 || !isdigit(line[3])) {
+            free(line);
+            line = NULL;
+            len = 0;
+            continue;
+        }
+        vals = sscanf(line, "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, &cpu_num, &user,
+                &nice, &system, &idle);
+
+        free(line);
+        line = NULL;
+        len = 0;
+
+        if (vals != 5) {
+            ALOGE("%s: failed to read CPU information from file: %s", __func__, strerror(errno));
+            fclose(file);
+            return errno ? -errno : -EIO;
+        }
+
+        active = user + nice + system;
+        total = active + idle;
+
+        // Read online CPU information.
+        snprintf(file_name, MAX_LENGTH, CPU_ONLINE_FILE_FORMAT, cpu_num);
+        cpu_file = fopen(file_name, "r");
+        online = 0;
+        if (cpu_file == NULL) {
+            ALOGE("%s: failed to open file: %s (%s)", __func__, file_name, strerror(errno));
+            // /sys/devices/system/cpu/cpu0/online is missing on some systems, because cpu0 can't
+            // be offline.
+            online = cpu_num == 0;
+        } else if (1 != fscanf(cpu_file, "%d", &online)) {
+            ALOGE("%s: failed to read CPU online information from file: %s (%s)", __func__,
+                    file_name, strerror(errno));
+            fclose(file);
+            fclose(cpu_file);
+            return errno ? -errno : -EIO;
+        }
+        fclose(cpu_file);
+
+        if (list != NULL) {
+            list[size] = (cpu_usage_t) {
+                .name = CPU_LABEL,
+                .active = active,
+                .total = total,
+                .is_online = online
+            };
+        }
+
+        size++;
+    }
+
+    fclose(file);
+    return size;
+}
+
+static ssize_t get_cooling_devices(thermal_module_t *module, cooling_device_t *list, size_t size) {
+    return 0;
+}
+
+static struct hw_module_methods_t thermal_module_methods = {
+    .open = NULL,
+};
+
+thermal_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag = HARDWARE_MODULE_TAG,
+        .module_api_version = THERMAL_HARDWARE_MODULE_API_VERSION_0_1,
+        .hal_api_version = HARDWARE_HAL_API_VERSION,
+        .id = THERMAL_HARDWARE_MODULE_ID,
+        .name = "Default Thermal HAL",
+        .author = "The Android Open Source Project",
+        .methods = &thermal_module_methods,
+    },
+
+    .getTemperatures = get_temperatures,
+    .getCpuUsages = get_cpu_usages,
+    .getCoolingDevices = get_cooling_devices,
+};
index 38fea86..d899d6b 100644 (file)
@@ -55,11 +55,6 @@ static const unsigned k_force_channels = 0;
 
 #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;
 
@@ -449,8 +444,6 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,
     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;
 }
 
@@ -560,6 +553,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
     } 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
@@ -569,17 +563,17 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
             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);
+        proposed_channel_count = audio_channel_count_from_out_mask(config->channel_mask);
     }
+    out->hal_channel_count = proposed_channel_count;
+
     /* 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_config.channels = out->hal_channel_count;
     proxy_prepare(&out->proxy, out->profile, &proxy_config);
 
     /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */
diff --git a/modules/vehicle/Android.mk b/modules/vehicle/Android.mk
new file mode 100644 (file)
index 0000000..a666bc6
--- /dev/null
@@ -0,0 +1,28 @@
+# 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 := vehicle.default
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_C_INCLUDES := hardware/libhardware
+LOCAL_SRC_FILES := vehicle.c timeUtil.cpp
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/modules/vehicle/timeUtil.cpp b/modules/vehicle/timeUtil.cpp
new file mode 100644 (file)
index 0000000..fb27dad
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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 <stdint.h>
+#include <utils/SystemClock.h>
+
+extern "C" {
+    int64_t elapsedRealtimeNano() {
+        return android::elapsedRealtimeNano();
+    }
+}
diff --git a/modules/vehicle/vehicle.c b/modules/vehicle/vehicle.c
new file mode 100644 (file)
index 0000000..a26f27c
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ * 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 "vehicle_hw_default"
+#define LOG_NDEBUG 1
+#define RADIO_PRESET_NUM 6
+
+#define UNUSED __attribute__((__unused__))
+
+#include <errno.h>
+#include <inttypes.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <cutils/log.h>
+#include <system/radio.h>
+#include <hardware/hardware.h>
+#include <hardware/vehicle.h>
+
+extern int64_t elapsedRealtimeNano();
+
+static char VEHICLE_MAKE[] = "android_car";
+
+typedef struct vehicle_device_impl {
+    vehicle_hw_device_t vehicle_device;
+    uint32_t initialized_;
+    vehicle_event_callback_fn event_fn_;
+    vehicle_error_callback_fn error_fn_;
+} vehicle_device_impl_t ;
+
+static pthread_mutex_t lock_;
+
+typedef struct subscription {
+    // Each subscription has it's own thread.
+    pthread_t thread_id;
+    int32_t prop;
+    float sample_rate;
+    pthread_mutex_t lock;
+    // This field should be protected by the above mutex.
+    // TODO change this to something better as flag alone takes long time to finish.
+    uint32_t stop_thread;
+    vehicle_device_impl_t* impl;
+    pthread_t thread;
+    pthread_cond_t cond;
+    char name[100];
+} subscription_t;
+
+static vehicle_prop_config_t CONFIGS[] = {
+    {
+        .prop = VEHICLE_PROPERTY_INFO_MAKE,
+        .access = VEHICLE_PROP_ACCESS_READ,
+        .change_mode = VEHICLE_PROP_CHANGE_MODE_STATIC,
+        .value_type = VEHICLE_VALUE_TYPE_STRING,
+        .min_sample_rate = 0,
+        .max_sample_rate = 0,
+        .hal_data = NULL,
+    },
+    {
+        .prop = VEHICLE_PROPERTY_GEAR_SELECTION,
+        .access = VEHICLE_PROP_ACCESS_READ,
+        .change_mode = VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
+        .value_type = VEHICLE_VALUE_TYPE_INT32,
+        .min_sample_rate = 0,
+        .max_sample_rate = 0,
+        .hal_data = NULL,
+    },
+    {
+        .prop = VEHICLE_PROPERTY_DRIVING_STATUS,
+        .access = VEHICLE_PROP_ACCESS_READ,
+        .change_mode = VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
+        .value_type = VEHICLE_VALUE_TYPE_INT32,
+        .min_sample_rate = 0,
+        .max_sample_rate = 0,
+        .hal_data = NULL,
+    },
+    {
+        .prop = VEHICLE_PROPERTY_PARKING_BRAKE_ON,
+        .access = VEHICLE_PROP_ACCESS_READ,
+        .change_mode = VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
+        .value_type = VEHICLE_VALUE_TYPE_BOOLEAN,
+        .min_sample_rate = 0,
+        .max_sample_rate = 0,
+        .hal_data = NULL,
+    },
+    {
+        .prop = VEHICLE_PROPERTY_PERF_VEHICLE_SPEED,
+        .access = VEHICLE_PROP_ACCESS_READ,
+        .change_mode = VEHICLE_PROP_CHANGE_MODE_CONTINUOUS,
+        .value_type = VEHICLE_VALUE_TYPE_FLOAT,
+        .min_sample_rate = 0.1,
+        .max_sample_rate = 10.0,
+        .hal_data = NULL,
+    },
+    {
+        .prop = VEHICLE_PROPERTY_RADIO_PRESET,
+        .access = VEHICLE_PROP_ACCESS_READ_WRITE,
+        .change_mode = VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
+        .value_type = VEHICLE_VALUE_TYPE_INT32_VEC4,
+        .vehicle_radio_num_presets = RADIO_PRESET_NUM,
+        .min_sample_rate = 0,
+        .max_sample_rate = 0,
+        .hal_data = NULL,
+    },
+};
+
+vehicle_prop_config_t* find_config(int prop) {
+    unsigned int i;
+    for (i = 0; i < sizeof(CONFIGS) / sizeof(vehicle_prop_config_t); i++) {
+        if (CONFIGS[i].prop == prop) {
+            return &CONFIGS[i];
+        }
+    }
+    return NULL;
+}
+
+static int alloc_vehicle_str_from_cstr(const char* string, vehicle_str_t* vehicle_str) {
+    int len = strlen(string);
+    vehicle_str->data = (uint8_t*) malloc(len);
+    if (vehicle_str->data == NULL) {
+        return -ENOMEM;
+    }
+    memcpy(vehicle_str->data, string, len);
+    vehicle_str->len = len;
+    return 0;
+}
+
+static vehicle_prop_config_t const * vdev_list_properties(vehicle_hw_device_t* device UNUSED,
+        int* num_properties) {
+    ALOGD("vdev_list_properties.");
+
+    *num_properties = sizeof(CONFIGS) / sizeof(vehicle_prop_config_t);
+    return CONFIGS;
+}
+
+static int vdev_init(vehicle_hw_device_t* device,
+                     vehicle_event_callback_fn event_callback_fn,
+                     vehicle_error_callback_fn error_callback_fn) {
+    ALOGD("vdev_init.");
+    vehicle_device_impl_t* impl = (vehicle_device_impl_t*)device;
+    pthread_mutex_lock(&lock_);
+    if (impl->initialized_) {
+        ALOGE("vdev_init: Callback and Error functions are already existing.");
+        pthread_mutex_unlock(&lock_);
+        return -EEXIST;
+    }
+
+    impl->initialized_ = 1;
+    impl->event_fn_ = event_callback_fn;
+    impl->error_fn_ = error_callback_fn;
+    pthread_mutex_unlock(&lock_);
+    return 0;
+}
+
+static int vdev_release(vehicle_hw_device_t* device) {
+    vehicle_device_impl_t* impl = (vehicle_device_impl_t*)device;
+    pthread_mutex_lock(&lock_);
+    if (!impl->initialized_) {
+        ALOGD("vdev_release: Already released before, returning early.");
+    } else {
+        // unsubscribe_all()
+        impl->initialized_ = 0;
+    }
+    pthread_mutex_unlock(&lock_);
+    return 0;
+}
+
+static int vdev_get(vehicle_hw_device_t* device UNUSED, vehicle_prop_value_t* data) {
+    ALOGD("vdev_get.");
+    //TODO all data supporting read should support get
+    if (!data) {
+        ALOGE("vdev_get: Data cannot be null.");
+        return -EINVAL;
+    }
+    vehicle_prop_config_t* config = find_config(data->prop);
+    if (config == NULL) {
+        ALOGE("vdev_get: cannot find config 0x%x", data->prop);
+        return -EINVAL;
+    }
+    data->value_type = config->value_type;
+    // for STATIC type, time can be just 0 instead
+    data->timestamp = elapsedRealtimeNano();
+    int r;
+    switch (data->prop) {
+        case VEHICLE_PROPERTY_INFO_MAKE:
+            r = alloc_vehicle_str_from_cstr(VEHICLE_MAKE, &(data->value.str_value));
+            if (r != 0) {
+                ALOGE("vdev_get: alloc failed");
+                return r;
+            }
+            break;
+
+        case VEHICLE_PROPERTY_RADIO_PRESET: {
+              int radio_preset = data->value.int32_array[0];
+              if (radio_preset < VEHICLE_RADIO_PRESET_MIN_VALUE ||
+                  radio_preset >= RADIO_PRESET_NUM) {
+                  ALOGE("%s Invalid radio preset: %d\n", __func__, radio_preset);
+                  return -1;
+              }
+              ALOGD("%s Radio Preset number: %d", __func__, radio_preset);
+              int32_t selector = radio_preset % 2 == 0;
+              // Populate the channel and subchannel to be some variation of the
+              // preset number for mocking.
+
+              // Restore the preset number.
+              data->value.int32_array[0] = radio_preset;
+              // Channel type values taken from
+              // system/core/include/system/radio.h
+              data->value.int32_array[1] = selector ? RADIO_BAND_FM : RADIO_BAND_AM;
+              // For FM set a value in Mhz and for AM set a value in Khz range
+              // (channel).
+              data->value.int32_array[2] = selector ? 99000000 : 100000;
+              // For FM we have a sub-channel and we care about it, for AM pass
+              // a dummy value.
+              data->value.int32_array[3] = selector ? radio_preset : -1;
+              break;
+        }
+
+        default:
+            // actual implementation will be much complex than this. It should track proper last
+            // state. Here just fill with zero.
+            memset(&(data->value), 0, sizeof(data->value));
+            break;
+    }
+    ALOGI("vdev_get, type 0x%x, time %" PRId64 ", value_type %d", data->prop, data->timestamp,
+            data->value_type);
+    return 0;
+}
+
+static void vdev_release_memory_from_get(struct vehicle_hw_device* device UNUSED,
+        vehicle_prop_value_t *data) {
+    switch (data->value_type) {
+        case VEHICLE_VALUE_TYPE_STRING:
+        case VEHICLE_VALUE_TYPE_BYTES:
+            free(data->value.str_value.data);
+            data->value.str_value.data = NULL;
+            break;
+        default:
+            ALOGW("release_memory_from_get for property 0x%x which is not string or bytes type 0x%x"
+                    , data->prop, data->value_type);
+            break;
+    }
+}
+
+static int vdev_set(vehicle_hw_device_t* device UNUSED, const vehicle_prop_value_t* data) {
+    ALOGD("vdev_set.");
+    // Just print what data will be setting here.
+    ALOGD("Setting property %d with value type %d\n", data->prop, data->value_type);
+    vehicle_prop_config_t* config = find_config(data->prop);
+    if (config == NULL) {
+        ALOGE("vdev_set: cannot find config 0x%x", data->prop);
+        return -EINVAL;
+    }
+    if (config->value_type != data->value_type) {
+        ALOGE("vdev_set: type mismatch, passed 0x%x expecting 0x%x", data->value_type,
+                config->value_type);
+        return -EINVAL;
+    }
+    switch (data->value_type) {
+        case VEHICLE_VALUE_TYPE_FLOAT:
+            ALOGD("Value type: FLOAT\nValue: %f\n", data->value.float_value);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32:
+            ALOGD("Value type: INT32\nValue: %d\n", data->value.int32_value);
+            break;
+        case VEHICLE_VALUE_TYPE_INT64:
+            ALOGD("Value type: INT64\nValue: %lld\n", data->value.int64_value);
+            break;
+        case VEHICLE_VALUE_TYPE_BOOLEAN:
+            ALOGD("Value type: BOOLEAN\nValue: %d\n", data->value.boolean_value);
+            break;
+        case VEHICLE_VALUE_TYPE_STRING:
+            ALOGD("Value type: STRING\n Size: %d\n", data->value.str_value.len);
+            // NOTE: We only handle ASCII strings here.
+            // Print the UTF-8 string.
+            char *ascii_out = (char *) malloc ((data->value.str_value.len + 1) * sizeof (char));
+            memcpy(ascii_out, data->value.str_value.data, data->value.str_value.len);
+            ascii_out[data->value.str_value.len] = '\0';
+            ALOGD("Value: %s\n", ascii_out);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC4:
+            ALOGD("Value type: INT32_VEC4\nValue[0]: %d Value[1] %d Value[2] %d Value[3] %d",
+                  data->value.int32_array[0], data->value.int32_array[1],
+                  data->value.int32_array[2], data->value.int32_array[3]);
+            break;
+        default:
+            ALOGD("Value type not yet handled: %d.\n", data->value_type);
+    }
+    return 0;
+}
+
+void print_subscribe_info(vehicle_device_impl_t* impl UNUSED) {
+    unsigned int i;
+    for (i = 0; i < sizeof(CONFIGS) / sizeof(vehicle_prop_config_t); i++) {
+        subscription_t* sub = (subscription_t*)CONFIGS[i].hal_data;
+        if (sub != NULL) {
+            ALOGD("prop: %d rate: %f", sub->prop, sub->sample_rate);
+        }
+    }
+}
+
+// This should be run in a separate thread always.
+void fake_event_thread(struct subscription *sub) {
+    if (!sub) {
+        ALOGE("oops! subscription object cannot be NULL.");
+        exit(-1);
+    }
+    prctl(PR_SET_NAME, (unsigned long)sub->name, 0, 0, 0);
+    // Emit values in a loop, every 2 seconds.
+    while (1) {
+        // Create a random value depending on the property type.
+        vehicle_prop_value_t event;
+        event.prop = sub->prop;
+        event.timestamp = elapsedRealtimeNano();
+        switch (sub->prop) {
+            case VEHICLE_PROPERTY_DRIVING_STATUS:
+                event.value_type = VEHICLE_VALUE_TYPE_INT32;
+                switch ((event.timestamp & 0x30000000)>>28) {
+                    case 0:
+                        event.value.driving_status = VEHICLE_DRIVING_STATUS_UNRESTRICTED;
+                        break;
+                    case 1:
+                        event.value.driving_status = VEHICLE_DRIVING_STATUS_NO_VIDEO;
+                        break;
+                    case 2:
+                        event.value.driving_status = VEHICLE_DRIVING_STATUS_NO_KEYBOARD_INPUT;
+                        break;
+                    default:
+                        event.value.driving_status = VEHICLE_DRIVING_STATUS_NO_CONFIG;
+                }
+                break;
+            case VEHICLE_PROPERTY_GEAR_SELECTION:
+                event.value_type = VEHICLE_VALUE_TYPE_INT32;
+                switch ((event.timestamp & 0x30000000)>>28) {
+                    case 0:
+                        event.value.gear_selection = VEHICLE_GEAR_PARK;
+                        break;
+                    case 1:
+                        event.value.gear_selection = VEHICLE_GEAR_NEUTRAL;
+                        break;
+                    case 2:
+                        event.value.gear_selection = VEHICLE_GEAR_DRIVE;
+                        break;
+                    case 3:
+                        event.value.gear_selection = VEHICLE_GEAR_REVERSE;
+                        break;
+                }
+                break;
+            case VEHICLE_PROPERTY_PARKING_BRAKE_ON:
+                event.value_type = VEHICLE_VALUE_TYPE_BOOLEAN;
+                if (event.timestamp & 0x20000000) {
+                    event.value.parking_brake = VEHICLE_FALSE;
+                } else {
+                    event.value.parking_brake = VEHICLE_TRUE;
+                }
+                break;
+            case VEHICLE_PROPERTY_PERF_VEHICLE_SPEED:
+                event.value_type = VEHICLE_VALUE_TYPE_FLOAT;
+                event.value.vehicle_speed = (float) ((event.timestamp & 0xff000000)>>24);
+                break;
+            case VEHICLE_PROPERTY_RADIO_PRESET:
+                event.value_type = VEHICLE_VALUE_TYPE_INT32_VEC4;
+                int presetInfo1[4] = {1  /* preset number */, 0  /* AM Band */, 1000, 0};
+                int presetInfo2[4] = {2  /* preset number */, 1  /* FM Band */, 1000, 0};
+                if (event.timestamp & 0x20000000) {
+                    memcpy(event.value.int32_array, presetInfo1, sizeof(presetInfo1));
+                } else {
+                    memcpy(event.value.int32_array, presetInfo2, sizeof(presetInfo2));
+                }
+                break;
+            default: // unsupported
+                if (sub->impl == NULL) {
+                    ALOGE("subscription impl NULL");
+                    return;
+                }
+                if (sub->impl->error_fn_ != NULL) {
+                    sub->impl->error_fn_(-EINVAL, VEHICLE_PROPERTY_INVALID,
+                            VEHICLE_OPERATION_GENERIC);
+                } else {
+                    ALOGE("Error function is null");
+                }
+                ALOGE("Unsupported prop 0x%x, quit", sub->prop);
+                return;
+        }
+        if (sub->impl->event_fn_ != NULL) {
+            sub->impl->event_fn_(&event);
+        } else {
+            ALOGE("Event function is null");
+            return;
+        }
+        pthread_mutex_lock(&sub->lock);
+        if (sub->stop_thread) {
+            ALOGD("exiting subscription request here.");
+            // Do any cleanup here.
+            pthread_mutex_unlock(&sub->lock);
+            return;
+        }
+        struct timespec now;
+        clock_gettime(CLOCK_REALTIME, &now);
+        now.tv_sec += 1; // sleep for one sec
+        pthread_cond_timedwait(&sub->cond, &sub->lock, &now);
+        pthread_mutex_unlock(&sub->lock);
+    }
+}
+
+static int vdev_subscribe(vehicle_hw_device_t* device, int32_t prop, float sample_rate,
+        int32_t zones UNUSED) {
+    ALOGD("vdev_subscribe 0x%x, %f", prop, sample_rate);
+    vehicle_device_impl_t* impl = (vehicle_device_impl_t*)device;
+    // Check that the device is initialized.
+    pthread_mutex_lock(&lock_);
+    if (!impl->initialized_) {
+        pthread_mutex_unlock(&lock_);
+        ALOGE("vdev_subscribe: have you called init()?");
+        return -EINVAL;
+    }
+    vehicle_prop_config_t* config = find_config(prop);
+    if (config == NULL) {
+        pthread_mutex_unlock(&lock_);
+        ALOGE("vdev_subscribe not supported property 0x%x", prop);
+        return -EINVAL;
+    }
+    if ((config->access != VEHICLE_PROP_ACCESS_READ) &&
+        (config->access != VEHICLE_PROP_ACCESS_READ_WRITE)) {
+        pthread_mutex_unlock(&lock_);
+        ALOGE("vdev_subscribe read not supported on the property 0x%x", prop);
+        return -EINVAL;
+    }
+    if (config->change_mode == VEHICLE_PROP_CHANGE_MODE_STATIC) {
+        pthread_mutex_unlock(&lock_);
+        ALOGE("vdev_subscribe cannot subscribe static property 0x%x", prop);
+        return -EINVAL;
+    }
+    if ((config->change_mode == VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) && (sample_rate != 0)) {
+        pthread_mutex_unlock(&lock_);
+        ALOGE("vdev_subscribe on change type should have 0 sample rate, property 0x%x, sample rate %f",
+                prop, sample_rate);
+        return -EINVAL;
+    }
+    if ((config->max_sample_rate < sample_rate) || (config->min_sample_rate > sample_rate)) {
+
+        ALOGE("vdev_subscribe property 0x%x, invalid sample rate %f, min:%f, max:%f",
+                prop, sample_rate, config->min_sample_rate, config->max_sample_rate);
+        pthread_mutex_unlock(&lock_);
+        return -EINVAL;
+    }
+    subscription_t* sub = (subscription_t*)config->hal_data;
+    if (sub == NULL) {
+        sub = calloc(1, sizeof(subscription_t));
+        sub->prop = prop;
+        sub->sample_rate = sample_rate;
+        sub->stop_thread = 0;
+        sub->impl = impl;
+        pthread_mutex_init(&sub->lock, NULL);
+        pthread_cond_init(&sub->cond, NULL);
+        config->hal_data = sub;
+        sprintf(sub->name, "vhal0x%x", prop);
+    } else if (sub->sample_rate != sample_rate){ // sample rate changed
+        //TODO notify this to fake sensor thread
+        sub->sample_rate = sample_rate;
+        pthread_mutex_unlock(&lock_);
+        return 0;
+    }
+    int ret_code = pthread_create(
+                                  &sub->thread, NULL, (void *(*)(void*))fake_event_thread, sub);
+    print_subscribe_info(impl);
+    pthread_mutex_unlock(&lock_);
+    return 0;
+}
+
+static int vdev_unsubscribe(vehicle_hw_device_t* device, int32_t prop) {
+    ALOGD("vdev_unsubscribe 0x%x", prop);
+    vehicle_device_impl_t* impl = (vehicle_device_impl_t*)device;
+    pthread_mutex_lock(&lock_);
+    vehicle_prop_config_t* config = find_config(prop);
+    if (config == NULL) {
+        pthread_mutex_unlock(&lock_);
+        return -EINVAL;
+    }
+    subscription_t* sub = (subscription_t*)config->hal_data;
+    if (sub == NULL) {
+        pthread_mutex_unlock(&lock_);
+        return -EINVAL;
+    }
+    config->hal_data = NULL;
+    pthread_mutex_unlock(&lock_);
+    pthread_mutex_lock(&sub->lock);
+    sub->stop_thread = 1;
+    pthread_cond_signal(&sub->cond);
+    pthread_mutex_unlock(&sub->lock);
+    pthread_join(sub->thread, NULL);
+    pthread_cond_destroy(&sub->cond);
+    pthread_mutex_destroy(&sub->lock);
+    free(sub);
+    pthread_mutex_lock(&lock_);
+    print_subscribe_info(impl);
+    pthread_mutex_unlock(&lock_);
+    return 0;
+}
+
+static int vdev_close(hw_device_t* device) {
+    vehicle_device_impl_t* impl = (vehicle_device_impl_t*)device;
+    if (impl) {
+        free(impl);
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+static int vdev_dump(struct vehicle_hw_device* device UNUSED, int fd UNUSED) {
+    //TODO
+    return 0;
+}
+
+/*
+ * The open function is provided as an interface in harwdare.h which fills in
+ * all the information about specific implementations and version specific
+ * informations in hw_device_t structure. After calling open() the client should
+ * use the hw_device_t to execute any Vehicle HAL device specific functions.
+ */
+static int vdev_open(const hw_module_t* module, const char* name UNUSED,
+                     hw_device_t** device) {
+    ALOGD("vdev_open");
+
+    // Oops, out of memory!
+    vehicle_device_impl_t* vdev = calloc(1, sizeof(vehicle_device_impl_t));
+    if (vdev == NULL) {
+        return -ENOMEM;
+    }
+
+    // Common functions provided by harware.h to access module and device(s).
+    vdev->vehicle_device.common.tag = HARDWARE_DEVICE_TAG;
+    vdev->vehicle_device.common.version = VEHICLE_DEVICE_API_VERSION_1_0;
+    vdev->vehicle_device.common.module = (hw_module_t *) module;
+    vdev->vehicle_device.common.close = vdev_close;
+
+    // Define the Vehicle HAL device specific functions.
+    vdev->vehicle_device.list_properties = vdev_list_properties;
+    vdev->vehicle_device.init = vdev_init;
+    vdev->vehicle_device.release = vdev_release;
+    vdev->vehicle_device.get = vdev_get;
+    vdev->vehicle_device.release_memory_from_get = vdev_release_memory_from_get;
+    vdev->vehicle_device.set = vdev_set;
+    vdev->vehicle_device.subscribe = vdev_subscribe;
+    vdev->vehicle_device.unsubscribe = vdev_unsubscribe;
+    vdev->vehicle_device.dump = vdev_dump;
+
+    *device = (hw_device_t *) vdev;
+    return 0;
+}
+
+static struct hw_module_methods_t hal_module_methods = {
+    .open = vdev_open,
+};
+
+/*
+ * This structure is mandatory to be implemented by each HAL implementation. It
+ * exposes the open method (see hw_module_methods_t above) which opens a device.
+ * The vehicle HAL is supposed to be used as a single device HAL hence all the
+ * functions should be implemented inside of the vehicle_hw_device_t struct (see
+ * the vehicle.h in include/ folder.
+ */
+vehicle_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag = HARDWARE_MODULE_TAG,
+        .module_api_version = VEHICLE_MODULE_API_VERSION_1_0,
+        .hal_api_version = HARDWARE_HAL_API_VERSION,
+        .id = VEHICLE_HARDWARE_MODULE_ID,
+        .name = "Default vehicle HW HAL",
+        .author = "",
+        .methods = &hal_module_methods,
+    },
+};
diff --git a/modules/vr/Android.mk b/modules/vr/Android.mk
new file mode 100644 (file)
index 0000000..43c8e92
--- /dev/null
@@ -0,0 +1,26 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := vr.default
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := vr.c
+LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -Wno-unused-parameter
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/vr/vr.c b/modules/vr/vr.c
new file mode 100644 (file)
index 0000000..c5af593
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "VrHal"
+
+#include <hardware/vr.h>
+#include <hardware/hardware.h>
+
+static void vr_init(struct vr_module *module) {
+    // NOOP
+}
+
+static void vr_set_vr_mode(struct vr_module *module, bool enabled) {
+    // NOOP
+}
+
+static struct hw_module_methods_t vr_module_methods = {
+    .open = NULL,
+};
+
+
+vr_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag                = HARDWARE_MODULE_TAG,
+        .module_api_version = VR_MODULE_API_VERSION_1_0,
+        .hal_api_version    = HARDWARE_HAL_API_VERSION,
+        .id                 = VR_HARDWARE_MODULE_ID,
+        .name               = "Demo VR HAL",
+        .author             = "The Android Open Source Project",
+        .methods            = &vr_module_methods,
+    },
+
+    .init = vr_init,
+    .set_vr_mode = vr_set_vr_mode,
+};
index 3a2df69..661c693 100644 (file)
@@ -23,7 +23,6 @@
 #include "hardware/camera2.h"
 
 #include <common/CameraModule.h>
-#include <device2/Camera2Device.h>
 #include <device3/Camera3Device.h>
 
 #include "camera2_utils.h"
@@ -92,14 +91,10 @@ struct CameraModuleFixture {
         struct camera_info info;
         ASSERT_EQ(OK, mModule->getCameraInfo(cameraID, &info));
 
-        ASSERT_GE((int)info.device_version, CAMERA_DEVICE_API_VERSION_2_0) <<
+        ASSERT_GE((int)info.device_version, CAMERA_DEVICE_API_VERSION_3_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:
index 3e29ad6..eb64db1 100644 (file)
@@ -495,9 +495,6 @@ TEST_F(CameraMultiStreamTest, DISABLED_MultiBurst) {
         jpegData = availableJpegSizes.data.i32;
         jpegCount = availableJpegSizes.count;
     } else {
-        const int32_t *implDefResolutions;
-        size_t   implDefResolutionsCount;
-
         getResolutionList(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, &implDefData, &implDefCount);
         ASSERT_NE(0u, implDefCount)
             << "Missing implementation defined sizes";
index fc5fb36..bf7fb42 100644 (file)
@@ -186,7 +186,6 @@ protected:
     void getResolutionList(int32_t format,
             const int32_t **list,
             size_t *count) {
-        status_t res;
         ALOGV("Getting resolutions for format %x", format);
         if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) {
             return;
index a3b8c47..de9ae8a 100644 (file)
@@ -29,8 +29,6 @@
 #include <gui/CpuConsumer.h>
 #include <gui/Surface.h>
 
-#include <device2/Camera2Device.h>
-
 #include "CameraStreamFixture.h"
 #include "TestExtensions.h"
 
index 315233e..39599da 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <gtest/gtest.h>
 
+#include <stdlib.h>
+
 #include "TestExtensions.h"
 
 namespace android {
@@ -37,9 +39,7 @@ class DISABLED_ForkedTest : public ::testing::Test {
 // intentionally fail
 TEST_F(DISABLED_ForkedTest, FailCrash) {
     TEST_EXTENSION_FORKING_INIT;
-
-    //intentionally crash
-    *(int*)0 = 0xDEADBEEF;
+    abort();
 }
 
 TEST_F(DISABLED_ForkedTest, SucceedNormal) {
index d962939..c63c32a 100644 (file)
@@ -208,13 +208,13 @@ int MetadataQueue::consumer_dequeue(const camera2_request_queue_src_ops_t *q,
     return queue->dequeue(buffer, true);
 }
 
-int MetadataQueue::consumer_free(const camera2_request_queue_src_ops_t *q,
+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,
+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 =
@@ -224,7 +224,7 @@ int MetadataQueue::producer_dequeue(const camera2_frame_queue_dst_ops_t *q,
         return OK;
 }
 
-int MetadataQueue::producer_cancel(const camera2_frame_queue_dst_ops_t *q,
+int MetadataQueue::producer_cancel(const camera2_frame_queue_dst_ops_t * /* q */,
         camera_metadata_t *old_buffer) {
     free_camera_metadata(old_buffer);
     return OK;
@@ -386,12 +386,21 @@ status_t StreamAdapter::connectToDevice(camera2_device_t *d,
         return res;
     }
 
-    res = native_window_set_buffers_geometry(mConsumerInterface.get(),
-            mWidth, mHeight, mFormat);
+    res = native_window_set_buffers_dimensions(mConsumerInterface.get(),
+            mWidth, mHeight);
     if (res != OK) {
-        ALOGE("%s: Unable to configure buffer geometry"
-                " %d x %d, format 0x%x for stream %d",
-                __FUNCTION__, mWidth, mHeight, mFormat, mId);
+        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;
     }
@@ -454,8 +463,8 @@ cleanUpBuffers:
         res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
                 anwBuffers[i], -1);
     }
-    delete anwBuffers;
-    delete buffers;
+    delete[] anwBuffers;
+    delete[] buffers;
 
     return res;
 }
index 4207ea8..acb9d2d 100644 (file)
 
 template<size_t> static constexpr size_t CheckSizeHelper(size_t, size_t);
 
-template<> constexpr size_t CheckSizeHelper<4>(size_t size32, size_t size64) {
+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) {
+template<> constexpr size_t CheckSizeHelper<8>(size_t /* size32 */, size_t size64) {
     return size64;
 }
 
index 4cae9eb..367f5f4 100644 (file)
@@ -3,6 +3,7 @@ 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)
index 76f4564..5c16afb 100644 (file)
@@ -337,8 +337,8 @@ static int cnw_perform(aWindow *base, int op, ...) {
                TRACE("set scaling mode %d\n", va_arg(ap,int));
                return 0;
        case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
-               int w = va_arg(ap,int);
-               int h = va_arg(ap,int);
+               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;
@@ -377,7 +377,7 @@ static int hwc_init(CNativeWindow *win) {
        unsigned i;
        int r;
        uint32_t configs[32];
-       uint32_t numconfigs = 32;
+       size_t numconfigs = 32;
        int32_t values[8];
 
        if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
index 167cbc2..3aeb2f8 100644 (file)
@@ -2,12 +2,19 @@ LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_C_INCLUDES += hardware/libhardware/modules/input/evdev
+LOCAL_C_INCLUDES += $(TOP)/external/gmock/include
 
 LOCAL_SRC_FILES:= \
+    BitUtils_test.cpp \
     InputDevice_test.cpp \
     InputHub_test.cpp \
+    InputMocks.cpp \
+    MouseInputMapper_test.cpp \
+    SwitchInputMapper_test.cpp \
     TestHelpers.cpp
 
+LOCAL_STATIC_LIBRARIES := libgmock
+
 LOCAL_SHARED_LIBRARIES := \
     libinput_evdev \
     liblog \
@@ -17,6 +24,11 @@ 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
 
diff --git a/tests/input/evdev/BitUtils_test.cpp b/tests/input/evdev/BitUtils_test.cpp
new file mode 100644 (file)
index 0000000..76fc8af
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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 "BitUtils.h"
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace tests {
+
+TEST(BitInRange, testInvalidRange) {
+    uint8_t arr[2] = { 0xff, 0xff };
+    EXPECT_FALSE(testBitInRange(arr, 0, 0));
+    EXPECT_FALSE(testBitInRange(arr, 1, 0));
+}
+
+TEST(BitInRange, testNoBits) {
+    uint8_t arr[1];
+    arr[0] = 0;
+    EXPECT_FALSE(testBitInRange(arr, 0, 8));
+}
+
+TEST(BitInRange, testOneBit) {
+    uint8_t arr[1];
+    for (int i = 0; i < 8; ++i) {
+        arr[0] = 1 << i;
+        EXPECT_TRUE(testBitInRange(arr, 0, 8));
+    }
+}
+
+TEST(BitInRange, testZeroStart) {
+    uint8_t arr[1] = { 0x10 };
+    for (int i = 0; i < 5; ++i) {
+        EXPECT_FALSE(testBitInRange(arr, 0, i));
+    }
+    for (int i = 5; i <= 8; ++i) {
+        EXPECT_TRUE(testBitInRange(arr, 0, i));
+    }
+}
+
+TEST(BitInRange, testByteBoundaryEnd) {
+    uint8_t arr[1] = { 0x10 };
+    for (int i = 0; i < 5; ++i) {
+        EXPECT_TRUE(testBitInRange(arr, i, 8));
+    }
+    for (int i = 5; i <= 8; ++i) {
+        EXPECT_FALSE(testBitInRange(arr, i, 8));
+    }
+}
+
+TEST(BitInRange, testMultiByteArray) {
+    // bits set: 11 and 16
+    uint8_t arr[3] = { 0x00, 0x08, 0x01 };
+    for (int start = 0; start < 24; ++start) {
+        for (int end = start + 1; end <= 24; ++end) {
+            if (start > 16 || end <= 11 || (start > 11 && end <= 16)) {
+                EXPECT_FALSE(testBitInRange(arr, start, end))
+                    << "range = (" << start << ", " << end << ")";
+            } else {
+                EXPECT_TRUE(testBitInRange(arr, start, end))
+                    << "range = (" << start << ", " << end << ")";
+            }
+        }
+    }
+}
+
+}  // namespace tests
+}  // namespace android
index a96d664..bd57491 100644 (file)
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "InputHub_test"
-//#define LOG_NDEBUG 0
+#include "InputDevice.h"
+
+#include <memory>
 
 #include <linux/input.h>
 
@@ -23,8 +24,9 @@
 
 #include <utils/Timers.h>
 
-#include "InputDevice.h"
 #include "InputHub.h"
+#include "InputMocks.h"
+#include "MockInputHost.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
 
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::ReturnNull;
+
 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";
+class EvdevDeviceTest : public ::testing::Test {
+protected:
+    virtual void SetUp() {
+        // Creating device identifiers and definitions should always happen.
+        EXPECT_CALL(mHost, createDeviceIdentifier(_, _, _, _, _))
+            .WillOnce(ReturnNull());
+        EXPECT_CALL(mHost, createDeviceDefinition())
+            .WillOnce(Return(&mDeviceDef));
+        // InputMappers may cause any of these to be called, but we are not
+        // testing these here.
+        ON_CALL(mHost, createInputReportDefinition())
+            .WillByDefault(Return(&mReportDef));
+        ON_CALL(mHost, createOutputReportDefinition())
+            .WillByDefault(Return(&mReportDef));
+        ON_CALL(mHost, registerDevice(_, _))
+            .WillByDefault(ReturnNull());
+    }
+
+    MockInputHost mHost;
+    // Ignore uninteresting calls on the report definitions by using NiceMocks.
+    NiceMock<MockInputReportDefinition> mReportDef;
+    NiceMock<MockInputDeviceDefinition> mDeviceDef;
 };
 
-TEST(EvdevDeviceTest, testOverrideTime) {
+TEST_F(EvdevDeviceTest, testOverrideTime) {
     auto node = std::make_shared<MockInputDeviceNode>();
-    auto device = std::make_unique<EvdevDevice>(node);
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
     ASSERT_TRUE(device != nullptr);
 
     // Send two timestamp override events before an input event.
@@ -97,9 +95,9 @@ TEST(EvdevDeviceTest, testOverrideTime) {
     EXPECT_EQ(when, keyUp.when);
 }
 
-TEST(EvdevDeviceTest, testWrongClockCorrection) {
+TEST_F(EvdevDeviceTest, testWrongClockCorrection) {
     auto node = std::make_shared<MockInputDeviceNode>();
-    auto device = std::make_unique<EvdevDevice>(node);
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
     ASSERT_TRUE(device != nullptr);
 
     auto now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -113,9 +111,9 @@ TEST(EvdevDeviceTest, testWrongClockCorrection) {
     EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS));
 }
 
-TEST(EvdevDeviceTest, testClockCorrectionOk) {
+TEST_F(EvdevDeviceTest, testClockCorrectionOk) {
     auto node = std::make_shared<MockInputDeviceNode>();
-    auto device = std::make_unique<EvdevDevice>(node);
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
     ASSERT_TRUE(device != nullptr);
 
     auto now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -130,5 +128,73 @@ TEST(EvdevDeviceTest, testClockCorrectionOk) {
     EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS));
 }
 
+TEST_F(EvdevDeviceTest, testN7v2Touchscreen) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getElanTouchscreen());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_TOUCH|INPUT_DEVICE_CLASS_TOUCH_MT,
+            device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2ButtonJack) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getButtonJack());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2HeadsetJack) {
+    // Eventually these mock device tests will all expect these calls. For now
+    // only the SwitchInputMapper has been implemented.
+    // TODO: move this expectation out to a common function
+    EXPECT_CALL(mHost, createInputReportDefinition());
+    EXPECT_CALL(mHost, createOutputReportDefinition());
+    EXPECT_CALL(mHost, freeReportDefinition(_));
+    EXPECT_CALL(mHost, registerDevice(_, _));
+
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getHeadsetJack());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_SWITCH, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2H2wButton) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getH2wButton());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testN7v2GpioKeys) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getGpioKeys());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testNexusPlayerGpioKeys) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getGpioKeys());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testNexusPlayerMidPowerBtn) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getMidPowerBtn());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testNexusRemote) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getNexusRemote());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testAsusGamepad) {
+    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getAsusGamepad());
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+    EXPECT_EQ(INPUT_DEVICE_CLASS_JOYSTICK|INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
+}
+
+TEST_F(EvdevDeviceTest, testMocks) {
+    auto node = std::make_shared<MockInputDeviceNode>();
+    auto device = std::make_unique<EvdevDevice>(&mHost, node);
+}
+
 }  // namespace tests
 }  // namespace android
index f2c8edf..64671ff 100644 (file)
  * limitations under the License.
  */
 
-#define LOG_TAG "InputHub_test"
-//#define LOG_NDEBUG 0
-
-#include <linux/input.h>
+#include "InputHub.h"
 
 #include <chrono>
 #include <memory>
 #include <mutex>
 
+#include <linux/input.h>
+
 #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
@@ -41,11 +38,11 @@ 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>)>;
+using InputCbFunc = std::function<void(const std::shared_ptr<InputDeviceNode>&, InputEvent&, nsecs_t)>;
+using DeviceCbFunc = std::function<void(const std::shared_ptr<InputDeviceNode>&)>;
 
-static const InputCbFunc kNoopInputCb = [](std::shared_ptr<InputDeviceNode>, InputEvent&, nsecs_t){};
-static const DeviceCbFunc kNoopDeviceCb = [](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:
@@ -57,14 +54,14 @@ public:
     void setDeviceAddedCallback(DeviceCbFunc cb) { mDeviceAddedCb = cb; }
     void setDeviceRemovedCallback(DeviceCbFunc cb) { mDeviceRemovedCb = cb; }
 
-    virtual void onInputEvent(std::shared_ptr<InputDeviceNode> node, InputEvent& event,
+    virtual void onInputEvent(const 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 {
+    virtual void onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) override {
         mDeviceAddedCb(node);
     }
-    virtual void onDeviceRemoved(std::shared_ptr<InputDeviceNode> node) override {
+    virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) override {
         mDeviceRemovedCb(node);
     }
 
@@ -101,7 +98,7 @@ TEST_F(InputHubTest, DISABLED_testDeviceAdded) {
     std::string pathname;
     // Expect that this callback will run and set handle and pathname.
     mCallback->setDeviceAddedCallback(
-            [&](std::shared_ptr<InputDeviceNode> node) {
+            [&](const std::shared_ptr<InputDeviceNode>& node) {
                 pathname = node->getPath();
             });
 
@@ -136,11 +133,11 @@ TEST_F(InputHubTest, DISABLED_testDeviceRemoved) {
     std::shared_ptr<InputDeviceNode> tempNode;
     // Expect that these callbacks will run for the above device file.
     mCallback->setDeviceAddedCallback(
-            [&](std::shared_ptr<InputDeviceNode> node) {
+            [&](const std::shared_ptr<InputDeviceNode>& node) {
                 tempNode = node;
             });
     mCallback->setDeviceRemovedCallback(
-            [&](std::shared_ptr<InputDeviceNode> node) {
+            [&](const std::shared_ptr<InputDeviceNode>& node) {
                 EXPECT_EQ(tempNode, node);
             });
 
@@ -182,7 +179,8 @@ TEST_F(InputHubTest, DISABLED_testInputEvent) {
     // 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) {
+            [&](const 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());
@@ -211,7 +209,7 @@ TEST_F(InputHubTest, DISABLED_testCallbackOrder) {
     // Setup the callback for input events. Should run before the device
     // callback.
     mCallback->setInputCallback(
-            [&](std::shared_ptr<InputDeviceNode>, InputEvent&, nsecs_t) {
+            [&](const std::shared_ptr<InputDeviceNode>&, InputEvent&, nsecs_t) {
                 ASSERT_FALSE(deviceCallbackFinished);
                 inputCallbackFinished = true;
             });
@@ -219,7 +217,7 @@ TEST_F(InputHubTest, DISABLED_testCallbackOrder) {
     // Setup the callback for device removal. Should run after the input
     // callback.
     mCallback->setDeviceRemovedCallback(
-            [&](std::shared_ptr<InputDeviceNode> node) {
+            [&](const std::shared_ptr<InputDeviceNode>& node) {
                 ASSERT_TRUE(inputCallbackFinished)
                     << "input callback did not run before device changed callback";
                 // Make sure the correct device was removed.
diff --git a/tests/input/evdev/InputMocks.cpp b/tests/input/evdev/InputMocks.cpp
new file mode 100644 (file)
index 0000000..bd09a3d
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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 "InputMocks.h"
+
+namespace android {
+
+bool MockInputDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
+    auto iter = mKeys.lower_bound(startKey);
+    if (iter == mKeys.end()) return false;
+    return *iter < endKey;
+}
+
+namespace MockNexus7v2 {
+
+MockInputDeviceNode* getElanTouchscreen() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event0");
+    node->setName("elan-touchscreen");
+    // Location not set
+    // UniqueId not set
+    node->setBusType(0);
+    node->setVendorId(0);
+    node->setProductId(0);
+    node->setVersion(0);
+    // No keys
+    // No relative axes
+    // TODO: set the AbsoluteAxisInfo pointers
+    node->addAbsAxis(ABS_MT_SLOT, nullptr);
+    node->addAbsAxis(ABS_MT_TOUCH_MAJOR, nullptr);
+    node->addAbsAxis(ABS_MT_POSITION_X, nullptr);
+    node->addAbsAxis(ABS_MT_POSITION_Y, nullptr);
+    node->addAbsAxis(ABS_MT_TRACKING_ID, nullptr);
+    node->addAbsAxis(ABS_MT_PRESSURE, nullptr);
+    // No switches
+    // No forcefeedback
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getLidInput() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event1");
+    node->setName("lid_input");
+    node->setLocation("/dev/input/lid_indev");
+    // UniqueId not set
+    node->setBusType(0);
+    node->setVendorId(0);
+    node->setProductId(0);
+    node->setVersion(0);
+    // No keys
+    // No relative axes
+    // No absolute axes
+    node->addSwitch(SW_LID);
+    // No forcefeedback
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getButtonJack() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event2");
+    node->setName("apq8064-tabla-snd-card Button Jack");
+    node->setLocation("ALSA");
+    // UniqueId not set
+    node->setBusType(0);
+    node->setVendorId(0);
+    node->setProductId(0);
+    node->setVersion(0);
+    node->addKeys(BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7);
+    // No relative axes
+    // No absolute axes
+    // No switches
+    // No forcefeedback
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getHeadsetJack() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event3");
+    node->setName("apq8064-tabla-snd-card Headset Jack");
+    node->setLocation("ALSA");
+    // UniqueId not set
+    node->setBusType(0);
+    node->setVendorId(0);
+    node->setProductId(0);
+    node->setVersion(0);
+    // No keys
+    // No relative axes
+    // No absolute axes
+    node->addSwitch(SW_HEADPHONE_INSERT);
+    node->addSwitch(SW_MICROPHONE_INSERT);
+    node->addSwitch(SW_LINEOUT_INSERT);
+    // ASUS adds some proprietary switches, but we'll only see two of them.
+    node->addSwitch(0x0e);  // SW_HPHL_OVERCURRENT
+    node->addSwitch(0x0f);  // SW_HPHR_OVERCURRENT
+    // No forcefeedback
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getH2wButton() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event4");
+    node->setName("h2w button");
+    // Location not set
+    // UniqueId not set
+    node->setBusType(0);
+    node->setVendorId(0);
+    node->setProductId(0);
+    node->setVersion(0);
+    node->addKeys(KEY_MEDIA);
+    // No relative axes
+    // No absolute axes
+    // No switches
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getGpioKeys() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event5");
+    node->setName("gpio-keys");
+    node->setLocation("gpio-keys/input0");
+    // UniqueId not set
+    node->setBusType(0x0019);
+    node->setVendorId(0x0001);
+    node->setProductId(0x0001);
+    node->setVersion(0x0100);
+    node->addKeys(KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_POWER);
+    // No relative axes
+    // No absolute axes
+    // No switches
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+}  // namespace MockNexus7v2
+
+namespace MockNexusPlayer {
+
+MockInputDeviceNode* getGpioKeys() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event0");
+    node->setName("gpio-keys");
+    node->setLocation("gpio-keys/input0");
+    // UniqueId not set
+    node->setBusType(0x0019);
+    node->setVendorId(0x0001);
+    node->setProductId(0x0001);
+    node->setVersion(0x0100);
+    node->addKeys(KEY_CONNECT);
+    // No relative axes
+    // No absolute axes
+    // No switches
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getMidPowerBtn() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event1");
+    node->setName("mid_powerbtn");
+    node->setLocation("power-button/input0");
+    // UniqueId not set
+    node->setBusType(0x0019);
+    node->setVendorId(0);
+    node->setProductId(0);
+    node->setVersion(0);
+    node->addKeys(KEY_POWER);
+    // No relative axes
+    // No absolute axes
+    // No switches
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getNexusRemote() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event2");
+    node->setName("Nexus Remote");
+    // Location not set
+    node->setUniqueId("78:86:D9:50:A0:54");
+    node->setBusType(0x0005);
+    node->setVendorId(0x18d1);
+    node->setProductId(0x2c42);
+    node->setVersion(0);
+    node->addKeys(KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_BACK, KEY_PLAYPAUSE,
+            KEY_HOMEPAGE, KEY_SEARCH, KEY_SELECT);
+    // No relative axes
+    node->addAbsAxis(ABS_MISC, nullptr);
+    // No switches
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    return node;
+}
+
+MockInputDeviceNode* getAsusGamepad() {
+    auto node = new MockInputDeviceNode();
+    node->setPath("/dev/input/event3");
+    node->setName("ASUS Gamepad");
+    // Location not set
+    node->setUniqueId("C5:30:CD:50:A0:54");
+    node->setBusType(0x0005);
+    node->setVendorId(0x0b05);
+    node->setProductId(0x4500);
+    node->setVersion(0x0040);
+    node->addKeys(KEY_BACK, KEY_HOMEPAGE, BTN_A, BTN_B, BTN_X, BTN_Y, BTN_TL, BTN_TR,
+            BTN_MODE, BTN_THUMBL, BTN_THUMBR);
+    // No relative axes
+    node->addAbsAxis(ABS_X, nullptr);
+    node->addAbsAxis(ABS_Y, nullptr);
+    node->addAbsAxis(ABS_Z, nullptr);
+    node->addAbsAxis(ABS_RZ, nullptr);
+    node->addAbsAxis(ABS_GAS, nullptr);
+    node->addAbsAxis(ABS_BRAKE, nullptr);
+    node->addAbsAxis(ABS_HAT0X, nullptr);
+    node->addAbsAxis(ABS_HAT0Y, nullptr);
+    node->addAbsAxis(ABS_MISC, nullptr);
+    node->addAbsAxis(0x29, nullptr);
+    node->addAbsAxis(0x2a, nullptr);
+    // No switches
+    node->addInputProperty(INPUT_PROP_DIRECT);
+    // Note: this device has MSC and LED bitmaps as well.
+    return node;
+}
+
+}  // namespace MockNexusPlayer
+
+}  // namespace android
diff --git a/tests/input/evdev/InputMocks.h b/tests/input/evdev/InputMocks.h
new file mode 100644 (file)
index 0000000..78e0279
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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_MOCKS_H_
+#define ANDROID_INPUT_MOCKS_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include <linux/input.h>
+
+#include "InputHub.h"
+
+namespace android {
+
+class MockInputDeviceNode : public InputDeviceNode {
+public:
+    MockInputDeviceNode() = default;
+    virtual ~MockInputDeviceNode() = default;
+
+    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; }
+
+    void setPath(const std::string& path) { mPath = path; }
+    void setName(const std::string& name) { mName = name; }
+    void setLocation(const std::string& location) { mLocation = location; }
+    void setUniqueId(const std::string& uniqueId) { mUniqueId = uniqueId; }
+
+    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; }
+
+    void setBusType(uint16_t busType) { mBusType = busType; }
+    void setVendorId(uint16_t vendorId) { mVendorId = vendorId; }
+    void setProductId(uint16_t productId) { mProductId = productId; }
+    void setVersion(uint16_t version) { mVersion = version; }
+
+    virtual bool hasKey(int32_t key) const override { return mKeys.count(key); }
+    virtual bool hasKeyInRange(int32_t startKey, int32_t endKey) const override;
+    virtual bool hasRelativeAxis(int axis) const override { return mRelAxes.count(axis); }
+    virtual bool hasAbsoluteAxis(int32_t axis) const override { return mAbsAxes.count(axis); }
+    virtual bool hasSwitch(int32_t sw) const override { return mSwitches.count(sw); }
+    virtual bool hasForceFeedback(int32_t ff) const override { return mForceFeedbacks.count(ff); }
+    virtual bool hasInputProperty(int32_t property) const override {
+        return mInputProperties.count(property);
+    }
+
+    // base case
+    void addKeys() {}
+    // inductive case
+    template<typename I, typename... Is>
+    void addKeys(I key, Is... keys) {
+        // Add the first key
+        mKeys.insert(key);
+        // Recursively add the remaining keys
+        addKeys(keys...);
+    }
+
+    void addRelAxis(int32_t axis) { mRelAxes.insert(axis); }
+    void addAbsAxis(int32_t axis, AbsoluteAxisInfo* info) { mAbsAxes[axis] = info; }
+    void addSwitch(int32_t sw) { mSwitches.insert(sw); }
+    void addForceFeedback(int32_t ff) { mForceFeedbacks.insert(ff); }
+    void addInputProperty(int32_t property) { mInputProperties.insert(property); }
+
+    virtual int32_t getKeyState(int32_t key) const override { return 0; }
+    virtual int32_t getSwitchState(int32_t sw) const override { return 0; }
+    virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override {
+        auto iter = mAbsAxes.find(axis);
+        if (iter != mAbsAxes.end()) {
+            return iter->second;
+        }
+        return nullptr;
+    }
+    virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override {
+        // TODO
+        return 0;
+    }
+
+    virtual void vibrate(nsecs_t duration) override {}
+    virtual void cancelVibrate() override {}
+
+    virtual void disableDriverKeyRepeat() override { mKeyRepeatDisabled = true; }
+
+    bool isDriverKeyRepeatEnabled() { return mKeyRepeatDisabled; }
+
+private:
+    std::string mPath = "/test";
+    std::string mName = "Test Device";
+    std::string mLocation = "test/0";
+    std::string mUniqueId = "test-id";
+
+    uint16_t mBusType = 0;
+    uint16_t mVendorId = 0;
+    uint16_t mProductId = 0;
+    uint16_t mVersion = 0;
+
+    std::set<int32_t> mKeys;
+    std::set<int32_t> mRelAxes;
+    std::map<int32_t, AbsoluteAxisInfo*> mAbsAxes;
+    std::set<int32_t> mSwitches;
+    std::set<int32_t> mForceFeedbacks;
+    std::set<int32_t> mInputProperties;
+
+    bool mKeyRepeatDisabled = false;
+};
+
+namespace MockNexus7v2 {
+MockInputDeviceNode* getElanTouchscreen();
+MockInputDeviceNode* getLidInput();
+MockInputDeviceNode* getButtonJack();
+MockInputDeviceNode* getHeadsetJack();
+MockInputDeviceNode* getH2wButton();
+MockInputDeviceNode* getGpioKeys();
+}  // namespace MockNexus7v2
+
+namespace MockNexusPlayer {
+MockInputDeviceNode* getGpioKeys();
+MockInputDeviceNode* getMidPowerBtn();
+MockInputDeviceNode* getNexusRemote();
+MockInputDeviceNode* getAsusGamepad();
+}  // namespace MockNexusPlayer
+
+}  // namespace android
+
+#endif  // ANDROID_INPUT_MOCKS_H_
diff --git a/tests/input/evdev/MockInputHost.h b/tests/input/evdev/MockInputHost.h
new file mode 100644 (file)
index 0000000..aae0564
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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_MOCK_INPUT_HOST_H_
+#define ANDROID_MOCK_INPUT_HOST_H_
+
+#include "InputHost.h"
+
+#include "gmock/gmock.h"
+
+
+namespace android {
+namespace tests {
+
+class MockInputReport : public InputReport {
+public:
+    MockInputReport() : InputReport(nullptr, {}, nullptr) {}
+    MOCK_METHOD4(setIntUsage, void(InputCollectionId id, InputUsage usage, int32_t value,
+                int32_t arityIndex));
+    MOCK_METHOD4(setBoolUsage, void(InputCollectionId id, InputUsage usage, bool value,
+                int32_t arityIndex));
+    MOCK_METHOD1(reportEvent, void(InputDeviceHandle* d));
+};
+
+class MockInputReportDefinition : public InputReportDefinition {
+public:
+    MockInputReportDefinition() : InputReportDefinition(nullptr, {}, nullptr) {}
+    MOCK_METHOD2(addCollection, void(InputCollectionId id, int32_t arity));
+    MOCK_METHOD5(declareUsage, void(InputCollectionId id, InputUsage usage, int32_t min,
+                int32_t max, float resolution));
+    MOCK_METHOD3(declareUsages, void(InputCollectionId id, InputUsage* usage, size_t usageCount));
+    MOCK_METHOD0(allocateReport, InputReport*());
+};
+
+class MockInputDeviceDefinition : public InputDeviceDefinition {
+public:
+    MockInputDeviceDefinition() : InputDeviceDefinition(nullptr, {}, nullptr) {}
+    MOCK_METHOD1(addReport, void(InputReportDefinition* r));
+};
+
+class MockInputProperty : public InputProperty {
+public:
+    MockInputProperty() : InputProperty(nullptr, {}, nullptr) {}
+    virtual ~MockInputProperty() {}
+    MOCK_CONST_METHOD0(getKey, const char*());
+    MOCK_CONST_METHOD0(getValue, const char*());
+};
+
+class MockInputPropertyMap : public InputPropertyMap {
+public:
+    MockInputPropertyMap() : InputPropertyMap(nullptr, {}, nullptr) {}
+    virtual ~MockInputPropertyMap() {}
+    MOCK_CONST_METHOD1(getDeviceProperty, InputProperty*(const char* key));
+    MOCK_CONST_METHOD1(freeDeviceProperty, void(InputProperty* property));
+};
+
+class MockInputHost : public InputHostInterface {
+public:
+    MOCK_METHOD5(createDeviceIdentifier, InputDeviceIdentifier*(
+                const char* name, int32_t productId, int32_t vendorId, InputBus bus,
+                const char* uniqueId));
+    MOCK_METHOD0(createDeviceDefinition, InputDeviceDefinition*());
+    MOCK_METHOD0(createInputReportDefinition, InputReportDefinition*());
+    MOCK_METHOD0(createOutputReportDefinition, InputReportDefinition*());
+    MOCK_METHOD1(freeReportDefinition, void(InputReportDefinition* reportDef));
+    MOCK_METHOD2(registerDevice, InputDeviceHandle*(InputDeviceIdentifier* id,
+                InputDeviceDefinition* d));
+    MOCK_METHOD1(unregisterDevice, void(InputDeviceHandle* handle));
+    MOCK_METHOD1(getDevicePropertyMap, InputPropertyMap*(InputDeviceIdentifier* id));
+    MOCK_METHOD1(freeDevicePropertyMap, void(InputPropertyMap* propertyMap));
+};
+
+}  // namespace tests
+}  // namespace android
+
+#endif  // ANDROID_MOCK_INPUT_HOST_H_
diff --git a/tests/input/evdev/MouseInputMapper_test.cpp b/tests/input/evdev/MouseInputMapper_test.cpp
new file mode 100644 (file)
index 0000000..7e1f376
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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 <memory>
+
+#include <linux/input.h>
+
+#include <gtest/gtest.h>
+
+#include "InputMocks.h"
+#include "MockInputHost.h"
+#include "MouseInputMapper.h"
+
+using ::testing::_;
+using ::testing::Args;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::UnorderedElementsAre;
+
+namespace android {
+namespace tests {
+
+class MouseInputMapperTest : public ::testing::Test {
+protected:
+     virtual void SetUp() override {
+         mMapper = std::make_unique<MouseInputMapper>();
+     }
+
+     MockInputHost mHost;
+     std::unique_ptr<MouseInputMapper> mMapper;
+};
+
+TEST_F(MouseInputMapperTest, testConfigureDevice) {
+    MockInputReportDefinition reportDef;
+    MockInputDeviceNode deviceNode;
+    deviceNode.addKeys(BTN_LEFT, BTN_RIGHT, BTN_MIDDLE);
+    deviceNode.addRelAxis(REL_X);
+    deviceNode.addRelAxis(REL_Y);
+
+    const auto id = INPUT_COLLECTION_ID_MOUSE;
+    EXPECT_CALL(reportDef, addCollection(id, 1));
+    EXPECT_CALL(reportDef, declareUsage(id, INPUT_USAGE_AXIS_X, _, _, _));
+    EXPECT_CALL(reportDef, declareUsage(id, INPUT_USAGE_AXIS_Y, _, _, _));
+    EXPECT_CALL(reportDef, declareUsages(id, _, 3))
+        .With(Args<1,2>(UnorderedElementsAre(
+                        INPUT_USAGE_BUTTON_PRIMARY,
+                        INPUT_USAGE_BUTTON_SECONDARY,
+                        INPUT_USAGE_BUTTON_TERTIARY)));
+
+    EXPECT_TRUE(mMapper->configureInputReport(&deviceNode, &reportDef));
+}
+
+TEST_F(MouseInputMapperTest, testConfigureDevice_noXAxis) {
+    MockInputReportDefinition reportDef;
+    MockInputDeviceNode deviceNode;
+
+    EXPECT_CALL(reportDef, addCollection(INPUT_COLLECTION_ID_MOUSE, 1));
+    EXPECT_CALL(reportDef, declareUsage(_, _, _, _, _)).Times(0);
+    EXPECT_CALL(reportDef, declareUsages(_, _, _)).Times(0);
+
+    EXPECT_FALSE(mMapper->configureInputReport(&deviceNode, &reportDef));
+}
+
+TEST_F(MouseInputMapperTest, testProcessInput) {
+    MockInputReportDefinition reportDef;
+    MockInputDeviceNode deviceNode;
+    deviceNode.addKeys(BTN_LEFT, BTN_RIGHT, BTN_MIDDLE);
+    deviceNode.addRelAxis(REL_X);
+    deviceNode.addRelAxis(REL_Y);
+
+    EXPECT_CALL(reportDef, addCollection(_, _));
+    EXPECT_CALL(reportDef, declareUsage(_, _, _, _, _)).Times(2);
+    EXPECT_CALL(reportDef, declareUsages(_, _, 3));
+
+    mMapper->configureInputReport(&deviceNode, &reportDef);
+
+    MockInputReport report;
+    EXPECT_CALL(reportDef, allocateReport())
+        .WillOnce(Return(&report));
+
+    {
+        // Test two switch events in order
+        InSequence s;
+        const auto id = INPUT_COLLECTION_ID_MOUSE;
+        EXPECT_CALL(report, setIntUsage(id, INPUT_USAGE_AXIS_X, 5, 0));
+        EXPECT_CALL(report, setIntUsage(id, INPUT_USAGE_AXIS_Y, -3, 0));
+        EXPECT_CALL(report, reportEvent(_));
+        EXPECT_CALL(report, setBoolUsage(id, INPUT_USAGE_BUTTON_PRIMARY, 1, 0));
+        EXPECT_CALL(report, reportEvent(_));
+        EXPECT_CALL(report, setBoolUsage(id, INPUT_USAGE_BUTTON_PRIMARY, 0, 0));
+        EXPECT_CALL(report, reportEvent(_));
+    }
+
+    InputEvent events[] = {
+        {0, EV_REL, REL_X, 5},
+        {1, EV_REL, REL_Y, -3},
+        {2, EV_SYN, SYN_REPORT, 0},
+        {0, EV_KEY, BTN_LEFT, 1},
+        {1, EV_SYN, SYN_REPORT, 0},
+        {2, EV_KEY, BTN_LEFT, 0},
+        {3, EV_SYN, SYN_REPORT, 0},
+    };
+    for (auto e : events) {
+        mMapper->process(e);
+    }
+}
+
+}  // namespace tests
+}  // namespace android
+
diff --git a/tests/input/evdev/SwitchInputMapper_test.cpp b/tests/input/evdev/SwitchInputMapper_test.cpp
new file mode 100644 (file)
index 0000000..ee90b2c
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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 <memory>
+
+#include <linux/input.h>
+
+#include <gtest/gtest.h>
+
+#include "InputMocks.h"
+#include "MockInputHost.h"
+#include "SwitchInputMapper.h"
+
+using ::testing::_;
+using ::testing::Args;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::UnorderedElementsAre;
+
+namespace android {
+namespace tests {
+
+class SwitchInputMapperTest : public ::testing::Test {
+protected:
+     virtual void SetUp() override {
+         mMapper = std::make_unique<SwitchInputMapper>();
+     }
+
+     MockInputHost mHost;
+     std::unique_ptr<SwitchInputMapper> mMapper;
+};
+
+TEST_F(SwitchInputMapperTest, testConfigureDevice) {
+    MockInputReportDefinition reportDef;
+    MockInputDeviceNode deviceNode;
+    deviceNode.addSwitch(SW_LID);
+    deviceNode.addSwitch(SW_CAMERA_LENS_COVER);
+
+    EXPECT_CALL(reportDef, addCollection(INPUT_COLLECTION_ID_SWITCH, 1));
+    EXPECT_CALL(reportDef, declareUsages(INPUT_COLLECTION_ID_SWITCH, _, 2))
+        .With(Args<1,2>(UnorderedElementsAre(INPUT_USAGE_SWITCH_LID,
+                        INPUT_USAGE_SWITCH_CAMERA_LENS_COVER)));
+
+    EXPECT_TRUE(mMapper->configureInputReport(&deviceNode, &reportDef));
+}
+
+TEST_F(SwitchInputMapperTest, testConfigureDevice_noSwitches) {
+    MockInputReportDefinition reportDef;
+    MockInputDeviceNode deviceNode;
+
+    EXPECT_CALL(reportDef, addCollection(_, _)).Times(0);
+    EXPECT_CALL(reportDef, declareUsages(_, _, _)).Times(0);
+
+    EXPECT_FALSE(mMapper->configureInputReport(&deviceNode, &reportDef));
+}
+
+TEST_F(SwitchInputMapperTest, testProcessInput) {
+    MockInputReportDefinition reportDef;
+    MockInputDeviceNode deviceNode;
+    deviceNode.addSwitch(SW_LID);
+
+    EXPECT_CALL(reportDef, addCollection(_, _));
+    EXPECT_CALL(reportDef, declareUsages(_, _, _));
+
+    mMapper->configureInputReport(&deviceNode, &reportDef);
+
+    MockInputReport report;
+    EXPECT_CALL(reportDef, allocateReport())
+        .WillOnce(Return(&report));
+
+    {
+        // Test two switch events in order
+        InSequence s;
+        EXPECT_CALL(report, setBoolUsage(INPUT_COLLECTION_ID_SWITCH, INPUT_USAGE_SWITCH_LID, 1, 0));
+        EXPECT_CALL(report, reportEvent(_));
+        EXPECT_CALL(report, setBoolUsage(INPUT_COLLECTION_ID_SWITCH, INPUT_USAGE_SWITCH_LID, 0, 0));
+        EXPECT_CALL(report, reportEvent(_));
+    }
+
+    InputEvent events[] = {
+        {0, EV_SW, SW_LID, 1},
+        {1, EV_SYN, SYN_REPORT, 0},
+        {2, EV_SW, SW_LID, 0},
+        {3, EV_SYN, SYN_REPORT, 0},
+    };
+    for (auto e : events) {
+        mMapper->process(e);
+    }
+}
+
+}  // namespace tests
+}  // namespace android
+
index 63b579e..9898a6f 100644 (file)
@@ -17,6 +17,8 @@
 #define LOG_TAG "TestHelpers"
 #define LOG_NDEBUG 0
 
+#include "TestHelpers.h"
+
 #include <dirent.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -26,8 +28,6 @@
 
 #include <utils/Log.h>
 
-#include "TestHelpers.h"
-
 namespace android {
 
 static const char kTmpDirTemplate[] = "/data/local/tmp/XXXXXX";
index e5e1dfd..6266d40 100644 (file)
@@ -395,8 +395,8 @@ class KeymasterGenerateECTest : public KeymasterBaseTest,
 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,
+            .modulus_size = GetParam(),
+            .public_exponent = RSA_F4,
     };
 
     uint8_t* key_blob;
@@ -443,7 +443,7 @@ INSTANTIATE_TEST_CASE_P(RSA,
 TEST_P(KeymasterGenerateECTest, GenerateKeyPair_EC_Success) {
     keymaster_keypair_t key_type = TYPE_EC;
     keymaster_ec_keygen_params_t params = {
-            field_size: GetParam(),
+            .field_size = GetParam(),
     };
 
     uint8_t* key_blob;
@@ -864,8 +864,8 @@ TEST_F(KeymasterTest, SignData_RSA_Raw_Success) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     uint8_t* sig;
@@ -904,7 +904,7 @@ TEST_F(KeymasterTest, SignData_EC_Success) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_ec_sign_params_t params = {
-            digest_type: DIGEST_NONE,
+            .digest_type = DIGEST_NONE,
     };
 
     uint8_t* sig;
@@ -952,8 +952,8 @@ TEST_F(KeymasterTest, SignData_RSA_Raw_InvalidSizeInput_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     uint8_t* sig;
@@ -971,8 +971,8 @@ TEST_F(KeymasterTest, SignData_RSA_Raw_InvalidSizeInput_Failure) {
 
 TEST_F(KeymasterTest, SignData_RSA_Raw_NullKey_Failure) {
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     uint8_t* sig;
@@ -1002,8 +1002,8 @@ TEST_F(KeymasterTest, SignData_RSA_Raw_NullInput_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     uint8_t* sig;
@@ -1030,8 +1030,8 @@ TEST_F(KeymasterTest, SignData_RSA_Raw_NullOutput_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     uint8_t* sig;
@@ -1061,8 +1061,8 @@ TEST_F(KeymasterTest, VerifyData_RSA_Raw_Success) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1));
@@ -1092,7 +1092,7 @@ TEST_F(KeymasterTest, VerifyData_EC_Raw_Success) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_ec_sign_params_t params = {
-            digest_type: DIGEST_NONE,
+            .digest_type = DIGEST_NONE,
     };
 
     uint8_t* sig;
@@ -1129,8 +1129,8 @@ TEST_F(KeymasterTest, VerifyData_RSA_Raw_BadSignature_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     ASSERT_EQ(-1,
@@ -1154,7 +1154,7 @@ TEST_F(KeymasterTest, VerifyData_EC_Raw_BadSignature_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_ec_sign_params_t params = {
-            digest_type: DIGEST_NONE,
+            .digest_type = DIGEST_NONE,
     };
 
     ASSERT_EQ(-1,
@@ -1166,8 +1166,8 @@ TEST_F(KeymasterTest, VerifyData_EC_Raw_BadSignature_Failure) {
 
 TEST_F(KeymasterTest, VerifyData_RSA_Raw_NullKey_Failure) {
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1));
@@ -1194,8 +1194,8 @@ TEST_F(KeymasterTest, VerifyData_RSA_NullInput_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     UniqueReadOnlyBlob testSig(TEST_SIGN_RSA_SIGNATURE_1, sizeof(TEST_SIGN_RSA_SIGNATURE_1));
@@ -1222,8 +1222,8 @@ TEST_F(KeymasterTest, VerifyData_RSA_NullSignature_Failure) {
     UniqueKey key(&sDevice, key_blob, key_blob_length);
 
     keymaster_rsa_sign_params_t params = {
-            digest_type: DIGEST_NONE,
-            padding_type: PADDING_NONE,
+            .digest_type = DIGEST_NONE,
+            .padding_type = PADDING_NONE,
     };
 
     UniqueReadOnlyBlob testData(TEST_SIGN_DATA_1, sizeof(TEST_SIGN_DATA_1));
index 3c8eae9..55b7785 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
 #include <string.h>
 #include <stdint.h>
 #include <string.h>
@@ -57,7 +58,7 @@ char const* getSensorName(int type) {
     return "ukn";
 }
 
-int main(int argc, char** argv)
+int main(int /* argc */, char** /* argv */)
 {
     int err;
     struct sensors_poll_device_t* device;
@@ -131,7 +132,7 @@ int main(int argc, char** argv)
             const sensors_event_t& data = buffer[i];
 
             if (data.version != sizeof(sensors_event_t)) {
-                printf("incorrect event version (version=%d, expected=%d",
+                printf("incorrect event version (version=%d, expected=%zu",
                         data.version, sizeof(sensors_event_t));
                 break;
             }
@@ -144,7 +145,7 @@ int main(int argc, char** argv)
                 case SENSOR_TYPE_GRAVITY:
                 case SENSOR_TYPE_LINEAR_ACCELERATION:
                 case SENSOR_TYPE_ROTATION_VECTOR:
-                    printf("sensor=%s, time=%lld, value=<%5.1f,%5.1f,%5.1f>\n",
+                    printf("sensor=%s, time=%" PRId64 ", value=<%5.1f,%5.1f,%5.1f>\n",
                             getSensorName(data.type),
                             data.timestamp,
                             data.data[0],
@@ -158,14 +159,14 @@ int main(int argc, char** argv)
                 case SENSOR_TYPE_PROXIMITY:
                 case SENSOR_TYPE_RELATIVE_HUMIDITY:
                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
-                    printf("sensor=%s, time=%lld, value=%f\n",
+                    printf("sensor=%s, time=%" PRId64 ", value=%f\n",
                             getSensorName(data.type),
                             data.timestamp,
                             data.data[0]);
                     break;
 
                 default:
-                    printf("sensor=%d, time=%lld, value=<%f,%f,%f, ...>\n",
+                    printf("sensor=%d, time=% " PRId64 ", value=<%f,%f,%f, ...>\n",
                             data.type,
                             data.timestamp,
                             data.data[0],
diff --git a/tests/vehicle/Android.mk b/tests/vehicle/Android.mk
new file mode 100644 (file)
index 0000000..eb41725
--- /dev/null
@@ -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)
+
+# Build native tests.
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    vehicle_tests.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libhardware \
+
+LOCAL_CFLAGS += -Wall -Wextra
+
+LOCAL_MODULE:= vehicle_tests
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_NATIVE_TEST)
+
+# Build HAL command line utility.
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := vehicle-hal-tool.c
+LOCAL_MODULE := vehicle-hal-tool
+LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware liblog
+
+include $(BUILD_EXECUTABLE)
diff --git a/tests/vehicle/README b/tests/vehicle/README
new file mode 100644 (file)
index 0000000..b8fc7d4
--- /dev/null
@@ -0,0 +1,73 @@
+What does this document tell?
+
+This document details how to use the vehicle service if you are implementhing
+HAL. It lists the various places to look for code and how to build and test the
+code on your own dev device.
+
+This code also provides a simple command line utility for the target to test the
+vehicle HAL.
+
+What is the code?
+
+The code is split into folowing logical components:
+a) hardware/libhardware/include/hardware/vehicle.h - this is the main HAL
+interface that will be required to be implemented by the OEMs. It includes all
+documentation necessary to understand what vehicle subsystems are exposed,
+various units, capabilities and any other relevant details about the HAL design
+itself.
+
+b) hardware/libhardware/modules/vehicle/vehicle.c
+This is a reference implementation for the OEMs to have a peek into getting
+started with a barebones structure. There are implementation for each of the
+critical HAL functions such as, get(), set() and subscribe().
+
+c) hardware/libhardware/tests/vehicle/vehicle_test.cpp & vehicle_test_fixtures.h
+These are native tests that can be run on the target to validate basic
+features of HAL implementation. Things such as loading of HAL and
+basic functions are implemented (by check if the returned functions are not NULL
+pointers) can be asserted. It also checks if the subscribe function is doing its
+job by spitting out data at continuous intervals and printed on the stdout.
+
+d) hardware/libhardware/tests/vehicle/vehicle-hal-tool.c
+This tool will provide you with a simple utility which can set commands to the
+HAL such as:
+i) Getting a property (and printing its value).
+ii) Setting a property (and the HAL will take some setting action).
+iii) Subscribe to a property (and the HAL should send you values at some certain
+intevals).
+
+See the usage() function in vehicle-hal-tool.c for details on how to use the
+binary.
+
+How to build and run?
+
+You can build everything by issuing the following from the top of directory. It
+is assumed that you have done a first run of make from the top level so that
+intermediates are generated.
+
+$ croot
+$ mmm hardware/libhardware
+
+This will generate the following binaries that we care about:
+i) out/target/product/XXX/system/lib/hw/vehicle.default.so
+ii) out/target/product/XXX/data/nativetest/vehicle_tests
+iii) out/target/product/XXX/system/bin/vehicle-hal-tool
+
+The location for the first shared library would be:
+$ adb push out/target/product/XXX/system/lib/hw/vehicle.default.so
+/system/lib/hw
+You can also use 'adb sync' if you like, although this is the easiest least
+hassle way of putting it in place.
+
+The second binary is a native test - which is nothing but an executable for the
+target device. You can load it anywhere in your /data directory and run it as:
+$ adb push out/target/product/XXX/data/nativetest/vehicle_tests
+/data/tmp/vehicle_tests
+$ adb shell
+$ ./data/tmp/vehicle_tests
+<...output should be spitted with passing tests for atleast the reference
+implementation ...>
+
+The last binary is the command line tool, to push the binary on your target do:
+$ adb push out/target/product/XXX/system/bin/vehicle-hal-tool
+/data/tmp/vehicle-hal-tool
diff --git a/tests/vehicle/vehicle-hal-tool.c b/tests/vehicle/vehicle-hal-tool.c
new file mode 100755 (executable)
index 0000000..c93790a
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ * 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 "vehicle-hal-tool"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <hardware/hardware.h>
+#include <hardware/vehicle.h>
+
+#include <cutils/log.h>
+
+void usage() {
+    printf("Usage: "
+            "./vehicle-hal-tool [-l] [-m -p -t [-v]]\n"
+            "-l - List properties\n"
+            "-m - Mode (cannot be used with -l). Accepted strings: get, set or sub.\n"
+            "-p - Property (only used with -m)\n"
+            "-t - Type (only used with -m)\n"
+            "-w - Wait time in seconds (only used with -m set to sub)\n"
+            "-v - Value to which vehicle_prop_value is set\n"
+            "Depending on the type pass the value:\n"
+            "Int: pass a quoted integer\n"
+            "Float: pass a quoted float\n"
+            "Int array: pass a quoted space delimited int array, eg: \"1 2 3 4\" for\n:"
+            "setting int32_array's all 4 elements (see VEHICLE_VALUE_TYPE_INT32_VEC4\n"
+            "String: pass a normal string\n\n"
+            "The configurations to use the tool are as follows:\n"
+            "List Properties\n"
+            "---------------\n"
+            "./vehicle-hal-tool -l \n"
+            "Lists the various properties defined in HAL implementation. Use this to check if "
+            "the HAL implementation is correctly set up and exposing the capabilities correctly.\n"
+
+            "Get Properties\n"
+            "---------------\n"
+            "./vehicle-hal-tool -m get -p <prop> -t <type> [-v <vehicle_prop_value>]\n"
+            "Example: ./vehicle-hal-tool -m get -p 1028 -t 3 # VEHICLE_PROPERTY_DRIVING_STATUS\n"
+            "./vehicle-hal-tool -m get -p 257 -t 1 # VEHICLE_PROPERTY_INFO_MAKE\n"
+            "./vehicle-hal-tool -m get -p 2049 -t 19 -v \"3 0 0 0\"\n"
+            "                                 # VEHICLE_PROPERTY_RADIO_PRESET\n"
+            "with preset value set to 3.\n\n"
+            "Set properties\n"
+            "--------------\n"
+            "./vehicle-hal-tool -m set -p 10 -t 1 -v random_property\n"
+            "Set properties may not be applicable to most properties\n\n"
+            "Subscribe properties\n"
+            "--------------------\n"
+            "Subscribes to be notified about a property change (depending on whether\n"
+            "it is a on change property or a continuous property) for seconds provided\n"
+            "as -w paramter.\n"
+            "./vehicle-hal-tool -m sub -p 1028 -w 10\n"
+    );
+}
+
+void list_all_properties(vehicle_hw_device_t *device) {
+    int num_configs = -1;
+    const vehicle_prop_config_t *configs = device->list_properties(device, &num_configs);
+    if (num_configs < 0) {
+        printf("List configs error. %d", num_configs);
+        exit(1);
+    }
+
+    printf("Listing configs\n--------------------\n");
+    int i = 0;
+    for (i = 0; i < num_configs; i++) {
+        const vehicle_prop_config_t *config_temp = configs + i;
+        printf("Property ID: %d\n"
+               "Property config_flags: %d\n"
+               "Property change mode: %d\n"
+               "Property min sample rate: %f\n"
+               "Property max sample rate: %f\n",
+               config_temp->prop, config_temp->config_flags, config_temp->change_mode,
+               config_temp->min_sample_rate, config_temp->max_sample_rate);
+    }
+}
+
+static void print_property(const vehicle_prop_value_t *data) {
+    switch (data->value_type) {
+        case VEHICLE_VALUE_TYPE_STRING:
+            printf("Value type: STRING\n Size: %d\n", data->value.str_value.len);
+            // This implementation only supports ASCII.
+            char *ascii_out = (char *) malloc((data->value.str_value.len + 1) * sizeof(char));
+            memcpy(ascii_out, data->value.str_value.data, data->value.str_value.len);
+            ascii_out[data->value.str_value.len] = '\0';
+            printf("Value Type: STRING %s\n", ascii_out);
+            break;
+        case VEHICLE_VALUE_TYPE_BYTES:
+            printf("Value type: BYTES\n Size: %d", data->value.bytes_value.len);
+            for (int i = 0; i < data->value.bytes_value.len; i++) {
+                if ((i % 16) == 0) {
+                    printf("\n %04X: ", i);
+                }
+                printf("%02X ", data->value.bytes_value.data[i]);
+            }
+            printf("\n");
+            break;
+        case VEHICLE_VALUE_TYPE_BOOLEAN:
+            printf("Value type: BOOLEAN\nValue: %d\n", data->value.boolean_value);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
+            printf("Value type: ZONED_BOOLEAN\nZone: %d\n", data->zone);
+            printf("Value: %d\n", data->value.boolean_value);
+            break;
+        case VEHICLE_VALUE_TYPE_INT64:
+            printf("Value type: INT64\nValue: %" PRId64 "\n", data->value.int64_value);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT:
+            printf("Value type: FLOAT\nValue: %f\n", data->value.float_value);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
+            printf("Value type: FLOAT_VEC2\nValue[0]: %f ", data->value.float_array[0]);
+            printf("Value[1]: %f\n", data->value.float_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
+            printf("Value type: FLOAT_VEC3\nValue[0]: %f ", data->value.float_array[0]);
+            printf("Value[1]: %f ", data->value.float_array[1]);
+            printf("Value[2]: %f\n", data->value.float_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
+            printf("Value type: FLOAT_VEC4\nValue[0]: %f ", data->value.float_array[0]);
+            printf("Value[1]: %f ", data->value.float_array[1]);
+            printf("Value[2]: %f ", data->value.float_array[2]);
+            printf("Value[3]: %f\n", data->value.float_array[3]);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32:
+            printf("Value type: INT32\nValue: %d\n", data->value.int32_value);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC2:
+            printf("Value type: INT32_VEC2\nValue[0]: %d ", data->value.int32_array[0]);
+            printf("Value[1]: %d\n", data->value.int32_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC3:
+            printf("Value type: INT32_VEC3\nValue[0]: %d ", data->value.int32_array[0]);
+            printf("Value[1]: %d ", data->value.int32_array[1]);
+            printf("Value[2]: %d\n", data->value.int32_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC4:
+            printf("Value type: INT32_VEC4\nValue[0]: %d ", data->value.int32_array[0]);
+            printf("Value[1]: %d ", data->value.int32_array[1]);
+            printf("Value[2]: %d ", data->value.int32_array[2]);
+            printf("Value[3]: %d\n", data->value.int32_array[3]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
+            printf("Value type: ZONED_FLOAT\nZone: %d ", data->zone);
+            printf("Value: %f\n", data->value.float_value);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
+            printf("Value type: ZONED_FLOAT_VEC2\nZone: %d ", data->zone);
+            printf("Value[0]: %f", data->value.float_array[0]);
+            printf("Value[1]: %f\n", data->value.float_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+            printf("Value type: ZONED_FLOAT_VEC3\nZone: %d ", data->zone);
+            printf("Value[0]: %f ", data->value.float_array[0]);
+            printf("Value[1]: %f ", data->value.float_array[1]);
+            printf("Value[2]: %f\n", data->value.float_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
+            printf("Value type: ZONED_FLOAT_VEC4\nZone: %d ", data->zone);
+            printf("Value[0]: %f ", data->value.float_array[0]);
+            printf("Value[1]: %f ", data->value.float_array[1]);
+            printf("Value[2]: %f ", data->value.float_array[2]);
+            printf("Value[3]: %f\n", data->value.float_array[3]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32:
+            printf("Value type: ZONED_INT32\nZone: %d ", data->zone);
+            printf("Value: %d\n", data->value.int32_value);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
+            printf("Value type: ZONED_INT32_VEC2\nZone: %d ", data->zone);
+            printf("Value[0]: %d ", data->value.int32_array[0]);
+            printf("Value[1]: %d\n", data->value.int32_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+            printf("Value type: ZONED_INT32_VEC3\nZone: %d ", data->zone);
+            printf("Value[0]: %d ", data->value.int32_array[0]);
+            printf("Value[1]: %d ", data->value.int32_array[1]);
+            printf("Value[2]: %d\n", data->value.int32_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
+            printf("Value type: ZONED_INT32_VEC4\nZone: %d ", data->zone);
+            printf("Value[0]: %d ", data->value.int32_array[0]);
+            printf("Value[1]: %d ", data->value.int32_array[1]);
+            printf("Value[2]: %d ", data->value.int32_array[2]);
+            printf("Value[3]: %d\n", data->value.int32_array[3]);
+            break;
+        default:
+            printf("Value type not yet handled: %d.\n", data->value_type);
+    }
+}
+
+void get_property(
+    vehicle_hw_device_t *device, int32_t property, int32_t type, char *value_string) {
+    vehicle_prop_value_t *data = (vehicle_prop_value_t *) malloc (sizeof(vehicle_prop_value_t));
+
+    // Parse the string according to type.
+    if (value_string != NULL && strlen(value_string) > 0) {
+        switch (type) {
+            case VEHICLE_VALUE_TYPE_INT32:
+                sscanf(value_string, "%d", &(data->value.int32_value));
+                break;
+            case VEHICLE_VALUE_TYPE_INT32_VEC4:
+            {
+                int32_t vec[4];
+                sscanf(value_string, "%d %d %d %d", &vec[0], &vec[1], &vec[2], &vec[3]);
+                memcpy(data->value.int32_array, vec, sizeof(vec));
+                break;
+            }
+            default:
+                printf("%s Setting value type not supported: %d\n", __func__, type);
+                exit(1);
+        }
+    }
+
+    data->prop = property;
+    int ret_code = device->get(device, data);
+    if (ret_code != 0) {
+        printf("Cannot get property: %d\n", ret_code);
+        exit(1);
+    }
+
+    // We simply convert the data into the type mentioned by the result of the
+    // get call.
+    printf("Get output\n------------\n");
+    print_property(data);
+    free(data);
+}
+
+void set_property(vehicle_hw_device_t *device,
+                  int32_t property,
+                  int32_t type,
+                  char *data) {
+    vehicle_prop_value_t vehicle_data;
+    vehicle_data.prop = property;
+    vehicle_data.value_type = type;
+    int32_t zone = 0;
+    float value = 0.0;
+    switch (type) {
+        case VEHICLE_VALUE_TYPE_STRING:
+            // TODO: Make the code generic to UTF8 characters.
+            vehicle_data.value.str_value.len = strlen(data);
+            vehicle_data.value.str_value.data =
+                (uint8_t *) malloc (strlen(data) * sizeof(uint8_t));
+            memcpy(vehicle_data.value.str_value.data, data, strlen(data) + 1);
+            break;
+        case VEHICLE_VALUE_TYPE_BYTES: {
+                int len = strlen(data);
+                int numBytes = (len + 1) / 3;
+                uint8_t *buf = calloc(numBytes, sizeof(uint8_t));
+                char *byte = strtok(data, " ");
+                for (int i = 0; byte != NULL && i < numBytes; i++) {
+                    buf[i] = strtol(data, NULL, 16);
+                    byte = strtok(NULL, " ");
+                }
+                vehicle_data.value.bytes_value.len = numBytes;
+                vehicle_data.value.bytes_value.data = buf;
+            }
+            break;
+        case VEHICLE_VALUE_TYPE_BOOLEAN:
+            vehicle_data.value.boolean_value = atoi(data);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
+            sscanf(data, "%d %d", &vehicle_data.zone,
+                &vehicle_data.value.boolean_value);
+            break;
+        case VEHICLE_VALUE_TYPE_INT64:
+            vehicle_data.value.int64_value = atoi(data);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT:
+            vehicle_data.value.float_value = atof(data);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
+            sscanf(data, "%f %f", &vehicle_data.value.float_array[0],
+                &vehicle_data.value.float_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
+            sscanf(data, "%f %f %f", &vehicle_data.value.float_array[0],
+                &vehicle_data.value.float_array[1],
+                &vehicle_data.value.float_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
+            sscanf(data, "%f %f %f %f", &vehicle_data.value.float_array[0],
+                &vehicle_data.value.float_array[1],
+                &vehicle_data.value.float_array[2],
+                &vehicle_data.value.float_array[3]);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32:
+            vehicle_data.value.int32_value = atoi(data);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC2:
+            sscanf(data, "%d %d", &vehicle_data.value.int32_array[0],
+                &vehicle_data.value.int32_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC3:
+            sscanf(data, "%d %d %d", &vehicle_data.value.int32_array[0],
+                &vehicle_data.value.int32_array[1],
+                &vehicle_data.value.int32_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_INT32_VEC4:
+            sscanf(data, "%d %d %d %d", &vehicle_data.value.int32_array[0],
+                &vehicle_data.value.int32_array[1],
+                &vehicle_data.value.int32_array[2],
+                &vehicle_data.value.int32_array[3]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
+            sscanf(data, "%d %f", &zone, &value);
+            vehicle_data.zone = zone;
+            vehicle_data.value.float_value = value;
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
+            sscanf(data, "%d %f %f", &vehicle_data.zone,
+                &vehicle_data.value.float_array[0],
+                &vehicle_data.value.float_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+            sscanf(data, "%d %f %f %f", &vehicle_data.zone,
+                &vehicle_data.value.float_array[0],
+                &vehicle_data.value.float_array[1],
+                &vehicle_data.value.float_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
+            sscanf(data, "%d %f %f %f %f", &vehicle_data.zone,
+                &vehicle_data.value.float_array[0],
+                &vehicle_data.value.float_array[1],
+                &vehicle_data.value.float_array[2],
+                &vehicle_data.value.float_array[3]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32:
+            sscanf(data, "%d %d", &vehicle_data.zone,
+                &vehicle_data.value.int32_value);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
+            sscanf(data, "%d %d %d", &vehicle_data.zone,
+                &vehicle_data.value.int32_array[0],
+                &vehicle_data.value.int32_array[1]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+            sscanf(data, "%d %d %d %d", &vehicle_data.zone,
+                &vehicle_data.value.int32_array[0],
+                &vehicle_data.value.int32_array[1],
+                &vehicle_data.value.int32_array[2]);
+            break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
+            sscanf(data, "%d %d %d %d %d", &vehicle_data.zone,
+                &vehicle_data.value.int32_array[0],
+                &vehicle_data.value.int32_array[1],
+                &vehicle_data.value.int32_array[2],
+                &vehicle_data.value.int32_array[3]);
+            break;
+        default:
+            printf("set_property: Value type not yet handled: %d\n", type);
+            exit(1);
+    }
+    printf("Setting Property id: %d\n", vehicle_data.prop);
+    print_property(&vehicle_data);
+
+    int ret_code = device->set(device, &vehicle_data);
+    if (ret_code != 0) {
+        printf("Cannot set property: %d\n", ret_code);
+        exit(1);
+    }
+}
+
+int vehicle_event_callback(const vehicle_prop_value_t *event_data) {
+    // Print what we got.
+    printf("Got some value from callback property: %d\n", event_data->prop);
+    printf("Timestamp: %" PRId64 "\n", event_data->timestamp);
+    print_property(event_data);
+    return 0;
+}
+
+int vehicle_error_callback(int32_t error_code, int32_t property, int32_t operation) {
+    // Print what we got.
+    printf("Error code obtained: %d\n", error_code);
+    return 0;
+}
+
+void subscribe_to_property(
+    vehicle_hw_device_t *device,
+    int32_t prop,
+    float sample_rate,
+    uint32_t wait_in_seconds) {
+    // Init the device with a callback.
+    int ret_code = device->subscribe(device, prop, 0, 0);
+    if (ret_code != 0) {
+        printf("Could not subscribe: %d\n", ret_code);
+        exit(1);
+    }
+
+    // Callbacks will happen on one of the threads created by the HAL hence we
+    // can simply sleep here and see the output.
+    sleep(wait_in_seconds);
+
+    // Unsubscribe and uninit.
+    ret_code = device->unsubscribe(device, prop);
+    if (ret_code != 0) {
+        printf("Error unsubscribing the HAL, still continuining to uninit HAL ...");
+    }
+}
+
+int main(int argc, char* argv[]) {
+    // Open the vehicle module and just ask for the list of properties.
+    const hw_module_t *hw_module = NULL;
+    int ret_code = hw_get_module(VEHICLE_HARDWARE_MODULE_ID, &hw_module);
+    if (ret_code != 0) {
+        printf("Cannot open the hw module. Does the HAL exist? %d\n", ret_code);
+        return -1;
+    }
+
+    vehicle_module_t *vehicle_module = (vehicle_module_t *)(hw_module);
+    hw_device_t *device = NULL;
+    ret_code = vehicle_module->common.methods->open(hw_module, NULL, &device);
+    if (!device) {
+        printf("Cannot open the hw device: %d\n", ret_code);
+        return -1;
+    }
+    vehicle_hw_device_t *vehicle_device = (vehicle_hw_device_t *) (device);
+    printf("HAL Loaded!\n");
+
+    vehicle_device->init(vehicle_device, vehicle_event_callback, vehicle_error_callback);
+
+    // If this is a list properties command - we check for -l command.
+    int list_properties = 0;
+    // Type of the property (see #defines in vehicle.h).
+    int property = -1;
+    // Type of the value of the property (see enum vehicle_value_type).
+    int type = -1;
+    // Whether the mode is "get" or "set".
+    char mode[100] = "";
+    // Actual value as a string representation (supports only PODs for now).
+    // TODO: Support structures and complex types in the tool.
+    char value[100] = "";
+    // Wait time for the subscribe type of calls.
+    // We keep a default in case the user does not specify one.
+    int wait_time_in_sec = 10;
+    // Sample rate for subscribe type of calls.
+    // Default value is 0 for onchange type of properties.
+    int sample_rate = 0;
+    // Int array string which represents the vehicle_value_t in array of
+    // numbers. See vehicle_prop_value_t.value.int32_array.
+    char int_array_string[1000]; int_array_string[0] = '\0';
+
+    int opt;
+    while ((opt = getopt(argc, argv, "lm:p:t:v:w:s:")) != -1) {
+        switch (opt) {
+            case 'l':
+                list_properties = 1;
+                break;
+            case 'm':
+                strcpy(mode, optarg);
+                break;
+            case 'p':
+                property = atoi(optarg);
+                break;
+            case 't':
+                type = atoi(optarg);
+                break;
+            case 'v':
+                strcpy(value, optarg);
+                break;
+            case 'w':
+                wait_time_in_sec = atoi(optarg);
+                break;
+            case 's':
+                sample_rate = atoi(optarg);
+                break;
+        }
+    }
+
+    // We should have atleast one of list properties or mode (for get or set).
+    if (!list_properties &&
+        !(!strcmp(mode, "get") || !strcmp(mode, "set") || !strcmp(mode, "sub"))) {
+        usage();
+        exit(1);
+    }
+
+    if (list_properties) {
+        printf("Listing properties...\n");
+        list_all_properties(vehicle_device);
+    } else if (!strcmp(mode, "get")) {
+        printf("Getting property ...\n");
+        if (property == -1) {
+            printf("Use -p to pass a valid Property.\n");
+            usage();
+            exit(1);
+        }
+
+        int32_t int_array_list[4];
+        int count = -1;
+        if (strlen(int_array_string) > 0) {
+            count = sscanf(int_array_string, "%d%d%d%d",
+                   &int_array_list[0], &int_array_list[1], &int_array_list[2], &int_array_list[3]);
+        }
+
+        get_property(vehicle_device, property, type, value);
+    } else if (!strcmp(mode, "set")) {
+        printf("Setting property ...\n");
+        if (property == -1 || type == -1) {
+            printf("Use -p to pass a valid Property and -t to pass a valid Type.\n");
+            usage();
+            exit(1);
+        }
+        set_property(vehicle_device, property, type, value);
+    } else if (!strcmp(mode, "sub")) {
+        printf("Subscribing property ...\n");
+        if (property == -1 || wait_time_in_sec <= 0) {
+            printf("Use -p to pass a valid property and -w to pass a valid wait time(s)\n");
+            usage();
+            exit(1);
+        }
+        subscribe_to_property(vehicle_device, property, sample_rate, wait_time_in_sec);
+    }
+
+    ret_code = vehicle_device->release(vehicle_device);
+    if (ret_code != 0) {
+        printf("Error uniniting HAL, exiting anyways.");
+    }
+    return 0;
+}
diff --git a/tests/vehicle/vehicle_test_fixtures.h b/tests/vehicle/vehicle_test_fixtures.h
new file mode 100644 (file)
index 0000000..a9572ba
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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_HAL_VEHICLE_TEST_
+#define __ANDROID_HAL_VEHICLE_TEST_
+
+#include <gtest/gtest.h>
+#include <hardware/hardware.h>
+#include <hardware/vehicle.h>
+
+namespace tests {
+
+static const uint64_t kVersion = HARDWARE_DEVICE_API_VERSION_2(1, 0, 1);
+
+class VehicleModule : public testing::Test {
+public:
+    VehicleModule() :
+        vehicle_module_(NULL) {}
+    ~VehicleModule() {}
+protected:
+    virtual void SetUp() {
+        const hw_module_t *hw_module = NULL;
+        ASSERT_EQ(0, hw_get_module(VEHICLE_HARDWARE_MODULE_ID, &hw_module))
+                    << "Can't get vehicle module";
+        ASSERT_TRUE(NULL != hw_module)
+                    << "hw_get_module didn't return a valid hardware module";
+
+        vehicle_module_ = reinterpret_cast<const vehicle_module_t*>(hw_module);
+    }
+    const vehicle_module_t* vehicle_module() { return vehicle_module_; }
+private:
+    const vehicle_module_t* vehicle_module_;
+};
+
+
+int VehicleEventCallback(const vehicle_prop_value_t* event_data) {
+    // Print what we got.
+    std::cout << "got some value from callback: "
+              << event_data->prop
+              << " uint32 value: "
+              << event_data->value.int32_value << "\n";
+    return 0;
+}
+
+ int VehicleErrorCallback(int32_t /*error_code*/, int32_t /*property*/, int32_t /*operation*/) {
+    // Do nothing.
+    return 0;
+}
+
+class VehicleDevice : public VehicleModule {
+public:
+    VehicleDevice() :
+        vehicle_device_(NULL) {}
+    ~VehicleDevice() {}
+protected:
+    virtual void SetUp() {
+        VehicleModule::SetUp();
+        hw_device_t *device = NULL;
+        ASSERT_TRUE(NULL != vehicle_module()->common.methods->open)
+                    << "Vehicle open() is unimplemented";
+        ASSERT_EQ(0, vehicle_module()->common.methods->open(
+            (const hw_module_t*)vehicle_module(), NULL, &device))
+                << "Can't open vehicle device";
+        ASSERT_TRUE(NULL != device)
+                    << "Vehicle open() returned a NULL device";
+        ASSERT_EQ(kVersion, device->version)
+                    << "Unsupported version";
+        vehicle_device_ = reinterpret_cast<vehicle_hw_device_t*>(device);
+    }
+    vehicle_hw_device_t* vehicle_device() { return vehicle_device_; }
+    vehicle_event_callback_fn callback_fn() {
+      return VehicleEventCallback;
+    }
+    vehicle_error_callback_fn error_fn() {
+      return VehicleErrorCallback;
+    }
+
+ private:
+    vehicle_hw_device_t* vehicle_device_;
+};
+
+}  // namespace tests
+
+#endif  // __ANDROID_HAL_VEHICLE_TEST_
diff --git a/tests/vehicle/vehicle_tests.cpp b/tests/vehicle/vehicle_tests.cpp
new file mode 100644 (file)
index 0000000..4c15570
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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 <gtest/gtest.h>
+#include "vehicle_test_fixtures.h"
+#include "hardware/vehicle.h"
+
+namespace tests {
+
+// Check if list_properties command exists.
+TEST_F(VehicleDevice, isThereListProperties) {
+    ASSERT_TRUE(NULL != vehicle_device()->list_properties)
+        << "list_properties() function is not implemented";
+    std::cout << "Test succeeds.\n";
+}
+
+// HAL should provide atleast one property. The output of this command should be
+// used to verify the vailidity of the function.
+TEST_F(VehicleDevice, listPropertiesMoreThanOne) {
+    vehicle_prop_config_t const* config;
+    int num_configs = -1;
+    config = vehicle_device()->list_properties(vehicle_device(), &num_configs);
+    ASSERT_TRUE(num_configs > -1) << "list_properties() call failed.";
+    ASSERT_TRUE(num_configs > 0) << "list_properties() returned zero items.";
+    std::cout << "Number of properties reported: " << num_configs << "\n";
+    for (int i = 0; i < num_configs; i++) {
+        // Print each of the properties.
+        const vehicle_prop_config_t& config_temp = config[i];
+        std::cout << "Property ID: " << config_temp.prop << "\n";
+        std::cout << "Property flags: " << config_temp.config_flags << "\n";
+        std::cout << "Property change mode: " << config_temp.change_mode << "\n";
+        std::cout << "Property min sample rate: " << config_temp.min_sample_rate << "\n";
+        std::cout << "Property max sample rate: " << config_temp.max_sample_rate << "\n\n";
+    }
+}
+
+// Test get() command.
+// The fields are hardcoded in the dummy implementation and here.
+TEST_F(VehicleDevice, getDriveState) {
+    vehicle_prop_value_t data;
+    data.prop = VEHICLE_PROPERTY_DRIVING_STATUS;
+    // Set drive_state field to EINVAL so that we can check that its valid when
+    // it comes back.
+    data.value_type = -EINVAL;
+    data.value.driving_status = -EINVAL;
+    vehicle_device()->get(vehicle_device(), &data);
+
+    // Check that retured values are not invalid.
+    ASSERT_NE(data.value_type, -EINVAL) << "Drive state value type should be integer.";
+    ASSERT_NE(data.value.driving_status, -EINVAL) << "Driving status should be positive.";
+
+    std::cout << "Driving status value type: " << data.value_type << "\n"
+              << "Driving status: " << data.value.driving_status << "\n";
+}
+
+// Test the workflows for subscribe and init/release.
+// Subscribe will return error before init() is called or after release() is
+// called.
+TEST_F(VehicleDevice, initTest) {
+    // Test that init on a new device works. When getting an instance, we are
+    // already calling 'open' on the device.
+    int ret_code =
+        vehicle_device()->init(vehicle_device(), callback_fn(), error_fn());
+    ASSERT_EQ(ret_code, 0) << "ret code: " << ret_code;
+
+    // Trying to init again should return an error.
+    ret_code = vehicle_device()->init(vehicle_device(), callback_fn(), error_fn());
+    ASSERT_EQ(ret_code, -EEXIST) << "ret code: " << ret_code;
+
+    // Uninit should always return 0.
+    ret_code = vehicle_device()->release(vehicle_device());
+    ASSERT_EQ(ret_code, 0) << "ret code: " << ret_code;
+
+    // We should be able to init again.
+    ret_code = vehicle_device()->init(vehicle_device(), callback_fn(), error_fn());
+    ASSERT_EQ(ret_code, 0) << "ret code: " << ret_code;
+
+    // Finally release.
+    ret_code = vehicle_device()->release(vehicle_device());
+    ASSERT_EQ(ret_code, 0) << "ret_code: " << ret_code;
+}
+
+// Test that subscribe works.
+// We wait for 10 seconds while which the vehicle.c can post messages from
+// within it's own thread.
+TEST_F(VehicleDevice, subscribeTest) {
+    // If the device is not init subscribe should fail off the bat.
+    int ret_code = vehicle_device()->subscribe(vehicle_device(), VEHICLE_PROPERTY_DRIVING_STATUS,
+            0, 0);
+    ASSERT_EQ(ret_code, -EINVAL) << "Return code is: " << ret_code;
+
+    // Let's init the device.
+    ret_code = vehicle_device()->init(vehicle_device(), callback_fn(), error_fn());
+    ASSERT_EQ(ret_code, 0) << "Return code is: " << ret_code;
+
+    // Subscribe should now go through.
+    ret_code = vehicle_device()->subscribe(vehicle_device(), VEHICLE_PROPERTY_DRIVING_STATUS, 0, 0);
+    ASSERT_EQ(ret_code, 0) << "Return code is: " << ret_code;
+
+    // We should start getting some messages thrown from the callback. Let's
+    // wait for 20 seconds before unsubscribing.
+    std::cout << "Sleeping for 20 seconds.";
+    sleep(20);
+    std::cout << "Waking from sleep.";
+
+    // This property does not exist, so we should get -EINVAL.
+    ret_code = vehicle_device()->unsubscribe(vehicle_device(), VEHICLE_PROPERTY_INFO_VIN);
+    ASSERT_EQ(ret_code, -EINVAL) << "Return code is: " << ret_code;
+
+    // This property exists, so we should get a success return code - also this
+    // will be a blocking call.
+    ret_code = vehicle_device()->unsubscribe(vehicle_device(), VEHICLE_PROPERTY_DRIVING_STATUS);
+    ASSERT_EQ(ret_code, 0) << "Return code is: " << ret_code;
+}
+
+}  // namespace tests