Merge "vehicle hal refactoring from hal review" into nyc-dev
diff --git a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
index 7c052f9..adb1281 100644
--- a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
+++ b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
@@ -30,6 +30,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -136,17 +137,93 @@
     public static class CarHvacBaseProperty {
         protected final int mPropertyId;
         protected final int mType;
-        protected final int mZone;
+        protected final int mZones;
 
-        public CarHvacBaseProperty(int propId, int type, int zone) {
+        public CarHvacBaseProperty(int propId, int type, int zones) {
             mPropertyId = propId;
             mType       = type;
-            mZone       = zone;
+            mZones       = zones;
         }
 
-        public int getPropertyId() { return mPropertyId; }
-        public int getType()       { return mType; }
-        public int getZone()       { return mZone; }
+        public int getPropertyId() {
+            return mPropertyId;
+        }
+
+        public int getType() {
+            return mType;
+        }
+
+        /**
+         * Return bit flags of supported zones.
+         */
+        public int getZones()       { return mZones; }
+
+        /**
+         * Return an active zone for Hvac event. This will return only one zone.
+         * If there is no valid zone, this will return 0.
+         */
+        public int getZone() {
+            if (mZones == 0) {
+                return 0;
+            }
+            int flag = 0x1;
+            for (int i = 0; i < 32; i++) {
+                if ((flag & mZones) != 0) {
+                    return flag;
+                }
+                flag <<= 1;
+            }
+            return 0;
+        }
+
+        public static int zoneToIndex(int zone) {
+            if (zone == 0) {
+                return 0;
+            }
+            int flag = 0x1;
+            for (int i = 0; i < 32; i++) {
+                if ((flag & zone) != 0) {
+                    return i;
+                }
+                flag <<= 1;
+            }
+            return 0;
+        }
+
+        public static int getNumZones(int zones) {
+            int numZones = 0;
+            int flag = 0x1;
+            for (int i = 0; i < 32; i++) {
+                if ((flag & zones) != 0) {
+                    numZones++;
+                }
+                flag <<= 1;
+            }
+            return numZones;
+        }
+
+        @Override
+        public String toString() {
+            return "CarHvacBaseProperty [mPropertyId=0x" + Integer.toHexString(mPropertyId) +
+                    ", mType=0x" + Integer.toHexString(mType) +
+                    ", mZones=0x" + Integer.toHexString(mZones) + "]";
+        }
+
+        protected void assertZonedProperty() {
+            if (mPropertyId <= MAX_GLOBAL_PROPETY_ID) {
+                throw new IllegalArgumentException(
+                        "assertZonedProperty called for non-zoned property 0x" +
+                                Integer.toHexString(mPropertyId));
+            }
+        }
+
+        protected void assertNonZonedProperty() {
+            if (mPropertyId > MAX_GLOBAL_PROPETY_ID) {
+                throw new IllegalArgumentException(
+                        "assertNonZonedProperty called for zoned property 0x" +
+                        Integer.toHexString(mPropertyId));
+            }
+        }
     }
 
     public static final class CarHvacBooleanProperty extends CarHvacBaseProperty {
@@ -156,65 +233,150 @@
     }
 
     public static final class CarHvacFloatProperty extends CarHvacBaseProperty {
-        private float mMaxValue;
-        private float mMinValue;
+        private final float[] mMaxValues;
+        private final float[] mMinValues;
 
-        public CarHvacFloatProperty(int propId, int zone, float max, float min) {
-            super(propId, PROPERTY_TYPE_FLOAT, zone);
-            mMaxValue      = max;
-            mMinValue      = min;
+        public CarHvacFloatProperty(int propId, int zones, float[] maxs, float mins[]) {
+            super(propId, PROPERTY_TYPE_FLOAT, zones);
+            int expectedLength = zones == 0 ? 1 : getNumZones(zones);
+            if (maxs.length != expectedLength || mins.length != expectedLength) {
+                throw new IllegalArgumentException("Expected length:" + expectedLength +
+                        " while maxs length:" + maxs.length + " mins length:" + mins.length +
+                        " property:0x" + Integer.toHexString(propId));
+            }
+            mMaxValues      = maxs;
+            mMinValues      = mins;
         }
 
-        public float getMaxValue()      { return mMaxValue; }
-        public float getMinValue()      { return mMinValue; }
+        /**
+         * Get max value. Should be used only for non-zoned property.
+         */
+        public float getMaxValue() {
+            assertNonZonedProperty();
+            return mMaxValues[0];
+        }
+
+        /**
+         * Get min value. Should be used only for non-zoned property.
+         */
+        public float getMinValue() {
+            assertNonZonedProperty();
+            return mMinValues[0];
+        }
+
+        public float getMaxValue(int zone) {
+            assertZonedProperty();
+            return mMaxValues[zoneToIndex(zone)];
+        }
+
+        public float getMinValue(int zone) {
+            assertZonedProperty();
+            return mMinValues[zoneToIndex(zone)];
+        }
+
+        @Override
+        public String toString() {
+            return "CarHvacFloatProperty [mMaxValues=" + Arrays.toString(mMaxValues)
+                    + ", mMinValues=" + Arrays.toString(mMinValues) + " " + super.toString() + "]";
+        }
     }
 
     public static final class CarHvacIntProperty extends CarHvacBaseProperty {
-        private int mMaxValue;
-        private int mMinValue;
+        private int[] mMaxValues;
+        private int[] mMinValues;
 
-        public CarHvacIntProperty(int propId, int zone, int max, int min) {
-            super(propId, PROPERTY_TYPE_INT, zone);
-            mMaxValue      = max;
-            mMinValue      = min;
+        public CarHvacIntProperty(int propId, int zones, int[] maxs, int[] mins) {
+            super(propId, PROPERTY_TYPE_INT, zones);
+            int expectedLength = zones == 0 ? 1 : getNumZones(zones);
+            if (maxs.length != expectedLength || mins.length != expectedLength) {
+                throw new IllegalArgumentException("Expected length:" + expectedLength +
+                        " while maxs length:" + maxs.length + " mins length:" + mins.length +
+                        " property:0x" + Integer.toHexString(propId));
+            }
+            mMaxValues      = maxs;
+            mMinValues      = mins;
         }
 
-        public int getMaxValue()      { return mMaxValue; }
-        public int getMinValue()      { return mMinValue; }
+        /**
+         * Get max value. Should be used only for non-zoned property.
+         */
+        public int getMaxValue() {
+            assertNonZonedProperty();
+            return mMaxValues[0];
+        }
+
+        /**
+         * Get min value. Should be used only for non-zoned property.
+         */
+        public int getMinValue() {
+            assertNonZonedProperty();
+            return mMinValues[0];
+        }
+
+        public int getMaxValue(int zone) {
+            assertZonedProperty();
+            return mMaxValues[zoneToIndex(zone)];
+        }
+
+        public int getMinValue(int zone) {
+            assertZonedProperty();
+            return mMinValues[zoneToIndex(zone)];
+        }
+
+        @Override
+        public String toString() {
+            return "CarHvacIntProperty [mMaxValues=" + Arrays.toString(mMaxValues)
+                    + ", mMinValues=" + Arrays.toString(mMinValues) + " " + super.toString() + "]";
+        }
     }
 
     public static final class CarHvacBooleanValue extends CarHvacBaseProperty {
         private boolean mValue;
 
-        public CarHvacBooleanValue(int propId, int zone, boolean value) {
-            super(propId, PROPERTY_TYPE_BOOLEAN, zone);
+        public CarHvacBooleanValue(int propId, int zones, boolean value) {
+            super(propId, PROPERTY_TYPE_BOOLEAN, zones);
             mValue = value;
         }
 
         public boolean getValue() { return mValue; }
+
+        @Override
+        public String toString() {
+            return "CarHvacBooleanValue [mValue=" + mValue + " " + super.toString() + "]";
+        }
     }
 
 
     public static final class CarHvacFloatValue extends CarHvacBaseProperty {
         private float mValue;
 
-        public CarHvacFloatValue(int propId, int zone, float value) {
-            super(propId, PROPERTY_TYPE_FLOAT, zone);
+        public CarHvacFloatValue(int propId, int zones, float value) {
+            super(propId, PROPERTY_TYPE_FLOAT, zones);
             mValue = value;
         }
 
         public float getValue() { return mValue; }
+
+        @Override
+        public String toString() {
+            return "CarHvacFloatValue [mValue=" + mValue + " " + super.toString() + "]";
+        }
     }
 
     public static final class CarHvacIntValue extends CarHvacBaseProperty {
         private int mValue;
 
-        public CarHvacIntValue(int propId, int zone, int value) {
-            super(propId, PROPERTY_TYPE_INT, zone);
+        public CarHvacIntValue(int propId, int zones, int value) {
+            super(propId, PROPERTY_TYPE_INT, zones);
             mValue = value;
         }
 
         public int getValue() { return mValue; }
+
+        @Override
+        public String toString() {
+            return "CarHvacIntValue [mValue=" + mValue + " " + super.toString() + "]";
+        }
     }
 
     public interface CarHvacEventListener {
@@ -353,19 +515,19 @@
             switch (carProp.getType()) {
                 case PROPERTY_TYPE_BOOLEAN: {
                     CarHvacBooleanProperty newProp =
-                            new CarHvacBooleanProperty(carProp.getPropertyId(), carProp.getZone());
+                            new CarHvacBooleanProperty(carProp.getPropertyId(), carProp.getZones());
                     hvacProps.add(newProp);
                 } break;
                 case PROPERTY_TYPE_FLOAT: {
                     CarHvacFloatProperty newProp =
-                            new CarHvacFloatProperty(carProp.getPropertyId(), carProp.getZone(),
-                                    carProp.getFloatMax(), carProp.getFloatMin());
+                            new CarHvacFloatProperty(carProp.getPropertyId(), carProp.getZones(),
+                                    carProp.getFloatMaxs(), carProp.getFloatMins());
                     hvacProps.add(newProp);
                 } break;
                 case PROPERTY_TYPE_INT: {
                     CarHvacIntProperty newProp =
-                            new CarHvacIntProperty(carProp.getPropertyId(), carProp.getZone(),
-                                    carProp.getIntMax(), carProp.getIntMin());
+                            new CarHvacIntProperty(carProp.getPropertyId(), carProp.getZones(),
+                                    carProp.getIntMaxs(), carProp.getIntMins());
                     hvacProps.add(newProp);
                 } break;
             }
@@ -478,7 +640,8 @@
         }
         try {
             // Set floatMin and floatMax to 0, as they are ignored in set()
-            CarHvacProperty carProp = new CarHvacProperty(prop, zone, 0, 0, val);
+            CarHvacProperty carProp = new CarHvacProperty(prop, zone,
+                    new float[] { 0 }, new float[] { 0 }, val);
             mService.setProperty(carProp);
         } catch (RemoteException ex) {
             Log.e(TAG, "setFloatProperty failed with " + ex.toString());
@@ -491,7 +654,8 @@
         }
         try {
             // Set intMin and intMax to 0, as they are ignored in set()
-            CarHvacProperty carProp = new CarHvacProperty(prop, zone, 0, 0, val);
+            CarHvacProperty carProp = new CarHvacProperty(prop, zone,
+                    new int[] { 0 }, new int[] { 0 }, val);
             mService.setProperty(carProp);
         } catch (RemoteException ex) {
             Log.e(TAG, "setIntProperty failed with " + ex.toString());
diff --git a/car-lib/src/android/car/hardware/hvac/CarHvacProperty.java b/car-lib/src/android/car/hardware/hvac/CarHvacProperty.java
index ff85bab..e94b2a6 100644
--- a/car-lib/src/android/car/hardware/hvac/CarHvacProperty.java
+++ b/car-lib/src/android/car/hardware/hvac/CarHvacProperty.java
@@ -29,15 +29,15 @@
 @SystemApi
 public class CarHvacProperty implements Parcelable {
 
-    private final int   mPropertyId;
-    private final int   mType;
-    private int         mZone;
-    private final float mFloatMax;
-    private final float mFloatMin;
-    private float[]     mFloatValues;
-    private final int   mIntMax;
-    private final int   mIntMin;
-    private int[]       mIntValues;
+    private final int mPropertyId;
+    private final int mType;
+    private int mZones;
+    private final float[] mFloatMaxs;
+    private final float[] mFloatMins;
+    private float[] mFloatValues;
+    private final int[] mIntMaxs;
+    private final int[] mIntMins;
+    private int[] mIntValues;
 
     public int describeContents() {
         return 0;
@@ -46,12 +46,12 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mPropertyId);
         out.writeInt(mType);
-        out.writeInt(mZone);
-        out.writeFloat(mFloatMax);
-        out.writeFloat(mFloatMin);
+        out.writeInt(mZones);
+        out.writeFloatArray(mFloatMaxs);
+        out.writeFloatArray(mFloatMins);
         out.writeFloatArray(mFloatValues);
-        out.writeInt(mIntMax);
-        out.writeInt(mIntMin);
+        out.writeIntArray(mIntMaxs);
+        out.writeIntArray(mIntMins);
         out.writeIntArray(mIntValues);
     }
 
@@ -69,12 +69,12 @@
     private CarHvacProperty(Parcel in) {
         mPropertyId = in.readInt();
         mType = in.readInt();
-        mZone = in.readInt();
-        mFloatMax = in.readFloat();
-        mFloatMin = in.readFloat();
+        mZones = in.readInt();
+        mFloatMaxs = in.createFloatArray();
+        mFloatMins = in.createFloatArray();
         mFloatValues = in.createFloatArray();
-        mIntMax = in.readInt();
-        mIntMin = in.readInt();
+        mIntMaxs = in.createIntArray();
+        mIntMins = in.createIntArray();
         mIntValues = in.createIntArray();
     }
 
@@ -84,97 +84,97 @@
     public CarHvacProperty(CarHvacProperty that) {
         mPropertyId = that.getPropertyId();
         mType = that.getType();
-        mZone = that.getZone();
-        mFloatMax = that.getFloatMax();
-        mFloatMin = that.getFloatMin();
+        mZones = that.getZones();
+        mFloatMaxs = that.getFloatMaxs();
+        mFloatMins = that.getFloatMins();
         mFloatValues = that.getFloatValues();
-        mIntMax = that.getIntMax();
-        mIntMin = that.getIntMin();
+        mIntMaxs = that.getIntMaxs();
+        mIntMins = that.getIntMins();
         mIntValues =  that.getIntValues();
     }
     /**
      * Constructor for a boolean property
      */
-    public CarHvacProperty(int propertyId, int zone, boolean value) {
+    public CarHvacProperty(int propertyId, int zones, boolean value) {
         mPropertyId = propertyId;
         mType = CarHvacManager.PROPERTY_TYPE_BOOLEAN;
-        mZone = zone;
-        mIntMax = 1;
-        mIntMin = 0;
+        mZones = zones;
+        mIntMaxs = new int[] { 1 };
+        mIntMins = new int[] { 0 };
         mIntValues = new int[] { value ? 1 : 0 };
-        mFloatMax = 0;
-        mFloatMin = 0;
+        mFloatMaxs = null;
+        mFloatMins = null;
     }
 
 
     /**
      * Constructor for a float property
      */
-    public CarHvacProperty(int propertyId, int zone, float min, float max, float value) {
+    public CarHvacProperty(int propertyId, int zones, float[] mins, float[] maxs, float value) {
         mPropertyId = propertyId;
         mType = CarHvacManager.PROPERTY_TYPE_FLOAT;
-        mZone = zone;
-        mFloatMax = max;
-        mFloatMin = min;
+        mZones = zones;
+        mFloatMaxs = maxs;
+        mFloatMins = mins;
         mFloatValues = new float[] {value};
         mIntValues = null;
-        mIntMax = 0;
-        mIntMin = 0;
+        mIntMaxs = null;
+        mIntMins = null;
     }
 
     /**
      * Constructor for an integer property
      */
-    public CarHvacProperty(int propertyId, int zone, int min, int max, int value) {
+    public CarHvacProperty(int propertyId, int zones, int[] mins, int[] maxs, int value) {
         mPropertyId = propertyId;
         mType = CarHvacManager.PROPERTY_TYPE_INT;
-        mZone = zone;
-        mIntMax = max;
-        mIntMin = min;
+        mZones = zones;
+        mIntMaxs = maxs;
+        mIntMins = mins;
         mIntValues = new int[] { value };
-        mFloatMax = 0;
-        mFloatMin = 0;
+        mFloatMaxs = null;
+        mFloatMins = null;
     }
 
     /**
      * Constructor for an integer vector property
      */
-    public CarHvacProperty(int propertyId, int zone, int min, int max, int[] values) {
+    public CarHvacProperty(int propertyId, int zones, int[] mins, int[] maxs, int[] values) {
         mPropertyId = propertyId;
         mType = CarHvacManager.PROPERTY_TYPE_INT_VECTOR;
-        mZone = zone;
-        mIntMax = max;
-        mIntMin = min;
+        mZones = zones;
+        mIntMaxs = maxs;
+        mIntMins = mins;
         mIntValues = Arrays.copyOf(values, values.length);
-        mFloatMax = 0;
-        mFloatMin = 0;
+        mFloatMaxs = null;
+        mFloatMins = null;
     }
 
     /**
      * Constructor for a float vector property
      */
-    public CarHvacProperty(int propertyId, int zone, float min, float max, float[] values) {
+    public CarHvacProperty(int propertyId, int zones, float[] mins, float[] maxs, float[] values) {
         mPropertyId = propertyId;
         mType = CarHvacManager.PROPERTY_TYPE_FLOAT_VECTOR;
-        mZone = zone;
-        mFloatMax = max;
-        mFloatMin = min;
+        mZones = zones;
+        mFloatMaxs = maxs;
+        mFloatMins = mins;
         mFloatValues = Arrays.copyOf(values, values.length);
-        mIntMax = 0;
-        mIntMin = 0;
+        mIntMaxs = null;
+        mIntMins = null;
     }
 
     // Getters.
     public int   getPropertyId()     { return mPropertyId; }
     public int   getType()           { return mType; }
-    public int   getZone()           { return mZone; }
+    public int   getZones()           { return mZones; }
     public boolean getBooleanValue() { return mIntValues[0] == 1; }
-    public float getFloatMax()       { return mFloatMax; }
-    public float getFloatMin()       { return mFloatMin; }
+    public float[] getFloatMaxs()       { return mFloatMaxs; }
+    public float[] getFloatMins()       { return mFloatMins; }
     public float getFloatValue()     { return mFloatValues[0]; }
     public float[] getFloatValues()  { return mFloatValues; }
-    public int   getIntMax()         { return mIntMax; }
-    public int   getIntMin()         { return mIntMin; }
+    public int[]   getIntMaxs()         { return mIntMaxs; }
+    public int[]   getIntMins()         { return mIntMins; }
     public int   getIntValue()       { return mIntValues[0]; }
     public int[] getIntValues()      { return mIntValues; }
 
@@ -199,35 +199,35 @@
         assertType(CarHvacManager.PROPERTY_TYPE_INT_VECTOR);
         mFloatValues = Arrays.copyOf(values, values.length);
     }
-    public void setZone(int zone)   { mZone  = zone; }
+    public void setZones(int zones)   { mZones  = zones; }
 
     @Override
     public String toString() {
         String myString = "mPropertyId: "  + mPropertyId + "\n" +
                           "mType:       "  + mType       + "\n" +
-                          "mZone:       "  + mZone       + "\n";
+                          "mZones:       "  + mZones       + "\n";
         switch (mType) {
             case CarHvacManager.PROPERTY_TYPE_BOOLEAN:
                 myString += "mIntValue:   "  + mIntValues[0] + "\n";
                 break;
             case CarHvacManager.PROPERTY_TYPE_FLOAT:
-                myString += "mFloatMax:   "  + mFloatMax   + "\n" +
-                            "mFloatMin:   "  + mFloatMin   + "\n" +
+                myString += "mFloatMaxs:   "  + Arrays.toString(mFloatMaxs) + "\n" +
+                            "mFloatMins:   "  + Arrays.toString(mFloatMins) + "\n" +
                             "mFloatValue: "  + mFloatValues[0] + "\n";
                 break;
             case CarHvacManager.PROPERTY_TYPE_INT:
-                myString += "mIntMax:     "  + mIntMax     + "\n" +
-                            "mIntMin:     "  + mIntMin     + "\n" +
+                myString += "mIntMax:     "  + Arrays.toString(mIntMaxs) + "\n" +
+                            "mIntMin:     "  + Arrays.toString(mIntMins) + "\n" +
                             "mIntValue:   "  + mIntValues[0] + "\n";
                 break;
             case CarHvacManager.PROPERTY_TYPE_INT_VECTOR:
-                myString += "mIntMax:     "  + mIntMax     + "\n" +
-                            "mIntMin:     "  + mIntMin     + "\n" +
+                myString += "mIntMax:     "  + Arrays.toString(mIntMaxs) + "\n" +
+                            "mIntMin:     "  + Arrays.toString(mIntMins) + "\n" +
                             "mIntValues:  "  + Arrays.toString(mIntValues) + "\n";
                 break;
             case CarHvacManager.PROPERTY_TYPE_FLOAT_VECTOR:
-                myString += "mFloatMax:     "  + mFloatMax     + "\n" +
-                            "mFloatMin:     "  + mFloatMin     + "\n" +
+                myString += "mFloatMax:     "  + Arrays.toString(mFloatMaxs) + "\n" +
+                            "mFloatMin:     "  + Arrays.toString(mFloatMins) + "\n" +
                             "mFloatValues:  "  + Arrays.toString(mFloatValues) + "\n";
                 break;
             default:
@@ -238,37 +238,49 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        CarHvacProperty that = (CarHvacProperty) o;
-        return mPropertyId == that.mPropertyId &&
-                mType == that.mType &&
-                mZone == that.mZone &&
-                Float.compare(that.mFloatMax, mFloatMax) == 0 &&
-                Float.compare(that.mFloatMin, mFloatMin) == 0 &&
-                mIntMax == that.mIntMax &&
-                mIntMin == that.mIntMin &&
-                Arrays.equals(mFloatValues, that.mFloatValues) &&
-                Arrays.equals(mIntValues, that.mIntValues);
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Arrays.hashCode(mFloatMaxs);
+        result = prime * result + Arrays.hashCode(mFloatMins);
+        result = prime * result + Arrays.hashCode(mFloatValues);
+        result = prime * result + Arrays.hashCode(mIntMaxs);
+        result = prime * result + Arrays.hashCode(mIntMins);
+        result = prime * result + Arrays.hashCode(mIntValues);
+        result = prime * result + mPropertyId;
+        result = prime * result + mType;
+        result = prime * result + mZones;
+        return result;
     }
 
     @Override
-    public int hashCode() {
-        return Objects.hash(
-                mPropertyId,
-                mType,
-                mZone,
-                mFloatMax,
-                mFloatMin,
-                mFloatValues,
-                mIntMax,
-                mIntMin,
-                mIntValues);
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        CarHvacProperty other = (CarHvacProperty) obj;
+        if (!Arrays.equals(mFloatMaxs, other.mFloatMaxs))
+            return false;
+        if (!Arrays.equals(mFloatMins, other.mFloatMins))
+            return false;
+        if (!Arrays.equals(mFloatValues, other.mFloatValues))
+            return false;
+        if (!Arrays.equals(mIntMaxs, other.mIntMaxs))
+            return false;
+        if (!Arrays.equals(mIntMins, other.mIntMins))
+            return false;
+        if (!Arrays.equals(mIntValues, other.mIntValues))
+            return false;
+        if (mPropertyId != other.mPropertyId)
+            return false;
+        if (mType != other.mType)
+            return false;
+        if (mZones != other.mZones)
+            return false;
+        return true;
     }
 
     private void assertType(int expectedType) {
diff --git a/libvehiclenetwork/include/IVehicleNetwork.h b/libvehiclenetwork/include/IVehicleNetwork.h
index 5f33ee1..19e439f 100644
--- a/libvehiclenetwork/include/IVehicleNetwork.h
+++ b/libvehiclenetwork/include/IVehicleNetwork.h
@@ -82,10 +82,30 @@
                                  Parcel* reply,
                                  uint32_t flags = 0);
     virtual bool isOperationAllowed(int32_t property, bool isWrite) = 0;
+    virtual void releaseMemoryFromGet(vehicle_prop_value_t* value) = 0;
 };
 
 // ----------------------------------------------------------------------------
 
+class VehicleNetworkUtil {
+public:
+    static int countNumberOfZones(int32_t zones) {
+        if (zones == 0) { // no-zone, treat as one zone.
+            return 1;
+        }
+        int count = 0;
+        uint32_t flag = 0x1;
+        for (int i = 0; i < 32; i++) {
+            if ((flag & zones) != 0) {
+                count++;
+            }
+            flag <<= 1;
+        }
+        return count;
+    }
+};
+
+// ----------------------------------------------------------------------------
 }; // namespace android
 
 #endif /* ANDROID_IVEHICLE_NETWORK_H */
diff --git a/libvehiclenetwork/include/VehicleNetworkDataTypes.h b/libvehiclenetwork/include/VehicleNetworkDataTypes.h
index bc6d25d4..f5cc209 100644
--- a/libvehiclenetwork/include/VehicleNetworkDataTypes.h
+++ b/libvehiclenetwork/include/VehicleNetworkDataTypes.h
@@ -63,6 +63,22 @@
         if (config->config_string.data != NULL && config->config_string.len > 0){
             delete[] config->config_string.data;
         }
+        switch (config->prop) {
+            case VEHICLE_VALUE_TYPE_ZONED_INT32:
+            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
+            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
+                delete[] config->int32_max_values;
+                delete[] config->int32_min_values;
+            } break;
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
+                delete[] config->float_max_values;
+                delete[] config->float_min_values;
+            } break;
+        }
     };
 
     static bool isTheSame(const vehicle_prop_config_t& l, const vehicle_prop_config_t& r) {
diff --git a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetwork.java b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetwork.java
index 331f93c..3ac5040 100644
--- a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetwork.java
+++ b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetwork.java
@@ -31,7 +31,6 @@
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
-import com.android.car.vehiclenetwork.VehicleNetworkProto.ZonedValue;
 import com.android.internal.annotations.GuardedBy;
 
 import java.lang.ref.WeakReference;
@@ -312,10 +311,10 @@
     public int getZonedIntProperty(int property, int zone) throws IllegalArgumentException {
         VehiclePropValue v = getProperty(
                 property, zone, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32);
-        if (v.getZonedValue().getInt32ValuesCount() != 1) {
+        if (v.getInt32ValuesCount() != 1) {
             throw new IllegalStateException();
         }
-        return v.getZonedValue().getInt32Values(0);
+        return v.getInt32Values(0);
     }
 
     /**
@@ -335,8 +334,8 @@
             throws IllegalArgumentException {
         VehiclePropValue v = getProperty(
                 property, zone, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32);
-        assertVectorLength(v.getZonedValue().getInt32ValuesCount(), property, v.getValueType());
-        return toIntArray(v.getZonedValue().getInt32ValuesList());
+        assertVectorLength(v.getInt32ValuesCount(), property, v.getValueType());
+        return toIntArray(v.getInt32ValuesList());
     }
 
     /**
@@ -368,8 +367,8 @@
             throws IllegalArgumentException {
         VehiclePropValue v = getProperty(property, zone,
                 VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT);
-        assertVectorLength(v.getZonedValue().getFloatValuesCount(), property, v.getValueType());
-        return toFloatArray(v.getZonedValue().getFloatValuesList());
+        assertVectorLength(v.getFloatValuesCount(), property, v.getValueType());
+        return toFloatArray(v.getFloatValuesList());
     }
 
     /**
@@ -694,9 +693,7 @@
                 VehiclePropValueUtil.createBuilder(property, valueType, 0);
 
         if (zone != NO_ZONE) {
-            valuePrototypeBuilder.setZonedValue(ZonedValue.newBuilder().
-                    setZoneOrWindow(zone).
-                    build());
+            valuePrototypeBuilder.setZone(zone);
         }
 
         VehiclePropValue v = getProperty(valuePrototypeBuilder.build());
diff --git a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetworkConsts.java b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetworkConsts.java
index 6cc3f05..003451f 100644
--- a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetworkConsts.java
+++ b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehicleNetworkConsts.java
@@ -615,9 +615,11 @@
 public static final int VEHICLE_VALUE_TYPE_ZONED_FLOAT = 0x30;
 public static final int VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2 = 0x31;
 public static final int VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3 = 0x32;
+public static final int VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4 = 0x33;
 public static final int VEHICLE_VALUE_TYPE_ZONED_INT32 = 0x40;
 public static final int VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2 = 0x41;
 public static final int VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3 = 0x42;
+public static final int VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4 = 0x43;
 public static String enumToString(int v) {
 switch(v) {
 case VEHICLE_VALUE_TYPE_SHOUD_NOT_USE: return "VEHICLE_VALUE_TYPE_SHOUD_NOT_USE";
@@ -637,9 +639,11 @@
 case VEHICLE_VALUE_TYPE_ZONED_FLOAT: return "VEHICLE_VALUE_TYPE_ZONED_FLOAT";
 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2: return "VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2";
 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: return "VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3";
+case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: return "VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4";
 case VEHICLE_VALUE_TYPE_ZONED_INT32: return "VEHICLE_VALUE_TYPE_ZONED_INT32";
 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2: return "VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2";
 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: return "VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3";
+case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: return "VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4";
 default: return "UNKNOWN";
 }
 }
@@ -679,50 +683,6 @@
 }
 }
 
-public static class VehicleErrorCode {
-public static final int VEHICLE_NO_ERROR = 0x0;
-public static final int VEHICLE_ERROR_UNKNOWN = (-2147483647 - 1);
-public static final int VEHICLE_ERROR_NO_MEMORY = -12;
-public static final int VEHICLE_ERROR_INVALID_OPERATION = -38;
-public static final int VEHICLE_ERROR_BAD_VALUE = -22;
-public static final int VEHICLE_ERROR_BAD_TYPE = (VEHICLE_ERROR_UNKNOWN + 1);
-public static final int VEHICLE_ERROR_NAME_NOT_FOUND = -2;
-public static final int VEHICLE_ERROR_PERMISSION_DENIED = -1;
-public static final int VEHICLE_ERROR_NO_INIT = -19;
-public static final int VEHICLE_ERROR_ALREADY_EXISTS = -17;
-public static final int VEHICLE_ERROR_DEAD_OBJECT = -32;
-public static final int VEHICLE_ERROR_FAILED_TRANSACTION = (VEHICLE_ERROR_UNKNOWN + 2);
-public static final int VEHICLE_ERROR_BAD_INDEX = -75;
-public static final int VEHICLE_ERROR_NOT_ENOUGH_DATA = -61;
-public static final int VEHICLE_ERROR_WOULD_BLOCK = -11;
-public static final int VEHICLE_ERROR_TIMED_OUT = -110;
-public static final int VEHICLE_ERROR_UNKNOWN_TRANSACTION = -74;
-public static final int VEHICLE_FDS_NOT_ALLOWED = (VEHICLE_ERROR_UNKNOWN + 7);
-public static String enumToString(int v) {
-switch(v) {
-case VEHICLE_NO_ERROR: return "VEHICLE_NO_ERROR";
-case VEHICLE_ERROR_UNKNOWN: return "VEHICLE_ERROR_UNKNOWN";
-case VEHICLE_ERROR_NO_MEMORY: return "VEHICLE_ERROR_NO_MEMORY";
-case VEHICLE_ERROR_INVALID_OPERATION: return "VEHICLE_ERROR_INVALID_OPERATION";
-case VEHICLE_ERROR_BAD_VALUE: return "VEHICLE_ERROR_BAD_VALUE";
-case VEHICLE_ERROR_BAD_TYPE: return "VEHICLE_ERROR_BAD_TYPE";
-case VEHICLE_ERROR_NAME_NOT_FOUND: return "VEHICLE_ERROR_NAME_NOT_FOUND";
-case VEHICLE_ERROR_PERMISSION_DENIED: return "VEHICLE_ERROR_PERMISSION_DENIED";
-case VEHICLE_ERROR_NO_INIT: return "VEHICLE_ERROR_NO_INIT";
-case VEHICLE_ERROR_ALREADY_EXISTS: return "VEHICLE_ERROR_ALREADY_EXISTS";
-case VEHICLE_ERROR_DEAD_OBJECT: return "VEHICLE_ERROR_DEAD_OBJECT";
-case VEHICLE_ERROR_FAILED_TRANSACTION: return "VEHICLE_ERROR_FAILED_TRANSACTION";
-case VEHICLE_ERROR_BAD_INDEX: return "VEHICLE_ERROR_BAD_INDEX";
-case VEHICLE_ERROR_NOT_ENOUGH_DATA: return "VEHICLE_ERROR_NOT_ENOUGH_DATA";
-case VEHICLE_ERROR_WOULD_BLOCK: return "VEHICLE_ERROR_WOULD_BLOCK";
-case VEHICLE_ERROR_TIMED_OUT: return "VEHICLE_ERROR_TIMED_OUT";
-case VEHICLE_ERROR_UNKNOWN_TRANSACTION: return "VEHICLE_ERROR_UNKNOWN_TRANSACTION";
-case VEHICLE_FDS_NOT_ALLOWED: return "VEHICLE_FDS_NOT_ALLOWED";
-default: return "UNKNOWN";
-}
-}
-}
-
 public static class VehiclePropChangeMode {
 public static final int VEHICLE_PROP_CHANGE_MODE_STATIC = 0x00;
 public static final int VEHICLE_PROP_CHANGE_MODE_ON_CHANGE = 0x01;
diff --git a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropConfigUtil.java b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropConfigUtil.java
index 506bb2c..61e675b 100644
--- a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropConfigUtil.java
+++ b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropConfigUtil.java
@@ -36,6 +36,22 @@
                 .build();
     }
 
+    public static VehiclePropConfig createZonedProperty(
+            int property, int propAccess, int changeType, int valueType, int zones,
+            int configFlags) {
+            return VehiclePropConfig.newBuilder().
+                    setProp(property).
+                    setAccess(propAccess).
+                    setChangeMode(changeType).
+                    setValueType(valueType).
+                    setPermissionModel(VehiclePermissionModel.VEHICLE_PERMISSION_NO_RESTRICTION).
+                    setZones(zones).
+                    addConfigArray(configFlags).
+                    setSampleRateMax(0).
+                    setSampleRateMin(0).
+                    build();
+    }
+
     public static VehiclePropConfig createProperty(
         int property, int propAccess, int changeType, int valueType, int configFlags) {
         return getBuilder(property,
diff --git a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropValueUtil.java b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropValueUtil.java
index 66e613f..78b2141 100644
--- a/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropValueUtil.java
+++ b/libvehiclenetwork/java/src/com/android/car/vehiclenetwork/VehiclePropValueUtil.java
@@ -17,7 +17,6 @@
 
 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
-import com.android.car.vehiclenetwork.VehicleNetworkProto.ZonedValue;
 
 import com.google.protobuf.ByteString;
 
@@ -40,7 +39,7 @@
 
     public static VehiclePropValue createIntVectorValue(int property, int[] values,
             long timestamp) {
-        VehiclePropValue.Builder builder =createBuilder(property,
+        VehiclePropValue.Builder builder = createBuilder(property,
                 getVectorValueType(VehicleValueType.VEHICLE_VALUE_TYPE_INT32, values.length),
                 timestamp);
         for (int v : values) {
@@ -57,7 +56,7 @@
 
     public static VehiclePropValue createFloatVectorValue(int property, float[] values,
             long timestamp) {
-        VehiclePropValue.Builder builder =createBuilder(property,
+        VehiclePropValue.Builder builder = createBuilder(property,
                 getVectorValueType(VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT, values.length),
                 timestamp);
         for (float v : values) {
@@ -93,60 +92,49 @@
     public static VehiclePropValue createZonedIntValue(int property, int zone, int value,
             long timestamp) {
         return createBuilder(property, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32, timestamp).
-                setZonedValue(ZonedValue.newBuilder().
-                        setZoneOrWindow(zone).
-                        addInt32Values(value).
-                        build()).
+                setZone(zone).
+                addInt32Values(value).
                 build();
     }
 
     public static VehiclePropValue createZonedIntVectorValue(int property, int zone, int[] values,
             long timestamp) {
-        ZonedValue.Builder zonedValueBuilder = ZonedValue.newBuilder()
-                .setZoneOrWindow(zone);
-        for (int value : values) {
-            zonedValueBuilder.addInt32Values(value);
-        }
         int valueType = getVectorValueType(
                 VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32, values.length);
-        return createBuilder(property, valueType, timestamp).
-                setZonedValue(zonedValueBuilder.build()).
-                build();
+        VehiclePropValue.Builder builder = createBuilder(property, valueType, timestamp).
+                setZone(zone);
+        for (int value : values) {
+            builder.addInt32Values(value);
+        }
+        return builder.build();
     }
 
     public static VehiclePropValue createZonedFloatVectorValue(int property, int zone,
             float[] values, long timestamp) {
-        ZonedValue.Builder zonedValueBuilder = ZonedValue.newBuilder()
-                .setZoneOrWindow(zone);
-        for (float value : values) {
-            zonedValueBuilder.addFloatValues(value);
-        }
         int valueType = getVectorValueType(
                 VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT, values.length);
-        return createBuilder(property, valueType, timestamp).
-                setZonedValue(zonedValueBuilder.build()).
-                build();
+        VehiclePropValue.Builder builder =  createBuilder(property, valueType, timestamp).
+                setZone(zone);
+        for (float value : values) {
+            builder.addFloatValues(value);
+        }
+        return builder.build();
     }
 
 
     public static VehiclePropValue createZonedBooleanValue(int property, int zone, boolean value,
             long timestamp) {
         return createBuilder(property, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN,timestamp).
-                setZonedValue(ZonedValue.
-                        newBuilder().
-                        setZoneOrWindow(zone).
-                        addInt32Values(value ? 1 : 0).
-                        build()).
+                setZone(zone).
+                addInt32Values(value ? 1 : 0).
                 build();
     }
 
     public static VehiclePropValue createZonedFloatValue(int property, int zone, float value,
             long timestamp) {
         return createBuilder(property, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT,timestamp).
-                setZonedValue(ZonedValue.newBuilder().
-                        setZoneOrWindow(zone).
-                        addFloatValues(value).
-                        build()).
+                setZone(zone).
+                addFloatValues(value).
                 build();
     }
 
@@ -180,7 +168,8 @@
             case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3:
             case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4:
             case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
-            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: {
+            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:{
                 return createFloatVectorValue(property, new float[getVectorLength(valueType)], 0);
             }
             case VehicleValueType.VEHICLE_VALUE_TYPE_INT32: {
@@ -190,7 +179,8 @@
             case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3:
             case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4:
             case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
-            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: {
+            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
                 return createIntVectorValue(property, new int[getVectorLength(valueType)], 0);
             }
 
@@ -220,6 +210,8 @@
                 return 3;
             case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4:
             case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4:
+            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
+            case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
                 return 4;
             default:
                 throw new IllegalArgumentException("Unknown value type: " + vehicleValueType);
@@ -244,25 +236,10 @@
                         + "\n")
                 .append("stringValue: " + value.getStringValue() + "\n")
                 .append("byteValue: " + Arrays.toString(value.getBytesValue().toByteArray()) + "\n")
-                .append("zonedValue: {" + toString(value.getZonedValue(), "    ") + "}")
+                .append("zone: {" + value.getZone() + "}")
                 .toString();
     }
 
-    private static String toString(ZonedValue zonedValue, String indent) {
-        if (zonedValue == null) {
-            return "null";
-        }
-
-        return new StringBuilder()
-                .append(indent + "zoneOrWindow: " + zonedValue.getZoneOrWindow() + "\n")
-                .append(indent + "int32Values: "
-                        + Arrays.toString(toIntArray(zonedValue.getInt32ValuesList())) + "\n")
-                .append(indent + "floatValues: "
-                        + Arrays.toString(toFloatArray(zonedValue.getFloatValuesList())) + "\n")
-                .toString();
-
-    }
-
     public static int[] toIntArray(List<Integer> collection) {
         int[] array = new int[collection.size()];
         int i = 0;
diff --git a/libvehiclenetwork/native/IVehicleNetwork.cpp b/libvehiclenetwork/native/IVehicleNetwork.cpp
index d70a698..09da0ee 100644
--- a/libvehiclenetwork/native/IVehicleNetwork.cpp
+++ b/libvehiclenetwork/native/IVehicleNetwork.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "VehicleNetwork"
 
 #include <memory>
+#include <string.h>
 
 #include <binder/IPCThreadState.h>
 
@@ -285,20 +286,22 @@
         } break;
         case GET_PROPERTY: {
             CHECK_INTERFACE(IVehicleNetwork, data, reply);
-            ScopedVehiclePropValue value;
-            r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
+            vehicle_prop_value_t value;
+            memset(&value, 0, sizeof(value));
+            r = VehiclePropValueBinderUtil::readFromParcel(data, &value,
                     false /* deleteMembers */, true /*canIgnoreNoData*/);
             if (r != NO_ERROR) {
                 ALOGE("getProperty cannot read %d", r);
                 return r;
             }
-            if (!isOperationAllowed(value.value.prop, false)) {
+            if (!isOperationAllowed(value.prop, false)) {
                 return PERMISSION_DENIED;
             }
-            r = getProperty(&(value.value));
+            r = getProperty(&value);
             if (r == NO_ERROR) {
                 reply->writeNoException();
-                r = VehiclePropValueBinderUtil::writeToParcel(*reply, value.value);
+                r = VehiclePropValueBinderUtil::writeToParcel(*reply, value);
+                releaseMemoryFromGet(&value);
             }
             return r;
         } break;
diff --git a/libvehiclenetwork/native/VehicleNetworkProtoUtil.cpp b/libvehiclenetwork/native/VehicleNetworkProtoUtil.cpp
index 164b95a..2d7e6c9 100644
--- a/libvehiclenetwork/native/VehicleNetworkProtoUtil.cpp
+++ b/libvehiclenetwork/native/VehicleNetworkProtoUtil.cpp
@@ -40,6 +40,7 @@
     out.set_prop(in.prop);
     out.set_value_type(in.value_type);
     out.set_timestamp(in.timestamp);
+    out.set_zone(in.zone);
     switch (in.value_type) {
         case VEHICLE_VALUE_TYPE_STRING: {
             //TODO fix ugly copy here for inplace mode
@@ -64,7 +65,8 @@
         case VEHICLE_VALUE_TYPE_INT64: {
             out.set_int64_value(in.value.int64_value);
         } break;
-        case VEHICLE_VALUE_TYPE_BOOLEAN: {
+        case VEHICLE_VALUE_TYPE_BOOLEAN:
+        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN: {
             out.add_int32_values(in.value.int32_value);
         } break;
         case VEHICLE_VALUE_TYPE_INT32:
@@ -76,35 +78,23 @@
                 out.add_int32_values(in.value.int32_array[i]);
             }
         } break;
-        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
         case VEHICLE_VALUE_TYPE_ZONED_INT32:
         case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: {
-            int expectedSize;
-            if (in.value_type == VEHICLE_VALUE_TYPE_ZONED_BOOLEAN) {
-                expectedSize = 1;
-            } else {
-                expectedSize = in.value_type - VEHICLE_VALUE_TYPE_ZONED_INT32 + 1;
-            }
-            ZonedValue* zonedValue = new ZonedValue();
-            ASSERT_OR_HANDLE_NO_MEMORY(zonedValue, return NO_MEMORY);
-            zonedValue->set_zone_or_window(in.value.zoned_int32_array.zone);
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
+            int expectedSize = in.value_type - VEHICLE_VALUE_TYPE_ZONED_INT32 + 1;
             for (int i = 0; i < expectedSize; i++) {
-                zonedValue->add_int32_values(in.value.zoned_int32_array.values[i]);
+                out.add_int32_values(in.value.int32_array[i]);
             }
-            out.set_allocated_zoned_value(zonedValue);
         } break;
         case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
         case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: {
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
             int expectedSize = in.value_type - VEHICLE_VALUE_TYPE_ZONED_FLOAT + 1;
-            ZonedValue* zonedValue = new ZonedValue();
-            ASSERT_OR_HANDLE_NO_MEMORY(zonedValue, return NO_MEMORY);
-            zonedValue->set_zone_or_window(in.value.zoned_float_array.zone);
             for (int i = 0; i < expectedSize; i++) {
-                zonedValue->add_float_values(in.value.zoned_float_array.values[i]);
+                out.add_float_values(in.value.float_array[i]);
             }
-            out.set_allocated_zoned_value(zonedValue);
         } break;
     }
     return NO_ERROR;
@@ -115,6 +105,7 @@
     out.prop = in.prop();
     out.value_type = in.value_type();
     out.timestamp = in.timestamp();
+    out.zone = in.zone();
     switch (out.value_type) {
         case VEHICLE_VALUE_TYPE_STRING: {
             if (!in.has_string_value()) {
@@ -158,20 +149,11 @@
                 return r;
             }
         } break;
-        case VEHICLE_VALUE_TYPE_FLOAT: {
-            if (in.float_values_size() != 1) {
-                if (canIgnoreNoData) {
-                    return NO_ERROR;
-                }
-                ALOGE("float value, wrong size %d, expecting 1", in.float_values_size());
-                return BAD_VALUE;
-            }
-            out.value.float_value = in.float_values(0);
-        } break;
+        case VEHICLE_VALUE_TYPE_FLOAT:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
-            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_FLOAT_VEC2 + 2;
+            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_FLOAT + 1;
             if (in.float_values_size() != expectedSize) {
                 if (canIgnoreNoData) {
                     return NO_ERROR;
@@ -194,7 +176,8 @@
             }
             out.value.int64_value = in.int64_value();
         } break;
-        case VEHICLE_VALUE_TYPE_BOOLEAN: {
+        case VEHICLE_VALUE_TYPE_BOOLEAN:
+        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN: {
             if (in.int32_values_size() != 1) {
                 if (canIgnoreNoData) {
                     return NO_ERROR;
@@ -221,60 +204,39 @@
                 out.value.int32_array[i] = in.int32_values(i);
             }
         } break;
-        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
+
         case VEHICLE_VALUE_TYPE_ZONED_INT32:
         case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: {
-            if (!in.has_zoned_value()) {
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
+            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_ZONED_INT32 + 1;
+            if (in.int32_values_size() != expectedSize) {
                 if (canIgnoreNoData) {
                     return NO_ERROR;
                 }
-                ALOGE("no zoned value");
-                return BAD_VALUE;
-            }
-            const ZonedValue& zonedValue = in.zoned_value();
-            out.value.zoned_int32_array.zone = zonedValue.zone_or_window();
-            int expectedSize;
-            if (out.value_type == VEHICLE_VALUE_TYPE_ZONED_BOOLEAN) {
-                expectedSize = 1;
-            } else {
-                expectedSize = out.value_type - VEHICLE_VALUE_TYPE_ZONED_INT32 + 1;
-            }
-            if (zonedValue.int32_values_size() != expectedSize) {
-                if (canIgnoreNoData) {
-                    return NO_ERROR;
-                }
-                ALOGE("Wrong data length in zoned int boolean value, expected:%d, got:%d",
-                        expectedSize, zonedValue.int32_values_size());
+                ALOGE("int32 value, wrong size %d, expecting %d", in.int32_values_size(),
+                        expectedSize);
                 return BAD_VALUE;
             }
             for (int i = 0; i < expectedSize; i++) {
-                out.value.zoned_int32_array.values[i] = zonedValue.int32_values(i);
+                out.value.int32_array[i] = in.int32_values(i);
             }
         } break;
         case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
         case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: {
-            if (!in.has_zoned_value()) {
-                if (canIgnoreNoData) {
-                    return NO_ERROR;
-                }
-                ALOGE("no zoned value");
-                return BAD_VALUE;
-            }
-            const ZonedValue& zonedValue = in.zoned_value();
-            out.value.zoned_float_array.zone = zonedValue.zone_or_window();
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:{
             int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_ZONED_FLOAT + 1;
-            if (zonedValue.float_values_size() != expectedSize) {
+            if (in.float_values_size() != expectedSize) {
                 if (canIgnoreNoData) {
                     return NO_ERROR;
                 }
-                ALOGE("Wrong data length in zoned float value, expected:%d, got:%d",
-                                        expectedSize, zonedValue.float_values_size());
+                ALOGE("float value, wrong size %d, expecting %d", in.float_values_size(),
+                        expectedSize);
                 return BAD_VALUE;
             }
             for (int i = 0; i < expectedSize; i++) {
-                out.value.zoned_float_array.values[i] = zonedValue.float_values(i);
+                out.value.float_array[i] = in.float_values(i);
             }
         } break;
         default: {
@@ -332,6 +294,7 @@
     out.set_change_mode(in.change_mode);
     out.set_value_type(in.value_type);
     out.set_permission_model(in.permission_model);
+    out.set_zones(in.vehicle_zone_flags);
     for (unsigned int i = 0; i < sizeof(in.config_array) / sizeof(int32_t); i++) {
         out.add_config_array(in.config_array[i]);
     }
@@ -344,26 +307,80 @@
         case VEHICLE_VALUE_TYPE_FLOAT:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
-        case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
+            out.add_float_maxs(in.float_max_value);
+            out.add_float_mins(in.float_min_value);
+        } break;
         case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
         case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: {
-            out.set_float_max(in.float_max_value);
-            out.set_float_min(in.float_min_value);
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
+            int numZones = VehicleNetworkUtil::countNumberOfZones(in.vehicle_zone_flags);
+            if (in.float_min_values == NULL) {
+                if (in.float_max_values == NULL) {
+                    // all the same min/max
+                    for (int i = 0; i < numZones; i++) {
+                        out.add_float_maxs(in.float_max_value);
+                        out.add_float_mins(in.float_min_value);
+                    }
+                } else { // invalid combination
+                    ALOGW("Zoned property 0x%x, min_values NULL while max_values not NULL",
+                            in.prop);
+                    return BAD_VALUE;
+                }
+            } else {
+                if (in.float_max_values != NULL) {
+                    for (int i = 0; i < numZones; i++) {
+                        out.add_float_maxs(in.float_max_values[i]);
+                        out.add_float_mins(in.float_min_values[i]);
+                    }
+                } else { // invalid combination
+                    ALOGW("Zoned property 0x%x, max_values NULL while min_values not NULL",
+                            in.prop);
+                    return BAD_VALUE;
+                }
+            }
         } break;
         case VEHICLE_VALUE_TYPE_INT64: {
-            out.set_int64_max(in.int64_max_value);
-            out.set_int64_min(in.int64_min_value);
+            out.add_int64_maxs(in.int64_max_value);
+            out.add_int64_mins(in.int64_min_value);
         } break;
         case VEHICLE_VALUE_TYPE_INT32:
         case VEHICLE_VALUE_TYPE_INT32_VEC2:
         case VEHICLE_VALUE_TYPE_INT32_VEC3:
-        case VEHICLE_VALUE_TYPE_INT32_VEC4:
+        case VEHICLE_VALUE_TYPE_INT32_VEC4:  {
+            out.add_int32_maxs(in.int32_max_value);
+            out.add_int32_mins(in.int32_min_value);
+        } break;
         case VEHICLE_VALUE_TYPE_ZONED_INT32:
         case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: {
-            out.set_int32_max(in.int32_max_value);
-            out.set_int32_min(in.int32_min_value);
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
+            int numZones = VehicleNetworkUtil::countNumberOfZones(in.vehicle_zone_flags);
+            if (in.int32_min_values == NULL) {
+                if (in.int32_max_values == NULL) {
+                    // all the same min/max
+                    for (int i = 0; i < numZones; i++) {
+                        out.add_int32_maxs(in.int32_max_value);
+                        out.add_int32_mins(in.int32_min_value);
+                    }
+                } else { // invalid combination
+                    ALOGW("Zoned property 0x%x, min_values NULL while max_values not NULL",
+                            in.prop);
+                    return BAD_VALUE;
+                }
+            } else {
+                if (in.int32_max_values != NULL) {
+                    for (int i = 0; i < numZones; i++) {
+                        out.add_int32_maxs(in.int32_max_values[i]);
+                        out.add_int32_mins(in.int32_min_values[i]);
+                    }
+                } else { // invalid combination
+                    ALOGW("Zoned property 0x%x, max_values NULL while min_values not NULL",
+                            in.prop);
+                    return BAD_VALUE;
+                }
+            }
         } break;
     }
     out.set_sample_rate_max(in.max_sample_rate);
@@ -378,6 +395,7 @@
     out.change_mode = in.change_mode();
     out.value_type = in.value_type();
     out.permission_model = in.permission_model();
+    out.vehicle_zone_flags = in.zones();
     int maxConfigSize = sizeof(out.config_array) / sizeof(int32_t);
     int configSize = in.config_array_size();
     if (configSize > maxConfigSize) {
@@ -404,23 +422,58 @@
         case VEHICLE_VALUE_TYPE_FLOAT:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
         case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
-        case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: {
-            if (in.has_float_max() && in.has_float_min()) {
-                out.float_max_value = in.float_max();
-                out.float_min_value = in.float_min();
+        case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
+            if ((in.float_maxs_size() == 1) && (in.float_mins_size() == 1)) {
+                out.float_max_value = in.float_maxs(0);
+                out.float_min_value = in.float_mins(0);
             } else {
                 ALOGW("no float max/min for property 0x%x", out.prop);
                 out.float_max_value = 0;
                 out.float_min_value = 0;
             }
         } break;
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
+            int numZones = VehicleNetworkUtil::countNumberOfZones(out.vehicle_zone_flags);
+            int maxSize = in.float_maxs_size();
+            int minSize = in.float_mins_size();
+            if (maxSize != minSize) {
+                ALOGW("Zoned property 0x%x, config maxSize %d minSize %d", out.prop, maxSize,
+                        minSize);
+                return BAD_VALUE;
+            }
+            if (maxSize == 0) {
+                out.float_max_value = 0;
+                out.float_min_value = 0;
+                out.float_max_values = NULL;
+                out.float_min_values = NULL;
+            } else if (maxSize == 1) { // one for all
+                out.float_max_value = in.float_maxs(0);
+                out.float_min_value = in.float_mins(0);
+                out.float_max_values = NULL;
+                out.float_min_values = NULL;
+            } else if (numZones > 1){
+                if (numZones != maxSize) {
+                    ALOGW("Zoned property 0x%x, config maxSize %d num Zones %d", out.prop, maxSize,
+                                            numZones);
+                    return BAD_VALUE;
+                }
+                out.float_max_values = new float[numZones];
+                ASSERT_OR_HANDLE_NO_MEMORY(out.float_max_values, return NO_MEMORY);
+                out.float_min_values = new float[numZones];
+                ASSERT_OR_HANDLE_NO_MEMORY(out.float_min_values, return NO_MEMORY);
+                for (int i = 0; i < numZones; i++) {
+                    out.float_max_values[i] = in.float_maxs(i);
+                    out.float_min_values[i] = in.float_mins(i);
+                }
+            }
+        } break;
         case VEHICLE_VALUE_TYPE_INT64: {
-            if (in.has_int64_max() && in.has_int64_min()) {
-                out.int64_max_value = in.int64_max();
-                out.int64_min_value = in.int64_min();
+            if ((in.int64_maxs_size() == 1) && (in.int64_mins_size() == 1)) {
+                out.int64_max_value = in.int64_maxs(0);
+                out.int64_min_value = in.int64_mins(0);
             } else {
                 ALOGW("no int64 max/min for property 0x%x", out.prop);
                 out.int64_max_value = 0;
@@ -430,19 +483,54 @@
         case VEHICLE_VALUE_TYPE_INT32:
         case VEHICLE_VALUE_TYPE_INT32_VEC2:
         case VEHICLE_VALUE_TYPE_INT32_VEC3:
-        case VEHICLE_VALUE_TYPE_INT32_VEC4:
-        case VEHICLE_VALUE_TYPE_ZONED_INT32:
-        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
-        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: {
-            if (in.has_int32_max() && in.has_int32_min()) {
-                out.int32_max_value = in.int32_max();
-                out.int32_min_value = in.int32_min();
+        case VEHICLE_VALUE_TYPE_INT32_VEC4: {
+            if ((in.int32_maxs_size() == 1) && (in.int32_mins_size() == 1)) {
+                out.int32_max_value = in.int32_maxs(0);
+                out.int32_min_value = in.int32_mins(0);
             } else {
                 ALOGW("no int32 max/min for property 0x%x", out.prop);
                 out.int32_max_value = 0;
                 out.int32_min_value = 0;
             }
         } break;
+        case VEHICLE_VALUE_TYPE_ZONED_INT32:
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
+            int numZones = VehicleNetworkUtil::countNumberOfZones(out.vehicle_zone_flags);
+            int maxSize = in.int32_maxs_size();
+            int minSize = in.int32_mins_size();
+            if (maxSize != minSize) {
+                ALOGW("Zoned property 0x%x, config maxSize %d minSize %d", out.prop, maxSize,
+                        minSize);
+                return BAD_VALUE;
+            }
+            if (maxSize == 0) {
+                out.int32_max_value = 0;
+                out.int32_min_value = 0;
+                out.int32_max_values = NULL;
+                out.int32_min_values = NULL;
+            } else if (maxSize == 1) { // one for all
+                out.int32_max_value = in.int32_maxs(0);
+                out.int32_min_value = in.int32_mins(0);
+                out.int32_max_values = NULL;
+                out.int32_min_values = NULL;
+            } else if (numZones > 1){
+                if (numZones != maxSize) {
+                    ALOGW("Zoned property 0x%x, config maxSize %d num Zones %d", out.prop, maxSize,
+                                            numZones);
+                    return BAD_VALUE;
+                }
+                out.int32_max_values = new int32_t[numZones];
+                ASSERT_OR_HANDLE_NO_MEMORY(out.int32_max_values, return NO_MEMORY);
+                out.int32_min_values = new int32_t[numZones];
+                ASSERT_OR_HANDLE_NO_MEMORY(out.int32_min_values, return NO_MEMORY);
+                for (int i = 0; i < numZones; i++) {
+                    out.int32_max_values[i] = in.int32_maxs(i);
+                    out.int32_min_values[i] = in.int32_mins(i);
+                }
+            }
+        } break;
     }
     out.max_sample_rate = in.sample_rate_max();
     out.min_sample_rate = in.sample_rate_min();
diff --git a/libvehiclenetwork/proto/VehicleNetworkProto.proto b/libvehiclenetwork/proto/VehicleNetworkProto.proto
index 4cd81e4..487ecfd 100644
--- a/libvehiclenetwork/proto/VehicleNetworkProto.proto
+++ b/libvehiclenetwork/proto/VehicleNetworkProto.proto
@@ -24,40 +24,35 @@
     required int32 change_mode = 3;
     required int32 value_type = 4;
     required int32 permission_model = 5;
-    repeated int32 config_array = 6;
-    required float sample_rate_max = 7;
-    required float sample_rate_min = 8;
-    optional string config_string = 9;
-    optional float float_max = 10;
-    optional float float_min = 11;
-    optional int32 int32_max = 12;
-    optional int32 int32_min = 13;
-    optional int64 int64_max = 14;
-    optional int64 int64_min = 15;
+    optional int32 zones = 6;
+    repeated int32 config_array = 7;
+    required float sample_rate_max = 8;
+    required float sample_rate_min = 9;
+    optional string config_string = 10;
+    repeated float float_maxs = 11;
+    repeated float float_mins = 12;
+    repeated int32 int32_maxs = 13;
+    repeated int32 int32_mins = 14;
+    repeated int64 int64_maxs = 15;
+    repeated int64 int64_mins = 16;
 };
 
 message VehiclePropConfigs {
     repeated VehiclePropConfig configs = 1;
 };
 
-message ZonedValue {
-    required int32 zone_or_window = 1;
-    repeated int32 int32_values = 2; // also covers boolean value.
-    repeated float float_values = 3;
-};
-
 message VehiclePropValue {
     // common data
     required int32 prop = 1;
     required int32 value_type = 2;
     optional int64 timestamp = 3; // required for valid data from HAL, but can be skipped for set.
     // values
-    repeated int32 int32_values= 4; // this also covers boolean value.
-    optional int64 int64_value = 5;
-    repeated float float_values = 6;
-    optional string string_value = 7;
-    optional bytes bytes_value = 8;
-    optional ZonedValue zoned_value = 9;
+    optional int32 zone = 4;
+    repeated int32 int32_values= 5; // this also covers boolean value.
+    optional int64 int64_value = 6;
+    repeated float float_values = 7;
+    optional string string_value = 8;
+    optional bytes bytes_value = 9;
 };
 
 message VehiclePropValues {
diff --git a/service/src/com/android/car/CarServiceUtils.java b/service/src/com/android/car/CarServiceUtils.java
index fba0470..b47e22c 100644
--- a/service/src/com/android/car/CarServiceUtils.java
+++ b/service/src/com/android/car/CarServiceUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.car;
 
+import java.util.List;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -138,4 +140,22 @@
             }
         }
     }
+
+    public static float[] toFloatArray(List<Float> list) {
+        final int size = list.size();
+        final float[] array = new float[size];
+        for (int i = 0; i < size; ++i) {
+            array[i] = list.get(i);
+        }
+        return array;
+    }
+
+    public static int[] toIntArray(List<Integer> list) {
+        final int size = list.size();
+        final int[] array = new int[size];
+        for (int i = 0; i < size; ++i) {
+            array[i] = list.get(i);
+        }
+        return array;
+    }
 }
diff --git a/service/src/com/android/car/hal/HvacHalService.java b/service/src/com/android/car/hal/HvacHalService.java
index 610a66a..6b3e50f 100644
--- a/service/src/com/android/car/hal/HvacHalService.java
+++ b/service/src/com/android/car/hal/HvacHalService.java
@@ -24,6 +24,7 @@
 import android.util.Log;
 
 import com.android.car.CarLog;
+import com.android.car.CarServiceUtils;
 import com.android.car.vehiclenetwork.VehicleNetwork;
 import com.android.car.vehiclenetwork.VehicleNetworkConsts;
 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
@@ -121,34 +122,24 @@
         if(value != null) {
             switch(hvacProp.getType()) {
                 case CarHvacManager.PROPERTY_TYPE_BOOLEAN:
-                    hvacProp.setBooleanValue(zoned
-                            ? value.getZonedValue().getInt32Values(0) == 1
-                            : value.getInt32Values(0) == 1);
+                    hvacProp.setBooleanValue(value.getInt32Values(0) == 1);
                     break;
                 case CarHvacManager.PROPERTY_TYPE_INT:
-                    hvacProp.setIntValue(zoned
-                            ? value.getZonedValue().getInt32Values(0)
-                            : value.getInt32Values(0));
+                    hvacProp.setIntValue(value.getInt32Values(0));
                     break;
                 case CarHvacManager.PROPERTY_TYPE_FLOAT:
-                    hvacProp.setFloatValue(zoned
-                            ? value.getZonedValue().getFloatValues(0)
-                            : value.getFloatValues(0));
+                    hvacProp.setFloatValue(value.getFloatValues(0));
                     break;
                 case CarHvacManager.PROPERTY_TYPE_INT_VECTOR:
-                    hvacProp.setIntValues(toIntArray(zoned
-                            ? value.getZonedValue().getInt32ValuesList()
-                            : value.getInt32ValuesList()));
+                    hvacProp.setIntValues(toIntArray(value.getInt32ValuesList()));
                     break;
                 case CarHvacManager.PROPERTY_TYPE_FLOAT_VECTOR:
                     hvacProp.setFloatValues(
-                            toFloatArray(zoned
-                                    ? value.getZonedValue().getFloatValuesList()
-                                    : value.getFloatValuesList()));
+                            toFloatArray(value.getFloatValuesList()));
                     break;
             }
             if (zoned) {
-                hvacProp.setZone(zone);
+                hvacProp.setZones(zone);
             }
         } else {
             hvacProp = null;
@@ -160,7 +151,7 @@
     public void setHvacProperty(CarHvacProperty prop) {
         int halProp = hvacToHalPropId(prop.getPropertyId());
         VehicleNetwork vehicleNetwork = mVehicleHal.getVehicleNetwork();
-        int zone = prop.getZone();
+        int zone = prop.getZones();
         boolean zoned = CarHvacManager.isZonedProperty(prop.getPropertyId());
 
         switch(prop.getType()) {
@@ -254,40 +245,44 @@
             if (hvacPropId != 0) {
                 CarHvacProperty hvacProp;
                 int halType = p.getValueType();
-                int valZone = p.getConfigArray(0);
+                int valZone = p.getZones();
 
                 switch(halType) {
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
                         hvacProp = new CarHvacProperty(hvacPropId, valZone, false);
                         break;
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT: {
-                        float valMin = p.getFloatMin();
-                        float valMax = p.getFloatMax();
-                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMin, valMax, 0);
+                        float[] valMins = CarServiceUtils.toFloatArray(p.getFloatMinsList());
+                        float[] valMaxs = CarServiceUtils.toFloatArray(p.getFloatMaxsList());
+                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMins, valMaxs, 0);
                         break;
                     }
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32: {
-                        int valMin = p.getInt32Min();
-                        int valMax = p.getInt32Max();
-                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMin, valMax, 0);
+                        int[] valMins = CarServiceUtils.toIntArray(p.getInt32MinsList());
+                        int[] valMaxs = CarServiceUtils.toIntArray(p.getInt32MaxsList());
+                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMins, valMaxs, 0);
                         break;
                     }
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+                    case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
                     {
-                        int valMin = p.getInt32Min();
-                        int valMax = p.getInt32Max();
+                        int[] valMins = CarServiceUtils.toIntArray(p.getInt32MinsList());
+                        int[] valMaxs = CarServiceUtils.toIntArray(p.getInt32MaxsList());
                         int[] values = new int[VehiclePropValueUtil.getVectorLength(halType)];
-                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMin, valMax, values);
+                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMins, valMaxs,
+                                values);
                         break;
                     }
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+                    case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
                     {
-                        float valMin = p.getFloatMin();
-                        float valMax = p.getFloatMax();
+                        float[] valMins = CarServiceUtils.toFloatArray(p.getFloatMinsList());
+                        float[] valMaxs = CarServiceUtils.toFloatArray(p.getFloatMaxsList());
                         float[] values = new float[VehiclePropValueUtil.getVectorLength(halType)];
-                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMin, valMax, values);
+                        hvacProp = new CarHvacProperty(hvacPropId, valZone, valMins, valMaxs,
+                                values);
                         break;
                     }
 
@@ -326,21 +321,21 @@
             if (hvacPropId != 0) {
                 CarHvacEvent event = null;
                 int halType = v.getValueType();
-                int zone = v.getZonedValue().getZoneOrWindow();
+                int zone = v.getZone();
 
                 switch(halType) {
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
                         event = new CarHvacEvent(CarHvacEvent.HVAC_EVENT_PROPERTY_CHANGE,
-                                hvacPropId, zone, v.getZonedValue().getInt32Values(0) == 1);
+                                hvacPropId, zone, v.getInt32Values(0) == 1);
                         break;
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT: {
                         event = new CarHvacEvent(CarHvacEvent.HVAC_EVENT_PROPERTY_CHANGE,
-                                hvacPropId, zone, v.getZonedValue().getFloatValues(0));
+                                hvacPropId, zone, v.getFloatValues(0));
                         break;
                     }
                     case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32: {
                         event = new CarHvacEvent(CarHvacEvent.HVAC_EVENT_PROPERTY_CHANGE,
-                                hvacPropId, zone, v.getZonedValue().getInt32Values(0));
+                                hvacPropId, zone, v.getInt32Values(0));
                         break;
                     }
                     default:
diff --git a/service/src/com/android/car/hal/PowerHalService.java b/service/src/com/android/car/hal/PowerHalService.java
index 8cf412a..04559f7 100644
--- a/service/src/com/android/car/hal/PowerHalService.java
+++ b/service/src/com/android/car/hal/PowerHalService.java
@@ -266,7 +266,7 @@
         VehiclePropConfig brightnessProperty = mProperties.get(
                 VehicleNetworkConsts.VEHICLE_PROPERTY_DISPLAY_BRIGHTNESS);
         if (brightnessProperty != null) {
-            mMaxDisplayBrightness = brightnessProperty.getInt32Max();
+            mMaxDisplayBrightness = brightnessProperty.getInt32Maxs(0);
             if (mMaxDisplayBrightness <= 0) {
                 Log.w(CarLog.TAG_POWER, "Max display brightness from vehicle HAL is invald:" +
                         mMaxDisplayBrightness);
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index ef0e6c7..9bb076b 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -321,17 +321,17 @@
             builder.append(",config:" + Integer.toHexString(config.getConfigArray(0)));
             builder.append(",fs min:" + config.getSampleRateMin());
             builder.append(",fs max:" + config.getSampleRateMax());
-            if (config.hasFloatMin()) {
-                builder.append(",v min:" + config.getFloatMin());
-                builder.append(",v max:" + config.getFloatMax());
+            for (int i = 0; i < config.getFloatMaxsCount(); i++) {
+                builder.append(",v min:" + config.getFloatMins(i));
+                builder.append(",v max:" + config.getFloatMaxs(i));
             }
-            if (config.hasInt32Min()) {
-                builder.append(",v min:" + config.getInt32Min());
-                builder.append(",v max:" + config.getInt32Max());
+            for (int i = 0; i < config.getInt32MaxsCount(); i++) {
+                builder.append(",v min:" + config.getInt32Mins(i));
+                builder.append(",v max:" + config.getInt32Maxs(i));
             }
-            if (config.hasInt64Min()) {
-                builder.append(",v min:" + config.getInt64Min());
-                builder.append(",v max:" + config.getInt64Max());
+            for (int i = 0; i < config.getInt64MaxsCount(); i++) {
+                builder.append(",v min:" + config.getInt64Mins(i));
+                builder.append(",v max:" + config.getInt64Maxs(i));
             }
             writer.println(builder.toString());
         }
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java
index 002b387..f41fda2 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java
@@ -62,12 +62,17 @@
     private float mCurDTemp = 23;
     private float mCurPTemp = 23;
     private CarHvacManager mCarHvacManager;
+    private int mZoneForAcOn;
+    private int mZoneForSetTempD;
+    private int mZoneForSetTempP;
+    private int mZoneForFanSpeed;
+    private int mZoneForFanPosition;
 
     private final CarHvacManager.CarHvacEventListener mHvacListener =
             new CarHvacManager.CarHvacEventListener () {
                 @Override
                 public void onChangeEvent(final CarHvacManager.CarHvacBaseProperty value) {
-                    int zone = value.getZone();
+                    int zones = value.getZones();
                     switch(value.getPropertyId()) {
                         case CarHvacManager.HVAC_ZONED_AC_ON:
                             mTbAc.setChecked(((CarHvacBooleanValue)value).getValue());
@@ -91,30 +96,27 @@
                             }
                             break;
                         case CarHvacManager.HVAC_ZONED_FAN_SPEED_SETPOINT:
-                            mCurFanSpeed = ((CarHvacIntValue)value).getValue();
-                            mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
+                            if ((zones & mZoneForFanSpeed) != 0) {
+                                mCurFanSpeed = ((CarHvacIntValue)value).getValue();
+                                mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
+                            }
                             break;
                         case CarHvacManager.HVAC_ZONED_TEMP_SETPOINT:
-                            switch(zone) {
-                                case VehicleZone.VEHICLE_ZONE_ROW_1_LEFT:
-                                    mCurDTemp = ((CarHvacFloatValue)value).getValue();
-                                    mTvDTemp.setText(String.valueOf(mCurDTemp));
-                                    break;
-                                case VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT:
-                                    mCurPTemp = ((CarHvacFloatValue)value).getValue();
-                                    mTvPTemp.setText(String.valueOf(mCurPTemp));
-                                    break;
-                                default:
-                                    Log.w(TAG, "Unknown zone = " + zone);
-                                    break;
+                            if ((zones & mZoneForSetTempD) != 0) {
+                                mCurDTemp = ((CarHvacFloatValue)value).getValue();
+                                mTvDTemp.setText(String.valueOf(mCurDTemp));
+                            }
+                            if ((zones & mZoneForSetTempP) != 0) {
+                                mCurPTemp = ((CarHvacFloatValue)value).getValue();
+                                mTvPTemp.setText(String.valueOf(mCurPTemp));
                             }
                             break;
                         case CarHvacManager.HVAC_WINDOW_DEFROSTER_ON:
-                            if((zone & VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD) ==
+                            if((zones & VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD) ==
                                     VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD) {
                                 mTbDefrostFront.setChecked(((CarHvacBooleanValue)value).getValue());
                             }
-                            if((zone & VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD) ==
+                            if((zones & VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD) ==
                                     VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD) {
                                 mTbDefrostRear.setChecked(((CarHvacBooleanValue)value).getValue());
                             }
@@ -158,41 +160,24 @@
             int type = prop.getType();
 
             if(DBG) {
-                switch(type) {
-                    case CarHvacManager.PROPERTY_TYPE_BOOLEAN:
-                        Log.d(TAG, "propertyId = " + propId + " type = " + type +
-                                " zone = " + prop.getZone());
-                        break;
-                    case CarHvacManager.PROPERTY_TYPE_FLOAT:
-                        CarHvacFloatProperty f = (CarHvacFloatProperty)prop;
-                        Log.d(TAG, "propertyId = " + propId + " type = " + type +
-                                " zone = " + f.getZone() + " min = " + f.getMinValue() +
-                                " max = " + f.getMaxValue());
-                        break;
-                    case CarHvacManager.PROPERTY_TYPE_INT:
-                        CarHvacIntProperty i = (CarHvacIntProperty)prop;
-                        Log.d(TAG, "propertyId = " + propId + " type = " + type +
-                                " zone = " + i.getZone() + " min = " + i.getMinValue() +
-                                " max = " + i.getMaxValue());
-                        break;
-                }
+                Log.d(TAG, prop.toString());
             }
 
             switch(propId) {
                 case CarHvacManager.HVAC_ZONED_AC_ON:
-                    configureAcOn(v);
+                    configureAcOn(v, prop);
                     break;
                 case CarHvacManager.HVAC_ZONED_FAN_POSITION:
-                    configureFanPosition(v);
+                    configureFanPosition(v, prop);
                     break;
                 case CarHvacManager.HVAC_ZONED_FAN_SPEED_SETPOINT:
-                    configureFanSpeed(v);
+                    configureFanSpeed(v, prop);
                     break;
                 case CarHvacManager.HVAC_ZONED_TEMP_SETPOINT:
-                    configureTempSetpoint(v);
+                    configureTempSetpoint(v, prop);
                     break;
                 case CarHvacManager.HVAC_WINDOW_DEFROSTER_ON:
-                    configureDefrosterOn(v, prop.getZone());
+                    configureDefrosterOn(v, prop.getZones());
                     break;
                 default:
                     Log.w(TAG, "propertyId " + propId + " is not handled");
@@ -219,19 +204,49 @@
         mCarHvacManager = hvacManager;
     }
 
-    private void configureAcOn(View v) {
+    private static int getFirstZone(int zones) {
+        if (zones == 0) {
+            return 0;
+        }
+        int flag = 0x1;
+        for (int i = 0; i < 32; i++) {
+            if ((flag & zones) != 0) {
+                return flag;
+            }
+            flag <<= 1;
+        }
+        return 0;
+    }
+
+    private static int getNextZone(int zones, int startingZone) {
+        int flag = startingZone << 1;
+        while (flag != 0x80000000) {
+            if ((flag & zones) != 0) {
+                return flag;
+            }
+            flag <<= 1;
+        }
+        if ((flag & zones) != 0) {
+            return flag;
+        }
+        return 0;
+    }
+
+    private void configureAcOn(View v, CarHvacBaseProperty prop) {
+        mZoneForAcOn = getFirstZone(prop.getZones());
         mTbAc = (ToggleButton)v.findViewById(R.id.tbAc);
         mTbAc.setEnabled(true);
         mTbAc.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 // TODO handle zone properly
-                mCarHvacManager.setBooleanProperty(CarHvacManager.HVAC_ZONED_AC_ON, 0x8,
+                mCarHvacManager.setBooleanProperty(CarHvacManager.HVAC_ZONED_AC_ON, mZoneForAcOn,
                         mTbAc.isChecked());
             }
         });
     }
 
-    private void configureFanPosition(View v) {
+    private void configureFanPosition(View v, CarHvacBaseProperty prop) {
+        mZoneForFanPosition = getFirstZone(prop.getZones());
         RadioGroup rg = (RadioGroup)v.findViewById(R.id.rgFanPosition);
         rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
             @Override
@@ -239,18 +254,18 @@
                 switch(checkedId) {
                     case R.id.rbPositionFace:
                         mCarHvacManager.setIntProperty(CarHvacManager.HVAC_ZONED_FAN_POSITION,
-                                VehicleZone.VEHICLE_ZONE_ROW_1_ALL,
+                                mZoneForFanPosition,
                                 VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FACE);
                         break;
                     case R.id.rbPositionFloor:
                         mCarHvacManager.setIntProperty(CarHvacManager.HVAC_ZONED_FAN_POSITION,
-                                VehicleZone.VEHICLE_ZONE_ROW_1_ALL,
+                                mZoneForFanPosition,
                                 VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FLOOR);
                         break;
                     case R.id.rbPositionFaceAndFloor:
                         mCarHvacManager.setIntProperty(CarHvacManager.HVAC_ZONED_FAN_POSITION,
-                                VehicleZone.VEHICLE_ZONE_ROW_1_ALL, VehicleHvacFanDirection.
-                                        VEHICLE_HVAC_FAN_DIRECTION_FACE_AND_FLOOR);
+                                mZoneForFanPosition,
+                                VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FACE_AND_FLOOR);
                         break;
                 }
             }
@@ -264,10 +279,11 @@
         mRbFanPositionFloor.setClickable(true);
     }
 
-    private void configureFanSpeed(View v) {
+    private void configureFanSpeed(View v, CarHvacBaseProperty prop) {
+        mZoneForFanSpeed = getFirstZone(prop.getZones());
         mCurFanSpeed = mCarHvacManager.getIntProperty(
                 CarHvacManager.HVAC_ZONED_FAN_SPEED_SETPOINT,
-                VehicleZone.VEHICLE_ZONE_ROW_1_ALL);
+                mZoneForFanSpeed);
 
         Button btnFanSpeedUp = (Button) v.findViewById(R.id.btnFanSpeedUp);
         btnFanSpeedUp.setEnabled(true);
@@ -277,7 +293,7 @@
                     mCurFanSpeed++;
                     mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
                     mCarHvacManager.setIntProperty(CarHvacManager.HVAC_ZONED_FAN_SPEED_SETPOINT,
-                            VehicleZone.VEHICLE_ZONE_ROW_1_ALL, mCurFanSpeed);
+                            mZoneForFanSpeed, mCurFanSpeed);
                 }
             }
         });
@@ -290,71 +306,96 @@
                     mCurFanSpeed--;
                     mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
                     mCarHvacManager.setIntProperty(CarHvacManager.HVAC_ZONED_FAN_SPEED_SETPOINT,
-                            VehicleZone.VEHICLE_ZONE_ROW_1_ALL, mCurFanSpeed);
+                            mZoneForFanSpeed, mCurFanSpeed);
                 }
             }
         });
     }
 
-    private void configureTempSetpoint(View v) {
-        mCurDTemp = mCarHvacManager.getFloatProperty(
-                CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
-                VehicleZone.VEHICLE_ZONE_ROW_1_LEFT);
-        mCurPTemp = mCarHvacManager.getFloatProperty(
-                CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
-                VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT);
-
+    private void configureTempSetpoint(View v, CarHvacBaseProperty prop) {
+        mZoneForSetTempD = 0;
+        if ((prop.getZones() & VehicleZone.VEHICLE_ZONE_ROW_1_LEFT) != 0) {
+            mZoneForSetTempD = VehicleZone.VEHICLE_ZONE_ROW_1_LEFT;
+        }
+        mZoneForSetTempP = 0;
+        if ((prop.getZones() & VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT) != 0) {
+            mZoneForSetTempP = VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT;
+        }
+        if (mZoneForSetTempD == 0) {
+            mZoneForSetTempD = getFirstZone(prop.getZones());
+        }
+        if (mZoneForSetTempP == 0) {
+            mZoneForSetTempP = getNextZone(prop.getZones(), mZoneForSetTempD);
+        }
+        int numZones = CarHvacBaseProperty.getNumZones(prop.getZones());
+        if (numZones < 2) {
+            mZoneForSetTempP = 0;
+        }
         Button btnDTempUp = (Button) v.findViewById(R.id.btnDTempUp);
-        btnDTempUp.setEnabled(true);
-        btnDTempUp.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                if(mCurDTemp < 29.5) {
-                    mCurDTemp += 0.5;
-                    mTvDTemp.setText(String.valueOf(mCurDTemp));
-                    mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
-                            VehicleZone.VEHICLE_ZONE_ROW_1_LEFT, mCurDTemp);
+        if (mZoneForSetTempD != 0) {
+            mCurDTemp = mCarHvacManager.getFloatProperty(
+                    CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
+                    mZoneForSetTempD);
+            btnDTempUp.setEnabled(true);
+            btnDTempUp.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    if(mCurDTemp < 29.5) {
+                        mCurDTemp += 0.5;
+                        mTvDTemp.setText(String.valueOf(mCurDTemp));
+                        mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
+                                mZoneForSetTempD, mCurDTemp);
+                    }
                 }
-            }
-        });
+            });
 
-        Button btnDTempDn = (Button) v.findViewById(R.id.btnDTempDn);
-        btnDTempDn.setEnabled(true);
-        btnDTempDn.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                if(mCurDTemp > 15.5) {
-                    mCurDTemp -= 0.5;
-                    mTvDTemp.setText(String.valueOf(mCurDTemp));
-                    mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
-                            VehicleZone.VEHICLE_ZONE_ROW_1_LEFT, mCurDTemp);
+            Button btnDTempDn = (Button) v.findViewById(R.id.btnDTempDn);
+            btnDTempDn.setEnabled(true);
+            btnDTempDn.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    if(mCurDTemp > 15.5) {
+                        mCurDTemp -= 0.5;
+                        mTvDTemp.setText(String.valueOf(mCurDTemp));
+                        mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
+                                mZoneForSetTempD, mCurDTemp);
+                    }
                 }
-            }
-        });
+            });
+        } else {
+            btnDTempUp.setEnabled(false);
+        }
 
         Button btnPTempUp = (Button) v.findViewById(R.id.btnPTempUp);
-        btnPTempUp.setEnabled(true);
-        btnPTempUp.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                if (mCurPTemp < 29.5) {
-                    mCurPTemp += 0.5;
-                    mTvPTemp.setText(String.valueOf(mCurPTemp));
-                    mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
-                            VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT, mCurPTemp);
+        if (mZoneForSetTempP !=0 ) {
+            mCurPTemp = mCarHvacManager.getFloatProperty(
+                    CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
+                    mZoneForSetTempP);
+            btnPTempUp.setEnabled(true);
+            btnPTempUp.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    if (mCurPTemp < 29.5) {
+                        mCurPTemp += 0.5;
+                        mTvPTemp.setText(String.valueOf(mCurPTemp));
+                        mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
+                                mZoneForSetTempP, mCurPTemp);
+                    }
                 }
-            }
-        });
+            });
 
-        Button btnPTempDn = (Button) v.findViewById(R.id.btnPTempDn);
-        btnPTempDn.setEnabled(true);
-        btnPTempDn.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                if (mCurPTemp > 15.5) {
-                    mCurPTemp -= 0.5;
-                    mTvPTemp.setText(String.valueOf(mCurPTemp));
-                    mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
-                            VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT, mCurPTemp);
+            Button btnPTempDn = (Button) v.findViewById(R.id.btnPTempDn);
+            btnPTempDn.setEnabled(true);
+            btnPTempDn.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    if (mCurPTemp > 15.5) {
+                        mCurPTemp -= 0.5;
+                        mTvPTemp.setText(String.valueOf(mCurPTemp));
+                        mCarHvacManager.setFloatProperty(CarHvacManager.HVAC_ZONED_TEMP_SETPOINT,
+                                mZoneForSetTempP, mCurPTemp);
+                    }
                 }
-            }
-        });
+            });
+        } else {
+            btnPTempUp.setEnabled(false);
+        }
     }
 
     private void configureDefrosterOn(View v, int zone) {
diff --git a/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java b/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
index 13d0936..497e6c6 100644
--- a/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
@@ -212,21 +212,21 @@
                 case CarHvacManager.PROPERTY_TYPE_BOOLEAN:
                     CarHvacBooleanValue boolVal = (CarHvacBooleanValue) value;
                     mEventBoolVal = boolVal.getValue();
-                    mEventZoneVal = boolVal.getZone();
+                    mEventZoneVal = boolVal.getZones();
                     Log.d(TAG, "onChangeEvent - propId = " + boolVal.getPropertyId() +
                             " bool = " + boolVal.getValue());
                     break;
                 case CarHvacManager.PROPERTY_TYPE_FLOAT:
                     CarHvacFloatValue floatVal = (CarHvacFloatValue) value;
                     mEventFloatVal = floatVal.getValue();
-                    mEventZoneVal = floatVal.getZone();
+                    mEventZoneVal = floatVal.getZones();
                     Log.d(TAG, "onChangeEvent - propId = " + floatVal.getPropertyId() +
                             " float = " + floatVal.getValue());
                     break;
                 case CarHvacManager.PROPERTY_TYPE_INT:
                     CarHvacIntValue intVal = (CarHvacIntValue) value;
                     mEventIntVal = intVal.getValue();
-                    mEventZoneVal = intVal.getZone();
+                    mEventZoneVal = intVal.getZones();
                     Log.d(TAG, "onChangeEvent - propId = " + intVal.getPropertyId() +
                             " int = " + intVal.getValue());
                     break;
diff --git a/tests/libvehiclenetwork-java-test/Android.mk b/tests/libvehiclenetwork-java-test/Android.mk
index bde7dda..6dae564 100644
--- a/tests/libvehiclenetwork-java-test/Android.mk
+++ b/tests/libvehiclenetwork-java-test/Android.mk
@@ -15,7 +15,7 @@
 #
 
 LOCAL_PATH:= $(call my-dir)
-
+##################################
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -36,3 +36,14 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 include $(BUILD_PACKAGE)
+
+##################################
+include $(CLEAR_VARS)
+#vendor_vns_policy for testing purpose
+LOCAL_MODULE := vendor_vns_policy.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/vns
+include $(BUILD_PREBUILT)
+
diff --git a/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkMockedTest.java b/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkMockedTest.java
index 7b3c5e6..78b0ece 100644
--- a/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkMockedTest.java
+++ b/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkMockedTest.java
@@ -31,7 +31,6 @@
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
-import com.android.car.vehiclenetwork.VehicleNetworkProto.ZonedValue;
 import com.android.car.vehiclenetwork.VehiclePropConfigUtil;
 import com.android.car.vehiclenetwork.VehiclePropValueUtil;
 
@@ -111,21 +110,25 @@
                 new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createIntVectorValue(
                         CUSTOM_PROPERTY_INT32_VEC2, new int[2], 0)));
         mVehicleHalMock.registerProperty(
-                VehiclePropConfigUtil.createProperty(
+                VehiclePropConfigUtil.createZonedProperty(
                         CUSTOM_PROPERTY_ZONED_INT32_VEC3,
                         VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                         VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
-                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3, 0x0),
+                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3,
+                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
+                        0x0),
                 new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedIntVectorValue(
                         CUSTOM_PROPERTY_ZONED_INT32_VEC3,
                         VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
                         new int[3], 0)));
         mVehicleHalMock.registerProperty(
-                VehiclePropConfigUtil.createProperty(
+                VehiclePropConfigUtil.createZonedProperty(
                         CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                         VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                         VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
-                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2, 0x0),
+                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2,
+                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
+                        0x0),
                 new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedFloatVectorValue(
                         CUSTOM_PROPERTY_ZONED_FLOAT_VEC2,
                         VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
@@ -139,11 +142,13 @@
                 new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createFloatVectorValue(
                         CUSTOM_PROPERTY_FLOAT_VEC2, new float[2], 0)));
         mVehicleHalMock.registerProperty(
-                VehiclePropConfigUtil.createProperty(
+                VehiclePropConfigUtil.createZonedProperty(
                         CUSTOM_PROPERTY_ZONED_FLOAT_VEC3,
                         VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE,
                         VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
-                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3, 0x0),
+                        VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3,
+                        VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
+                        0x0),
                 new DefaultVehiclePropertyHandler(VehiclePropValueUtil.createZonedFloatVectorValue(
                         CUSTOM_PROPERTY_ZONED_FLOAT_VEC3,
                         VehicleZone.VEHICLE_ZONE_ROW_1_LEFT,
@@ -328,7 +333,7 @@
         final int ZONE = VehicleZone.VEHICLE_ZONE_ROW_1_LEFT;
         final int[] VALUES = new int[] {10, 20, 30};
         mVehicleNetwork.startMocking(mVehicleHalMock);
-        mVehicleNetwork.subscribe(PROPERTY, ZONE);
+        mVehicleNetwork.subscribe(PROPERTY, 0, ZONE);
         VehiclePropValue value = VehiclePropValueUtil.createZonedIntVectorValue(
                 PROPERTY, ZONE, VALUES, 0);
         mVehicleNetwork.injectEvent(value);
@@ -366,6 +371,7 @@
 
         @Override
         public void onVehicleNetworkEvents(VehiclePropValues values) {
+            Log.i(TAG, "onVehicleNetworkEvents");
             mValuesReceived = values;
             mEventWait.release();
         }
@@ -501,7 +507,7 @@
 
         @Override
         public synchronized VehiclePropValue onPropertyGet(VehiclePropValue property) {
-            int zone = getZoneOrDefault(property.getZonedValue());
+            int zone = property.getZone();
             VehiclePropValue value = mZoneValueMap.get(zone);
             if (value == null) {
                 Log.w(TAG, "Property not found: " + property.getProp() + ", zone: " + zone);
@@ -511,7 +517,8 @@
 
         @Override
         public void onPropertySubscribe(int property, float sampleRate, int zones) {
-            // TODO Auto-generated method stub
+            Log.i(TAG, "Property subscribed:0x" + Integer.toHexString(property) +
+                    " zones:0x" + Integer.toHexString(zones));
         }
 
         @Override
@@ -520,12 +527,7 @@
         }
 
         private void setValue(VehiclePropValue value) {
-            mZoneValueMap.put(getZoneOrDefault(value.getZonedValue()), VehiclePropValue.newBuilder(value).build());
-        }
-
-        private int getZoneOrDefault(ZonedValue value) {
-            return value != null ? value.getZoneOrWindow() : 0;
-
+            mZoneValueMap.put(value.getZone(), VehiclePropValue.newBuilder(value).build());
         }
     }
 }
diff --git a/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTest.java b/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTest.java
index dc2d472..5febc7e 100644
--- a/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTest.java
+++ b/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTest.java
@@ -118,7 +118,7 @@
                 build();
             mVehicleNetwork.setProperty(value);
             fail();
-        } catch (IllegalArgumentException e) {
+        } catch (SecurityException e) {
             // expected
         }
         VehiclePropConfigs configs = mVehicleNetwork.listProperties();
@@ -154,7 +154,7 @@
         try {
             mVehicleNetwork.subscribe(-1, 0);
             fail();
-        } catch (IllegalArgumentException e) {
+        } catch (SecurityException e) {
             //expected
         }
         VehiclePropConfigs configs = mVehicleNetwork.listProperties();
diff --git a/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTestUtil.java b/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTestUtil.java
index 0542cfb..91c155b 100644
--- a/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTestUtil.java
+++ b/tests/libvehiclenetwork-java-test/src/com/android/car/vehiclenetwork/libtest/VehicleNetworkTestUtil.java
@@ -17,7 +17,6 @@
 
 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
-import com.android.car.vehiclenetwork.VehicleNetworkProto.ZonedValue;
 import com.google.protobuf.ByteString;
 
 public class VehicleNetworkTestUtil {
@@ -38,11 +37,9 @@
                 break;
             case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32:
             case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
-                builder.setZonedValue(ZonedValue.newBuilder().setZoneOrWindow(0).addInt32Values(0).
-                        build());
+                builder.setZone(0).addInt32Values(0);
             case VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT:
-                builder.setZonedValue(ZonedValue.newBuilder().setZoneOrWindow(0).addFloatValues(0f).
-                        build());
+                builder.setZone(0).addFloatValues(0f);
             case VehicleValueType.VEHICLE_VALUE_TYPE_INT64:
                 builder.setInt64Value(0);
                 break;
diff --git a/tests/libvehiclenetwork-java-test/vendor_vns_policy.xml b/tests/libvehiclenetwork-java-test/vendor_vns_policy.xml
new file mode 100644
index 0000000..8d48fdb
--- /dev/null
+++ b/tests/libvehiclenetwork-java-test/vendor_vns_policy.xml
@@ -0,0 +1,34 @@
+<ALLOW>
+  <PROPERTY name="CUSTOM_PROPERTY_INT32" value = "0x70000000">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_ZONED_INT32" value = "0x70000001">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_ZONED_INT32_VEC2" value = "0x70000002">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_ZONED_INT32_VEC3" value = "0x70000003">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_ZONED_FLOAT_VEC2" value = "0x70000004">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_ZONED_FLOAT_VEC3" value = "0x70000005">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_FLOAT_VEC2" value = "0x70000006">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+
+  <PROPERTY name="CUSTOM_PROPERTY_INT32_VEC2" value = "0x70000007">
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
+  </PROPERTY>
+</ALLOW>
+
diff --git a/vehicle_network_service/VehicleHalPropertyUtil.h b/vehicle_network_service/VehicleHalPropertyUtil.h
index da0d476..0a9eb31 100644
--- a/vehicle_network_service/VehicleHalPropertyUtil.h
+++ b/vehicle_network_service/VehicleHalPropertyUtil.h
@@ -26,6 +26,8 @@
 
 #include <utils/String8.h>
 
+#include <IVehicleNetwork.h>
+
 namespace android {
 
 class VechilePropertyUtil {
@@ -33,20 +35,46 @@
     static void dumpProperty(String8& msg, const vehicle_prop_config_t& config) {
         msg.appendFormat("property 0x%x, access:0x%x, change_mode:0x%x, value_type:0x%x",
                 config.prop, config.access, config.change_mode, config.value_type);
-        msg.appendFormat(",permission:0x%x, conflg_flag:0x%x, fsmin:%f, fsmax:%f",
-                config.permission_model, config.config_flags, config.min_sample_rate,
-                config.max_sample_rate);
+        msg.appendFormat(",permission:0x%x, zones:0x%x, conflg_flag:0x%x, fsmin:%f, fsmax:%f",
+                config.permission_model, config.vehicle_zone_flags, config.config_flags,
+                config.min_sample_rate, config.max_sample_rate);
         switch (config.value_type) {
             case VEHICLE_VALUE_TYPE_FLOAT:
             case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
             case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
-            case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
-            case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
-            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
-            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: {
+            case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
                 msg.appendFormat(",v min:%f, v max:%f\n", config.float_min_value,
                         config.float_max_value);
             } break;
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
+            case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
+                if (config.float_min_values == NULL) {
+                    if (config.float_max_values == NULL) {
+                        msg.appendFormat(",v min:%f, v max:%f\n", config.float_min_value,
+                                config.float_max_value);
+                    } else {
+                        msg.appendFormat(", ERROR: float_max_values not NULL while min is NULL");
+
+                    }
+                } else {
+                    if (config.float_max_values == NULL) {
+                        msg.appendFormat(", ERROR: float_min_values not NULL while max is NULL");
+                    } else {
+                        int n = VehicleNetworkUtil::countNumberOfZones(
+                                config.vehicle_zone_flags);
+                        msg.appendFormat(", v min:");
+                        for (int i = 0; i < n; i++) {
+                            msg.appendFormat("%f,", config.float_min_values[i]);
+                        }
+                        msg.appendFormat(", v max:");
+                        for (int i = 0; i < n; i++) {
+                            msg.appendFormat("%f,", config.float_max_values[i]);
+                        }
+                    }
+                }
+            } break;
             case VEHICLE_VALUE_TYPE_INT64: {
                 msg.appendFormat(",v min:%" PRId64 " max:%" PRId64 "\n", config.int64_min_value,
                         config.int64_max_value);
@@ -54,13 +82,39 @@
             case VEHICLE_VALUE_TYPE_INT32:
             case VEHICLE_VALUE_TYPE_INT32_VEC2:
             case VEHICLE_VALUE_TYPE_INT32_VEC3:
-            case VEHICLE_VALUE_TYPE_INT32_VEC4:
-            case VEHICLE_VALUE_TYPE_ZONED_INT32:
-            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
-            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: {
+            case VEHICLE_VALUE_TYPE_INT32_VEC4: {
                 msg.appendFormat(",v min:%d, v max:%d\n", config.int32_min_value,
                         config.int32_max_value);
             } break;
+            case VEHICLE_VALUE_TYPE_ZONED_INT32:
+            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
+            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
+            case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
+                if (config.int32_min_values == NULL) {
+                    if (config.int32_max_values == NULL) {
+                        msg.appendFormat(",v min:%d, v max:%d\n", config.int32_min_value,
+                                config.int32_max_value);
+                    } else {
+                        msg.appendFormat(", ERROR: int32_max_values not NULL while min is NULL");
+
+                    }
+                } else {
+                    if (config.int32_max_values == NULL) {
+                        msg.appendFormat(", ERROR: int32_min_values not NULL while max is NULL");
+                    } else {
+                        int n = VehicleNetworkUtil::countNumberOfZones(
+                                config.vehicle_zone_flags);
+                        msg.appendFormat(", v min:");
+                        for (int i = 0; i < n; i++) {
+                            msg.appendFormat("%d,", config.int32_min_values[i]);
+                        }
+                        msg.appendFormat(", v max:");
+                        for (int i = 0; i < n; i++) {
+                            msg.appendFormat("%d,", config.int32_max_values[i]);
+                        }
+                    }
+                }
+            } break;
             default:
                 msg.appendFormat("\n");
         }
diff --git a/vehicle_network_service/VehicleNetworkService.cpp b/vehicle_network_service/VehicleNetworkService.cpp
index d717e7a..2a6b574 100644
--- a/vehicle_network_service/VehicleNetworkService.cpp
+++ b/vehicle_network_service/VehicleNetworkService.cpp
@@ -517,13 +517,43 @@
         }
         return r;
     }
-    status_t r = mDevice->get(mDevice, data);
+    /*
+     * get call can return NOT_READY error when hal has not fetched all data. In that case,
+     * keep retrying for certain time with some sleep. This will happen only at initial stage.
+     */
+    status_t r = -EAGAIN;
+    int retryCount = 0;
+    while (true) {
+        r = mDevice->get(mDevice, data);
+        if (r == NO_ERROR) {
+            break;
+        }
+        if (r != -EAGAIN) {
+            break;
+        }
+        retryCount++;
+        if (retryCount > MAX_GET_RETRY_FOR_NOT_READY) {
+            ALOGE("Vehicle hal keep retrying not ready after multiple retries");
+            break;
+        }
+        usleep(GET_WAIT_US);
+    }
     if (r != NO_ERROR) {
         ALOGW("getProperty 0x%x failed, HAL returned %d", data->prop, r);
     }
     return r;
 }
 
+void VehicleNetworkService::releaseMemoryFromGet(vehicle_prop_value_t* value) {
+    switch (value->prop) {
+    case VEHICLE_VALUE_TYPE_STRING:
+    case VEHICLE_VALUE_TYPE_BYTES: {
+        Mutex::Autolock autoLock(mLock);
+        mDevice->release_memory_from_get(mDevice, value);
+    } break;
+    }
+}
+
 status_t VehicleNetworkService::setProperty(const vehicle_prop_value_t& data) {
     bool isInternalProperty = false;
     bool inMocking = false;
@@ -774,6 +804,7 @@
 }
 
 status_t VehicleNetworkService::injectEvent(const vehicle_prop_value_t& value) {
+    ALOGI("injectEvent property:0x%x", value.prop);
     return onHalEvent(&value, true);
 }
 
diff --git a/vehicle_network_service/VehicleNetworkService.h b/vehicle_network_service/VehicleNetworkService.h
index 5d6afee..6c2a998 100644
--- a/vehicle_network_service/VehicleNetworkService.h
+++ b/vehicle_network_service/VehicleNetworkService.h
@@ -295,6 +295,7 @@
     virtual sp<VehiclePropertiesHolder> listProperties(int32_t property = 0);
     virtual status_t setProperty(const vehicle_prop_value_t& value);
     virtual status_t getProperty(vehicle_prop_value_t* value);
+    virtual void releaseMemoryFromGet(vehicle_prop_value_t* value);
     virtual status_t subscribe(const sp<IVehicleNetworkListener> &listener, int32_t property,
             float sampleRate, int32_t zones);
     virtual void unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t property);
@@ -334,6 +335,9 @@
     static int eventCallback(const vehicle_prop_value_t *eventData);
     static int errorCallback(int32_t errorCode, int32_t property, int32_t operation);
 private:
+    static const int GET_WAIT_US = 100000;
+    static const int MAX_GET_RETRY_FOR_NOT_READY = 30;
+
     VehiclePropertyAccessControl mVehiclePropertyAccessControl;
     static VehicleNetworkService* sInstance;
     sp<HandlerThread> mHandlerThread;
diff --git a/vns_policy/vns_policy.xml b/vns_policy/vns_policy.xml
index 0fb5be0..5b0a396 100644
--- a/vns_policy/vns_policy.xml
+++ b/vns_policy/vns_policy.xml
@@ -1,6 +1,7 @@
 <ALLOW>
   <PROPERTY name="VEHICLE_PROPERTY_INVALID" value = "0x0">
-    <UID name="AID_SYSTEM" access="r" value="1000"/>
+    <!--  Property 0 write is used to allow hal mocking -->
+    <UID name="AID_SYSTEM" access="rw" value="1000"/>
     <UID name="AID_AUDIOSERVER" access="r" value="1041"/>
   </PROPERTY>