Merge "Define EventQueueFlagBits"
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 88ab796..3a7c284 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -29,6 +29,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <hwbinder/IPCThreadState.h>
+
 #include <VtsHalHidlTargetTestBase.h>
 
 #include <android-base/logging.h>
@@ -63,6 +65,7 @@
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::IPCThreadState;
 using ::android::hardware::kSynchronizedReadWrite;
 using ::android::hardware::MessageQueue;
 using ::android::hardware::MQDescriptorSync;
@@ -170,15 +173,25 @@
 
 TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
     doc::test("Calling openDevice(\"primary\") should return the primary device.");
-    Result result;
-    sp<IDevice> baseDevice;
-    ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
-    ASSERT_OK(result);
-    ASSERT_TRUE(baseDevice != nullptr);
+    {
+        Result result;
+        sp<IDevice> baseDevice;
+        ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
+        ASSERT_OK(result);
+        ASSERT_TRUE(baseDevice != nullptr);
 
-    Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
-    ASSERT_TRUE(primaryDevice.isOk());
-    ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+        Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+        ASSERT_TRUE(primaryDevice.isOk());
+        ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+    }  // Destroy local IDevice proxy
+    // FIXME: there is no way to know when the remote IDevice is being destroyed
+    //        Binder does not support testing if an object is alive, thus
+    //        wait for 100ms to let the binder destruction propagates and
+    //        the remote device has the time to be destroyed.
+    //        flushCommand makes sure all local command are sent, thus should reduce
+    //        the latency between local and remote destruction.
+    IPCThreadState::self()->flushCommands();
+    usleep(100);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/current.txt b/current.txt
index 4e5ec41..d41d8d3 100644
--- a/current.txt
+++ b/current.txt
@@ -388,8 +388,10 @@
 a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types
 5f936a5befde7af8d2a683670f80a836b4741e94d84b7b39026da3ed78be9906 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
-1a5ae9793223658174258b523763c557abad6fb917df0b8e3cc097fc89035811 android.hardware.neuralnetworks@1.0::types
-4310eb8272f085914952f3bfb73a8f8bb477a80e8b93596f0ea5acb58546b66d android.hardware.neuralnetworks@1.1::types
+1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types
+e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types
+810b03825c633b21982871a8aa690db94285947fca71881de71bf293ad0aa9c5 android.hardware.neuralnetworks@1.2::types
+79f3820a02f37bb0f84bca1a07900fd5bd819ec5a60ed14b205e1dc5e24a51b2 android.hardware.neuralnetworks@1.2::IDevice
 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse
 271187e261b30c01a33011aea257c07a2d2f05b72943ebee89e973e997849973 android.hardware.radio@1.0::types
 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal
index 653fd79..5e42c17 100644
--- a/fastboot/1.0/IFastboot.hal
+++ b/fastboot/1.0/IFastboot.hal
@@ -29,4 +29,14 @@
      *     reformatting.
      */
     getPartitionType(string partitionName) generates (FileSystemType type, Result result);
+
+    /**
+     * Executes a fastboot OEM command.
+     *
+     * @param oemCmdArgs The oem command that is passed to the fastboot HAL.
+     * @response result Returns the status SUCCESS if the operation is successful,
+     *     INVALID_ARGUMENT for bad arguments,
+     *     FAILURE_UNKNOWN for an invalid/unsupported command.
+     */
+    doOemCommand(string oemCmd) generates (Result result);
 };
diff --git a/fastboot/1.0/types.hal b/fastboot/1.0/types.hal
index 8453deb..3fbe639 100644
--- a/fastboot/1.0/types.hal
+++ b/fastboot/1.0/types.hal
@@ -53,9 +53,9 @@
 struct Result {
     Status status;
     /**
-     * Error message pertaining to the status. It must be a failure message for
+     * Message pertaining to the status. It must be a failure message for
      * Status FAILURE_UNKNOWN/NOT_SUPPORTED or an informative message for
      * Status SUCCESS.
      */
-    string error;
+    string message;
 };
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 8b8c7ae..0a3e88b 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -71,6 +71,7 @@
 class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    protected:
     void SetUp() override {
+        VtsHalHidlTargetTestBase::SetUp();
         ASSERT_NO_FATAL_FAILURE(
             mComposer = std::make_unique<Composer>(
                 GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
@@ -100,6 +101,7 @@
             EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
             EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
         }
+        VtsHalHidlTargetTestBase::TearDown();
     }
 
     // returns an invalid display id (one that has not been registered to a
@@ -668,6 +670,11 @@
 
         ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
+        Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
+        mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                             IComposerClient::Attribute::WIDTH);
+        mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                              IComposerClient::Attribute::HEIGHT);
         mWriter = std::make_unique<CommandWriterBase>(1024);
         mReader = std::make_unique<TestCommandReader>();
     }
@@ -679,12 +686,13 @@
 
     const native_handle_t* allocate() {
         IMapper::BufferDescriptorInfo info{};
-        info.width = 64;
-        info.height = 64;
+        info.width = mDisplayWidth;
+        info.height = mDisplayHeight;
         info.layerCount = 1;
         info.format = PixelFormat::RGBA_8888;
         info.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
+                                  BufferUsage::COMPOSER_OVERLAY);
 
         return mGralloc->allocate(info);
     }
@@ -693,6 +701,8 @@
 
     std::unique_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<TestCommandReader> mReader;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
 
    private:
     std::unique_ptr<Gralloc> mGralloc;
@@ -779,6 +789,60 @@
 }
 
 /**
+ * Test IComposerClient::Command::PRESENT_DISPLAY
+ *
+ * Test that IComposerClient::Command::PRESENT_DISPLAY works without
+ * additional call to validateDisplay when only the layer buffer handle and
+ * surface damage have been set
+ */
+TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) {
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON);
+    mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB);
+
+    auto handle = allocate();
+    ASSERT_NE(nullptr, handle);
+
+    IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+    mWriter->setLayerDisplayFrame(displayFrame);
+    mWriter->setLayerPlaneAlpha(1);
+    mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+    mWriter->setLayerTransform(static_cast<Transform>(0));
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, displayFrame));
+    mWriter->setLayerZOrder(10);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
+    mWriter->setLayerBuffer(0, handle, -1);
+    mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        GTEST_SUCCEED() << "Composition change requested, skipping test";
+        return;
+    }
+
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->selectLayer(layer);
+    auto handle2 = allocate();
+    ASSERT_NE(nullptr, handle2);
+    mWriter->setLayerBuffer(0, handle2, -1);
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
+    mWriter->presentDisplay();
+    execute();
+}
+
+/**
  * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
diff --git a/health/storage/1.0/default/Android.bp b/health/storage/1.0/default/Android.bp
new file mode 100644
index 0000000..4723443
--- /dev/null
+++ b/health/storage/1.0/default/Android.bp
@@ -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.
+ */
+
+cc_binary {
+    name: "android.hardware.health.storage@1.0-service",
+    vendor: true,
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.health.storage@1.0-service.rc"],
+    srcs: [
+        "Storage.cpp",
+        "service.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.health.storage@1.0",
+    ],
+
+    static_libs: [
+        "libfstab",
+    ],
+
+    vintf_fragments: [
+        "manifest_android.hardware.health.storage@1.0.xml",
+    ],
+}
diff --git a/health/storage/1.0/default/Storage.cpp b/health/storage/1.0/default/Storage.cpp
new file mode 100644
index 0000000..2e53c50
--- /dev/null
+++ b/health/storage/1.0/default/Storage.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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 "Storage.h"
+
+#include <sstream>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fstab/fstab.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
+
+using base::ReadFileToString;
+using base::Timer;
+using base::Trim;
+using base::WriteStringToFd;
+using base::WriteStringToFile;
+
+std::string getGarbageCollectPath() {
+    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+                                                               fs_mgr_free_fstab);
+    struct fstab_rec* rec = NULL;
+
+    for (int i = 0; i < fstab->num_entries; i++) {
+        if (fs_mgr_has_sysfs_path(&fstab->recs[i])) {
+            rec = &fstab->recs[i];
+            break;
+        }
+    }
+    if (!rec) {
+        return "";
+    }
+
+    std::string path;
+    path.append(rec->sysfs_path);
+    path = path + "/manual_gc";
+
+    return path;
+}
+
+Return<void> Storage::garbageCollect(uint64_t timeoutSeconds,
+                                     const sp<IGarbageCollectCallback>& cb) {
+    Result result = Result::SUCCESS;
+    std::string path = getGarbageCollectPath();
+
+    if (path.empty()) {
+        LOG(WARNING) << "Cannot find Dev GC path";
+        result = Result::UNKNOWN_ERROR;
+    } else {
+        Timer timer;
+        LOG(INFO) << "Start Dev GC on " << path;
+        while (1) {
+            std::string require;
+            if (!ReadFileToString(path, &require)) {
+                PLOG(WARNING) << "Reading manual_gc failed in " << path;
+                result = Result::IO_ERROR;
+                break;
+            }
+            require = Trim(require);
+            if (require == "" || require == "off" || require == "disabled") {
+                LOG(DEBUG) << "No more to do Dev GC";
+                break;
+            }
+            LOG(DEBUG) << "Trigger Dev GC on " << path;
+            if (!WriteStringToFile("1", path)) {
+                PLOG(WARNING) << "Start Dev GC failed on " << path;
+                result = Result::IO_ERROR;
+                break;
+            }
+            if (timer.duration() >= std::chrono::seconds(timeoutSeconds)) {
+                LOG(WARNING) << "Dev GC timeout";
+                // Timeout is not treated as an error. Try next time.
+                break;
+            }
+            sleep(2);
+        }
+        LOG(INFO) << "Stop Dev GC on " << path;
+        if (!WriteStringToFile("0", path)) {
+            PLOG(WARNING) << "Stop Dev GC failed on " << path;
+            result = Result::IO_ERROR;
+        }
+    }
+
+    if (cb != nullptr) {
+        auto ret = cb->onFinish(result);
+        if (!ret.isOk()) {
+            LOG(WARNING) << "Cannot return result to callback: " << ret.description();
+        }
+    }
+    return Void();
+}
+
+Return<void> Storage::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
+    if (handle == nullptr || handle->numFds < 1) {
+        return Void();
+    }
+
+    int fd = handle->data[0];
+    std::stringstream output;
+
+    std::string path = getGarbageCollectPath();
+    if (path.empty()) {
+        output << "Cannot find Dev GC path";
+    } else {
+        std::string require;
+
+        if (ReadFileToString(path, &require)) {
+            output << path << ":" << require << std::endl;
+        }
+
+        if (WriteStringToFile("0", path)) {
+            output << "stop success" << std::endl;
+        }
+    }
+
+    if (!WriteStringToFd(output.str(), fd)) {
+        PLOG(WARNING) << "debug: cannot write to fd";
+    }
+
+    fsync(fd);
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace storage
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
diff --git a/health/storage/1.0/default/Storage.h b/health/storage/1.0/default/Storage.h
new file mode 100644
index 0000000..8c57ddb
--- /dev/null
+++ b/health/storage/1.0/default/Storage.h
@@ -0,0 +1,49 @@
+/*
+ * 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_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+#define ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+struct Storage : public IStorage {
+    Return<void> garbageCollect(uint64_t timeoutSeconds,
+                                const sp<IGarbageCollectCallback>& cb) override;
+    Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace storage
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
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
new file mode 100644
index 0000000..c6a1425
--- /dev/null
+++ b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
@@ -0,0 +1,5 @@
+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
+    class hal
+    user system
+    group system
diff --git a/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml b/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml
new file mode 100644
index 0000000..ffe854e
--- /dev/null
+++ b/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal>
+        <name>android.hardware.health.storage</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/health/storage/1.0/default/service.cpp b/health/storage/1.0/default/service.cpp
new file mode 100644
index 0000000..a945033
--- /dev/null
+++ b/health/storage/1.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 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 <hidl/HidlTransportSupport.h>
+#include "Storage.h"
+
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::UNKNOWN_ERROR;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::health::storage::V1_0::IStorage;
+using android::hardware::health::storage::V1_0::implementation::Storage;
+
+int main() {
+    configureRpcThreadpool(1, true);
+
+    sp<IStorage> service = new Storage();
+    status_t result = service->registerAsService();
+
+    if (result != OK) {
+        return result;
+    }
+
+    joinRpcThreadpool();
+    return UNKNOWN_ERROR;
+}
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..63591cf
--- /dev/null
+++ b/health/storage/1.0/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: "VtsHalHealthStorageV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
+    static_libs: ["android.hardware.health.storage@1.0"],
+    shared_libs: [
+        "libhidltransport"
+    ],
+}
+
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
new file mode 100644
index 0000000..5ad561c
--- /dev/null
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/HidlTransportSupport.h>
+#include <unistd.h>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+
+using ::std::literals::chrono_literals::operator""ms;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.description()
+
+// Dev GC timeout. This is the timeout used by vold.
+const uint64_t kDevGcTimeoutSec = 120;
+const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
+// Time accounted for RPC calls.
+const std::chrono::milliseconds kRpcTime{100};
+
+template <typename R>
+std::string toString(std::chrono::duration<R, std::milli> time) {
+    return std::to_string(time.count()) + "ms";
+}
+
+/** An atomic boolean flag that indicates whether a task has finished. */
+class Flag {
+   public:
+    void onFinish() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        onFinishLocked(&lock);
+    }
+    template <typename R, typename P>
+    bool wait(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        return waitLocked(&lock, duration);
+    }
+
+   protected:
+    /** Will unlock. */
+    void onFinishLocked(std::unique_lock<std::mutex>* lock) {
+        mFinished = true;
+        lock->unlock();
+        mCv.notify_all();
+    }
+    template <typename R, typename P>
+    bool waitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
+        mCv.wait_for(*lock, duration, [this] { return mFinished; });
+        return mFinished;
+    }
+
+    bool mFinished{false};
+    std::mutex mMutex;
+    std::condition_variable mCv;
+};
+
+class GcCallback : public IGarbageCollectCallback, public Flag {
+   public:
+    Return<void> onFinish(Result result) override {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mResult = result;
+        Flag::onFinishLocked(&lock);
+        return Void();
+    }
+
+    /**
+     * Wait for a specific "timeout". If GC has finished, test that the result
+     * is equal to the "expected" value.
+     */
+    template <typename R, typename P>
+    void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        if (waitLocked(&lock, timeout)) {
+            EXPECT_EQ(expected, mResult);
+        } else {
+            LOG(INFO) << "timeout after " << toString(timeout);
+        }
+    }
+
+   private:
+    Result mResult{Result::UNKNOWN_ERROR};
+};
+
+/** Test environment for Health Storage HIDL HAL. */
+class HealthStorageHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    /** get the test environment singleton */
+    static HealthStorageHidlEnvironment* Instance() {
+        static HealthStorageHidlEnvironment* instance = new HealthStorageHidlEnvironment();
+        return instance;
+    }
+    virtual void registerTestServices() override { registerTestService<IStorage>(); }
+
+   private:
+    HealthStorageHidlEnvironment() {}
+};
+
+class HealthStorageHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        fs = ::testing::VtsHalHidlTargetTestBase::getService<IStorage>(
+            HealthStorageHidlEnvironment::Instance()->getServiceName<IStorage>());
+
+        ASSERT_NE(fs, nullptr);
+        LOG(INFO) << "Service is remote " << fs->isRemote();
+    }
+
+    virtual void TearDown() override {
+        EXPECT_TRUE(ping(kRpcTime))
+            << "Service is not responsive; expect subsequent tests to fail.";
+    }
+
+    /**
+     * Ping the service and expect it to return after "timeout". Return true
+     * iff the service is responsive within "timeout".
+     */
+    template <typename R, typename P>
+    bool ping(std::chrono::duration<R, P> timeout) {
+        // Ensure the service is responsive after the test.
+        sp<IStorage> service = fs;
+        auto pingFlag = std::make_shared<Flag>();
+        std::thread([service, pingFlag] {
+            service->ping();
+            pingFlag->onFinish();
+        })
+            .detach();
+        return pingFlag->wait(timeout);
+    }
+
+    sp<IStorage> fs;
+};
+
+/**
+ * Ensure garbage collection works on null callback.
+ */
+TEST_F(HealthStorageHidlTest, GcNullCallback) {
+    auto ret = fs->garbageCollect(kDevGcTimeoutSec, nullptr);
+
+    ASSERT_OK(ret);
+
+    // Hold test process because HAL can be single-threaded and doing GC.
+    ASSERT_TRUE(ping(kDevGcTimeout + kRpcTime))
+        << "Service must be available after " << toString(kDevGcTimeout + kRpcTime);
+}
+
+/**
+ * Ensure garbage collection works on non-null callback.
+ */
+TEST_F(HealthStorageHidlTest, GcNonNullCallback) {
+    sp<GcCallback> cb = new GcCallback();
+    auto ret = fs->garbageCollect(kDevGcTimeoutSec, cb);
+    ASSERT_OK(ret);
+    cb->waitForResult(kDevGcTimeout + kRpcTime, Result::SUCCESS);
+}
+
+}  // namespace V1_0
+}  // namespace storage
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    using ::android::hardware::configureRpcThreadpool;
+    using ::android::hardware::health::storage::V1_0::HealthStorageHidlEnvironment;
+
+    configureRpcThreadpool(1, false /* callerWillJoin*/);
+    ::testing::AddGlobalTestEnvironment(HealthStorageHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    HealthStorageHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 887fdf1..0880b2f 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -68,6 +68,7 @@
  * The type of an operation in a model.
  */
 enum OperationType : int32_t {
+
     /**
      * Adds two tensors, element-wise.
      *
@@ -105,6 +106,8 @@
      *
      * Outputs:
      * * 0: The sum, a tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 27.
      */
     ADD = 0,
 
@@ -116,8 +119,10 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         sum_{i, j}(input[batch, row + i, col + j, channel]) / sum(1)
+     *     output[b, i, j, channel] =
+     *         sum_{di, dj}(
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, channel]
+     *         ) / sum(1)
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -171,7 +176,9 @@
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
-            [batches, out_height, out_width, depth].
+     *      [batches, out_height, out_width, depth].
+     *
+     * Available since API level 27.
      */
     AVERAGE_POOL_2D = 1,
 
@@ -198,6 +205,8 @@
      * Outputs:
      * * 0: The output, a tensor of the same {@link OperandType} as the input
      *      tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
+     *
+     * Available since API level 27.
      */
     CONCATENATION = 2,
 
@@ -213,12 +222,11 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         sum_{i, j} (
-     *             input[batch, row + i, col + j, k] *
-     *             filter[channel, row + i, col + j, k] +
-     *             bias[channel]
-     *         )
+     *     output[b, i, j, channel] =
+     *         sum_{di, dj, k} (
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, k] *
+     *             filter[channel, di, dj, k]
+     *         ) + bias[channel]
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -274,7 +282,7 @@
      * * 4: An {@link OperandType::INT32} scalar, specifying the stride when
      *      walking through input in the ‘width’ dimension.
      * * 5: An {@link OperandType::INT32} scalar, specifying the stride when
-    *       walking through input in the ‘height’ dimension.
+     *      walking through input in the ‘height’ dimension.
      * * 6: An {@link OperandType::INT32} scalar, and has to be one of the
      *      {@link FusedActivationFunc} values. Specifies the activation to
      *      invoke on the result.
@@ -284,6 +292,8 @@
      *      [batches, out_height, out_width, depth_out]. For output tensor of
      *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
      *      must be satisfied: output_scale > input_scale * filter_scale.
+     *
+     * Available since API level 27.
      */
     CONV_2D = 3,
 
@@ -307,7 +317,7 @@
      *         sum_{di, dj} (
      *             input[b, strides[1] * i + di, strides[2] * j + dj, k] *
      *             filter[1, di, dj, k * channel_multiplier + q]
-     *         )
+     *         ) + bias[k * channel_multiplier + q]
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -375,6 +385,8 @@
      *      [batches, out_height, out_width, depth_out]. For output tensor of
      *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
      *      must be satisfied: output_scale > input_scale * filter_scale.
+     *
+     * Available since API level 27.
      */
     DEPTHWISE_CONV_2D = 4,
 
@@ -409,6 +421,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batch, height*block_size,
      *      width*block_size, depth/(block_size*block_size)].
+     *
+     * Available since API level 27.
      */
     DEPTH_TO_SPACE = 5,
 
@@ -430,6 +444,8 @@
      * Outputs:
      * * 0: The output tensor of same shape as input0, but with
      *      {@link OperandType::TENSOR_FLOAT32}.
+     *
+     * Available since API level 27.
      */
     DEQUANTIZE = 6,
 
@@ -463,6 +479,8 @@
      * * 0: A n-D tensor with the same rank and shape as the Values
      *      tensor, except for the first dimension which has the same size
      *      as Lookups' only dimension.
+     *
+     * Available since API level 27.
      */
     EMBEDDING_LOOKUP = 7,
 
@@ -480,6 +498,8 @@
      * Outputs:
      * * 0: The output tensor, of the same {@link OperandType} and dimensions as
      *      the input tensor.
+     *
+     * Available since API level 27.
      */
     FLOOR = 8,
 
@@ -523,6 +543,8 @@
      *      tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
      *      condition must be satisfied:
      *      output_scale > input_scale * filter_scale.
+     *
+     * Available since API level 27.
      */
     FULLY_CONNECTED = 9,
 
@@ -571,6 +593,8 @@
      *      Stored as {@link OperandType::TENSOR_QUANT8_ASYMM} with offset 0
      *      and scale 1.0f.
      *      A non-zero byte represents True, a hit. A zero indicates otherwise.
+     *
+     * Available since API level 27.
      */
     HASHTABLE_LOOKUP = 10,
 
@@ -598,6 +622,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of the same shape as input
      *      [batches, height, width, depth].
+     *
+     * Available since API level 27.
      */
     L2_NORMALIZATION = 11,
 
@@ -609,8 +635,8 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         sqrt(sum_{i, j} pow(input[batch, row + i, col + j, channel], 2) /
+     *     output[b, i, j, c] =
+     *         sqrt(sum_{di, dj} pow(input[b, strides[1] * i + di, strides[2] * j + dj, c], 2) /
      *              sum(1))
      *
      * Supported tensor {@link OperandType}:
@@ -664,6 +690,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
+     *
+     * Available since API level 27.
      */
     L2_POOL_2D = 12,
 
@@ -700,6 +728,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     LOCAL_RESPONSE_NORMALIZATION = 13,
 
@@ -723,6 +753,8 @@
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
+     *
+     * Available since API level 27.
      */
     LOGISTIC = 14,
 
@@ -758,6 +790,8 @@
      *      If the projection type is Dense:
      *        Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
      *        A flattened tensor that represents projected bit vectors.
+     *
+     * Available since API level 27.
      */
     LSH_PROJECTION = 15,
 
@@ -952,6 +986,8 @@
      *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
      *      [batch_size, output_size]. This is effectively the same as the
      *      current “output state (out)” value.
+     *
+     * Available since API level 27.
      */
     LSTM = 16,
 
@@ -963,8 +999,10 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         max_{i, j} (input[batch, row + i, col + j, channel])
+     *     output[b, i, j, channel] =
+     *         max_{di, dj} (
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, channel]
+     *         )
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -1018,6 +1056,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
+     *
+     * Available since API level 27.
      */
     MAX_POOL_2D = 17,
 
@@ -1055,6 +1095,8 @@
      *      For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the following condition must be satisfied:
      *      output_scale > input1_scale * input2_scale.
+     *
+     * Available since API level 27.
      */
     MUL = 18,
 
@@ -1076,6 +1118,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     RELU = 19,
 
@@ -1097,6 +1141,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     RELU1 = 20,
 
@@ -1118,6 +1164,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     RELU6 = 21,
 
@@ -1141,6 +1189,8 @@
      *
      * Outputs:
      * * 0: The output tensor, of shape specified by the input shape.
+     *
+     * Available since API level 27.
      */
     RESHAPE = 22,
 
@@ -1167,6 +1217,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, new_height, new_width, depth].
+     *
+     * Available since API level 27.
      */
     RESIZE_BILINEAR = 23,
 
@@ -1222,6 +1274,8 @@
      *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
      *      [batch_size, num_units]. This is effectively the same as the
      *      current state value.
+     *
+     * Available since API level 27.
      */
     RNN = 24,
 
@@ -1251,6 +1305,8 @@
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
+     *
+     * Available since API level 27.
      */
     SOFTMAX = 25,
 
@@ -1284,6 +1340,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batches, height/block_size,
      *      width/block_size, depth_in*block_size*block_size].
+     *
+     * Available since API level 27.
      */
     SPACE_TO_DEPTH = 26,
 
@@ -1361,7 +1419,9 @@
      *      [batch_size, (memory_size - 1) * num_units * rank].
      * * 1: output.
      *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-         *      [batch_size, num_units].
+     *      [batch_size, num_units].
+     *
+     * Available since API level 27.
      */
     SVDF = 27,
 
@@ -1382,6 +1442,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     TANH = 28,
 
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index 7b2a21a..c9de76b 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -26,6 +26,7 @@
  * The type of an operation in a model.
  */
 enum OperationType : @1.0::OperationType {
+
     /**
      * BatchToSpace for N-dimensional tensors.
      *
@@ -50,6 +51,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     BATCH_TO_SPACE_ND = 29,
 
@@ -88,6 +91,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     DIV = 30,
 
@@ -118,6 +123,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     MEAN = 31,
 
@@ -150,6 +157,8 @@
      *      of the padding:
      *          output0.dimension[i] =
      *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
+     *
+     * Available since API level 28.
      */
     PAD = 32,
 
@@ -185,6 +194,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     SPACE_TO_BATCH_ND = 33,
 
@@ -214,6 +225,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0. Contains the
      *      same data as input, but has one or more dimensions of size 1
      *      removed.
+     *
+     * Available since API level 28.
      */
     SQUEEZE = 34,
 
@@ -234,28 +247,32 @@
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the tensor to be sliced.
-     * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the starts of
-     *      the dimensions of the input tensor to be sliced. The length must be
-     *      of rank(input0).
-     * * 2: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the ends of
-     *      the dimensions of the input tensor to be sliced. The length must be
-     *      of rank(input0).
-     * * 3: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the strides of
-     *      the dimensions of the input tensor to be sliced. The length must be
-     *      of rank(input0).
-     * * 4: An {@link OperandType::INT32} scalar, begin_mask. If the ith bit
+     * * 1: begin, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The
+     *      starts of the dimensions of the input tensor to be sliced. The
+     *      length must be of rank(input0).
+     * * 2: end, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The
+     *      ends of the dimensions of the input tensor to be sliced. The length
+     *      must be of rank(input0).
+     * * 3: strides, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The
+     *      strides of the dimensions of the input tensor to be sliced. The
+     *      length must be of rank(input0). The entries must be non-zero.
+     * * 4: begin_mask, an {@link OperandType::INT32} scalar. If the ith bit
      *      of begin_mask is set, begin[i] is ignored and the fullest possible
      *      range in that dimension is used instead.
-     * * 5: An {@link OperandType::INT32} scalar, end_mask. If the ith bit of
+     * * 5: end_mask, an {@link OperandType::INT32} scalar. If the ith bit of
      *      end_mask is set, end[i] is ignored and the fullest possible range in
      *      that dimension is used instead.
-     * * 6: An {@link OperandType::INT32} scalar, shrink_axis_mask. An int32
-     *      mask. If the ith bit of shrink_axis_mask is set, it implies that the
-     *      ith specification shrinks the dimensionality by 1. A slice of size 1
-     *      starting from begin[i] in the dimension must be preserved.
+     * * 6: shrink_axis_mask, an {@link OperandType::INT32} scalar. If the
+     *      ith bit of shrink_axis_mask is set, the ith dimension specification
+     *      shrinks the dimensionality by 1, taking on the value at index
+     *      begin[i]. In this case, the ith specification must define a
+     *      slice of size 1, e.g. begin[i] = x, end[i] = x + 1.
      *
      * Outputs:
-     * * 0: A tensor of the same {@link OperandType} as input0.
+     * * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k),
+     *      where k is the number of bits set in shrink_axis_mask.
+     *
+     * Available since API level 28.
      */
     STRIDED_SLICE = 35,
 
@@ -294,6 +311,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     SUB = 36,
 
@@ -319,8 +338,11 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     TRANSPOSE = 37,
+
 };
 
 /**
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 06606cc..61970f0 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -26,6 +26,7 @@
  * The type of an operation in a model.
  */
 enum OperationType : @1.1::OperationType {
+
 };
 
 /**
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index 042df6c..5ac38cd 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -20,8 +20,10 @@
     ],
     types: [
         "AccessNetwork",
+        "DataRegStateResult",
         "EmergencyNumber",
         "EmergencyServiceCategory",
+        "LteVopsInfo",
     ],
     gen_java: true,
 }
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index 6912d0a..3604953 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -71,4 +71,18 @@
      *   RadioError:CANCELLED
      */
     oneway emergencyDialResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
+     *        types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NOT_PROVISIONED
+     */
+    oneway getDataRegistrationStateResponse_1_3(RadioResponseInfo info,
+            DataRegStateResult dataRegResponse);
 };
diff --git a/radio/1.3/types.hal b/radio/1.3/types.hal
index c04451f..d472ca7 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -16,7 +16,10 @@
 
 package android.hardware.radio@1.3;
 
+import @1.0::RegState;
 import @1.2::AccessNetwork;
+import @1.2::CellIdentity;
+import @1.2::DataRegStateResult;
 
 enum AccessNetwork : @1.2::AccessNetwork {
     /**
@@ -81,3 +84,39 @@
     MIEC = 1 << 5, // Manually Initiated eCall (MIeC)
     AIEC = 1 << 6, // Automatically Initiated eCall (AIeC)
 };
+
+/**
+ * Type to define the LTE specific network capabilities for voice over PS including
+ * emergency and normal voice calls.
+ */
+struct LteVopsInfo {
+    /**
+     * This indicates if camped network support VoLTE services. This information is received
+     * from LTE network during LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU
+     * ACCEPT. Refer 3GPP 24.301 EPS network feature support -> IMS VoPS
+     */
+    bool isVopsSupported;
+    /**
+     * This indicates if camped network support VoLTE emergency bearers. This information
+     * is received from LTE network through two sources:
+     * a. During LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU ACCEPT. Refer
+     *    3GPP 24.301 EPS network feature support -> EMC BS
+     * b. In case device is not registered on network. Refer 3GPP 25.331 LTE RRC
+     *    SIB1 : ims-EmergencySupport-r9
+     * If device is registered on LTE, then this field indicates (a).
+     * In case of limited service on LTE this field indicates (b).
+     */
+    bool isEmcBearerSupported;
+};
+
+struct DataRegStateResult {
+    @1.2::DataRegStateResult base;
+    /**
+     * Network capabilities for voice over PS services. This info is valid only
+     * on LTE network and must be present when device is camped on LTE. vopsInfo
+     * will be empty when device is camped only on 2G/3G .
+     */
+    safe_union VopsInfo {
+        LteVopsInfo lteVopsInfo; // LTE network capability
+    } vopsInfo;
+};