Merge "Add libandroidicu as static lib in the VtsHalAudio"
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index b5de262..393d3ec 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -218,7 +218,7 @@
     const auto& clients =
         mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::EVENTS_FROM_CAR);
 
-    for (auto client : clients) {
+    for (const auto& client : clients) {
         client->getCallback()->onPropertySetError(errorCode, property, areaId);
     }
 }
@@ -312,7 +312,7 @@
 void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
     auto clients =
         mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::EVENTS_FROM_ANDROID);
-    for (auto client : clients) {
+    for (const auto& client : clients) {
         client->getCallback()->onPropertySet(value);
     }
 }
diff --git a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
index ab2013d..23ab6bc 100644
--- a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
@@ -66,7 +66,7 @@
     static std::list<sp<IVehicleCallback>> extractCallbacks(
             const std::list<sp<HalClient>>& clients) {
         std::list<sp<IVehicleCallback>> callbacks;
-        for (auto c : clients) {
+        for (const auto& c : clients) {
             callbacks.push_back(c->getCallback());
         }
         return callbacks;
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
index 477a3cc..e62dc07 100644
--- a/camera/device/3.2/ICameraDeviceSession.hal
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -91,11 +91,11 @@
      * later configureStreams() call by the framework, and all the gralloc
      * buffers for it must be freed after the configureStreams() call returns.
      *
-     * If the stream is new, the maxBuffer field of the stream structure must be
-     * set to 0. The usage must be set to the consumer usage flags. The HAL
-     * device must set these fields in the configureStreams() return values.
-     * These fields are then used by the framework and the platform gralloc
-     * module to allocate the gralloc buffers for each stream.
+     * If the stream is new, the client must set the consumer usage flags in
+     * requestedConfiguration. Upon return, the HAL device must set producerUsage,
+     * maxBuffers, and other fields in the configureStreams() return values. These
+     * fields are then used by the framework and the platform gralloc module to
+     * allocate the gralloc buffers for each stream.
      *
      * Newly allocated buffers may be included in a capture request at any time
      * by the framework. Once a gralloc buffer is returned to the framework
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index dfbb976..297e778 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -262,7 +262,7 @@
             session->getInterface()->interfaceChain([](
                 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                     ALOGV("Session interface chain:");
-                    for (auto iface : interfaceChain) {
+                    for (const auto& iface : interfaceChain) {
                         ALOGV("  %s", iface.c_str());
                     }
                 });
diff --git a/camera/device/3.3/default/CameraDevice.cpp b/camera/device/3.3/default/CameraDevice.cpp
index ce5e1de..b4d279e 100644
--- a/camera/device/3.3/default/CameraDevice.cpp
+++ b/camera/device/3.3/default/CameraDevice.cpp
@@ -49,7 +49,7 @@
         session->getInterface()->interfaceChain([](
             ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                 ALOGV("Session interface chain:");
-                for (auto iface : interfaceChain) {
+                for (const auto& iface : interfaceChain) {
                     ALOGV("  %s", iface.c_str());
                 }
             });
diff --git a/camera/device/3.4/default/CameraDevice.cpp b/camera/device/3.4/default/CameraDevice.cpp
index d73833a..bc443de 100644
--- a/camera/device/3.4/default/CameraDevice.cpp
+++ b/camera/device/3.4/default/CameraDevice.cpp
@@ -49,7 +49,7 @@
         session->getInterface()->interfaceChain([](
             ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                 ALOGV("Session interface chain:");
-                for (auto iface : interfaceChain) {
+                for (const auto& iface : interfaceChain) {
                     ALOGV("  %s", iface.c_str());
                 }
             });
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
index 735cfbc..443549a 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
@@ -1,4 +1,4 @@
-service vendor.cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service
+service vendor.cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service-lazy
     interface android.hardware.cas@1.0::IMediaCasService default
     oneshot
     disabled
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
index 2e6e55d..516acfb 100644
--- a/cas/1.0/default/service.cpp
+++ b/cas/1.0/default/service.cpp
@@ -47,7 +47,7 @@
     android::status_t status;
     if (kLazyService) {
         auto serviceRegistrar = std::make_shared<LazyServiceRegistrar>();
-        status = serviceRegistrar->registerServiceWithCallback(service);
+        status = serviceRegistrar->registerService(service);
     } else {
         status = service->registerAsService();
     }
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index b88d88f..5f56ee9 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -70,7 +70,6 @@
         "compatibility_matrix.current.xml",
     ],
     kernel_configs: [
-        "kernel_config_current_4.4",
         "kernel_config_current_4.9",
         "kernel_config_current_4.14",
         "kernel_config_current_4.19",
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 6858819..0bd297b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -305,6 +305,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
         <version>1.0-2</version>
         <interface>
diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
index 7492152..629477a 100644
--- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
+++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
@@ -83,7 +83,7 @@
     sp<IContexthub> hubApi = ::testing::VtsHalHidlTargetTestBase::getService<IContexthub>();
 
     if (hubApi != nullptr) {
-      for (ContextHub hub : getHubsSync(hubApi)) {
+      for (const ContextHub& hub : getHubsSync(hubApi)) {
         hubIds.push_back(hub.hubId);
       }
     }
@@ -206,7 +206,7 @@
   hidl_vec<ContextHub> hubs = getHubsSync(hubApi);
   ALOGD("System reports %zu hubs", hubs.size());
 
-  for (ContextHub hub : hubs) {
+  for (const ContextHub& hub : hubs) {
     ALOGD("Checking hub ID %" PRIu32, hub.hubId);
 
     EXPECT_FALSE(hub.name.empty());
diff --git a/current.txt b/current.txt
index f0082a3..2e57feb 100644
--- a/current.txt
+++ b/current.txt
@@ -385,6 +385,7 @@
 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
 
 # ABI preserving changes to HALs during Android Q
+f72d23278af99a2f6a9c1d40352b67dbf1f582282f799f88f7235dc7c13892b5 android.hardware.camera.device@3.2::ICameraDeviceSession
 da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
 21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback
 d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index d03b2af..20a2ca4 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -177,7 +177,7 @@
 TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
     const char* kVendorStr = "Vendor module ";
     size_t count = 0;
-    for (auto config : contentConfigurations) {
+    for (const auto& config : contentConfigurations) {
         ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
         ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
                                                  << "has no serverUrl";
@@ -186,7 +186,7 @@
         ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
                                                 << "has no mime type";
         ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
-        for (auto key : config.keys) {
+        for (const auto& key : config.keys) {
             ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
                                               << " has zero length keyId";
             ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
@@ -245,7 +245,7 @@
  */
 TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
+    for (const auto& config : contentConfigurations) {
         EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
     }
 }
@@ -610,7 +610,7 @@
  */
 TEST_P(DrmHalVendorPluginTest, RestoreKeys) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
+    for (const auto& config : contentConfigurations) {
         if (config.policy.allowOffline) {
             auto sessionId = openSession();
             hidl_vec<uint8_t> keySetId =
@@ -645,7 +645,7 @@
  */
 TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
+    for (const auto& config : contentConfigurations) {
         if (config.policy.allowOffline) {
             auto sessionId = openSession();
             hidl_vec<uint8_t> keySetId =
@@ -1022,8 +1022,8 @@
  */
 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
-        for (auto key : config.keys) {
+    for (const auto& config : contentConfigurations) {
+        for (const auto& key : config.keys) {
             if (key.isSecure) {
                 EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
                 break;
@@ -1471,7 +1471,7 @@
  */
 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
+    for (const auto& config : contentConfigurations) {
         auto sessionId = openSession();
         loadKeys(sessionId, config);
         auto keyStatus = queryKeyStatus(sessionId);
@@ -1485,8 +1485,8 @@
  */
 TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
-        for (auto key : config.keys) {
+    for (const auto& config : contentConfigurations) {
+        for (const auto& key : config.keys) {
             const size_t kSegmentSize = 1024;
             vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
             const Pattern noPattern = {0, 0};
@@ -1513,8 +1513,8 @@
  */
 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
-        for (auto key : config.keys) {
+    for (const auto& config : contentConfigurations) {
+        for (const auto& key : config.keys) {
             const size_t kSegmentSize = 1024;
             vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
             const Pattern noPattern = {0, 0};
@@ -1540,8 +1540,8 @@
  */
 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
-        for (auto key : config.keys) {
+    for (const auto& config : contentConfigurations) {
+        for (const auto& key : config.keys) {
             vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
             const Pattern noPattern = {0, 0};
             const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
@@ -1567,8 +1567,8 @@
  */
 TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
     RETURN_IF_SKIPPED;
-    for (auto config : contentConfigurations) {
-        for (auto key : config.keys) {
+    for (const auto& config : contentConfigurations) {
+        for (const auto& key : config.keys) {
             vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
             const Pattern noPattern = {0, 0};
             const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
index 1246616..7dedd7f 100644
--- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -228,13 +228,13 @@
                                       const std::string& componentName, const VT& componentValue) {
      bool validAttribute = false;
      bool validComponent = false;
-     for (DrmMetricGroup::Attribute attribute : metric.attributes) {
+     for (const DrmMetricGroup::Attribute& attribute : metric.attributes) {
          if (attribute.name == attributeName &&
              ValueEquals(attribute.type, attributeValue, attribute)) {
              validAttribute = true;
          }
      }
-     for (DrmMetricGroup::Value value : metric.values) {
+     for (const DrmMetricGroup::Value& value : metric.values) {
          if (value.componentName == componentName &&
              ValueEquals(value.type, componentValue, value)) {
              validComponent = true;
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 2f531b4..6e668af 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -78,9 +78,9 @@
 ComposerClient::ComposerClient(const sp<IComposerClient>& client) : mClient(client) {}
 
 ComposerClient::~ComposerClient() {
-    for (auto it : mDisplayResources) {
+    for (const auto& it : mDisplayResources) {
         Display display = it.first;
-        DisplayResource& resource = it.second;
+        const DisplayResource& resource = it.second;
 
         for (auto layer : resource.layers) {
             EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index d74a07e..405784f 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -2,3 +2,4 @@
     class hal
     user system
     group system
+    capabilities WAKE_ALARM
diff --git a/health/2.0/README.md b/health/2.0/README.md
index 5efc51a..58ea9e3 100644
--- a/health/2.0/README.md
+++ b/health/2.0/README.md
@@ -67,6 +67,7 @@
         class hal
         user system
         group system
+        capabilities WAKE_ALARM
         file /dev/kmsg w
     ```
 
@@ -97,7 +98,7 @@
 1. Storage related APIs:
 
     1. If the device does not implement `IHealth.getDiskStats` and
-        `IHealth.getStorageInfo`, add `libstoragehealthdefault` to `static_libs`.
+        `IHealth.getStorageInfo`, add `libhealthstoragedefault` to `static_libs`.
 
     1. If the device implements one of these two APIs, add and implement the
         following functions in `HealthService.cpp`:
@@ -115,7 +116,7 @@
 
     ```
     # device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
-    /vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0
+    /vendor/bin/hw/android\.hardware\.health@2\.0-service\.<device> u:object_r:hal_health_default_exec:s0
 
     # device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
     # Add device specific permissions to hal_health_default domain, especially
diff --git a/health/2.0/default/healthd_common.cpp b/health/2.0/default/healthd_common.cpp
index 8ff409d..b5fdc8e 100644
--- a/health/2.0/default/healthd_common.cpp
+++ b/health/2.0/default/healthd_common.cpp
@@ -67,8 +67,6 @@
 
 #define POWER_SUPPLY_SUBSYSTEM "power_supply"
 
-// epoll_create() parameter is actually unused
-#define MAX_EPOLL_EVENTS 40
 static int uevent_fd;
 static int wakealarm_fd;
 
@@ -240,9 +238,9 @@
 }
 
 static int healthd_init() {
-    epollfd = epoll_create(MAX_EPOLL_EVENTS);
+    epollfd = epoll_create1(EPOLL_CLOEXEC);
     if (epollfd == -1) {
-        KLOG_ERROR(LOG_TAG, "epoll_create failed; errno=%d\n", errno);
+        KLOG_ERROR(LOG_TAG, "epoll_create1 failed; errno=%d\n", errno);
         return -1;
     }
 
diff --git a/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
index c6a1425..d5e1a29 100644
--- a/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
+++ b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
@@ -1,5 +1,7 @@
 service vendor.health-storage-hal-1-0 /vendor/bin/hw/android.hardware.health.storage@1.0-service
     interface android.hardware.health.storage@1.0::IStorage default
+    oneshot
+    disabled
     class hal
     user system
     group system
diff --git a/health/storage/1.0/default/service.cpp b/health/storage/1.0/default/service.cpp
index a945033..f4296f1 100644
--- a/health/storage/1.0/default/service.cpp
+++ b/health/storage/1.0/default/service.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <hidl/HidlLazyUtils.h>
 #include <hidl/HidlTransportSupport.h>
 #include "Storage.h"
 
@@ -23,6 +24,7 @@
 using android::UNKNOWN_ERROR;
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
+using android::hardware::LazyServiceRegistrar;
 using android::hardware::health::storage::V1_0::IStorage;
 using android::hardware::health::storage::V1_0::implementation::Storage;
 
@@ -30,7 +32,8 @@
     configureRpcThreadpool(1, true);
 
     sp<IStorage> service = new Storage();
-    status_t result = service->registerAsService();
+    LazyServiceRegistrar registrar;
+    status_t result = registrar.registerService(service);
 
     if (result != OK) {
         return result;
diff --git a/keymaster/3.0/vts/functional/keymaster_tags.h b/keymaster/3.0/vts/functional/keymaster_tags.h
index f241ef1..8544bf7 100644
--- a/keymaster/3.0/vts/functional/keymaster_tags.h
+++ b/keymaster/3.0/vts/functional/keymaster_tags.h
@@ -274,7 +274,10 @@
  */
 template <typename ValueT> class NullOr {
     template <typename T> struct reference_initializer {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+#pragma GCC diagnostic pop
     };
     template <typename T> struct pointer_initializer {
         static T init() { return nullptr; }
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 61c444c..97dab68 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -282,7 +282,10 @@
 class NullOr {
     template <typename T>
     struct reference_initializer {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+#pragma GCC diagnostic pop
     };
     template <typename T>
     struct pointer_initializer {
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.cpp b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
index 46bf243..a1c5a1a 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.cpp
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
@@ -1,10 +1,26 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "Callbacks.h"
 #include <android-base/logging.h>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
+namespace V1_2 {
 namespace implementation {
 
 CallbackBase::CallbackBase() : mNotified(false) {}
@@ -88,7 +104,15 @@
 PreparedModelCallback::~PreparedModelCallback() {}
 
 Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus,
-                                           const sp<IPreparedModel>& preparedModel) {
+                                           const sp<V1_0::IPreparedModel>& preparedModel) {
+    mErrorStatus = errorStatus;
+    mPreparedModel = preparedModel;
+    CallbackBase::notify();
+    return Void();
+}
+
+Return<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus,
+                                               const sp<V1_2::IPreparedModel>& preparedModel) {
     mErrorStatus = errorStatus;
     mPreparedModel = preparedModel;
     CallbackBase::notify();
@@ -100,7 +124,7 @@
     return mErrorStatus;
 }
 
-sp<IPreparedModel> PreparedModelCallback::getPreparedModel() {
+sp<V1_0::IPreparedModel> PreparedModelCallback::getPreparedModel() {
     wait();
     return mPreparedModel;
 }
@@ -115,13 +139,19 @@
     return Void();
 }
 
+Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus) {
+    mErrorStatus = errorStatus;
+    CallbackBase::notify();
+    return Void();
+}
+
 ErrorStatus ExecutionCallback::getStatus() {
     wait();
     return mErrorStatus;
 }
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_2
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h
index 570a4fb..e89980d 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.h
@@ -1,22 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
 #define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
 
 #include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
 #include <chrono>
 #include <condition_variable>
 #include <functional>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
 #include <mutex>
 #include <thread>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
+namespace V1_2 {
 namespace implementation {
 
+using V1_0::ErrorStatus;
+
 /**
  * The CallbackBase class is used internally by the NeuralNetworks runtime to
  * synchronize between different threads. An asynchronous task is launched
@@ -156,11 +176,11 @@
  * asynchronously with respect to the runtime. If a calling thread calls wait*
  * or get* on a PreparedModelCallback object and the corresponding asynchronous
  * task has not finished preparing the model, the calling thread will block
- * until the asynchronous task has called notify. For more information on the
- * synchronization behavior, refer to the CallbackBase class.
+ * until the asynchronous task has either called notify or notify_1_2. For more
+ * information on the synchronization behavior, refer to the CallbackBase class.
  *
  * This class inherits the basic blocking and signaling calls from
- * CallbackBase, and implements the HIDL notify call from
+ * CallbackBase, and implements the HIDL notify and notify_1_2 calls from
  * IPreparedModelCallback. This callback object is passed as an argument to
  * IDevice::prepareModel.
  */
@@ -170,15 +190,15 @@
     ~PreparedModelCallback() override;
 
     /**
-     * IPreparedModelCallback::notify marks the callback object with the return
-     * status of the asynchronous model preparation along with the prepared
-     * model, and calls CallbackBase::notify, enabling all prior and future
-     * wait* calls on the PreparedModelCallback object to proceed. For more
-     * information on the synchronization behavior, refer to the CallbackBase
-     * class.
+     * IPreparedModelCallback::notify and IPreparedModelCallback::notify_1_2
+     * mark the callback object with the return status of the asynchronous
+     * model preparation along with the prepared model, and call
+     * CallbackBase::notify, enabling all prior and future wait* calls on the
+     * PreparedModelCallback object to proceed. For more information on the
+     * synchronization behavior, refer to the CallbackBase class.
      *
-     * IPreparedModelCallback::notify must be called exactly once on a given
-     * PreparedModelCallback object.
+     * Either IPreparedModelCallback::notify or IPreparedModelCallback::notify_1_2
+     * must be called exactly once on a given PreparedModelCallback object.
      *
      * @param status Error status returned from asynchronously preparing the
      *               model; will be:
@@ -189,7 +209,9 @@
      * @param preparedModel Returned model that has been prepared for execution,
      *                      nullptr if the model was unable to be prepared.
      */
-    Return<void> notify(ErrorStatus status, const sp<IPreparedModel>& preparedModel) override;
+    Return<void> notify(ErrorStatus status, const sp<V1_0::IPreparedModel>& preparedModel) override;
+    Return<void> notify_1_2(ErrorStatus status,
+                            const sp<V1_2::IPreparedModel>& preparedModel) override;
 
     /**
      * Retrieves the error status returned from the asynchronous task launched
@@ -217,11 +239,11 @@
      *                       execution, nullptr if the model was unable to be
      *                       prepared.
      */
-    sp<IPreparedModel> getPreparedModel();
+    sp<V1_0::IPreparedModel> getPreparedModel();
 
- private:
+   private:
     ErrorStatus        mErrorStatus;
-    sp<IPreparedModel> mPreparedModel;
+    sp<V1_0::IPreparedModel> mPreparedModel;
 };
 
 /**
@@ -229,12 +251,12 @@
  * execution from a task executing asynchronously with respect to the runtime.
  * If a calling thread calls wait* or get* on a PreparedModelCallback object and
  * the corresponding asynchronous task has not finished the execution, the
- * calling thread will block until the asynchronous task has called notify. For
- * more information on the synchronization behavior, refer to the CallbackBase
- * class.
+ * calling thread will block until the asynchronous task has either called notify
+ * or notify_1_2. For more information on the synchronization behavior, refer to
+ * the CallbackBase class.
  *
  * This class inherits the basic blocking and signaling calls from
- * CallbackBase, and implements the HIDL notify call from
+ * CallbackBase, and implements the HIDL notify and notify_1_2 calls from
  * IExecutionCallback. This callback object is passed as an argument to
  * IPreparedModel::execute.
  */
@@ -244,14 +266,14 @@
     ~ExecutionCallback() override;
 
     /**
-     * IExecutionCallback::notify marks the callback object with the return
-     * status of the asynchronous execution that held this callback and enables
-     * all prior and future wait* calls on the ExecutionCallback object to
-     * proceed. For more information on the synchronization behavior, refer to
-     * the CallbackBase class.
+     * IExecutionCallback::notify and IExecutionCallback::notify_1_2 mark the
+     * callback object with the return status of the asynchronous execution that
+     * held this callback and enable all prior and future wait* calls on the
+     * ExecutionCallback object to proceed. For more information on the
+     * synchronization behavior, refer to the CallbackBase class.
      *
-     * IExecutionCallback::notify must be called exactly once on a given
-     * ExecutionCallback object.
+     * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must
+     * be called exactly once on a given ExecutionCallback object.
      *
      * @param status Error status returned from asynchronously preparing the
      *               model; will be:
@@ -263,6 +285,7 @@
      *               - INVALID_ARGUMENT if the input request is invalid
      */
     Return<void> notify(ErrorStatus status) override;
+    Return<void> notify_1_2(ErrorStatus status) override;
 
     /**
      * Retrieves the error status returned from the asynchronous task launched
@@ -299,7 +322,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_2
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index d2703cb..7c5b0bc 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -24,6 +24,11 @@
 #include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
@@ -34,8 +39,8 @@
 namespace neuralnetworks {
 
 namespace generated_tests {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::test_helper::bool8;
 using ::test_helper::compare;
 using ::test_helper::expectMultinomialDistributionWithinTolerance;
@@ -73,10 +78,32 @@
 
 // Top level driver for models and examples generated by test_generator.py
 // Test driver for those generated from ml/nn/runtime/test/spec
-void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>& preparedModel,
+                                                const Request& request,
+                                                sp<ExecutionCallback>& callback) {
+    return preparedModel->execute(request, callback);
+}
+static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+                                                const Request& request,
+                                                sp<ExecutionCallback>& callback) {
+    return preparedModel->execute_1_2(request, callback);
+}
+static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>&, const Request&) {
+    ADD_FAILURE() << "asking for synchronous execution at V1_0";
+    return ErrorStatus::GENERAL_FAILURE;
+}
+static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
+                                                const Request& request) {
+    return preparedModel->executeSynchronously(request);
+}
+enum class Synchronously { NO, YES };
+const float kDefaultAtol = 1e-5f;
+const float kDefaultRtol = 1e-5f;
+template <typename T_IPreparedModel>
+void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
                            const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model = false, float fpAtol = 1e-5f,
-                           float fpRtol = 1e-5f) {
+                           bool hasRelaxedFloat32Model = false, float fpAtol = kDefaultAtol,
+                           float fpRtol = kDefaultRtol, Synchronously sync = Synchronously::NO) {
     const uint32_t INPUT = 0;
     const uint32_t OUTPUT = 1;
 
@@ -169,18 +196,31 @@
         inputMemory->commit();
         outputMemory->commit();
 
-        // launch execution
-        sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-        ASSERT_NE(nullptr, executionCallback.get());
-        Return<ErrorStatus> executionLaunchStatus = preparedModel->execute(
-            {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, executionCallback);
-        ASSERT_TRUE(executionLaunchStatus.isOk());
-        EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+        if (sync == Synchronously::NO) {
+            SCOPED_TRACE("asynchronous");
 
-        // retrieve execution status
-        executionCallback->wait();
-        ErrorStatus executionReturnStatus = executionCallback->getStatus();
-        EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
+            // launch execution
+            sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+            ASSERT_NE(nullptr, executionCallback.get());
+            Return<ErrorStatus> executionLaunchStatus = ExecutePreparedModel(
+                preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools},
+                executionCallback);
+            ASSERT_TRUE(executionLaunchStatus.isOk());
+            EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+            // retrieve execution status
+            executionCallback->wait();
+            ErrorStatus executionReturnStatus = executionCallback->getStatus();
+            EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
+        } else {
+            SCOPED_TRACE("synchronous");
+
+            // execute
+            Return<ErrorStatus> executionStatus = ExecutePreparedModel(
+                preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
+            ASSERT_TRUE(executionStatus.isOk());
+            EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionStatus));
+        }
 
         // validate results
         outputMemory->read();
@@ -198,6 +238,23 @@
         }
     }
 }
+template <typename T_IPreparedModel>
+void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExample>& examples,
+                           bool hasRelaxedFloat32Model, Synchronously sync) {
+    EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
+                          kDefaultRtol, sync);
+}
+
+static void getPreparedModel(sp<PreparedModelCallback> callback,
+                             sp<V1_0::IPreparedModel>* preparedModel) {
+    *preparedModel = callback->getPreparedModel();
+}
+static void getPreparedModel(sp<PreparedModelCallback> callback,
+                             sp<V1_2::IPreparedModel>* preparedModel) {
+    sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
+    *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
+}
 
 void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
              std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
@@ -224,7 +281,8 @@
     // retrieve prepared model
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    sp<V1_0::IPreparedModel> preparedModel;
+    getPreparedModel(preparedModelCallback, &preparedModel);
 
     // early termination if vendor service cannot fully prepare model
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
@@ -270,7 +328,8 @@
     // retrieve prepared model
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    sp<V1_0::IPreparedModel> preparedModel;
+    getPreparedModel(preparedModelCallback, &preparedModel);
 
     // early termination if vendor service cannot fully prepare model
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
@@ -316,7 +375,8 @@
     // retrieve prepared model
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    sp<V1_2::IPreparedModel> preparedModel;
+    getPreparedModel(preparedModelCallback, &preparedModel);
 
     // early termination if vendor service cannot fully prepare model
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
@@ -332,7 +392,9 @@
     ASSERT_NE(nullptr, preparedModel.get());
 
     EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16);
+                          model.relaxComputationFloat32toFloat16, Synchronously::NO);
+    EvaluatePreparedModel(preparedModel, is_ignored, examples,
+                          model.relaxComputationFloat32toFloat16, Synchronously::YES);
 }
 
 }  // namespace generated_tests
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index 26b4d8b..55e5861 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -40,8 +40,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index b813c39..5d24fb5 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -27,8 +27,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index 1d3dee3..72a5007 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -33,8 +33,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::hidl::memory::V1_0::IMemory;
 using test_helper::for_all;
 using test_helper::MixedTyped;
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
index 290a9d3..d98ea04 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
@@ -40,8 +40,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
index a36b24c..1df3218 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
@@ -40,8 +40,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index d6c6533..b35a901 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -33,8 +33,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index e7d96c7..5225bf7 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -33,8 +33,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::hidl::memory::V1_0::IMemory;
 using test_helper::for_all;
 using test_helper::MixedTyped;
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index a64268f..970e8b5 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -36,6 +36,7 @@
 
 using V1_0::DeviceStatus;
 using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
 using V1_0::Operand;
 using V1_0::OperandType;
 using V1_0::Request;
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index e155bbd..528a2c7 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -9,6 +9,9 @@
     srcs: [
         "types.hal",
         "IDevice.hal",
+        "IExecutionCallback.hal",
+        "IPreparedModel.hal",
+        "IPreparedModelCallback.hal",
     ],
     interfaces: [
         "android.hardware.neuralnetworks@1.0",
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index aff4cf3..6a77961 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -17,9 +17,9 @@
 package android.hardware.neuralnetworks@1.2;
 
 import @1.0::ErrorStatus;
-import @1.0::IPreparedModelCallback;
 import @1.1::ExecutionPreference;
 import @1.1::IDevice;
+import IPreparedModelCallback;
 
 /**
  * This interface represents a device driver.
diff --git a/neuralnetworks/1.2/IExecutionCallback.hal b/neuralnetworks/1.2/IExecutionCallback.hal
new file mode 100644
index 0000000..667e0d6
--- /dev/null
+++ b/neuralnetworks/1.2/IExecutionCallback.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.2;
+
+import @1.0::ErrorStatus;
+import @1.0::IExecutionCallback;
+
+/**
+ * IExecutionCallback must be used to return the error status result from an
+ * execution asynchronously launched from IPreparedModel::execute.
+ */
+interface IExecutionCallback extends @1.0::IExecutionCallback {
+
+    /**
+     * Either notify_1_2 or notify must be invoked immediately after the asynchronous
+     * task has finished performing the execution. Either notify_1_2 or notify must be
+     * provided with the ErrorStatus from the execution. If the asynchronous task is
+     * not launched, either notify_1_2 or notify must be invoked with the appropriate
+     * error.
+     *
+     * @param status Error status returned from launching the asynchronous task
+     *               (if the launch fails) or from the asynchronous task itself
+     *               (if the launch succeeds). Must be:
+     *               - NONE if the asynchronous execution was successful
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                 unspecified error
+     *               - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                 not large enough to store the resultant values
+     *               - INVALID_ARGUMENT if one of the input arguments to
+     *                 prepareModel is invalid
+     */
+    oneway notify_1_2(ErrorStatus status);
+};
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
new file mode 100644
index 0000000..4e91c67
--- /dev/null
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.2;
+
+import @1.0::ErrorStatus;
+import @1.0::IPreparedModel;
+import @1.0::Request;
+import IExecutionCallback;
+
+/**
+ * IPreparedModel describes a model that has been prepared for execution and
+ * is used to launch executions.
+ */
+interface IPreparedModel extends @1.0::IPreparedModel {
+    /**
+     * Launches an asynchronous execution on a prepared model.
+     *
+     * The execution is performed asynchronously with respect to the caller.
+     * execute_1_2 must verify the inputs to the function are correct. If there is
+     * an error, execute_1_2 must immediately invoke the callback with the
+     * appropriate ErrorStatus value, then return with the same ErrorStatus. If
+     * the inputs to the function are valid and there is no error, execute_1_2 must
+     * launch an asynchronous task to perform the execution in the background,
+     * and immediately return with ErrorStatus::NONE. If the asynchronous task
+     * fails to launch, execute_1_2 must immediately invoke the callback with
+     * ErrorStatus::GENERAL_FAILURE, then return with
+     * ErrorStatus::GENERAL_FAILURE.
+     *
+     * When the asynchronous task has finished its execution, it must
+     * immediately invoke the callback object provided as an input to the
+     * execute_1_2 function. This callback must be provided with the ErrorStatus of
+     * the execution.
+     *
+     * If the prepared model was prepared from a model wherein all
+     * tensor operands have fully specified dimensions, and the inputs
+     * to the function are valid, then the execution should launch
+     * and complete successfully (ErrorStatus::NONE). There must be
+     * no failure unless the device itself is in a bad state.
+     *
+     * Any number of calls to the execute, execute_1_2, and executeSynchronously
+     * functions, in any combination, may be made concurrently, even on the same
+     * IPreparedModel object.
+     *
+     * @param request The input and output information on which the prepared
+     *                model is to be executed.
+     * @param callback A callback object used to return the error status of
+     *                 the execution. The callback object's notify function must
+     *                 be called exactly once, even if the execution was
+     *                 unsuccessful.
+     * @return status Error status of the call, must be:
+     *                - NONE if task is successfully launched
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                  not large enough to store the resultant values
+     *                - INVALID_ARGUMENT if one of the input arguments is
+     *                  invalid
+     */
+    execute_1_2(Request request, IExecutionCallback callback)
+        generates (ErrorStatus status);
+
+    /**
+     * Performs a synchronous execution on a prepared model.
+     *
+     * The execution is performed synchronously with respect to the caller.
+     * executeSynchronously must verify the inputs to the function are
+     * correct. If there is an error, executeSynchronously must immediately
+     * return with the appropriate ErrorStatus value. If the inputs to the
+     * function are valid and there is no error, executeSynchronously must
+     * perform the execution, and must not return until the execution is
+     * complete.
+     *
+     * If the prepared model was prepared from a model wherein all tensor
+     * operands have fully specified dimensions, and the inputs to the function
+     * are valid, then the execution should complete successfully
+     * (ErrorStatus::NONE). There must be no failure unless the device itself is
+     * in a bad state.
+     *
+     * Any number of calls to the execute, execute_1_2, and executeSynchronously
+     * functions, in any combination, may be made concurrently, even on the same
+     * IPreparedModel object.
+     *
+     * @param request The input and output information on which the prepared
+     *                model is to be executed.
+     * @return status Error status of the execution, must be:
+     *                - NONE if execution is performed successfully
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
+     *                  not large enough to store the resultant values
+     *                - INVALID_ARGUMENT if one of the input arguments is
+     *                  invalid
+     */
+    executeSynchronously(Request request)
+        generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.2/IPreparedModelCallback.hal b/neuralnetworks/1.2/IPreparedModelCallback.hal
new file mode 100644
index 0000000..d3830c6
--- /dev/null
+++ b/neuralnetworks/1.2/IPreparedModelCallback.hal
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.2;
+
+import @1.0::ErrorStatus;
+import @1.0::IPreparedModelCallback;
+import IPreparedModel;
+
+/**
+ * IPreparedModelCallback must be used to return a prepared model produced by an
+ * asynchronous task launched from IDevice::prepareModel.
+ */
+interface IPreparedModelCallback extends @1.0::IPreparedModelCallback {
+
+    /**
+     * Either notify_1_2 or notify must be invoked immediately after the asynchronous
+     * task holding this callback has finished preparing the model. If the model was
+     * successfully prepared, either notify_1_2 or notify must be invoked with
+     * ErrorStatus::NONE and the prepared model. If the model was not able to be
+     * successfully prepared, either notify_1_2 or notify must be invoked with the
+     * appropriate ErrorStatus and nullptr as the IPreparedModel. If the asynchronous
+     * task holding this callback fails to launch or if the model provided to
+     * IDevice::prepareModel is invalid, either notify_1_2 or notify must be invoked
+     * with the appropriate error as well as nullptr for the IPreparedModel.
+     *
+     * @param status Error status returned from the asynchronous model
+     *               preparation task; must be:
+     *               - NONE if the asynchronous task successfully prepared the
+     *                 model
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                 unspecified error
+     *               - INVALID_ARGUMENT if one of the input arguments to
+     *                 prepareModel is invalid
+     * @param preparedModel A model that has been asynchronously prepared for
+     *                      execution. If the model was unable to be prepared
+     *                      due to an error, nullptr must be passed in place of
+     *                      the IPreparedModel object.
+     */
+    oneway notify_1_2(ErrorStatus status, IPreparedModel preparedModel);
+};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index a1a1bad..7824d23 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -40,7 +40,7 @@
      * scale is a 32 bit floating point with value greater then zero.
      */
     TENSOR_QUANT16_SYMM = 7,
-    /** A tensor of 16 bit floating point values. */
+    /** A tensor of IEEE 754 16 bit floating point values. */
     TENSOR_FLOAT16 = 8,
     /**
      * A tensor of 8 bit boolean values.
@@ -49,16 +49,22 @@
      * represents false; any other value represents true.
      */
     TENSOR_BOOL8 = 9,
+    /** An IEEE 754 16 bit floating point scalar value. */
+    FLOAT16 = 10,
+    /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF
+     * OperandTypeRange::OPERAND_FUNDAMENTAL_MAX.
+     */
+    /* ADDING A NEW OEM TYPE REQUIRES UPDATING THE VALUE OF
+     * OperandTypeRange::OPERAND_OEM_MAX.
+     */
 };
 
 /**
- * The range of values in the OperandType enum.
- *
- * THE MAX VALUES MUST BE UPDATED WHEN ADDING NEW TYPES to the OperandType enum.
+ * The range of operand values in the OperandType enum.
  */
 enum OperandTypeRange : uint32_t {
     OPERAND_FUNDAMENTAL_MIN = 0,
-    OPERAND_FUNDAMENTAL_MAX = 9,
+    OPERAND_FUNDAMENTAL_MAX = 10,
     OPERAND_OEM_MIN     = 10000,
     OPERAND_OEM_MAX     = 10001,
 };
@@ -105,7 +111,7 @@
     QUANTIZE = 70,
     QUANTIZED_16BIT_LSTM = 71,
     RANDOM_MULTINOMIAL = 72,
-    REDUCE = 73,
+    REDUCE_PROD = 73,
     ROI_ALIGN = 74,
     RSQRT = 75,
     SELECT = 76,
@@ -122,16 +128,27 @@
     ROTATED_BBOX_TRANSFORM = 87,
     ABS = 88,
     ROI_POOLING = 89,
+    EQUAL = 90,
+    NOT_EQUAL = 91,
+    REDUCE_SUM = 92,
+    REDUCE_MAX = 93,
+    REDUCE_MIN = 94,
+    REDUCE_ANY = 95,
+    REDUCE_ALL = 96,
+    /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
+     * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX.
+     */
+    /* ADDING A NEW OEM OPERATION REQUIRES UPDATING THE VALUE OF
+     * OperationTypeRange::OPERATION_OEM_MAX.
+     */
 };
 
 /**
  * The range of values in the OperationType enum.
- *
- * THE MAX VALUES MUST BE UPDATED WHEN ADDING NEW TYPES to the OperationType enum.
  */
 enum OperationTypeRange : uint32_t {
     OPERATION_FUNDAMENTAL_MIN = 0,
-    OPERATION_FUNDAMENTAL_MAX = 87,
+    OPERATION_FUNDAMENTAL_MAX = 96,
     OPERATION_OEM_MIN = 10000,
     OPERATION_OEM_MAX = 10000,
 };
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
index 79d5a60..9bff09c 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
@@ -40,8 +40,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
index 42e22b0..56a61d4 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
@@ -40,8 +40,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
index aab5cb6..1c781ec 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
@@ -40,8 +40,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index c4f1b5e..8f6d54f 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -25,15 +25,14 @@
 namespace neuralnetworks {
 namespace V1_2 {
 
-using V1_0::IPreparedModel;
 using V1_0::OperandLifeTime;
 using V1_1::ExecutionPreference;
 
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
@@ -62,7 +61,7 @@
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    sp<IPreparedModel> preparedModel = getPreparedModel_1_2(preparedModelCallback);
     ASSERT_EQ(nullptr, preparedModel.get());
 }
 
@@ -152,6 +151,7 @@
 
 static uint32_t getInvalidRank(OperandType type) {
     switch (type) {
+        case OperandType::FLOAT16:
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
@@ -183,6 +183,7 @@
 
 static float getInvalidScale(OperandType type) {
     switch (type) {
+        case OperandType::FLOAT16:
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
@@ -215,6 +216,7 @@
 
 static std::vector<int32_t> getInvalidZeroPoints(OperandType type) {
     switch (type) {
+        case OperandType::FLOAT16:
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
@@ -258,6 +260,7 @@
     Operand newOperand = *operand;
     newOperand.type = type;
     switch (type) {
+        case OperandType::FLOAT16:
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
@@ -301,8 +304,9 @@
     for (const Operation& operation : model.operations) {
         // Skip mutateOperationOperandTypeTest for the following operations.
         // - LSH_PROJECTION's second argument is allowed to have any type.
-        // - ARGMIN and ARGMAX's first argument can be any of TENSOR_(FLOAT32|INT32|QUANT8_ASYMM).
-        // - CAST's argument can be any of TENSOR_(FLOAT32|INT32|QUANT8_ASYMM).
+        // - ARGMIN and ARGMAX's first argument can be any of
+        // TENSOR_(FLOAT16|FLOAT32|INT32|QUANT8_ASYMM).
+        // - CAST's argument can be any of TENSOR_(FLOAT16|FLOAT32|INT32|QUANT8_ASYMM).
         switch (operation.type) {
             case OperationType::LSH_PROJECTION: {
                 if (operand == operation.inputs[1]) {
@@ -312,8 +316,8 @@
             case OperationType::CAST:
             case OperationType::ARGMAX:
             case OperationType::ARGMIN: {
-                if (type == OperandType::TENSOR_FLOAT32 || type == OperandType::TENSOR_INT32 ||
-                    type == OperandType::TENSOR_QUANT8_ASYMM) {
+                if (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32 ||
+                    type == OperandType::TENSOR_INT32 || type == OperandType::TENSOR_QUANT8_ASYMM) {
                     return true;
                 }
             } break;
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index b663535..d80fbcf 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -33,8 +33,8 @@
 namespace vts {
 namespace functional {
 
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using ::android::hidl::memory::V1_0::IMemory;
 using test_helper::for_all;
 using test_helper::MixedTyped;
@@ -68,7 +68,7 @@
     // retrieve prepared model
     preparedModelCallback->wait();
     ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    *preparedModel = preparedModelCallback->getPreparedModel();
+    *preparedModel = getPreparedModel_1_2(preparedModelCallback);
 
     // The getSupportedOperations_1_2 call returns a list of operations that are
     // guaranteed not to fail if prepareModel_1_2 is called, and
@@ -97,17 +97,29 @@
 static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
                      Request request, const std::function<void(Request*)>& mutation) {
     mutation(&request);
-    SCOPED_TRACE(message + " [execute]");
 
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+    {
+        SCOPED_TRACE(message + " [execute_1_2]");
 
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+        sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+        ASSERT_NE(nullptr, executionCallback.get());
+        Return<ErrorStatus> executeLaunchStatus =
+            preparedModel->execute_1_2(request, executionCallback);
+        ASSERT_TRUE(executeLaunchStatus.isOk());
+        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+        executionCallback->wait();
+        ErrorStatus executionReturnStatus = executionCallback->getStatus();
+        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+    }
+
+    {
+        SCOPED_TRACE(message + " [executeSynchronously]");
+
+        Return<ErrorStatus> executeStatus = preparedModel->executeSynchronously(request);
+        ASSERT_TRUE(executeStatus.isOk());
+        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeStatus));
+    }
 }
 
 // Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
index 90a910c..4eced82 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
@@ -58,6 +58,12 @@
     ::testing::VtsHalHidlTargetTestBase::TearDown();
 }
 
+sp<IPreparedModel> getPreparedModel_1_2(
+    const sp<V1_2::implementation::PreparedModelCallback>& callback) {
+    sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
+    return V1_2::IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
+}
+
 }  // namespace functional
 }  // namespace vts
 
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index a87d788..dedab8d 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -17,6 +17,8 @@
 #ifndef VTS_HAL_NEURALNETWORKS_V1_2_H
 #define VTS_HAL_NEURALNETWORKS_V1_2_H
 
+#include "Callbacks.h"
+
 #include <android/hardware/neuralnetworks/1.0/types.h>
 #include <android/hardware/neuralnetworks/1.1/types.h>
 #include <android/hardware/neuralnetworks/1.2/IDevice.h>
@@ -77,6 +79,10 @@
 // Tag for the generated tests
 class GeneratedTest : public NeuralnetworksHidlTest {};
 
+// Utility function to get PreparedModel from callback and downcast to V1_2.
+sp<IPreparedModel> getPreparedModel_1_2(
+    const sp<V1_2::implementation::PreparedModelCallback>& callback);
+
 }  // namespace functional
 }  // namespace vts
 
diff --git a/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
new file mode 100644
index 0000000..c338e02
--- /dev/null
+++ b/nfc/1.2/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.nfc@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "INfc.hal",
+    ],
+    interfaces: [
+        "android.hardware.nfc@1.0",
+        "android.hardware.nfc@1.1",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "NfcConfig",
+    ],
+    gen_java: true,
+}
+
diff --git a/nfc/1.2/INfc.hal b/nfc/1.2/INfc.hal
new file mode 100644
index 0000000..4788fd7
--- /dev/null
+++ b/nfc/1.2/INfc.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.nfc@1.2;
+
+import @1.1::INfc;
+import @1.2::NfcConfig;
+
+interface INfc extends @1.1::INfc {
+    /**
+     * Fetches vendor specific configurations.
+     * @return config indicates support for certain features and
+     *     populates the vendor specific configs
+     */
+    getConfig_1_2() generates (NfcConfig config);
+};
diff --git a/nfc/1.2/types.hal b/nfc/1.2/types.hal
new file mode 100644
index 0000000..d6db9a8
--- /dev/null
+++ b/nfc/1.2/types.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.nfc@1.2;
+
+import @1.1::NfcConfig;
+
+struct NfcConfig {
+    @1.1::NfcConfig v1_1;
+
+    /*
+     * NFCEE ID for offhost UICC & eSE secure element.
+     * 0x00 if there aren't any. Refer NCI specification
+     */
+    vec<uint8_t> offHostRouteUicc;
+    vec<uint8_t> offHostRouteEse;
+
+    /** Default IsoDep route. 0x00 if there aren't any. Refer NCI spec */
+    uint8_t defaultIsoDepRoute;
+};
diff --git a/nfc/1.2/vts/functional/Android.bp b/nfc/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..13b254c
--- /dev/null
+++ b/nfc/1.2/vts/functional/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalNfcV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalNfcV1_2TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.nfc@1.0",
+        "android.hardware.nfc@1.1",
+        "android.hardware.nfc@1.2",
+    ],
+}
diff --git a/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
new file mode 100644
index 0000000..ee4a887
--- /dev/null
+++ b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "nfc_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/nfc/1.1/INfcClientCallback.h>
+#include <android/hardware/nfc/1.2/INfc.h>
+#include <android/hardware/nfc/1.2/types.h>
+#include <hardware/nfc.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::nfc::V1_0::NfcData;
+using ::android::hardware::nfc::V1_0::NfcStatus;
+using ::android::hardware::nfc::V1_1::INfcClientCallback;
+using ::android::hardware::nfc::V1_1::NfcEvent;
+using ::android::hardware::nfc::V1_2::INfc;
+using ::android::hardware::nfc::V1_2::NfcConfig;
+
+// Range of valid off host route ids
+constexpr unsigned int MIN_OFFHOST_ROUTE_ID = 0x80;
+constexpr unsigned int MAX_OFFHOST_ROUTE_ID = 0xFE;
+
+constexpr char kCallbackNameSendEvent[] = "sendEvent";
+constexpr char kCallbackNameSendData[] = "sendData";
+
+class NfcClientCallbackArgs {
+   public:
+    NfcEvent last_event_;
+    NfcStatus last_status_;
+    NfcData last_data_;
+};
+
+/* Callback class for data & Event. */
+class NfcClientCallback : public ::testing::VtsHalHidlTargetCallbackBase<NfcClientCallbackArgs>,
+                          public INfcClientCallback {
+   public:
+    virtual ~NfcClientCallback() = default;
+
+    /* sendEvent callback function - Records the Event & Status
+     * and notifies the TEST
+     **/
+    Return<void> sendEvent_1_1(NfcEvent event, NfcStatus event_status) override {
+        NfcClientCallbackArgs args;
+        args.last_event_ = event;
+        args.last_status_ = event_status;
+        NotifyFromCallback(kCallbackNameSendEvent, args);
+        return Void();
+    };
+
+    /** NFC 1.1 HAL shouldn't send 1.0 callbacks */
+    Return<void> sendEvent(__attribute__((unused))::android::hardware::nfc::V1_0::NfcEvent event,
+                           __attribute__((unused)) NfcStatus event_status) override {
+        return Void();
+    }
+
+    /* sendData callback function. Records the data and notifies the TEST*/
+    Return<void> sendData(const NfcData& data) override {
+        NfcClientCallbackArgs args;
+        args.last_data_ = data;
+        NotifyFromCallback(kCallbackNameSendData, args);
+        return Void();
+    };
+};
+
+// Test environment for Nfc HIDL HAL.
+class NfcHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static NfcHidlEnvironment* Instance() {
+        static NfcHidlEnvironment* instance = new NfcHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<INfc>(); }
+
+   private:
+    NfcHidlEnvironment() {}
+};
+
+// The main test class for NFC HIDL HAL.
+class NfcHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        nfc_ = ::testing::VtsHalHidlTargetTestBase::getService<INfc>();
+        ASSERT_NE(nfc_, nullptr);
+
+        nfc_cb_ = new NfcClientCallback();
+        ASSERT_NE(nfc_cb_, nullptr);
+
+        EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+        // Wait for OPEN_CPLT event
+        auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+        /*
+         * Close the hal and then re-open to make sure we are in a predictable
+         * state for all the tests.
+         */
+        EXPECT_EQ(NfcStatus::OK, nfc_->close());
+        // Wait for CLOSE_CPLT event
+        res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+        EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+        // Wait for OPEN_CPLT event
+        res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+    }
+
+    virtual void TearDown() override {
+        EXPECT_EQ(NfcStatus::OK, nfc_->close());
+        // Wait for CLOSE_CPLT event
+        auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+    }
+
+    sp<INfc> nfc_;
+    sp<NfcClientCallback> nfc_cb_;
+};
+
+/*
+ * getConfig:
+ * Calls getConfig()
+ * checks if fields in NfcConfig are populated correctly
+ */
+TEST_F(NfcHidlTest, GetExtendedConfig) {
+    nfc_->getConfig_1_2([](NfcConfig config) {
+        for (uint8_t uicc : config.offHostRouteUicc) {
+            EXPECT_GE(uicc, MIN_OFFHOST_ROUTE_ID);
+            EXPECT_LE(uicc, MAX_OFFHOST_ROUTE_ID);
+        }
+        for (uint8_t ese : config.offHostRouteEse) {
+            EXPECT_GE(ese, MIN_OFFHOST_ROUTE_ID);
+            EXPECT_LE(ese, MAX_OFFHOST_ROUTE_ID);
+        }
+        if (config.defaultIsoDepRoute != 0) {
+            EXPECT_GE(config.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
+            EXPECT_LE(config.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
+        }
+    });
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NfcHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NfcHidlEnvironment::Instance()->init(&argc, argv);
+
+    std::system("svc nfc disable"); /* Turn off NFC */
+    sleep(5);
+
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+
+    std::system("svc nfc enable"); /* Turn on NFC */
+    sleep(5);
+
+    return status;
+}
diff --git a/power/stats/1.0/Android.bp b/power/stats/1.0/Android.bp
new file mode 100644
index 0000000..9a956e4
--- /dev/null
+++ b/power/stats/1.0/Android.bp
@@ -0,0 +1,29 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.power.stats@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IPowerStats.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "EnergyData",
+        "PowerEntityInfo",
+        "PowerEntityStateInfo",
+        "PowerEntityStateResidencyData",
+        "PowerEntityStateResidencyResult",
+        "PowerEntityStateSpace",
+        "PowerEntityType",
+        "RailInfo",
+        "Status",
+    ],
+    gen_java: false,
+}
+
diff --git a/power/stats/1.0/IPowerStats.hal b/power/stats/1.0/IPowerStats.hal
new file mode 100644
index 0000000..74ceb8f
--- /dev/null
+++ b/power/stats/1.0/IPowerStats.hal
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.power.stats@1.0;
+
+interface IPowerStats {
+
+    /**
+     * Rail information:
+     * Reports information related to the rails being monitored.
+     *
+     * @return rails Information about monitored rails.
+     * @return status SUCCESS on success or NOT_SUPPORTED if
+     *     feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
+     *     access error.
+     */
+    getRailInfo()
+        generates(vec<RailInfo> rails, Status status);
+
+    /**
+     * Rail level energy measurements for low frequency clients:
+     * Reports accumulated energy since boot on each rail.
+     *
+     * @param railIndices Indices of rails for which data is required.
+     *     To get data for all rails pass an empty vector. Rail name to
+     *     index mapping can be queried from getRailInfo() API.
+     * @return data Energy values since boot for all requested rails.
+     * @return status SUCCESS on success or NOT_SUPPORTED if
+     *     feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
+     *     access error.
+     */
+    getEnergyData(vec<uint32_t> railIndices)
+        generates(vec<EnergyData> data, Status status);
+
+    /**
+     * Stream rail level power measurements for high frequency clients:
+     * Streams accumulated energy since boot on each rail. This API is
+     * asynchronous.
+     *
+     * @param timeMs Time(in ms) for which energyData should be streamed
+     * @param samplingRate Frequency(in Hz) at which samples should be
+     *     captured. If the requested sampling rate is not supported then
+     *     SUCCESS is returned and numSamples are reported back according
+     *     to the supported sampling rate.
+     * @return mqDesc Blocking Synchronous Fast Message Queue descriptor - One
+     *     writer(power.stats HAL) and one reader are supported. Data is
+     *     present in the following format in the queue:
+     *     +-----------------------+       <--
+     *     | EnergyData for rail 1 |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail 2 |         |
+     *     +-----------------------+         |
+     *     |          .            |         |-- 1st Sample
+     *     |          .            |         |
+     *     |          .            |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail n |         |
+     *     +-----------------------+       <--
+     *     |          .            |
+     *     |          .            |
+     *     |          .            |
+     *     +-----------------------+       <--
+     *     | EnergyData for rail 1 |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail 2 |         |
+     *     +-----------------------+         |
+     *     |          .            |         |-- kth Sample
+     *     |          .            |         |
+     *     |          .            |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail n |         |
+     *     +-----------------------+       <--
+     *
+     *     where,
+     *     n = railsPerSample
+     *     k = numSamples
+     *
+     * @return numSamples Number of samples which will be generated in timeMs.
+     * @return railsPerSample Number of rails measured per sample.
+     * @return status SUCCESS on success or FILESYSTEM_ERROR on filesystem
+     *     nodes access or NOT_SUPPORTED if feature is not enabled or
+     *     INSUFFICIENT_RESOURCES if there are not enough resources.
+     */
+    streamEnergyData(uint32_t timeMs, uint32_t samplingRate)
+        generates(fmq_sync<EnergyData> mqDesc, uint32_t numSamples,
+                uint32_t railsPerSample, Status status);
+
+    /**
+     * PowerEntity information:
+     * Reports information related to all supported PowerEntity(s) for which
+     * data is available. A PowerEntity is defined as a platform subsystem,
+     * peripheral, or power domain that impacts the total device power
+     * consumption.
+     *
+     * @return powerEntityInfos List of information on each PowerEntity
+     * @return status SUCCESS on success, NOT_SUPPORTED if feature is not
+     *     enabled, FILESYSTEM_ERROR if there was an error accessing the
+     *     filesystem.
+     */
+    getPowerEntityInfo()
+        generates(vec<PowerEntityInfo> powerEntityInfos, Status status);
+
+    /**
+     * PowerEntity state information:
+     * Reports the set of power states for which the specified
+     * PowerEntity(s) provide residency data.
+     *
+     * @param powerEntityIds collection of IDs of PowerEntity(s) for which
+     *     state information is requested. PowerEntity name to ID mapping may
+     *     be queried from getPowerEntityInfo(). To get state space
+     *     information for all PowerEntity(s) pass an empty vector.
+     *
+     * @return powerEntityStateSpaces PowerEntity state space information for
+     *     each specified PowerEntity that provides state space information.
+     * @return status SUCCESS on success, NOT_SUPPORTED if feature is not
+     *     enabled, FILESYSTEM_ERROR if there was an error accessing the
+     *     filesystem, INVALID_INPUT if any requested PowerEntity(s) do not
+     *     provide state space information and there was not a filesystem error.
+     */
+    getPowerEntityStateInfo(vec<uint32_t> powerEntityIds)
+        generates(vec<PowerEntityStateSpace> powerEntityStateSpaces,
+                  Status status);
+
+    /**
+     * PowerEntity residencies for low frequency clients:
+     * Reports accumulated residency data for each specified PowerEntity.
+     * Each PowerEntity may reside in one of multiple states. It may also
+     * transition to another state. Residency data is an accumulation of time
+     * that a specified PowerEntity resided in each of its possible states,
+     * the number of times that each state was entered, and a timestamp
+     * corresponding to the last time that state was entered. Data is
+     * accumulated starting from the last time the PowerEntity was reset.
+     *
+     * @param powerEntityId collection of IDs of PowerEntity(s) for which
+     *     residency data is requested. PowerEntity name to ID mapping may
+     *     be queried from getPowerEntityInfo(). To get state residency
+     *     data for all PowerEntity(s) pass an empty vector.
+     * @return stateResidencyResults state residency data for each specified
+     *     PowerEntity that provides state residency data.
+     * @return status SUCCESS on success, NOT_SUPPORTED if feature is not
+     *     enabled, FILESYSTEM_ERROR if there was an error accessing the
+     *     filesystem, INVALID_INPUT if any requested PowerEntity(s) do not
+     *     provide state residency data and there was not a filesystem error.
+     */
+    getPowerEntityStateResidencyData(vec<uint32_t> powerEntityIds)
+        generates(vec<PowerEntityStateResidencyResult> stateResidencyResults,
+                  Status status);
+};
diff --git a/power/stats/1.0/default/Android.bp b/power/stats/1.0/default/Android.bp
new file mode 100644
index 0000000..04270c1
--- /dev/null
+++ b/power/stats/1.0/default/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+
+cc_library_shared {
+    name: "android.hardware.power.stats@1.0-service",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.power.stats@1.0-service.rc"],
+    srcs: ["service.cpp", "PowerStats.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.power.stats@1.0",
+    ],
+    vendor: true,
+}
diff --git a/power/stats/1.0/default/PowerStats.cpp b/power/stats/1.0/default/PowerStats.cpp
new file mode 100644
index 0000000..810c575
--- /dev/null
+++ b/power/stats/1.0/default/PowerStats.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PowerStats.h"
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <exception>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace stats {
+namespace V1_0 {
+namespace implementation {
+
+#define MAX_FILE_PATH_LEN 128
+#define MAX_DEVICE_NAME_LEN 64
+#define MAX_QUEUE_SIZE 8192
+
+constexpr char kIioDirRoot[] = "/sys/bus/iio/devices/";
+constexpr char kDeviceName[] = "pm_device_name";
+constexpr char kDeviceType[] = "iio:device";
+constexpr uint32_t MAX_SAMPLING_RATE = 10;
+constexpr uint64_t WRITE_TIMEOUT_NS = 1000000000;
+
+void PowerStats::findIioPowerMonitorNodes() {
+    struct dirent* ent;
+    int fd;
+    char devName[MAX_DEVICE_NAME_LEN];
+    char filePath[MAX_FILE_PATH_LEN];
+    DIR* iioDir = opendir(kIioDirRoot);
+    if (!iioDir) {
+        ALOGE("Error opening directory: %s", kIioDirRoot);
+        return;
+    }
+    while (ent = readdir(iioDir), ent) {
+        if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0 &&
+            strlen(ent->d_name) > strlen(kDeviceType) &&
+            strncmp(ent->d_name, kDeviceType, strlen(kDeviceType)) == 0) {
+            snprintf(filePath, MAX_FILE_PATH_LEN, "%s/%s", ent->d_name, "name");
+            fd = openat(dirfd(iioDir), filePath, O_RDONLY);
+            if (fd < 0) {
+                ALOGW("Failed to open directory: %s", filePath);
+                continue;
+            }
+            if (read(fd, devName, MAX_DEVICE_NAME_LEN) < 0) {
+                ALOGW("Failed to read device name from file: %s(%d)", filePath, fd);
+                close(fd);
+                continue;
+            }
+
+            if (strncmp(devName, kDeviceName, strlen(kDeviceName)) == 0) {
+                snprintf(filePath, MAX_FILE_PATH_LEN, "%s/%s", kIioDirRoot, ent->d_name);
+                mPm.devicePaths.push_back(filePath);
+            }
+            close(fd);
+        }
+    }
+    closedir(iioDir);
+    return;
+}
+
+size_t PowerStats::parsePowerRails() {
+    std::string data;
+    std::string railFileName;
+    std::string spsFileName;
+    uint32_t index = 0;
+    uint32_t samplingRate;
+    for (const auto& path : mPm.devicePaths) {
+        railFileName = path + "/enabled_rails";
+        spsFileName = path + "/sampling_rate";
+        if (!android::base::ReadFileToString(spsFileName, &data)) {
+            ALOGW("Error reading file: %s", spsFileName.c_str());
+            continue;
+        }
+        samplingRate = strtoul(data.c_str(), NULL, 10);
+        if (!samplingRate || samplingRate == ULONG_MAX) {
+            ALOGE("Error parsing: %s", spsFileName.c_str());
+            break;
+        }
+        if (!android::base::ReadFileToString(railFileName, &data)) {
+            ALOGW("Error reading file: %s", railFileName.c_str());
+            continue;
+        }
+        std::istringstream railNames(data);
+        std::string line;
+        while (std::getline(railNames, line)) {
+            std::vector<std::string> words = android::base::Split(line, ":");
+            if (words.size() == 2) {
+                mPm.railsInfo.emplace(words[0], RailData{.devicePath = path,
+                                                         .index = index,
+                                                         .subsysName = words[1],
+                                                         .samplingRate = samplingRate});
+                index++;
+            } else {
+                ALOGW("Unexpected format in file: %s", railFileName.c_str());
+            }
+        }
+    }
+    return index;
+}
+
+int PowerStats::parseIioEnergyNode(std::string devName) {
+    int ret = 0;
+    std::string data;
+    std::string fileName = devName + "/energy_value";
+    if (!android::base::ReadFileToString(fileName, &data)) {
+        ALOGE("Error reading file: %s", fileName.c_str());
+        return -1;
+    }
+
+    std::istringstream energyData(data);
+    std::string line;
+    uint64_t timestamp = 0;
+    bool timestampRead = false;
+    while (std::getline(energyData, line)) {
+        std::vector<std::string> words = android::base::Split(line, ",");
+        if (timestampRead == false) {
+            if (words.size() == 1) {
+                timestamp = strtoull(words[0].c_str(), NULL, 10);
+                if (timestamp == 0 || timestamp == ULLONG_MAX) {
+                    ALOGW("Potentially wrong timestamp: %" PRIu64, timestamp);
+                }
+                timestampRead = true;
+            }
+        } else if (words.size() == 2) {
+            std::string railName = words[0];
+            if (mPm.railsInfo.count(railName) != 0) {
+                size_t index = mPm.railsInfo[railName].index;
+                mPm.reading[index].index = index;
+                mPm.reading[index].timestamp = timestamp;
+                mPm.reading[index].energy = strtoull(words[1].c_str(), NULL, 10);
+                if (mPm.reading[index].energy == ULLONG_MAX) {
+                    ALOGW("Potentially wrong energy value: %" PRIu64, mPm.reading[index].energy);
+                }
+            }
+        } else {
+            ALOGW("Unexpected format in file: %s", fileName.c_str());
+            ret = -1;
+            break;
+        }
+    }
+    return ret;
+}
+
+Status PowerStats::parseIioEnergyNodes() {
+    Status ret = Status::SUCCESS;
+    if (mPm.hwEnabled == false) {
+        return Status::NOT_SUPPORTED;
+    }
+
+    for (const auto& devicePath : mPm.devicePaths) {
+        if (parseIioEnergyNode(devicePath) < 0) {
+            ALOGE("Error in parsing power stats");
+            ret = Status::FILESYSTEM_ERROR;
+            break;
+        }
+    }
+    return ret;
+}
+
+PowerStats::PowerStats() {
+    findIioPowerMonitorNodes();
+    size_t numRails = parsePowerRails();
+    if (mPm.devicePaths.empty() || numRails == 0) {
+        mPm.hwEnabled = false;
+    } else {
+        mPm.hwEnabled = true;
+        mPm.reading.resize(numRails);
+    }
+}
+
+Return<void> PowerStats::getRailInfo(getRailInfo_cb _hidl_cb) {
+    hidl_vec<RailInfo> rInfo;
+    Status ret = Status::SUCCESS;
+    size_t index;
+    std::lock_guard<std::mutex> _lock(mPm.mLock);
+    if (mPm.hwEnabled == false) {
+        _hidl_cb(rInfo, Status::NOT_SUPPORTED);
+        return Void();
+    }
+    rInfo.resize(mPm.railsInfo.size());
+    for (const auto& railData : mPm.railsInfo) {
+        index = railData.second.index;
+        rInfo[index].railName = railData.first;
+        rInfo[index].subsysName = railData.second.subsysName;
+        rInfo[index].index = index;
+        rInfo[index].samplingRate = railData.second.samplingRate;
+    }
+    _hidl_cb(rInfo, ret);
+    return Void();
+}
+
+Return<void> PowerStats::getEnergyData(const hidl_vec<uint32_t>& railIndices,
+                                       getEnergyData_cb _hidl_cb) {
+    hidl_vec<EnergyData> eVal;
+    std::lock_guard<std::mutex> _lock(mPm.mLock);
+    Status ret = parseIioEnergyNodes();
+
+    if (ret != Status::SUCCESS) {
+        ALOGE("Failed to getEnergyData");
+        _hidl_cb(eVal, ret);
+        return Void();
+    }
+
+    if (railIndices.size() == 0) {
+        eVal.resize(mPm.railsInfo.size());
+        memcpy(&eVal[0], &mPm.reading[0], mPm.reading.size() * sizeof(EnergyData));
+    } else {
+        eVal.resize(railIndices.size());
+        int i = 0;
+        for (const auto& railIndex : railIndices) {
+            if (railIndex >= mPm.reading.size()) {
+                ret = Status::INVALID_INPUT;
+                eVal.resize(0);
+                break;
+            }
+            memcpy(&eVal[i], &mPm.reading[railIndex], sizeof(EnergyData));
+            i++;
+        }
+    }
+    _hidl_cb(eVal, ret);
+    return Void();
+}
+
+Return<void> PowerStats::streamEnergyData(uint32_t timeMs, uint32_t samplingRate,
+                                          streamEnergyData_cb _hidl_cb) {
+    std::lock_guard<std::mutex> _lock(mPm.mLock);
+    if (mPm.fmqSynchronized != nullptr) {
+        _hidl_cb(MessageQueueSync::Descriptor(), 0, 0, Status::INSUFFICIENT_RESOURCES);
+        return Void();
+    }
+    uint32_t sps = std::min(samplingRate, MAX_SAMPLING_RATE);
+    uint32_t numSamples = timeMs * sps / 1000;
+    mPm.fmqSynchronized.reset(new (std::nothrow) MessageQueueSync(MAX_QUEUE_SIZE, true));
+    if (mPm.fmqSynchronized == nullptr || mPm.fmqSynchronized->isValid() == false) {
+        mPm.fmqSynchronized = nullptr;
+        _hidl_cb(MessageQueueSync::Descriptor(), 0, 0, Status::INSUFFICIENT_RESOURCES);
+        return Void();
+    }
+    std::thread pollThread = std::thread([this, sps, numSamples]() {
+        uint64_t sleepTimeUs = 1000000 / sps;
+        uint32_t currSamples = 0;
+        while (currSamples < numSamples) {
+            mPm.mLock.lock();
+            if (parseIioEnergyNodes() == Status::SUCCESS) {
+                mPm.fmqSynchronized->writeBlocking(&mPm.reading[0], mPm.reading.size(),
+                                                   WRITE_TIMEOUT_NS);
+                mPm.mLock.unlock();
+                currSamples++;
+                if (usleep(sleepTimeUs) < 0) {
+                    ALOGW("Sleep interrupted");
+                    break;
+                }
+            } else {
+                mPm.mLock.unlock();
+                break;
+            }
+        }
+        mPm.mLock.lock();
+        mPm.fmqSynchronized = nullptr;
+        mPm.mLock.unlock();
+        return;
+    });
+    pollThread.detach();
+    _hidl_cb(*(mPm.fmqSynchronized)->getDesc(), numSamples, mPm.reading.size(), Status::SUCCESS);
+    return Void();
+}
+
+Return<void> PowerStats::getPowerEntityInfo(getPowerEntityInfo_cb _hidl_cb) {
+    hidl_vec<PowerEntityInfo> eInfo;
+    _hidl_cb(eInfo, Status::NOT_SUPPORTED);
+    return Void();
+}
+
+Return<void> PowerStats::getPowerEntityStateInfo(const hidl_vec<uint32_t>& powerEntityIds,
+                                                 getPowerEntityStateInfo_cb _hidl_cb) {
+    (void)powerEntityIds;
+    hidl_vec<PowerEntityStateSpace> powerEntityStateSpaces;
+    _hidl_cb(powerEntityStateSpaces, Status::NOT_SUPPORTED);
+    return Void();
+}
+
+Return<void> PowerStats::getPowerEntityStateResidencyData(
+    const hidl_vec<uint32_t>& powerEntityIds, getPowerEntityStateResidencyData_cb _hidl_cb) {
+    (void)powerEntityIds;
+    hidl_vec<PowerEntityStateResidencyResult> results;
+    _hidl_cb(results, Status::NOT_SUPPORTED);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace stats
+}  // namespace power
+}  // namespace hardware
+}  // namespace android
diff --git a/power/stats/1.0/default/PowerStats.h b/power/stats/1.0/default/PowerStats.h
new file mode 100644
index 0000000..fb2c6a8
--- /dev/null
+++ b/power/stats/1.0/default/PowerStats.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_POWERSTATS_V1_0_POWERSTATS_H
+#define ANDROID_HARDWARE_POWERSTATS_V1_0_POWERSTATS_H
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace stats {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::power::stats::V1_0::EnergyData;
+using ::android::hardware::power::stats::V1_0::PowerEntityInfo;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateInfo;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateResidencyData;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
+using ::android::hardware::power::stats::V1_0::PowerEntityStateSpace;
+using ::android::hardware::power::stats::V1_0::PowerEntityType;
+using ::android::hardware::power::stats::V1_0::RailInfo;
+using ::android::hardware::power::stats::V1_0::Status;
+
+typedef MessageQueue<EnergyData, kSynchronizedReadWrite> MessageQueueSync;
+struct RailData {
+    std::string devicePath;
+    uint32_t index;
+    std::string subsysName;
+    uint32_t samplingRate;
+};
+
+struct OnDeviceMmt {
+    std::mutex mLock;
+    bool hwEnabled;
+    std::vector<std::string> devicePaths;
+    std::map<std::string, RailData> railsInfo;
+    std::vector<EnergyData> reading;
+    std::unique_ptr<MessageQueueSync> fmqSynchronized;
+};
+
+struct PowerStats : public IPowerStats {
+    PowerStats();
+    // Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow.
+    Return<void> getRailInfo(getRailInfo_cb _hidl_cb) override;
+    Return<void> getEnergyData(const hidl_vec<uint32_t>& railIndices,
+                               getEnergyData_cb _hidl_cb) override;
+    Return<void> streamEnergyData(uint32_t timeMs, uint32_t samplingRate,
+                                  streamEnergyData_cb _hidl_cb) override;
+    Return<void> getPowerEntityInfo(getPowerEntityInfo_cb _hidl_cb) override;
+    Return<void> getPowerEntityStateInfo(const hidl_vec<uint32_t>& powerEntityIds,
+                                         getPowerEntityStateInfo_cb _hidl_cb) override;
+    Return<void> getPowerEntityStateResidencyData(
+        const hidl_vec<uint32_t>& powerEntityIds,
+        getPowerEntityStateResidencyData_cb _hidl_cb) override;
+
+   private:
+    OnDeviceMmt mPm;
+    void findIioPowerMonitorNodes();
+    size_t parsePowerRails();
+    int parseIioEnergyNode(std::string devName);
+    Status parseIioEnergyNodes();
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace stats
+}  // namespace power
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_POWERSTATS_V1_0_POWERSTATS_H
diff --git a/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc b/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
new file mode 100644
index 0000000..d7e546b
--- /dev/null
+++ b/power/stats/1.0/default/android.hardware.power.stats@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.power.stats-hal-1-0 /vendor/bin/hw/android.hardware.power.stats@1.0-service
+    class hal
+    user system
+    group system
diff --git a/power/stats/1.0/default/service.cpp b/power/stats/1.0/default/service.cpp
new file mode 100644
index 0000000..80649f5
--- /dev/null
+++ b/power/stats/1.0/default/service.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.power.stats@1.0-service"
+
+#include <android/log.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "PowerStats.h"
+
+using android::OK;
+using android::sp;
+using android::status_t;
+
+// libhwbinder:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::implementation::PowerStats;
+
+int main(int /* argc */, char** /* argv */) {
+    ALOGI("power.stats service 1.0 is starting.");
+
+    android::sp<IPowerStats> service = new PowerStats();
+    if (service == nullptr) {
+        ALOGE("Can not create an instance of power.stats HAL Iface, exiting.");
+        return 1;
+    }
+
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+    status_t status = service->registerAsService();
+    if (status != OK) {
+        ALOGE("Could not register service for power.stats HAL Iface (%d), exiting.", status);
+        return 1;
+    }
+
+    ALOGI("power.stats service is ready");
+    joinRpcThreadpool();
+
+    // In normal operation, we don't expect the thread pool to exit
+    ALOGE("power.stats service is shutting down");
+    return 1;
+}
diff --git a/power/stats/1.0/types.hal b/power/stats/1.0/types.hal
new file mode 100644
index 0000000..644224b
--- /dev/null
+++ b/power/stats/1.0/types.hal
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.power.stats@1.0;
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+    NOT_SUPPORTED = 1,
+    INVALID_INPUT = 2,
+    FILESYSTEM_ERROR = 3,
+    INSUFFICIENT_RESOURCES = 4,
+};
+
+struct RailInfo {
+    /** Index corresponding to the rail */
+    uint32_t index;
+    /** Name of the rail */
+    string railName;
+    /** Name of the subsystem to which this rail belongs */
+    string subsysName;
+    /** Hardware sampling rate */
+    uint32_t samplingRate;
+};
+
+struct EnergyData {
+    /**
+     * Index corresponding to the rail. This index matches
+     * the index returned in RailInfo
+     */
+    uint32_t index;
+    /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
+    uint64_t timestamp;
+    /** Accumulated energy since device boot in microwatt-seconds (uWs) */
+    uint64_t energy;
+};
+
+enum PowerEntityType : uint32_t {
+    /**
+     * A subsystem is a self-contained compute unit. Some examples include
+     * application processor, DSP, GPU.
+     */
+    SUBSYSTEM = 0,
+    /**
+     * A peripheral is an auxiliary device that connects to and works with a
+     * compute unit. Some examples include simple sensors, camera, display.
+     */
+    PERIPHERAL = 1,
+    /**
+     * A power domain is a single subsystem or a collection of subsystems
+     * that is controlled by a single voltage rail.
+     */
+    POWER_DOMAIN = 2,
+};
+
+/**
+ * PowerEntityInfo contains information, such as the ID, name, and type of a
+ * given PowerEntity.
+ */
+struct PowerEntityInfo {
+    /** Unique ID corresponding to the PowerEntity */
+    uint32_t powerEntityId;
+    /** Name of the PowerEntity */
+    string powerEntityName;
+    /** Type of the PowerEntity */
+    PowerEntityType type;
+};
+
+struct PowerEntityStateInfo {
+    /**
+     * ID corresponding to the state. Unique for a given PowerEntityStateSpace
+     */
+    uint32_t powerEntityStateId;
+    /** Name of the state */
+    string powerEntityStateName;
+};
+
+/**
+ * PowerEntityStateSpace contains the state space information of a given
+ * PowerEntity. The state space, is the set of possible states that a given
+ * PowerEntity provides residency data for.
+ */
+struct PowerEntityStateSpace {
+    /** Unique ID of the corresponding PowerEntity */
+    uint32_t powerEntityId;
+
+    /** List of states that the PowerEntity may reside in */
+    vec<PowerEntityStateInfo> states;
+};
+
+/** Contains residency data for a single state */
+struct PowerEntityStateResidencyData {
+    /** Unique ID of the corresponding PowerEntityStateInfo */
+    uint32_t powerEntityStateId;
+    /**
+     * Total time in milliseconds that the corresponding PowerEntity resided
+     * in this state since the PowerEntity was reset
+     */
+    uint64_t totalTimeInStateMs;
+    /**
+     * Total number of times that the state was entered since the corresponding
+     * PowerEntity was reset
+     */
+    uint64_t totalStateEntryCount;
+    /**
+     * Last time this state was entered. Time in milliseconds since the
+     * corresponding PowerEntity was reset
+     */
+    uint64_t lastEntryTimestampMs;
+};
+
+struct PowerEntityStateResidencyResult {
+    /** Unique ID of the corresponding PowerEntity */
+    uint32_t powerEntityId;
+    /** Residency data for each state the PowerEntity's state space */
+    vec<PowerEntityStateResidencyData> stateResidencyData;
+};
diff --git a/power/stats/1.0/vts/functional/Android.bp b/power/stats/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..4f0b325
--- /dev/null
+++ b/power/stats/1.0/vts/functional/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalPowerStatsV1_0TargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults"
+    ],
+    srcs: [
+        "VtsHalPowerStatsV1_0TargetTest.cpp"
+    ],
+    static_libs: [
+        "android.hardware.power.stats@1.0"
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libhidlbase",
+        "libfmq",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
new file mode 100644
index 0000000..9f007e4
--- /dev/null
+++ b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.power.stats.vts"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <inttypes.h>
+#include <algorithm>
+#include <random>
+#include <thread>
+
+namespace android {
+namespace power {
+namespace stats {
+namespace vts {
+namespace {
+
+using android::sp;
+using android::hardware::hidl_vec;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::PowerEntityInfo;
+using android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
+using android::hardware::power::stats::V1_0::PowerEntityStateSpace;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+
+}  // namespace
+
+typedef hardware::MessageQueue<EnergyData, kSynchronizedReadWrite> MessageQueueSync;
+// Test environment for Power HIDL HAL.
+class PowerStatsHidlEnv : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static PowerStatsHidlEnv* Instance() {
+        static PowerStatsHidlEnv* instance = new PowerStatsHidlEnv;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IPowerStats>(); }
+};
+
+class PowerStatsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        service_ = ::testing::VtsHalHidlTargetTestBase::getService<IPowerStats>(
+            PowerStatsHidlEnv::Instance()->getServiceName<IPowerStats>());
+        ASSERT_NE(service_, nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+    void getInfos(hidl_vec<PowerEntityInfo>& infos);
+    void getStateSpaces(hidl_vec<PowerEntityStateSpace>& stateSpaces,
+                        const std::vector<uint32_t>& ids);
+    void getResidencyResults(hidl_vec<PowerEntityStateResidencyResult>& results,
+                             const std::vector<uint32_t>& ids);
+    void getRandomIds(std::vector<uint32_t>& ids);
+
+    sp<IPowerStats> service_;
+};
+
+void PowerStatsHidlTest::getInfos(hidl_vec<PowerEntityInfo>& infos) {
+    Status status;
+    Return<void> ret = service_->getPowerEntityInfo([&status, &infos](auto rInfos, auto rStatus) {
+        status = rStatus;
+        infos = rInfos;
+    });
+    ASSERT_TRUE(ret.isOk());
+
+    if (status == Status::SUCCESS) {
+        ASSERT_NE(infos.size(), 0) << "powerEntityInfos must have entries if supported";
+    } else {
+        ASSERT_EQ(status, Status::NOT_SUPPORTED);
+        ASSERT_EQ(infos.size(), 0);
+        LOG(INFO) << "getPowerEntityInfo not supported";
+    }
+}
+
+void PowerStatsHidlTest::getStateSpaces(hidl_vec<PowerEntityStateSpace>& stateSpaces,
+                                        const std::vector<uint32_t>& ids = {}) {
+    Status status;
+    Return<void> ret = service_->getPowerEntityStateInfo(
+        ids, [&status, &stateSpaces](auto rStateSpaces, auto rStatus) {
+            status = rStatus;
+            stateSpaces = rStateSpaces;
+        });
+    ASSERT_TRUE(ret.isOk());
+
+    if (status == Status::SUCCESS) {
+        ASSERT_NE(stateSpaces.size(), 0) << "powerEntityStateSpaces must have entries if supported";
+    } else {
+        ASSERT_EQ(status, Status::NOT_SUPPORTED);
+        ASSERT_EQ(stateSpaces.size(), 0);
+        LOG(INFO) << "getPowerEntityStateInfo not supported";
+    }
+}
+
+void PowerStatsHidlTest::getResidencyResults(hidl_vec<PowerEntityStateResidencyResult>& results,
+                                             const std::vector<uint32_t>& ids = {}) {
+    Status status;
+    Return<void> ret = service_->getPowerEntityStateResidencyData(
+        ids, [&status, &results](auto rResults, auto rStatus) {
+            status = rStatus;
+            results = rResults;
+        });
+    ASSERT_TRUE(ret.isOk());
+
+    if (status == Status::SUCCESS) {
+        ASSERT_NE(results.size(), 0);
+    } else {
+        ASSERT_EQ(status, Status::NOT_SUPPORTED);
+        ASSERT_EQ(results.size(), 0);
+        LOG(INFO) << "getPowerEntityStateResidencyData not supported";
+    }
+}
+
+void PowerStatsHidlTest::getRandomIds(std::vector<uint32_t>& ids) {
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces);
+
+    if (stateSpaces.size() == 0) {
+        return;
+    }
+
+    for (auto stateSpace : stateSpaces) {
+        ids.push_back(stateSpace.powerEntityId);
+    }
+
+    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
+    auto gen = std::default_random_engine(seed);
+    std::uniform_int_distribution<uint32_t> dist(1, stateSpaces.size());
+
+    std::shuffle(ids.begin(), ids.end(), gen);
+    ids.resize(dist(gen));
+}
+
+// Each PowerEntity must have a valid name
+TEST_F(PowerStatsHidlTest, ValidatePowerEntityNames) {
+    hidl_vec<PowerEntityInfo> infos;
+    getInfos(infos);
+    for (auto info : infos) {
+        ASSERT_NE(info.powerEntityName, "");
+    }
+}
+
+// Each PowerEntity must have a unique ID
+TEST_F(PowerStatsHidlTest, ValidatePowerEntityIds) {
+    hidl_vec<PowerEntityInfo> infos;
+    getInfos(infos);
+
+    set<uint32_t> ids;
+    for (auto info : infos) {
+        ASSERT_TRUE(ids.insert(info.powerEntityId).second);
+    }
+}
+
+// Each PowerEntityStateSpace must have an associated PowerEntityInfo
+TEST_F(PowerStatsHidlTest, ValidateStateInfoAssociation) {
+    hidl_vec<PowerEntityInfo> infos;
+    getInfos(infos);
+
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces);
+
+    std::set<uint32_t> ids;
+    for (auto info : infos) {
+        ids.insert(info.powerEntityId);
+    }
+
+    for (auto stateSpace : stateSpaces) {
+        ASSERT_NE(ids.count(stateSpace.powerEntityId), 0);
+    }
+}
+
+// Each state must have a valid name
+TEST_F(PowerStatsHidlTest, ValidateStateNames) {
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces);
+
+    for (auto stateSpace : stateSpaces) {
+        for (auto state : stateSpace.states) {
+            ASSERT_NE(state.powerEntityStateName, "");
+        }
+    }
+}
+
+// Each state must have an ID that is unique to the PowerEntityStateSpace
+TEST_F(PowerStatsHidlTest, ValidateStateUniqueIds) {
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces);
+
+    for (auto stateSpace : stateSpaces) {
+        set<uint32_t> stateIds;
+        for (auto state : stateSpace.states) {
+            ASSERT_TRUE(stateIds.insert(state.powerEntityStateId).second);
+        }
+    }
+}
+
+// getPowerEntityStateInfo must support passing in requested IDs
+// Results must contain state space information for all requested IDs
+TEST_F(PowerStatsHidlTest, ValidateStateInfoAssociationSelect) {
+    std::vector<uint32_t> randomIds;
+    getRandomIds(randomIds);
+
+    if (randomIds.empty()) {
+        return;
+    }
+
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces, randomIds);
+
+    ASSERT_EQ(stateSpaces.size(), randomIds.size());
+
+    std::set<uint32_t> ids;
+    for (auto id : randomIds) {
+        ids.insert(id);
+    }
+    for (auto stateSpace : stateSpaces) {
+        ASSERT_NE(ids.count(stateSpace.powerEntityId), 0);
+    }
+}
+
+// Requested state space info must match initially obtained stateinfos
+TEST_F(PowerStatsHidlTest, ValidateStateInfoSelect) {
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces);
+    if (stateSpaces.size() == 0) {
+        return;
+    }
+
+    std::vector<uint32_t> randomIds;
+    getRandomIds(randomIds);
+    ASSERT_FALSE(randomIds.empty());
+
+    hidl_vec<PowerEntityStateSpace> selectedStateSpaces;
+    getStateSpaces(selectedStateSpaces, randomIds);
+
+    std::map<uint32_t, PowerEntityStateSpace> stateSpaceMap;
+    for (auto stateSpace : stateSpaces) {
+        stateSpaceMap[stateSpace.powerEntityId] = stateSpace;
+    }
+
+    for (auto stateSpace : selectedStateSpaces) {
+        auto it = stateSpaceMap.find(stateSpace.powerEntityId);
+        ASSERT_NE(it, stateSpaceMap.end());
+
+        ASSERT_EQ(stateSpace.states.size(), it->second.states.size());
+        for (auto i = 0; i < stateSpace.states.size(); i++) {
+            ASSERT_EQ(stateSpace.states[i].powerEntityStateId,
+                      it->second.states[i].powerEntityStateId);
+            ASSERT_EQ(stateSpace.states[i].powerEntityStateName,
+                      it->second.states[i].powerEntityStateName);
+        }
+    }
+}
+
+// stateResidencyResults must contain results for every PowerEntityStateSpace
+// returned by getPowerEntityStateInfo
+TEST_F(PowerStatsHidlTest, ValidateResidencyResultsAssociation) {
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces);
+
+    hidl_vec<PowerEntityStateResidencyResult> results;
+    getResidencyResults(results);
+
+    std::map<uint32_t, PowerEntityStateResidencyResult> resultsMap;
+    for (auto result : results) {
+        resultsMap[result.powerEntityId] = result;
+    }
+
+    for (auto stateSpace : stateSpaces) {
+        auto it = resultsMap.find(stateSpace.powerEntityId);
+        ASSERT_NE(it, resultsMap.end());
+
+        ASSERT_EQ(stateSpace.states.size(), it->second.stateResidencyData.size());
+
+        std::set<uint32_t> stateIds;
+        for (auto residency : it->second.stateResidencyData) {
+            stateIds.insert(residency.powerEntityStateId);
+        }
+
+        for (auto state : stateSpace.states) {
+            ASSERT_NE(stateIds.count(state.powerEntityStateId), 0);
+        }
+    }
+}
+
+// getPowerEntityStateResidencyData must support passing in requested IDs
+// stateResidencyResults must contain results for each PowerEntityStateSpace
+// returned by getPowerEntityStateInfo
+TEST_F(PowerStatsHidlTest, ValidateResidencyResultsAssociationSelect) {
+    std::vector<uint32_t> randomIds;
+    getRandomIds(randomIds);
+    if (randomIds.empty()) {
+        return;
+    }
+
+    hidl_vec<PowerEntityStateSpace> stateSpaces;
+    getStateSpaces(stateSpaces, randomIds);
+
+    hidl_vec<PowerEntityStateResidencyResult> results;
+    getResidencyResults(results, randomIds);
+
+    std::map<uint32_t, PowerEntityStateResidencyResult> resultsMap;
+    for (auto result : results) {
+        resultsMap[result.powerEntityId] = result;
+    }
+
+    for (auto stateSpace : stateSpaces) {
+        auto it = resultsMap.find(stateSpace.powerEntityId);
+        ASSERT_NE(it, resultsMap.end());
+
+        ASSERT_EQ(stateSpace.states.size(), it->second.stateResidencyData.size());
+
+        std::set<uint32_t> stateIds;
+        for (auto residency : it->second.stateResidencyData) {
+            stateIds.insert(residency.powerEntityStateId);
+        }
+
+        for (auto state : stateSpace.states) {
+            ASSERT_NE(stateIds.count(state.powerEntityStateId), 0);
+        }
+    }
+}
+
+TEST_F(PowerStatsHidlTest, ValidateRailInfo) {
+    hidl_vec<RailInfo> rails[2];
+    Status s;
+    auto cb = [&rails, &s](hidl_vec<RailInfo> rail_subsys, Status status) {
+        rails[0] = rail_subsys;
+        s = status;
+    };
+    Return<void> ret = service_->getRailInfo(cb);
+    EXPECT_TRUE(ret.isOk());
+    if (s == Status::SUCCESS) {
+        /* Rails size should be non-zero on SUCCESS*/
+        ASSERT_NE(rails[0].size(), 0);
+        /* check if indices returned are unique*/
+        set<uint32_t> ids;
+        for (auto rail : rails[0]) {
+            ASSERT_TRUE(ids.insert(rail.index).second);
+        }
+        auto cb = [&rails, &s](hidl_vec<RailInfo> rail_subsys, Status status) {
+            rails[1] = rail_subsys;
+            s = status;
+        };
+        Return<void> ret = service_->getRailInfo(cb);
+        EXPECT_TRUE(ret.isOk());
+        ASSERT_EQ(s, Status::SUCCESS);
+        ASSERT_EQ(rails[0].size(), rails[1].size());
+        /* check if data returned by two calls to getRailInfo is same*/
+        for (int i = 0; i < rails[0].size(); i++) {
+            ASSERT_NE(rails[0][i].railName, "");
+            ASSERT_NE(rails[0][i].subsysName, "");
+            int j = 0;
+            bool match = false;
+            for (j = 0; j < rails[1].size(); j++) {
+                if (rails[0][i].index == rails[1][j].index) {
+                    ASSERT_EQ(rails[0][i].railName, rails[1][i].railName);
+                    ASSERT_EQ(rails[0][i].subsysName, rails[1][i].subsysName);
+                    match = true;
+                    break;
+                }
+            }
+            ASSERT_TRUE(match);
+        }
+    } else if (s == Status::FILESYSTEM_ERROR) {
+        ALOGI("ValidateRailInfo returned FILESYSTEM_ERROR");
+        ASSERT_EQ(rails[0].size(), 0);
+    } else if (s == Status::NOT_SUPPORTED) {
+        ALOGI("ValidateRailInfo returned NOT_SUPPORTED");
+        ASSERT_EQ(rails[0].size(), 0);
+    } else if (s == Status::INVALID_INPUT) {
+        ALOGI("ValidateRailInfo returned INVALID_INPUT");
+        ASSERT_EQ(rails[0].size(), 0);
+    } else if (s == Status::INSUFFICIENT_RESOURCES) {
+        ALOGI("ValidateRailInfo returned INSUFFICIENT_RESOURCES");
+        ASSERT_EQ(rails[0].size(), 0);
+    }
+}
+
+TEST_F(PowerStatsHidlTest, ValidateAllPowerData) {
+    hidl_vec<EnergyData> measurements[2];
+    Status s;
+    auto cb = [&measurements, &s](hidl_vec<EnergyData> measure, Status status) {
+        measurements[0] = measure;
+        s = status;
+    };
+    Return<void> ret = service_->getEnergyData(hidl_vec<uint32_t>(), cb);
+    EXPECT_TRUE(ret.isOk());
+    if (s == Status::SUCCESS) {
+        /*measurements size should be non-zero on SUCCESS*/
+        ASSERT_NE(measurements[0].size(), 0);
+        auto cb = [&measurements, &s](hidl_vec<EnergyData> measure, Status status) {
+            measurements[1] = measure;
+            s = status;
+        };
+        Return<void> ret = service_->getEnergyData(hidl_vec<uint32_t>(), cb);
+        EXPECT_TRUE(ret.isOk());
+        ASSERT_EQ(s, Status::SUCCESS);
+        /*Both calls should returns same amount of data*/
+        ASSERT_EQ(measurements[0].size(), measurements[1].size());
+        /*Check is energy and timestamp are monotonically increasing*/
+        for (int i = 0; i < measurements[0].size(); i++) {
+            int j;
+            for (j = 0; j < measurements[1].size(); j++) {
+                if (measurements[0][i].index == measurements[1][j].index) {
+                    EXPECT_GE(measurements[1][j].timestamp, measurements[0][i].timestamp);
+                    EXPECT_GE(measurements[1][j].energy, measurements[0][i].energy);
+                    break;
+                }
+            }
+            /*Check is indices for two call match*/
+            ASSERT_NE(j, measurements[1].size());
+        }
+    } else if (s == Status::FILESYSTEM_ERROR) {
+        ALOGI("ValidateAllPowerData returned FILESYSTEM_ERROR");
+        ASSERT_EQ(measurements[0].size(), 0);
+    } else if (s == Status::NOT_SUPPORTED) {
+        ALOGI("ValidateAllPowerData returned NOT_SUPPORTED");
+        ASSERT_EQ(measurements[0].size(), 0);
+    } else if (s == Status::INVALID_INPUT) {
+        ALOGI("ValidateAllPowerData returned INVALID_INPUT");
+        ASSERT_EQ(measurements[0].size(), 0);
+    } else if (s == Status::INSUFFICIENT_RESOURCES) {
+        ALOGI("ValidateAllPowerData returned INSUFFICIENT_RESOURCES");
+        ASSERT_EQ(measurements[0].size(), 0);
+    }
+}
+
+TEST_F(PowerStatsHidlTest, ValidateFilteredPowerData) {
+    hidl_vec<RailInfo> rails;
+    hidl_vec<EnergyData> measurements;
+    hidl_vec<uint32_t> indices;
+    std::string debugString;
+    Status s;
+    auto cb = [&rails, &s](hidl_vec<RailInfo> rail_subsys, Status status) {
+        rails = rail_subsys;
+        s = status;
+    };
+    Return<void> ret = service_->getRailInfo(cb);
+    EXPECT_TRUE(ret.isOk());
+    std::time_t seed = std::time(nullptr);
+    std::srand(seed);
+    if (s == Status::SUCCESS) {
+        size_t sz = std::max(1, (int)(std::rand() % rails.size()));
+        indices.resize(sz);
+        for (int i = 0; i < sz; i++) {
+            int j = std::rand() % rails.size();
+            indices[i] = rails[j].index;
+            debugString += std::to_string(indices[i]) + ", ";
+        }
+        debugString += "\n";
+        ALOGI("ValidateFilteredPowerData for indices: %s", debugString.c_str());
+        auto cb = [&measurements, &s](hidl_vec<EnergyData> measure, Status status) {
+            measurements = measure;
+            s = status;
+        };
+        Return<void> ret = service_->getEnergyData(indices, cb);
+        EXPECT_TRUE(ret.isOk());
+        if (s == Status::SUCCESS) {
+            /* Make sure that all the measurements are returned */
+            ASSERT_EQ(sz, measurements.size());
+            for (int i = 0; i < measurements.size(); i++) {
+                int j;
+                bool match = false;
+                /* Check that the measurement belongs to the requested index */
+                for (j = 0; j < indices.size(); j++) {
+                    if (indices[j] == measurements[i].index) {
+                        match = true;
+                        break;
+                    }
+                }
+                ASSERT_TRUE(match);
+            }
+        }
+    } else {
+        /* size should be zero is stats is NOT SUCCESS */
+        ASSERT_EQ(rails.size(), 0);
+    }
+}
+
+void readEnergy(sp<IPowerStats> service_, uint32_t timeMs) {
+    std::unique_ptr<MessageQueueSync> mQueue;
+    Status s;
+    uint32_t railsInSample;
+    uint32_t totalSamples;
+    auto cb = [&s, &mQueue, &totalSamples, &railsInSample](
+                  const hardware::MQDescriptorSync<EnergyData>& in, uint32_t numSamples,
+                  uint32_t railsPerSample, Status status) {
+        mQueue.reset(new (std::nothrow) MessageQueueSync(in));
+        s = status;
+        totalSamples = numSamples;
+        railsInSample = railsPerSample;
+    };
+    service_->streamEnergyData(timeMs, 10, cb);
+    if (s == Status::SUCCESS) {
+        ASSERT_NE(nullptr, mQueue);
+        ASSERT_TRUE(mQueue->isValid());
+        bool rc;
+        int sampleCount = 0;
+        uint32_t totalQuants = railsInSample * totalSamples;
+        uint64_t timeout_ns = 10000000000;
+        if (totalSamples > 0) {
+            uint32_t batch = std::max(1, (int)((std::rand() % totalSamples) * railsInSample));
+            ALOGI("Read energy, timsMs: %u, batch: %u", timeMs, batch);
+            std::vector<EnergyData> data(batch);
+            while (sampleCount < totalQuants) {
+                rc = mQueue->readBlocking(&data[0], batch, timeout_ns);
+                if (rc == false) {
+                    break;
+                }
+                sampleCount = sampleCount + batch;
+                if (batch > totalQuants - sampleCount) {
+                    batch = 1;
+                }
+            }
+            ASSERT_EQ(totalQuants, sampleCount);
+        }
+    } else if (s == Status::FILESYSTEM_ERROR) {
+        ASSERT_FALSE(mQueue->isValid());
+        ASSERT_EQ(totalSamples, 0);
+        ASSERT_EQ(railsInSample, 0);
+    } else if (s == Status::NOT_SUPPORTED) {
+        ASSERT_FALSE(mQueue->isValid());
+        ASSERT_EQ(totalSamples, 0);
+        ASSERT_EQ(railsInSample, 0);
+    } else if (s == Status::INVALID_INPUT) {
+        ASSERT_FALSE(mQueue->isValid());
+        ASSERT_EQ(totalSamples, 0);
+        ASSERT_EQ(railsInSample, 0);
+    } else if (s == Status::INSUFFICIENT_RESOURCES) {
+        ASSERT_FALSE(mQueue->isValid());
+        ASSERT_EQ(totalSamples, 0);
+        ASSERT_EQ(railsInSample, 0);
+    }
+}
+
+TEST_F(PowerStatsHidlTest, StreamEnergyData) {
+    std::time_t seed = std::time(nullptr);
+    std::srand(seed);
+    std::thread thread1 = std::thread(readEnergy, service_, std::rand() % 5000);
+    thread1.join();
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(PowerStatsHidlEnv::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    PowerStatsHidlEnv::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
+}  // namespace vts
+}  // namespace stats
+}  // namespace power
+}  // namespace android
diff --git a/radio/1.4/Android.bp b/radio/1.4/Android.bp
index 6257112..ad114f3 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -26,6 +26,8 @@
         "CellConfigLte",
         "CellInfo",
         "CellInfoLte",
+        "DataCallFailCause",
+        "DataConnActiveStatus",
         "DataProfileInfo",
         "DataRegStateResult",
         "EmergencyNumber",
@@ -34,12 +36,14 @@
         "FrequencyRange",
         "LteVopsInfo",
         "NetworkScanResult",
+        "PdpProtocolType",
         "PhysicalChannelConfig",
         "RadioAccessFamily",
         "RadioCapability",
         "RadioFrequencyInfo",
         "RadioTechnology",
         "NrIndicators",
+        "SetupDataCallResult",
     ],
     gen_java: true,
 }
diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal
index c7a2c6b..8438777 100644
--- a/radio/1.4/IRadio.hal
+++ b/radio/1.4/IRadio.hal
@@ -106,6 +106,11 @@
      * Note this API is the same as IRadio.dial except using the
      * @1.4::EmergencyServiceCategory as the input param.
      *
+     * If the number in the 'dialInfo' field is identified as an emergency number in Android,
+     * Android use this request for its emergency call instead of @1.0::IRadio.dial. The
+     * implementation decides how to handle the call (e.g. emergency routing or normal
+     * routing).
+     *
      * If the dialed emergency number does not have a specified emergency service category, the
      * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED; iff either the
      * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED or the underlying
diff --git a/radio/1.4/IRadioIndication.hal b/radio/1.4/IRadioIndication.hal
index fac77f7..626b494 100644
--- a/radio/1.4/IRadioIndication.hal
+++ b/radio/1.4/IRadioIndication.hal
@@ -73,4 +73,18 @@
      */
     oneway currentPhysicalChannelConfigs_1_4(RadioIndicationType type,
             vec<PhysicalChannelConfig> configs);
-};
\ No newline at end of file
+
+    /**
+     * Indicates data call contexts have changed.
+     *
+     * @param type Type of radio indication
+     * @param dcList Array of SetupDataCallResult identical to that returned by
+     *        IRadio.getDataCallList(). It is the complete list of current data contexts including
+     *        new contexts that have been activated. A data call is only removed from this list
+     *        when below conditions matched.
+     *        1. The framework sends a IRadio.deactivateDataCall().
+     *        2. The radio is powered off/on.
+     *        3. Unsolicited disconnect from either modem or network side.
+     */
+    oneway dataCallListChanged_1_4(RadioIndicationType type, vec<SetupDataCallResult> dcList);
+};
diff --git a/radio/1.4/IRadioResponse.hal b/radio/1.4/IRadioResponse.hal
index d9a2bad..df40969 100644
--- a/radio/1.4/IRadioResponse.hal
+++ b/radio/1.4/IRadioResponse.hal
@@ -127,4 +127,41 @@
      *   RadioError:CANCELLED
      */
     oneway setPreferredNetworkTypeBitmapResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dcResponse List of DataCallResult as defined in types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    oneway getDataCallListResponse_1_4(RadioResponseInfo info, vec<SetupDataCallResult> dcResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dcResponse SetupDataCallResult defined in types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE must be returned on both success and failure of setup with the
+     *              DataCallResponse.status containing the actual status
+     *              For all other errors the DataCallResponse is ignored.
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OP_NOT_ALLOWED_BEFORE_REG_TO_NW
+     *   RadioError:OP_NOT_ALLOWED_DURING_VOICE_CALL
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    oneway setupDataCallResponse_1_4(RadioResponseInfo info, SetupDataCallResult dcResponse);
 };
diff --git a/radio/1.4/types.hal b/radio/1.4/types.hal
index 9c4f08c..d0eb0ac 100644
--- a/radio/1.4/types.hal
+++ b/radio/1.4/types.hal
@@ -19,6 +19,7 @@
 import @1.0::ApnAuthType;
 import @1.0::ApnTypes;
 import @1.0::CellInfoType;
+import @1.0::DataCallFailCause;
 import @1.0::DataProfileId;
 import @1.0::DataProfileInfoType;
 import @1.0::RadioAccessFamily;
@@ -54,11 +55,14 @@
  * Emergency number contains information of number, one or more service category(s), mobile country
  * code (mcc), and source(s) that indicate where it comes from.
  *
- * If the source of the emergency number is associated with country, field ‘mcc’ must be
- * provided; otherwise the field ‘mcc’ must be an empty string.
+ * If the source of the emergency number is associated with country, field ‘mcc’ must be provided;
+ * otherwise the field ‘mcc’ must be an empty string.
  *
- * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’ and 'categories' fields.
- * Multiple @1.4::EmergencyNumberSource should be merged into the bitfield for the same
+ * If the source of the emergency number is associated with network operator, field ‘mcc’ and
+ * 'mnc' must be provided; otherwise the field ‘mnc’ must be an empty string.
+ *
+ * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc' and 'categories'
+ * fields. Multiple @1.4::EmergencyNumberSource should be merged into the bitfield for the same
  * EmergencyNumber.
  *
  * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
@@ -74,6 +78,10 @@
      */
     string mcc;
     /**
+     * 2 or 3-digit Mobile Network Code, 0..999. Empty string if not applicable.
+     */
+    string mnc;
+    /**
      * The bitfield of @1.4::EmergencyServiceCategory(s). See @1.4::EmergencyServiceCategory for
      * the value of each bit.
      */
@@ -172,6 +180,1193 @@
     MMWAVE = 4,
 };
 
+/**
+ * Expose more setup data call failures.
+ */
+enum DataCallFailCause : @1.0::DataCallFailCause {
+    /**
+     * Network cannot provide the requested service and PDP context is deactivated because of LLC
+     * or SNDCP failure.
+     */
+    LLC_SNDCP = 0x19,
+    /**
+     * UE requested to modify QoS parameters or the bearer control mode, which is not compatible
+     * with the selected bearer control mode.
+     */
+    ACTIVATION_REJECTED_BCM_VIOLATION = 0x30,
+    /**
+     * Network has already initiated the activation, modification, or deactivation of bearer
+     * resources that was requested by the UE.
+     */
+    COLLISION_WITH_NW_INIT_REQ = 0x38,
+    /**
+     * Network supports IPv4v6 PDP type only. Non-IP type is not allowed. In LTE mode of operation,
+     * this is a PDN throttling cause code, meaning the UE may throttle further requests to the
+     * same APN.
+     */
+    ONLY_IPV4V6_ALLOWED = 0x39,
+    /**
+     * Network supports non-IP PDP type only. IPv4, IPv6 and IPv4v6 is not allowed. In LTE mode of
+     * operation, this is a PDN throttling cause code, meaning the UE can throttle further requests
+     * to the same APN.
+     */
+    ONLY_NON_IP_ALLOWED = 0x3A,
+    /**
+     * QCI indicated in the UE request cannot be supported.
+     */
+    UNSUPPORTED_QCI_VALUE = 0x3B,
+    /**
+     * Procedure requested by the UE was rejected because the bearer handling is not supported.
+     */
+    BEARER_HANDLING_NOT_SUPPORTED = 0x3C,
+    /**
+     * Not receiving a DNS address that was mandatory.
+     */
+    INVALID_DNS_ADDR = 0x7B,
+    /**
+     * Not receiving either a PCSCF or a DNS address, one of them being mandatory.
+     */
+    INVALID_PCSCF_DNS_ADDR = 0x7C,
+    /**
+     * Emergency call bring up on a different ePDG.
+     */
+    CALL_PREEMPT_BY_EMERGENCY_APN = 0x7F,
+    /**
+     * UE performs a detach or disconnect PDN action based on TE requirements.
+     */
+    UE_INIT_DETACH_OR_DISCONNECT = 0x80,
+
+    /**
+     * Reason unspecified for foreign agent rejected MIP registration.
+     */
+    MIP_FA_REASON_UNSPECIFIED = 0x7D0,
+    /**
+     * Foreign agent administratively prohibited MIP registration.
+     */
+    MIP_FA_ADMIN_PROHIBITED = 0x7D1,
+    /**
+     * Foreign agent rejected MIP registration because of insufficient resources.
+     */
+    MIP_FA_INSUFFICIENT_RESOURCES = 0x7D2,
+    /**
+     * Foreign agent rejected MIP registration because of MN-AAA authenticator was wrong.
+     */
+    MIP_FA_MOBILE_NODE_AUTH_FAILURE = 0x7D3,
+    /**
+     * Foreign agent rejected MIP registration because of home agent authentication failure.
+     */
+    MIP_FA_HA_AUTH_FAILURE = 0x7D4,
+    /**
+     * Foreign agent rejected MIP registration because of requested lifetime was too long.
+     */
+    MIP_FA_REQ_LIFETIME_TOO_LONG = 0x7D5,
+    /**
+     * Foreign agent rejected MIP registration because of malformed request.
+     */
+    MIP_FA_MALFORMED_REQUEST = 0x7D6,
+    /**
+     * Foreign agent rejected MIP registration because of malformed reply.
+     */
+    MIP_FA_MALFORMED_REPLY = 0x7D7,
+    /**
+     * Foreign agent rejected MIP registration because of requested encapsulation was unavailable.
+     */
+    MIP_FA_ENCAPSULATION_UNAVAILABLE = 0x7D8,
+    /**
+     * Foreign agent rejected MIP registration of VJ Header Compression was unavailable.
+     */
+    MIP_FA_VJHC_UNAVAILABLE = 0x7D9,
+    /**
+     * Foreign agent rejected MIP registration because of reverse tunnel was unavailable.
+     */
+    MIP_FA_REV_TUNNEL_UNAVAILABLE = 0x7DA,
+    /**
+     * Foreign agent rejected MIP registration because of reverse tunnel was mandatory but not
+     * requested by device.
+     */
+    MIP_FA_REV_TUNNEL_IS_MAND_AND_T_BIT_NOT_SET = 0x7DB,
+    /**
+     * Foreign agent rejected MIP registration because of delivery style was not supported.
+     */
+    MIP_FA_DELIVERY_STYLE_NOT_SUPP = 0x7DC,
+    /**
+     * Foreign agent rejected MIP registration because of missing NAI.
+     */
+    MIP_FA_MISSING_NAI = 0x7DD,
+    /**
+     * Foreign agent rejected MIP registration because of missing Home Agent.
+     */
+    MIP_FA_MISSING_HA = 0x7DE,
+    /**
+     * Foreign agent rejected MIP registration because of missing Home Address.
+     */
+    MIP_FA_MISSING_HOME_ADDR = 0x7DF,
+    /**
+     * Foreign agent rejected MIP registration because of unknown challenge.
+     */
+    MIP_FA_UNKNOWN_CHALLENGE = 0x7E0,
+    /**
+     * Foreign agent rejected MIP registration because of missing challenge.
+     */
+    MIP_FA_MISSING_CHALLENGE = 0x7E1,
+    /**
+     * Foreign agent rejected MIP registration because of stale challenge.
+     */
+    MIP_FA_STALE_CHALLENGE = 0x7E2,
+    /**
+     * Reason unspecified for home agent rejected MIP registration.
+     */
+    MIP_HA_REASON_UNSPECIFIED = 0x7E3,
+    /**
+     * Home agent administratively prohibited MIP registration.
+     */
+    MIP_HA_ADMIN_PROHIBITED = 0x7E4,
+    /**
+     * Home agent rejected MIP registration because of insufficient resources.
+     */
+    MIP_HA_INSUFFICIENT_RESOURCES = 0x7E5,
+    /**
+     * Home agent rejected MIP registration because of MN-HA authenticator was wrong.
+     */
+    MIP_HA_MOBILE_NODE_AUTH_FAILURE = 0x7E6,
+    /**
+     * Home agent rejected MIP registration because of foreign agent authentication failure.
+     */
+    MIP_HA_FA_AUTH_FAILURE = 0x7E7,
+    /**
+     * Home agent rejected MIP registration because of registration id mismatch.
+     */
+    MIP_HA_REGISTRATION_ID_MISMATCH = 0x7E8,
+    /**
+     * Home agent rejected MIP registration because of malformed request.
+     */
+    MIP_HA_MALFORMED_REQUEST = 0x7E9,
+    /**
+     * Home agent rejected MIP registration because of unknown home agent address.
+     */
+    MIP_HA_UNKNOWN_HA_ADDR = 0x7EA,
+    /**
+     * Home agent rejected MIP registration because of reverse tunnel was unavailable.
+     */
+    MIP_HA_REV_TUNNEL_UNAVAILABLE = 0x7EB,
+    /**
+     * Home agent rejected MIP registration because of reverse tunnel is mandatory but not
+     * requested by device.
+     */
+    MIP_HA_REV_TUNNEL_IS_MANDATORY_AND_T_BIT_NOT_SET = 0x7EC,
+    /**
+     * Home agent rejected MIP registration because of encapsulation unavailable.
+     */
+    MIP_HA_ENCAPSULATION_UNAVAILABLE = 0x7ED,
+    /**
+     * Tearing down is in progress.
+     */
+    CLOSE_IN_PROGRESS = 0x7EE,
+    /**
+     * Brought down by the network.
+     */
+    NW_INITIATED_TERMINATION = 0x7EF,
+    /**
+     * Another application in modem preempts the data call.
+     */
+    MODEM_APP_PREEMPTED = 0x7F0,
+    /**
+     * V4 PDN is in throttled state due to network providing only V6 address during the previous
+     * VSNCP bringup (subs_limited_to_v6).
+     */
+    ERR_PDN_IPV4_CALL_DISALLOWED = 0x7F1,
+    /**
+     * V4 PDN is in throttled state due to previous VSNCP bringup failure(s).
+     */
+    ERR_PDN_IPV4_CALL_THROTTLED = 0x7F2,
+    /**
+     * V6 PDN is in throttled state due to network providing only V4 address during the previous
+     * VSNCP bringup (subs_limited_to_v4).
+     */
+    ERR_PDN_IPV6_CALL_DISALLOWED = 0x7F3,
+    /**
+     * V6 PDN is in throttled state due to previous VSNCP bringup failure(s).
+     */
+    ERR_PDN_IPV6_CALL_THROTTLED = 0x7F4,
+    /**
+     * Modem restart.
+     */
+    MODEM_RESTART = 0x7F5,
+    /**
+     * PDP PPP calls are not supported.
+     */
+    PDP_PPP_NOT_SUPPORTED = 0x7F6,
+    /**
+     * RAT on which the data call is attempted/connected is no longer the preferred RAT.
+     */
+    UNPREFERRED_RAT = 0x7F7,
+    /**
+     * Physical link is in the process of cleanup.
+     */
+    PHYS_LINK_CLOSE_IN_PROGRESS = 0x7F8,
+    /**
+     * Interface bring up is attempted for an APN that is yet to be handed over to target RAT.
+     */
+    APN_PENDING_HANDOVER = 0x7F9,
+    /**
+     * APN bearer type in the profile does not match preferred network mode.
+     */
+    PROFILE_BEARER_INCOMPATIBLE = 0x7FA,
+    /**
+     * Card was refreshed or removed.
+     */
+    SIM_CARD_EVT = 0x7FB,
+    /**
+     * Device is going into lower power mode or powering down.
+     */
+    LPM_OR_PWR_DOWN = 0x7FC,
+    /**
+     * APN has been disabled.
+     */
+    APN_DISABLED = 0x7FD,
+    /**
+     * Maximum PPP inactivity timer expired.
+     */
+    MAX_PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE,
+    /**
+     * IPv6 address transfer failed.
+     */
+    IPV6_ADDR_TRANSFER_FAILED = 0x7FF,
+    /**
+     * Target RAT swap failed.
+     */
+    TRAT_SWAP_FAILED = 0x800,
+    /**
+     * Device falls back from eHRPD to HRPD.
+     */
+    EHRPD_TO_HRPD_FALLBACK = 0x801,
+    /**
+     * UE is in MIP-only configuration but the MIP configuration fails on call bring up due to
+     * incorrect provisioning.
+     */
+    MIP_CONFIG_FAILURE = 0x802,
+    /**
+     * PDN inactivity timer expired due to no data transmission in a configurable duration of time.
+     */
+    PDN_INACTIVITY_TIMER_EXPIRED = 0x803,
+    /**
+     * IPv4 data call bring up is rejected because the UE already maintains the allotted maximum
+     * number of IPv4 data connections.
+     */
+    MAX_V4_CONNECTIONS = 0x804,
+    /**
+     * IPv6 data call bring up is rejected because the UE already maintains the allotted maximum
+     * number of IPv6 data connections.
+     */
+    MAX_V6_CONNECTIONS = 0x805,
+    /**
+     * New PDN bring up is rejected during interface selection because the UE has already allotted
+     * the available interfaces for other PDNs.
+     */
+    APN_MISMATCH = 0x806,
+    /**
+     * New call bring up is rejected since the existing data call IP type doesn't match the
+     * requested IP.
+     */
+    IP_VERSION_MISMATCH = 0x807,
+    /**
+     * Dial up networking (DUN) call bring up is rejected since UE is in eHRPD RAT.
+     */
+    DUN_CALL_DISALLOWED = 0x808,
+    /**
+     * Rejected/Brought down since UE is transition between EPC and NONEPC RAT.
+     */
+    INTERNAL_EPC_NONEPC_TRANSITION = 0x809,
+    /**
+     * The current interface is being in use.
+     */
+    IFACE_IN_USE = 0x80A,
+    /**
+     * PDN connection to the APN is disallowed on the roaming network.
+     */
+    APN_DISALLOWED_ON_ROAMING = 0x80C,
+    /**
+     * APN-related parameters are changed.
+     */
+    APN_PARAM_CHANGED = 0x80D,
+    /**
+     * PDN is attempted to be brought up with NULL APN but NULL APN is not supported.
+     */
+    NULL_APN_DISALLOWED = 0x80E,
+    /**
+     * Thermal level increases and causes calls to be torn down when normal mode of operation is
+     * not allowed.
+     */
+    THERMAL_MITIGATION = 0x80F,
+    /**
+     * PDN Connection to a given APN is disallowed because data is disabled from the device user
+     * interface settings.
+     */
+    DATA_SETTINGS_DISABLED = 0x810,
+    /**
+     * PDN Connection to a given APN is disallowed because data roaming is disabled from the device
+     * user interface settings and the UE is roaming.
+     */
+    DATA_ROAMING_SETTINGS_DISABLED = 0x811,
+    /**
+     * Default data subscription switch occurs.
+     */
+    DDS_CALL_ABORT = 0x812,
+    /**
+     * PDN being brought up with an APN that is part of forbidden APN Name list.
+     */
+    INVALID_APN_NAME = 0x813,
+    /**
+     * Default data subscription switch is in progress.
+     */
+    DDS_SWITCH_IN_PROGRESS = 0x814,
+    /**
+     * Roaming is disallowed during call bring up.
+     */
+    CALL_DISALLOWED_IN_ROAMING = 0x815,
+    /**
+     * UE is unable to bring up a non-IP data call because the device is not camped on a NB1 cell.
+     */
+    NON_IP_NOT_SUPPORTED = 0x816,
+    /**
+     * Non-IP PDN is in throttled state due to previous VSNCP bringup failure(s).
+     */
+    ERR_PDN_NON_IP_CALL_THROTTLED = 0x817,
+    /**
+     * Non-IP PDN is in disallowed state due to the network providing only an IP address.
+     */
+    ERR_PDN_NON_IP_CALL_DISALLOWED = 0x818,
+    /**
+     * Device in CDMA locked state.
+     */
+    CDMA_LOCK = 0x819,
+    /**
+     * Received an intercept order from the base station.
+     */
+    CDMA_INTERCEPT = 0x81A,
+    /**
+     * Receiving a reorder from the base station.
+     */
+    CDMA_REORDER = 0x81B,
+    /**
+     * Receiving a release from the base station with a SO Reject reason.
+     */
+    CDMA_REL_SO_REJ = 0x81C,
+    /**
+     * Receiving an incoming call from the base station.
+     */
+    CDMA_INCOM_CALL = 0x81D,
+    /**
+     * RL/FL fade or receiving a call release from the base station.
+     */
+    CDMA_ALERT_STOP = 0x81E,
+    /**
+     * Channel acquisition failures. This indicates that device has failed acquiring all the
+     * channels in the PRL.
+     */
+    CHANNEL_ACQUISITION_FAILURE = 0x81F,
+    /**
+     * Maximum access probes transmitted.
+     */
+    MAX_ACCESS_PROBE = 0x820,
+    /**
+     * Concurrent service is not supported by base station.
+     */
+    CCS_NOT_SUPPORTED_BY_BS = 0x821,
+    /**
+     * There was no response received from the base station.
+     */
+    NO_RESPONSE_FROM_BS = 0x822,
+    /**
+     * The base station rejecting the call.
+     */
+    REJECTED_BY_BS = 0x823,
+    /**
+     * The concurrent services requested were not compatible.
+     */
+    CCS_INCOMPATIBLE = 0x824,
+    /**
+     * Device does not have CDMA service.
+     */
+    NO_CDMA_SRV = 0x825,
+    /**
+     * RUIM not being present.
+     */
+    UIM_NOT_PRESENT = 0x826,
+    /**
+     * Receiving a retry order from the base station.
+     */
+    CDMA_RETRY_ORDER = 0x827,
+    /**
+     * Access blocked by the base station.
+     */
+    ACCESS_BLOCK = 0x828,
+    /**
+     * Access blocked by the base station for all mobile devices.
+     */
+    ACCESS_BLOCK_ALL = 0x829,
+    /**
+     * Maximum access probes for the IS-707B call.
+     */
+    IS707B_MAX_ACC = 0x82A,
+    /**
+     * Put device in thermal emergency.
+     */
+    THERMAL_EMERGENCY = 0x82B,
+    /**
+     * In favor of a voice call or SMS when concurrent voice and data are not supported.
+     */
+    CCS_NOT_ALLOWED = 0x82C,
+    /**
+     * The other clients rejected incoming call.
+     */
+    INCOM_REJ = 0x82D,
+    /**
+     * No service on the gateway.
+     */
+    NO_GATEWAY_SRV = 0x82E,
+    /**
+     * GPRS context is not available.
+     */
+    NO_GPRS_CONTEXT = 0x82F,
+    /**
+     * Network refuses service to the MS because either an identity of the MS is not acceptable to
+     * the network or the MS does not pass the authentication check.
+     */
+    ILLEGAL_MS = 0x830,
+    /**
+     * ME could not be authenticated and the ME used is not acceptable to the network.
+     */
+    ILLEGAL_ME = 0x831,
+    /**
+     * Not allowed to operate either GPRS or non-GPRS services.
+     */
+    GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 0x832,
+    /**
+     * MS is not allowed to operate GPRS services.
+     */
+    GPRS_SERVICES_NOT_ALLOWED = 0x833,
+    /**
+     * No matching identity or context could be found in the network.
+     */
+    MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 0x834,
+    /**
+     * Mobile reachable timer has expired, or the GMM context data related to the subscription dose
+     * not exist in the SGSN.
+     */
+    IMPLICITLY_DETACHED = 0x835,
+    /**
+     * UE requests GPRS service, or the network initiates a detach request in a PLMN which does not
+     * offer roaming for GPRS services to that MS.
+     */
+    PLMN_NOT_ALLOWED = 0x836,
+    /**
+     * MS requests service, or the network initiates a detach request, in a location area where the
+     * HPLMN determines that the MS, by subscription, is not allowed to operate.
+     */
+    LA_NOT_ALLOWED = 0x837,
+    /**
+     * UE requests GPRS service or the network initiates a detach request in a PLMN that does not
+     * offer roaming for GPRS services.
+     */
+    GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 0x838,
+    /**
+     * PDP context already exists.
+     */
+    PDP_DUPLICATE = 0x839,
+    /**
+     * RAT change on the UE.
+     */
+    UE_RAT_CHANGE = 0x83A,
+    /**
+     * Network cannot serve a request from the MS due to congestion.
+     */
+    CONGESTION = 0x83B,
+    /**
+     * MS requests an establishment of the radio access bearers for all active PDP contexts by
+     * sending a service request message indicating data to the network, but the SGSN does not have
+     * any active PDP context.
+     */
+    NO_PDP_CONTEXT_ACTIVATED = 0x83C,
+    /**
+     * Access class blocking restrictions for the current camped cell.
+     */
+    ACCESS_CLASS_DSAC_REJECTION = 0x83D,
+    /**
+     * SM attempts PDP activation for a maximum of four attempts.
+     */
+    PDP_ACTIVATE_MAX_RETRY_FAILED = 0x83E,
+    /**
+     * Radio access bearer failure.
+     */
+    RAB_FAILURE = 0x83F,
+    /**
+     * Invalid EPS bearer identity in the request.
+     */
+    ESM_UNKNOWN_EPS_BEARER_CONTEXT = 0x840,
+    /**
+     * Data radio bearer is released by the RRC.
+     */
+    DRB_RELEASED_AT_RRC = 0x841,
+    /**
+     * Indicate the connection was released.
+     */
+    NAS_SIG_CONN_RELEASED = 0x842,
+    /**
+     * UE is detached.
+     */
+    EMM_DETACHED = 0x843,
+    /**
+     * Attach procedure is rejected by the network.
+     */
+    EMM_ATTACH_FAILED = 0x844,
+    /**
+     * Attach procedure is started for EMC purposes.
+     */
+    EMM_ATTACH_STARTED = 0x845,
+    /**
+     * Service request procedure failure.
+     */
+    LTE_NAS_SERVICE_REQ_FAILED = 0x846,
+    /**
+     * Active dedication bearer was requested using the same default bearer ID.
+     */
+    ESM_ACTIVE_DEDICATED_BEARER_REACTIVATED_BY_NW = 0x847,
+    /**
+     * Collision scenarios for the UE and network-initiated procedures.
+     */
+    ESM_LOWER_LAYER_FAILURE = 0x848,
+    /**
+     * Bearer must be deactivated to synchronize with the network.
+     */
+    ESM_SYNC_UP_WITH_NW = 0x849,
+    /**
+     * Active dedication bearer was requested for an existing default bearer.
+     */
+    ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 0x84A,
+    /**
+     * Bad OTA message is received from the network.
+     */
+    ESM_BAD_OTA_MESSAGE = 0x84B,
+    /**
+     * Download server rejected the call.
+     */
+    ESM_DS_REJECTED_THE_CALL = 0x84C,
+    /**
+     * PDN was disconnected by the downlaod server due to IRAT.
+     */
+    ESM_CONTEXT_TRANSFERED_DUE_TO_IRAT = 0x84D,
+    /**
+     * Dedicated bearer will be deactivated regardless of the network response.
+     */
+    DS_EXPLICIT_DEACT = 0x84E,
+    /**
+     * No specific local cause is mentioned, usually a valid OTA cause.
+     */
+    ESM_LOCAL_CAUSE_NONE = 0x84F,
+    /**
+     * Throttling is not needed for this service request failure.
+     */
+    LTE_NAS_SERVICE_REQ_FAILED_NO_THROTTLE = 0x850,
+    /**
+     * Access control list check failure at the lower layer.
+     */
+    ACCESS_CONTROL_LIST_CHECK_FAILURE = 0x851,
+    /**
+     * Service is not allowed on the requested PLMN.
+     */
+    LTE_NAS_SERVICE_REQ_FAILED_DS_DISALLOW = 0x852,
+    /**
+     * T3417 timer expiration of the service request procedure.
+     */
+    EMM_T3417_EXPIRED = 0x853,
+    /**
+     * Extended service request fails due to expiration of the T3417 EXT timer.
+     */
+    EMM_T3417_EXT_EXPIRED = 0x854,
+    /**
+     * Transmission failure of uplink data.
+     */
+    LRRC_UL_DATA_CNF_FAILURE_TXN = 0x855,
+    /**
+     * Uplink data delivery failed due to a handover.
+     */
+    LRRC_UL_DATA_CNF_FAILURE_HO = 0x856,
+    /**
+     * Uplink data delivery failed due to a connection release.
+     */
+    LRRC_UL_DATA_CNF_FAILURE_CONN_REL = 0x857,
+    /**
+     * Uplink data delivery failed due to a radio link failure.
+     */
+    LRRC_UL_DATA_CNF_FAILURE_RLF = 0x858,
+    /**
+     * RRC is not connected but the NAS sends an uplink data request.
+     */
+    LRRC_UL_DATA_CNF_FAILURE_CTRL_NOT_CONN = 0x859,
+    /**
+     * Connection failure at access stratum.
+     */
+    LRRC_CONN_EST_FAILURE = 0x85A,
+    /**
+     * Connection establishment is aborted due to another procedure.
+     */
+    LRRC_CONN_EST_FAILURE_ABORTED = 0x85B,
+    /**
+     * Connection establishment failed due to a lower layer RRC connection failure.
+     */
+    LRRC_CONN_EST_FAILURE_ACCESS_BARRED = 0x85C,
+    /**
+     * Connection establishment failed due to cell reselection at access stratum.
+     */
+    LRRC_CONN_EST_FAILURE_CELL_RESEL = 0x85D,
+    /**
+     * Connection establishment failed due to configuration failure at the RRC.
+     */
+    LRRC_CONN_EST_FAILURE_CONFIG_FAILURE = 0x85E,
+    /**
+     * Connection could not be established in the time limit.
+     */
+    LRRC_CONN_EST_FAILURE_TIMER_EXPIRED = 0x85F,
+    /**
+     * Connection establishment failed due to a link failure at the RRC.
+     */
+    LRRC_CONN_EST_FAILURE_LINK_FAILURE = 0x860,
+    /**
+     * Connection establishment failed as the RRC is not camped on any cell.
+     */
+    LRRC_CONN_EST_FAILURE_NOT_CAMPED = 0x861,
+    /**
+     * Connection establishment failed due to a service interval failure at the RRC.
+     */
+    LRRC_CONN_EST_FAILURE_SI_FAILURE = 0x862,
+    /**
+     * Connection establishment failed due to the network rejecting the UE connection request.
+     */
+    LRRC_CONN_EST_FAILURE_CONN_REJECT = 0x863,
+    /**
+     * Normal connection release.
+     */
+    LRRC_CONN_REL_NORMAL = 0x864,
+    /**
+     * Connection release failed due to radio link failure conditions.
+     */
+    LRRC_CONN_REL_RLF = 0x865,
+    /**
+     * Connection reestablishment failure.
+     */
+    LRRC_CONN_REL_CRE_FAILURE = 0x866,
+    /**
+     * UE is out of service during the call register.
+     */
+    LRRC_CONN_REL_OOS_DURING_CRE = 0x867,
+    /**
+     * Connection has been released by the RRC due to an abort request.
+     */
+    LRRC_CONN_REL_ABORTED = 0x868,
+    /**
+     * Connection released due to a system information block read error.
+     */
+    LRRC_CONN_REL_SIB_READ_ERROR = 0x869,
+    /**
+     * Network-initiated detach with reattach.
+     */
+    DETACH_WITH_REATTACH_LTE_NW_DETACH = 0x86A,
+    /**
+     * Network-initiated detach without reattach.
+     */
+    DETACH_WITHOUT_REATTACH_LTE_NW_DETACH = 0x86B,
+    /**
+     * ESM procedure maximum attempt timeout failure.
+     */
+    ESM_PROC_TIME_OUT = 0x86C,
+    /**
+     * No PDP exists with the given connection ID while modifying or deactivating or activation for
+     * an already active PDP.
+     */
+    INVALID_CONNECTION_ID = 0x86D,
+    /**
+     * Maximum NSAPIs have been exceeded during PDP activation.
+     */
+    INVALID_NSAPI = 0x86E,
+    /**
+     * Primary context for NSAPI does not exist.
+     */
+    INVALID_PRI_NSAPI = 0x86F,
+    /**
+     * Unable to encode the OTA message for MT PDP or deactivate PDP.
+     */
+    INVALID_FIELD = 0x870,
+    /**
+     * Radio access bearer is not established by the lower layers during activation, modification,
+     * or deactivation.
+     */
+    RAB_SETUP_FAILURE = 0x871,
+    /**
+     * Expiration of the PDP establish timer with a maximum of five retries.
+     */
+    PDP_ESTABLISH_MAX_TIMEOUT = 0x872,
+    /**
+     * Expiration of the PDP modify timer with a maximum of four retries.
+     */
+    PDP_MODIFY_MAX_TIMEOUT = 0x873,
+    /**
+     * Expiration of the PDP deactivate timer with a maximum of four retries.
+     */
+    PDP_INACTIVE_MAX_TIMEOUT = 0x874,
+    /**
+     * PDP activation failed due to RRC_ABORT or a forbidden PLMN.
+     */
+    PDP_LOWERLAYER_ERROR = 0x875,
+    /**
+     * MO PDP modify collision when the MT PDP is already in progress.
+     */
+    PDP_MODIFY_COLLISION = 0x876,
+    /**
+     * Radio resource is not available.
+     */
+    SM_NO_RADIO_AVAILABLE = 0x877,
+    /**
+     * Abort due to service not available.
+     */
+    SM_ABORT_SERVICE_NOT_AVAILABLE = 0x878,
+    /**
+     * Maximum size of the L2 message was exceeded.
+     */
+    MESSAGE_EXCEED_MAX_L2_LIMIT = 0x879,
+    /**
+     * NAS request was rejected by the network.
+     */
+    SM_NAS_SRV_REQ_FAILURE = 0x87A,
+    /**
+     * RRC connection establishment failure due to an error in the request message.
+     */
+    RRC_CONN_EST_FAILURE_REQ_ERROR = 0x87B,
+    /**
+     * RRC connection establishment failure due to a change in the tracking area ID.
+     */
+    RRC_CONN_EST_FAILURE_TAI_CHANGE = 0x87C,
+    /**
+     * RRC connection establishment failure because the RF was unavailable.
+     */
+    RRC_CONN_EST_FAILURE_RF_UNAVAILABLE = 0x87D,
+    /**
+     * Connection was aborted before deactivating the LTE stack due to a successful LX IRAT.
+     * (e.g., after IRAT handovers)
+     */
+    RRC_CONN_REL_ABORTED_IRAT_SUCCESS = 0x87E,
+    /**
+     * If the UE has an LTE radio link failure before security is established, the connection must
+     * be released and the UE must return to idle.
+     */
+    RRC_CONN_REL_RLF_SEC_NOT_ACTIVE = 0x87F,
+    /**
+     * Connection was aborted by the NAS after an IRAT to LTE IRAT handover.
+     */
+    RRC_CONN_REL_IRAT_TO_LTE_ABORTED = 0x880,
+    /**
+     * Connection was aborted before deactivating the LTE stack after a successful LR IRAT cell
+     * change order procedure.
+     */
+    RRC_CONN_REL_IRAT_FROM_LTE_TO_G_CCO_SUCCESS = 0x881,
+    /**
+     * Connection was aborted in the middle of a LG IRAT cell change order.
+     */
+    RRC_CONN_REL_IRAT_FROM_LTE_TO_G_CCO_ABORTED = 0x882,
+    /**
+     * IMSI present in the UE is unknown in the home subscriber server.
+     */
+    IMSI_UNKNOWN_IN_HSS = 0x883,
+    /**
+     * IMEI of the UE is not accepted by the network.
+     */
+    IMEI_NOT_ACCEPTED = 0x884,
+    /**
+     * EPS and non-EPS services are not allowed by the network.
+     */
+    EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 0x885,
+    /**
+     * EPS services are not allowed in the PLMN.
+     */
+    EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 0x886,
+    /**
+     * Mobile switching center is temporarily unreachable.
+     */
+    MSC_TEMPORARILY_NOT_REACHABLE = 0x887,
+    /**
+     * CS domain is not available.
+     */
+    CS_DOMAIN_NOT_AVAILABLE = 0x888,
+    /**
+     * ESM level failure.
+     */
+    ESM_FAILURE = 0x889,
+    /**
+     * MAC level failure.
+     */
+    MAC_FAILURE = 0x88A,
+    /**
+     * Synchronization failure.
+     */
+    SYNCH_FAILURE = 0x88B,
+    /**
+     * UE security capabilities mismatch.
+     */
+    UE_SECURITY_CAPABILITIES_MISMATCH = 0x88C,
+    /**
+     * Unspecified security mode reject.
+     */
+    SECURITY_MODE_REJ_UNSPECIFIED = 0x88D,
+    /**
+     * Unacceptable non-EPS authentication.
+     */
+    NON_EPS_AUTH_UNACCEPTABLE = 0x88E,
+    /**
+     * CS fallback call establishment is not allowed.
+     */
+    CS_FALLBACK_CALL_EST_NOT_ALLOWED = 0x88F,
+    /**
+     * No EPS bearer context was activated.
+     */
+    NO_EPS_BEARER_CONTEXT_ACTIVATED = 0x890,
+    /**
+     * Invalid EMM state.
+     */
+    EMM_INVALID_STATE = 0x891,
+    /**
+     * Non-Access Spectrum layer failure.
+     */
+    NAS_LAYER_FAILURE = 0x892,
+    /**
+     * Multiple PDP call feature is disabled.
+     */
+    MULTI_PDN_NOT_ALLOWED = 0x893,
+    /**
+     * Data call has been brought down because EMBMS is not enabled at the RRC layer.
+     */
+    EMBMS_NOT_ENABLED = 0x894,
+    /**
+     * Data call was unsuccessfully transferred during the IRAT handover.
+     */
+    PENDING_REDIAL_CALL_CLEANUP = 0x895,
+    /**
+     * EMBMS data call has been successfully brought down.
+     */
+    EMBMS_REGULAR_DEACTIVATION = 0x896,
+    /**
+     * Test loop-back data call has been successfully brought down.
+     */
+    TLB_REGULAR_DEACTIVATION = 0x897,
+    /**
+     * Lower layer registration failure.
+     */
+    LOWER_LAYER_REGISTRATION_FAILURE = 0x898,
+    /**
+     * Network initiates a detach on LTE with error cause ""data plan has been replenished or has
+     * expired.
+     */
+    DETACH_EPS_SERVICES_NOT_ALLOWED = 0x899,
+    /**
+     * UMTS interface is brought down due to handover from UMTS to iWLAN.
+     */
+    SM_INTERNAL_PDP_DEACTIVATION = 0x89A,
+    /**
+     * The reception of a connection deny message with a deny code of general or network busy.
+     */
+    CD_GEN_OR_BUSY = 0x89B,
+    /**
+     * The reception of a connection deny message with a deny code of billing failure or
+     * authentication failure.
+     */
+    CD_BILL_OR_AUTH = 0x89C,
+    /**
+     * HDR system has been changed due to redirection or the PRL was not preferred.
+     */
+    HDR_CHANGED = 0x89D,
+    /**
+     * Device exited HDR due to redirection or the PRL was not preferred.
+     */
+    HDR_EXITED = 0x89E,
+    /**
+     * Device does not have an HDR session.
+     */
+    HDR_NO_SESSION = 0x89F,
+    /**
+     * It is ending an HDR call origination in favor of a GPS fix.
+     */
+    HDR_ORIG_DURING_GPS_FIX = 0x8A0,
+    /**
+     * Connection setup on the HDR system was time out.
+     */
+    HDR_CS_TIMEOUT = 0x8A1,
+    /**
+     * Device failed to acquire a co-located HDR for origination.
+     */
+    COLLOC_ACQ_FAIL = 0x8A2,
+    /**
+     * OTASP commit is in progress.
+     */
+    OTASP_COMMIT_IN_PROG = 0x8A3,
+    /**
+     * Device has no hybrid HDR service.
+     */
+    NO_HYBR_HDR_SRV = 0x8A4,
+    /**
+     * HDR module could not be obtained because of the RF locked.
+     */
+    HDR_NO_LOCK_GRANTED = 0x8A5,
+    /**
+     * DBM or SMS is in progress.
+     */
+    HOLD_OTHER_IN_PROG = 0x8A6,
+    /**
+     * HDR module released the call due to fade.
+     */
+    HDR_FADE = 0x8A7,
+    /**
+     * HDR system access failure.
+     */
+    HDR_ACC_FAIL = 0x8A8,
+    /**
+     * P_rev supported by 1 base station is less than 6, which is not supported for a 1X data call.
+     * The UE must be in the footprint of BS which has p_rev >= 6 to support this SO33 call.
+     */
+    UNSUPPORTED_1X_PREV = 0x8A9,
+    /**
+     * Client ended the data call.
+     */
+    LOCAL_END = 0x8AA,
+    /**
+     * Device has no service.
+     */
+    NO_SRV = 0x8AB,
+    /**
+     * Device lost the system due to fade.
+     */
+    FADE = 0x8AC,
+    /**
+     * Receiving a release from the base station with no reason.
+     */
+    REL_NORMAL = 0x8AD,
+    /**
+     * Access attempt is already in progress.
+     */
+    ACC_IN_PROG = 0x8AE,
+    /**
+     * Access failure.
+     */
+    ACC_FAIL = 0x8AF,
+    /**
+     * Device is in the process of redirecting or handing off to a different target system.
+     */
+    REDIR_OR_HANDOFF = 0x8B0,
+    /**
+     * Device is operating in Emergency mode.
+     */
+    EMERGENCY_MODE = 0x8B1,
+    /**
+     * Device is in use (e.g., voice call).
+     */
+    PHONE_IN_USE = 0x8B2,
+    /**
+     * Device operational mode is different from the mode requested in the traffic channel bring up
+     */
+    INVALID_MODE = 0x8B3,
+    /**
+     * SIM was marked by the network as invalid for the circuit and/or packet service domain.
+     */
+    INVALID_SIM_STATE = 0x8B4,
+    /**
+     * There is no co-located HDR.
+     */
+    NO_COLLOC_HDR = 0x8B5,
+    /**
+     * UE is entering power save mode.
+     */
+    EMM_DETACHED_PSM = 0x8B6,
+    /**
+     * Dual switch from single standby to dual standby is in progress.
+     */
+    DUAL_SWITCH = 0x8B7,
+    /**
+     * Data call bring up fails in the PPP setup due to a timeout.
+     * (e.g., an LCP conf ack was not received from the network)
+     */
+    PPP_TIMEOUT = 0x8B8,
+    /**
+     * Data call bring up fails in the PPP setup due to an authorization failure.
+     * (e.g., authorization is required, but not negotiated with the network during an LCP phase)
+     */
+    PPP_AUTH_FAILURE = 0x8B9,
+    /**
+     * Data call bring up fails in the PPP setup due to an option mismatch.
+     */
+    PPP_OPTION_MISMATCH = 0x8BA,
+    /**
+     * Data call bring up fails in the PPP setup due to a PAP failure.
+     */
+    PPP_PAP_FAILURE = 0x8BB,
+    /**
+     * Data call bring up fails in the PPP setup due to a CHAP failure.
+     */
+    PPP_CHAP_FAILURE = 0x8BC,
+    /**
+     * Data call bring up fails in the PPP setup because the PPP is in the process of cleaning the
+     * previous PPP session.
+     */
+    PPP_ERR_CLOSE_IN_PROGRESS = 0x8BD,
+    /**
+     * IPv6 interface bring up fails because the network provided only the IPv4 address for the
+     * upcoming PDN permanent client can reattempt a IPv6 call bring up after the IPv4 interface is
+     * also brought down. However, there is no guarantee that the network will provide a IPv6
+     * address.
+     */
+    EHRPD_SUBS_LIMITED_TO_V4 = 0x8BE,
+    /**
+     * IPv4 interface bring up fails because the network provided only the IPv6 address for the
+     * upcoming PDN permanent client can reattempt a IPv4 call bring up after the IPv6 interface is
+     * also brought down. However there is no guarantee that the network will provide a IPv4
+     * address.
+     */
+    EHRPD_SUBS_LIMITED_TO_V6 = 0x8BF,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a VSNCP timeout error.
+     */
+    EHRPD_VSNCP_TIMEOUT = 0x8C0,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a general error
+     */
+    EHRPD_VSNCP_GEN_ERROR = 0x8C1,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the requested APN is unauthorized.
+     */
+    EHRPD_VSNCP_UNAUTH_APN = 0x8C2,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN limit has been exceeded.
+     */
+    EHRPD_VSNCP_PDN_LIMIT_EXCEED = 0x8C3,
+    /**
+     * Data call bring up fails in the VSNCP phase because the network rejected the VSNCP
+     * configuration request due to no PDN gateway.
+     */
+    EHRPD_VSNCP_NO_PDN_GW = 0x8C4,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN gateway is unreachable.
+     */
+    EHRPD_VSNCP_PDN_GW_UNREACH = 0x8C5,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request due to a PDN gateway reject.
+     */
+    EHRPD_VSNCP_PDN_GW_REJ = 0x8C6,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of insufficient parameter.
+     */
+    EHRPD_VSNCP_INSUFF_PARAM = 0x8C7,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of resource unavailable.
+     */
+    EHRPD_VSNCP_RESOURCE_UNAVAIL = 0x8C8,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of admin prohibited.
+     */
+    EHRPD_VSNCP_ADMIN_PROHIBIT = 0x8C9,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of PDN ID in use, or
+     * all existing PDNs are brought down with this end reason because one of the PDN bring up was
+     * rejected by the network with the reason of PDN ID in use.
+     */
+    EHRPD_VSNCP_PDN_ID_IN_USE = 0x8CA,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request for the reason of subscriber limitation.
+     */
+    EHRPD_VSNCP_SUBSCR_LIMITATION = 0x8CB,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN exists for this APN.
+     */
+    EHRPD_VSNCP_PDN_EXISTS_FOR_THIS_APN = 0x8CC,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with reconnect to this PDN not allowed, or an active data call is
+     * terminated by the network because reconnection to this PDN is not allowed. Upon receiving
+     * this error code from the network, the modem infinitely throttles the PDN until the next
+     * power cycle.
+     */
+    EHRPD_VSNCP_RECONNECT_NOT_ALLOWED = 0x8CD,
+    /**
+     * Device failure to obtain the prefix from the network.
+     */
+    IPV6_PREFIX_UNAVAILABLE = 0x8CE,
+    /**
+     * System preference change back to SRAT during handoff
+     */
+    HANDOFF_PREF_SYS_BACK_TO_SRAT = 0x8CF,
+};
+
+/**
+ * Data connection active status
+ */
+enum DataConnActiveStatus : int32_t {
+    /**
+     * Indicates the data connection is inactive.
+     */
+    INACTIVE = 0,
+    /**
+     * Indicates the data connection is active with physical link dormant.
+     */
+    DORMANT = 1,
+    /**
+     * Indicates the data connection is active with physical link up.
+     */
+    ACTIVE = 2,
+};
+
+/**
+ * Specifies the type of packet data protocol which is defined in TS 27.007 section 10.1.1.
+ */
+enum PdpProtocolType : int32_t {
+    /**
+     * Unknown protocol
+     */
+    UNKNOWN = -1,
+    /**
+     * Internet protocol
+     */
+    IP = 0,
+    /**
+     * Internet protocol, version 6
+     */
+    IPV6 = 1,
+    /**
+     * Virtual PDP type introduced to handle dual IP stack UE capability.
+     */
+    IPV4V6 = 2,
+    /**
+     * Point to point protocol
+     */
+    PPP = 3,
+    /**
+     * Transfer of Non-IP data to external packet data network
+     */
+    NON_IP = 4,
+    /**
+     * Ethernet protocol
+     */
+    ETHERNET = 5,
+    /**
+     * Transfer of Unstructured data to the Data Network via N6
+     */
+    UNSTRUCTURED = 6,
+};
+
 safe_union RadioFrequencyInfo {
     /** A rough frequency range. */
     FrequencyRange range;
@@ -191,7 +1386,7 @@
 
     /**
      * A list of data calls mapped to this physical channel. The context id must match the cid of
-     * @1.0::SetupDataCallResult. An empty list means the physical channel has no data call mapped
+     * @1.4::SetupDataCallResult. An empty list means the physical channel has no data call mapped
      * to it.
      */
     vec<int32_t> contextIds;
@@ -354,17 +1549,11 @@
     /** The APN name */
     string apn;
 
-    /**
-     * One of the PDP_type values in TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6",
-     * or "PPP".
-     */
-    string protocol;
+    /** PDP_type values */
+    PdpProtocolType protocol;
 
-    /**
-     * one of the PDP_type values in TS 27.007 section 10.1.1 used on roaming network. For example,
-     * "IP", "IPV6", "IPV4V6", or "PPP".
-     */
-    string roamingProtocol;
+    /** PDP_type values used on roaming network */
+    PdpProtocolType roamingProtocol;
 
     /** APN authentication type */
     ApnAuthType authType;
@@ -446,3 +1635,68 @@
 
     RadioCapabilityStatus status;
 };
+
+/**
+ * Overwritten from @1.0::SetupDataCallResult in order to update the DataCallFailCause to 1.4
+ * version.
+ */
+struct SetupDataCallResult {
+    /** Data call fail cause. DataCallFailCause.NONE if no error. */
+    DataCallFailCause cause;
+
+    /**
+     * If status != DataCallFailCause.NONE, this field indicates the suggested retry back-off timer
+     * value RIL wants to override the one pre-configured in FW. The unit is milliseconds.
+     * The value < 0 means no value is suggested.
+     * The value 0 means retry must be done ASAP.
+     * The value of INT_MAX(0x7fffffff) means no retry.
+     */
+    int32_t suggestedRetryTime;
+
+    /** Context ID, uniquely identifies this call. */
+    int32_t cid;
+
+    /** Data connection active status. */
+    DataConnActiveStatus active;
+
+    /**
+     * PDP_type values. If cause is DataCallFailCause.ONLY_SINGLE_BEARER_ALLOWED, this is the type
+     * supported such as "IP" or "IPV6".
+     */
+    PdpProtocolType type;
+
+    /** The network interface name. */
+    string ifname;
+
+    /**
+     * List of addresses with optional "/" prefix length, e.g., "192.0.1.3" or
+     * "192.0.1.11/16 2001:db8::1/64".  Typically one IPv4 or one IPv6 or one of each. If the
+     * prefix length is absent the addresses are assumed to be point to point with IPv4 having a
+     * prefix length of 32 and IPv6 128.
+     */
+    vec<string> addresses;
+
+    /**
+     * List of DNS server addresses, e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1". Empty if no dns
+     * server addresses returned.
+     */
+    vec<string> dnses;
+
+    /**
+     * List of default gateway addresses, e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1".
+     * When empty, the addresses represent point to point connections.
+     */
+    vec<string> gateways;
+
+    /**
+     * List of P-CSCF(Proxy Call State Control Function) addresses via PCO(Protocol Configuration
+     * Option), e.g., "2001:db8::1 2001:db8::2 2001:db8::3". Empty if not IMS client.
+     */
+    vec<string> pcscf;
+
+    /**
+     * MTU received from network. Value <= 0 means network has either not sent a value or sent an
+     * invalid value.
+     */
+    int32_t mtu;
+};