Merge "power: Adds a new power hint POWER_HINT_VR_MODE" into nyc-dev
diff --git a/include/hardware/audio_policy.h b/include/hardware/audio_policy.h
index 99cb044..bacb1e5 100644
--- a/include/hardware/audio_policy.h
+++ b/include/hardware/audio_policy.h
@@ -141,14 +141,14 @@
     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 @@
                            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 @@
 
     /* 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);
 
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
index 7772b38..1349114 100644
--- a/include/hardware/bluetooth.h
+++ b/include/hardware/bluetooth.h
@@ -89,8 +89,10 @@
     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 */
diff --git a/include/hardware/gps.h b/include/hardware/gps.h
index 354d343..a54948c 100644
--- a/include/hardware/gps.h
+++ b/include/hardware/gps.h
@@ -221,9 +221,12 @@
 typedef uint16_t AGpsRefLocationType;
 #define AGPS_REF_LOCATION_TYPE_GSM_CELLID   1
 #define AGPS_REF_LOCATION_TYPE_UMTS_CELLID  2
-#define AGPS_REG_LOCATION_TYPE_MAC          3
+#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 */
 #define AGPS_RIL_NETWORK_TYPE_MOBILE        0
 #define AGPS_RIL_NETWORK_TYPE_WIFI          1
@@ -359,7 +362,7 @@
  * If GNSS is still searching for a satellite, the corresponding state should be
  * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
  */
-typedef uint16_t GnssMeasurementState;
+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)
@@ -367,6 +370,14 @@
 #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. */
@@ -1711,10 +1722,10 @@
      *   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
+     *     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.
@@ -1737,7 +1748,7 @@
      *     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_GAL_TOW_DECODED 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.
@@ -1773,9 +1784,7 @@
      * comment at top of GnssMeasurement struct.)
      *
      * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
-     * 'drift' field as well, and
-     * GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE must be set in 'flags'
-     * field. (When providing the uncorrected pseudorange rate, do not apply the
+     * '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.
@@ -1843,6 +1852,8 @@
     /**
      * 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
      * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
@@ -2050,9 +2061,11 @@
      *
      * - For Beidou D2, this refers to the frame number, in the range of 1-120
      *
-     * - For Galileo F/NAV, this refers to the frame number, in the range of 1-N
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
      *
-     * - For Galileo I/NAV, this refers to the frame number in the range of 1-N
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
      */
     int16_t message_id;
 
@@ -2067,9 +2080,9 @@
      * - 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 subframe number in the range 1-12
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
      *
-     * - For Galileo I/NAV, this refers to the subframe number in the range 1-24
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
      */
     int16_t submessage_id;
 
@@ -2095,13 +2108,13 @@
      *   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 subframe contains 5 238-bit word (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 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 subframe contains 15 114-bit word (sync & tail
-     *   symbols excluded). Each word should be fit into 15-bytes, with MSB
-     *   first (skip B115-B120), covering a time period of 2 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;
 
diff --git a/include/hardware/hardware_properties.h b/include/hardware/hardware_properties.h
deleted file mode 100644
index 7c9bd4e..0000000
--- a/include/hardware/hardware_properties.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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_HARDWAREPROPERTIES_H
-#define ANDROID_INCLUDE_HARDWARE_HARDWAREPROPERTIES_H
-
-#include <stdint.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <hardware/hardware.h>
-
-__BEGIN_DECLS
-
-#define HARDWARE_PROPERTIES_HARDWARE_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1)
-
-/**
- * The id of this module
- */
-#define HARDWARE_PROPERTIES_HARDWARE_MODULE_ID "hardware_properties"
-
-/**
- * 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 hardware_properties_module {
-    struct hw_module_t common;
-
-    /*
-     * (*getCpuTemperatures) is called to get CPU temperatures in Celsius of
-     * each core.
-     *
-     * Returns number of cores or negative value on error.
-     *
-     */
-    ssize_t (*getCpuTemperatures)(struct hardware_properties_module *module, float **temps);
-
-    /*
-     * (*getGpuTemperatures) is called to get GPU temperatures in Celsius of
-     * each GPU.
-     *
-     * Returns number of GPUs or negative value on error.
-     *
-     */
-    ssize_t (*getGpuTemperatures)(struct hardware_properties_module *module, float **temps);
-
-    /*
-     * (*getBatteryTemperatures) is called to get battery temperatures in
-     * Celsius.
-     *
-     * Returns number of battery temperatures or negative value on error.
-     *
-     */
-    ssize_t (*getBatteryTemperatures)(struct hardware_properties_module *module, float **temps);
-
-    /*
-     * (*getCpuUsages) is called to get CPU usage information of each core:
-     * active and total times in ms since first boot.
-     *
-     * Returns number of cores or negative value on error.
-     *
-     */
-    ssize_t (*getCpuUsages)(struct hardware_properties_module *module,
-                            int64_t **active_times, int64_t **total_times);
-
-    /*
-     * (*getFanSpeeds) is called to get the fan speeds in RPM of each fan.
-     *
-     * Returns number of fans or negative value on error.
-     *
-     */
-    ssize_t (*getFanSpeeds)(struct hardware_properties_module *module,
-                        float **fan_speeds);
-} hardware_properties_module_t;
-
-__END_DECLS
-
-#endif  // ANDROID_INCLUDE_HARDWARE_HARDWAREPROPERTIES_H
diff --git a/include/hardware/thermal.h b/include/hardware/thermal.h
new file mode 100644
index 0000000..7fdf682
--- /dev/null
+++ b/include/hardware/thermal.h
@@ -0,0 +1,200 @@
+/*
+ * 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;
+} 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
index 4a080a1..9086d1c 100644
--- a/include/hardware/vehicle.h
+++ b/include/hardware/vehicle.h
@@ -1030,9 +1030,11 @@
     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,
 };
 
 /**
@@ -1061,30 +1063,6 @@
 };
 
 /**
- * Error code used in HAL implemnentation. Follows utils/Errors.h
- */
-enum vehicle_error_code {
-    VEHICLE_NO_ERROR    = 0x0,
-    VEHICLE_ERROR_UNKNOWN       = (-2147483647 - 1), // INT32_MIN value
-    VEHICLE_ERROR_NO_MEMORY           = -12, //ENOMEM
-    VEHICLE_ERROR_INVALID_OPERATION   = -38, //ENOSYS
-    VEHICLE_ERROR_BAD_VALUE           = -22, //EINVAL
-    VEHICLE_ERROR_BAD_TYPE            = (VEHICLE_ERROR_UNKNOWN + 1),
-    VEHICLE_ERROR_NAME_NOT_FOUND      = -2, //ENOENT
-    VEHICLE_ERROR_PERMISSION_DENIED   = -1, //EPERM
-    VEHICLE_ERROR_NO_INIT             = -19, //ENODEV
-    VEHICLE_ERROR_ALREADY_EXISTS      = -17, //EEXIST
-    VEHICLE_ERROR_DEAD_OBJECT         = -32, //EPIPE
-    VEHICLE_ERROR_FAILED_TRANSACTION  = (VEHICLE_ERROR_UNKNOWN + 2),
-    VEHICLE_ERROR_BAD_INDEX           = -75, //EOVERFLOW
-    VEHICLE_ERROR_NOT_ENOUGH_DATA     = -61, //ENODATA
-    VEHICLE_ERROR_WOULD_BLOCK         = -11, //EWOULDBLOCK
-    VEHICLE_ERROR_TIMED_OUT           = -110, //ETIMEDOUT
-    VEHICLE_ERROR_UNKNOWN_TRANSACTION = -74, //EBADMSG
-    VEHICLE_FDS_NOT_ALLOWED     = (VEHICLE_ERROR_UNKNOWN + 7),
-};
-
-/**
  * This describes how value of property can change.
  */
 enum vehicle_prop_change_mode {
@@ -1287,52 +1265,6 @@
  */
 typedef vehicle_str_t vehicle_bytes_t;
 
-typedef struct vehicle_zoned_int32 {
-    union {
-        int32_t zone;
-        int32_t seat;
-        int32_t window;
-    };
-    int32_t value;
-} vehicle_zoned_int32_t;
-
-typedef struct vehicle_zoned_int32_array {
-    union {
-        int32_t zone;
-        int32_t seat;
-        int32_t window;
-    };
-    int32_t values[3];
-} vehicle_zoned_int32_array_t;
-
-typedef struct vehicle_zoned_float {
-    union {
-        int32_t zone;
-        int32_t seat;
-        int32_t window;
-    };
-    float value;
-} vehicle_zoned_float_t;
-
-typedef struct vehicle_zoned_float_array {
-    union {
-        int32_t zone;
-        int32_t seat;
-        int32_t window;
-    };
-    float values[3];
-} vehicle_zoned_float_array_t;
-
-typedef struct vehicle_zoned_boolean {
-    union {
-        int32_t zone;
-        int32_t seat;
-        int32_t window;
-    };
-    vehicle_boolean_t value;
-} vehicle_zoned_boolean_t;
-
-
 typedef struct vehicle_prop_config {
     int32_t prop;
 
@@ -1358,17 +1290,13 @@
      * 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 {
         /**
-         * For generic configuration information
-         */
-        int32_t config_flags;
-
-        /**
          * The value is derived by ORing one or more of enum vehicle_zone members.
          */
         int32_t vehicle_zone_flags;
@@ -1376,7 +1304,16 @@
         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.
@@ -1419,6 +1356,8 @@
      *      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;
@@ -1428,6 +1367,8 @@
 
     /**
      * 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;
@@ -1457,59 +1398,30 @@
  * below). We define these properties outside in global scope so that HAL
  * implementation and HAL users (JNI) can typecast vehicle_hvac correctly.
  */
-typedef vehicle_zoned_int32_t vehicle_hvac_fan_speed_t;
-
-typedef vehicle_zoned_int32_t vehicle_hvac_fan_direction_t;
-
-typedef vehicle_zoned_float_t vehicle_hvac_zone_temperature_t;
-
-//TODO Typical seat heat/cooling is done in fixed steps. Needs better definition.
-//typedef struct vehicle_hvac_seat_temperature {
-//    // Value should be one of enum vehicle_seat.
-//    int32_t seat;
-//    float temperature;
-//} vehicle_hvac_heated_seat_temperature_t;
-
-typedef vehicle_zoned_boolean_t vehicle_hvac_defrost_on_t;
-
-typedef vehicle_zoned_boolean_t vehicle_hvac_ac_on_t;
-
-typedef vehicle_boolean_t vehicle_hvac_max_ac_on_t;
-
-typedef vehicle_boolean_t vehicle_hvac_max_defrost_on_t;
-
-typedef vehicle_boolean_t vehicle_hvac_recirc_on_t;
-
-typedef vehicle_boolean_t vehicle_hvac_dual_on_t;
-
 typedef struct vehicle_hvac {
     /**
      * Define one structure for each possible HVAC property.
      * NOTES:
-     * a) Zone is defined in enum vehicle_zone.
-     * b) Fan speed is a number from (0 - 6) where 6 is the highest speed. (TODO define enum)
-     * c) Temperature is a floating point Celcius scale.
-     * d) Direction is defined in enum vehicle_fan_direction.
+     * 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 {
-        vehicle_hvac_fan_speed_t fan_speed;
-        vehicle_hvac_fan_direction_t fan_direction;
-        vehicle_hvac_ac_on_t ac_on;
-        vehicle_hvac_max_ac_on_t max_ac_on;
-        vehicle_hvac_max_defrost_on_t max_defrost_on;
-        vehicle_hvac_recirc_on_t recirc_on;
-        vehicle_hvac_dual_on_t dual_on;
+        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_hvac_zone_temperature_t temperature_current;
-        vehicle_hvac_zone_temperature_t temperature_set;
+        float temperature_current;
+        float temperature_set;
 
-        //TODO Heated seat.
-        //vehicle_hvac_heated_seat_t heated_seat;
-
-        vehicle_hvac_defrost_on_t defrost_on;
+        vehicle_boolean_t defrost_on;
     };
 } vehicle_hvac_t;
 
@@ -1540,11 +1452,6 @@
     vehicle_str_t str_value;
     vehicle_bytes_t bytes_value;
     vehicle_boolean_t boolean_value;
-    vehicle_zoned_int32_t zoned_int32_value;
-    vehicle_zoned_int32_array_t zoned_int32_array;
-    vehicle_zoned_float_t zoned_float_value;
-    vehicle_zoned_float_array_t zoned_float_array;
-    vehicle_zoned_boolean_t zoned_boolean_value;
 
     // Vehicle Information.
     vehicle_str_t info_vin;
@@ -1615,6 +1522,15 @@
     /** 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;
 
@@ -1645,11 +1561,10 @@
 };
 
 /*
- * Suggests that an error condition has occured. error_code should be one of
- * enum vehicle_error_code.
+ * Suggests that an error condition has occurred.
  *
- * @param error_code Error code. It should be one of enum vehicle_error_code.
- *                   See error code for details.
+ * @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
@@ -1703,14 +1618,29 @@
      * 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 freeing memory for the pointer.
+     * 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.
diff --git a/modules/Android.mk b/modules/Android.mk
index 3dc4ca6..3bd0943 100644
--- a/modules/Android.mk
+++ b/modules/Android.mk
@@ -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 vehicle hardware_properties vr
+	tv_input fingerprint input vehicle thermal vr
 include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/hardware_properties/hardware_properties.c b/modules/hardware_properties/hardware_properties.c
deleted file mode 100644
index 89ef423..0000000
--- a/modules/hardware_properties/hardware_properties.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define LOG_TAG "HardwarePropertiesHAL"
-#include <utils/Log.h>
-
-#include <hardware/hardware.h>
-#include <hardware/hardware_properties.h>
-
-static ssize_t get_device_temperatures(
-    struct hardware_properties_module *module, float **temps) {
-    *temps = NULL;
-    errno = ENOSYS;
-    ALOGE("getDeviceTemperatures: %s", strerror(errno));
-    return -1;
-}
-
-static ssize_t get_cpu_usages(struct hardware_properties_module *module,
-                              int64_t **active_times, int64_t **total_times) {
-    *active_times = NULL;
-    *total_times = NULL;
-    errno = ENOSYS;
-    ALOGE("getCpuUsages: %s", strerror(errno));
-    return -1;
-}
-
-static ssize_t get_fan_speeds(struct hardware_properties_module *module,
-                              float **fan_speeds) {
-    *fan_speeds = NULL;
-    errno = ENOSYS;
-    ALOGE("getFanSpeeds: %s", strerror(errno));
-    return -1;
-}
-
-static struct hw_module_methods_t hardware_properties_module_methods = {
-    .open = NULL,
-};
-
-struct hardware_properties_module HAL_MODULE_INFO_SYM = {
-    .common = {
-        .tag = HARDWARE_MODULE_TAG,
-        .module_api_version = HARDWARE_PROPERTIES_HARDWARE_MODULE_API_VERSION_0_1,
-        .hal_api_version = HARDWARE_HAL_API_VERSION,
-        .id = HARDWARE_PROPERTIES_HARDWARE_MODULE_ID,
-        .name = "Default Hardware Properties HAL",
-        .author = "The Android Open Source Project",
-        .methods = &hardware_properties_module_methods,
-    },
-
-    .getCpuTemperatures = get_device_temperatures,
-    .getGpuTemperatures = get_device_temperatures,
-    .getBatteryTemperatures = get_device_temperatures,
-    .getCpuUsages = get_cpu_usages,
-    .getFanSpeeds = get_fan_speeds,
-};
diff --git a/modules/radio/Android.mk b/modules/radio/Android.mk
index e7647b2..221424f 100644
--- a/modules/radio/Android.mk
+++ b/modules/radio/Android.mk
@@ -17,17 +17,21 @@
 # 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
diff --git a/modules/radio/radio_hal_tool.c b/modules/radio/radio_hal_tool.c
index f5c7637..05d872e 100644
--- a/modules/radio/radio_hal_tool.c
+++ b/modules/radio/radio_hal_tool.c
@@ -151,7 +151,7 @@
             case RADIO_METADATA_TYPE_CLOCK:
                 printf("UTC Epoch: %lld\n"
                        "UTC Offset: %d\n",
-                       ((radio_metadata_clock_t *) value)->utc_seconds_since_epoch,
+                       (long long)((radio_metadata_clock_t *) value)->utc_seconds_since_epoch,
                        ((radio_metadata_clock_t *) value)->timezone_offset_in_minutes);
         }
     }
diff --git a/modules/soundtrigger/Android.mk b/modules/soundtrigger/Android.mk
index 325980c..bb58053 100644
--- a/modules/soundtrigger/Android.mk
+++ b/modules/soundtrigger/Android.mk
@@ -22,6 +22,5 @@
 LOCAL_SRC_FILES := sound_trigger_hw.c
 LOCAL_SHARED_LIBRARIES := liblog libcutils
 LOCAL_MODULE_TAGS := optional
-LOCAL_32_BIT_ONLY := true
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/hardware_properties/Android.mk b/modules/thermal/Android.mk
similarity index 83%
rename from modules/hardware_properties/Android.mk
rename to modules/thermal/Android.mk
index 41c02ea..80ad78a 100644
--- a/modules/hardware_properties/Android.mk
+++ b/modules/thermal/Android.mk
@@ -16,10 +16,11 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := hardware_properties.default
+LOCAL_MODULE := thermal.default
 LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := hardware_properties.c
-LOCAL_SHARED_LIBRARIES := liblog
+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
index 0000000..c45d87a
--- /dev/null
+++ b/modules/thermal/thermal.c
@@ -0,0 +1,181 @@
+/*
+ * 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,
+                };
+            }
+            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,
+};
diff --git a/modules/vehicle/vehicle.c b/modules/vehicle/vehicle.c
index 564630c..d8aa2cb 100644
--- a/modules/vehicle/vehicle.c
+++ b/modules/vehicle/vehicle.c
@@ -245,6 +245,21 @@
     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.
@@ -377,7 +392,7 @@
                     return;
                 }
                 if (sub->impl->error_fn_ != NULL) {
-                    sub->impl->error_fn_(VEHICLE_ERROR_UNKNOWN, VEHICLE_PROPERTY_INVALID,
+                    sub->impl->error_fn_(-EINVAL, VEHICLE_PROPERTY_INVALID,
                             VEHICLE_OPERATION_GENERIC);
                 } else {
                     ALOGE("Error function is null");
@@ -538,6 +553,7 @@
     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;
diff --git a/tests/vehicle/vehicle-hal-tool.c b/tests/vehicle/vehicle-hal-tool.c
index 8cc8476..3c3922f 100755
--- a/tests/vehicle/vehicle-hal-tool.c
+++ b/tests/vehicle/vehicle-hal-tool.c
@@ -89,6 +89,121 @@
     }
 }
 
+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));
@@ -122,45 +237,7 @@
     // We simply convert the data into the type mentioned by the result of the
     // get call.
     printf("Get output\n------------\n");
-    switch (data->value_type) {
-        case VEHICLE_VALUE_TYPE_FLOAT:
-            printf("Value type: FLOAT\nValue: %f\n", data->value.float_value);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32:
-            printf("Value type: INT32\nValue: %d\n", data->value.int32_value);
-            break;
-        case VEHICLE_VALUE_TYPE_INT64:
-            printf("Value type: INT64\nValue: %" PRId64 "\n", data->value.int64_value);
-            break;
-        case VEHICLE_VALUE_TYPE_BOOLEAN:
-            printf("Value type: BOOLEAN\nValue: %d\n", data->value.boolean_value);
-            break;
-        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: %s\n", ascii_out);
-            break;
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
-            printf("Value type: ZONED_FLOAT\nZone: %d\n", data->value.zoned_float_value.zone);
-            printf("Value type: ZONED_FLOAT\nValue: %f\n", data->value.zoned_float_value.value);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32_VEC3:
-            printf("Value type: INT32_VEC3\nValue[0]: %d\n", data->value.int32_array[0]);
-            printf("Value type: INT32_VEC3\nValue[1]: %d\n", data->value.int32_array[1]);
-            printf("Value type: INT32_VEC3\nValue[2]: %d\n", data->value.int32_array[2]);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32_VEC4:
-            printf("Value type: INT32_VEC4\nValue[0]: %d\n", data->value.int32_array[0]);
-            printf("Value type: INT32_VEC4\nValue[1]: %d\n", data->value.int32_array[1]);
-            printf("Value type: INT32_VEC4\nValue[2]: %d\n", data->value.int32_array[2]);
-            printf("Value type: INT32_VEC4\nValue[3]: %d\n", data->value.int32_array[3]);
-            break;
-        default:
-            printf("Value type not yet handled: %d.\n", data->value_type);
-    }
+    print_property(data);
     free(data);
 }
 
@@ -174,18 +251,6 @@
     int32_t zone = 0;
     float value = 0.0;
     switch (type) {
-        case VEHICLE_VALUE_TYPE_FLOAT:
-            vehicle_data.value.float_value = atof(data);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32:
-            vehicle_data.value.int32_value = atoi(data);
-            break;
-        case VEHICLE_VALUE_TYPE_INT64:
-            vehicle_data.value.int64_value = atoi(data);
-            break;
-        case VEHICLE_VALUE_TYPE_BOOLEAN:
-            vehicle_data.value.boolean_value = atoi(data);
-            break;
         case VEHICLE_VALUE_TYPE_STRING:
             // TODO: Make the code generic to UTF8 characters.
             vehicle_data.value.str_value.len = strlen(data);
@@ -193,45 +258,117 @@
                 (uint8_t *) malloc (strlen(data) * sizeof(uint8_t));
             memcpy(vehicle_data.value.str_value.data, data, strlen(data) + 1);
             break;
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
-            sscanf(data, "%d %f", &zone, &value);
-            vehicle_data.value.zoned_float_value.zone = zone;
-            vehicle_data.value.zoned_float_value.value = value;
-            printf("Value type: ZONED_FLOAT\nZone: %d\n", vehicle_data.value.zoned_float_value.zone);
-            printf("Value type: ZONED_FLOAT\nValue: %f\n", vehicle_data.value.zoned_float_value.value);
+        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]);
-            printf("Setting: Value type INT32_VEC2: %d %d\n",
-                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]);
-            printf("Setting: Value type INT32_VEC3: %d %d %d\n",
-                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]);
-            printf("Setting: Value type INT32_VEC4: %d %d %d %d\n",
-                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("Property id: %d\n", vehicle_data.prop);
+    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);
@@ -243,57 +380,16 @@
     // Print what we got.
     printf("Got some value from callback property: %d\n", event_data->prop);
     printf("Timestamp: %" PRId64 "\n", event_data->timestamp);
-    char *ascii_out;
-    switch (event_data->value_type) {
-        case VEHICLE_VALUE_TYPE_FLOAT:
-            printf("Float value: %f\n", event_data->value.float_value);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32:
-            printf("int32 value: %d\n", event_data->value.int32_value);
-            break;
-        case VEHICLE_VALUE_TYPE_INT64:
-            printf("int64 value: %" PRId64 "\n", event_data->value.int64_value);
-            break;
-        case VEHICLE_VALUE_TYPE_BOOLEAN:
-            printf("bool value: %d\n", event_data->value.boolean_value);
-            break;
-        case VEHICLE_VALUE_TYPE_STRING:
-            // TODO: Make the code generic to UTF8 characters.
-            ascii_out = (char *) malloc ((event_data->value.str_value.len + 1) * sizeof(char));
-            memcpy(ascii_out, event_data->value.str_value.data, event_data->value.str_value.len);
-            ascii_out[event_data->value.str_value.len] = '\0';
-            printf("Ascii value: %s\n", ascii_out);
-            break;
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
-            printf("Value type: ZONED_FLOAT\nZone: %d\n", event_data->value.zoned_float_value.zone);
-            printf("Value type: ZONED_FLOAT\nValue: %f\n", event_data->value.zoned_float_value.value);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32_VEC2:
-            printf("Value type: INT32_VEC2\nValue[0]: %d Value[1] %d\n",
-                  event_data->value.int32_array[0], event_data->value.int32_array[1]);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32_VEC3:
-            printf("Value type: INT32_VEC3\nValue[0]: %d Value[1] %d Value[2] %d\n",
-                  event_data->value.int32_array[0], event_data->value.int32_array[1],
-                  event_data->value.int32_array[2]);
-            break;
-        case VEHICLE_VALUE_TYPE_INT32_VEC4:
-            printf("Value type: INT32_VEC4\nValue[0]: %d Value[1] %d Value[2] %d Value[3] %d\n",
-                  event_data->value.int32_array[0], event_data->value.int32_array[1],
-                  event_data->value.int32_array[2], event_data->value.int32_array[3]);
-            break;
-        default:
-            printf("vehicle_event_callback: Value type not yet handled: %d\n",
-                    event_data->value_type);
-            exit(1);
-    }
+    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,
@@ -364,7 +460,6 @@
     char int_array_string[1000]; int_array_string[0] = '\0';
 
     int opt;
-    //TODO allow passing zone
     while ((opt = getopt(argc, argv, "lm:p:t:v:w:s:")) != -1) {
         switch (opt) {
             case 'l':