Merge changes from topic 'fix_mess'

* changes:
  Revert "Revert "android.hardware.camera.provider@2.4: set up /dev/vndbinder""
  Revert "Revert "composer: route binder traffic over vndbinder""
diff --git a/audio/effect/2.0/default/AudioBufferManager.cpp b/audio/effect/2.0/default/AudioBufferManager.cpp
index 603dbb8..bba0c4a 100644
--- a/audio/effect/2.0/default/AudioBufferManager.cpp
+++ b/audio/effect/2.0/default/AudioBufferManager.cpp
@@ -30,7 +30,10 @@
     ssize_t idx = mBuffers.indexOfKey(buffer.id);
     if (idx >= 0) {
         *wrapper = mBuffers[idx].promote();
-        if (*wrapper != nullptr) return true;
+        if (*wrapper != nullptr) {
+            (*wrapper)->getHalBuffer()->frameCount = buffer.frameCount;
+            return true;
+        }
         mBuffers.removeItemsAt(idx);
     }
     // Need to create and init a new AudioBufferWrapper.
diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp
index 10f9fdb..03a71fa 100644
--- a/camera/common/1.0/default/Android.bp
+++ b/camera/common/1.0/default/Android.bp
@@ -15,7 +15,8 @@
     shared_libs: [
         "liblog",
         "libhardware",
-        "libcamera_metadata"],
+        "libcamera_metadata",
+        "android.hardware.graphics.mapper@2.0"],
     include_dirs: ["system/media/private/camera/include"],
     export_include_dirs : ["include"]
 }
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index e22f26f..fd8b943 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -25,33 +25,27 @@
 namespace V1_0 {
 namespace helper {
 
-HandleImporter HandleImporter::sHandleImporter;
+using MapperError = android::hardware::graphics::mapper::V2_0::Error;
 
-HandleImporter& HandleImporter::getInstance() {
-    sHandleImporter.initialize();
-    return sHandleImporter;
-}
+HandleImporter::HandleImporter() : mInitialized(false) {}
 
-bool HandleImporter::initialize() {
-    // allow only one client
+void HandleImporter::initializeLocked() {
     if (mInitialized) {
-        return false;
-    }
-
-    if (!openGralloc()) {
-        return false;
-    }
-
-    mInitialized = true;
-    return true;
-}
-
-void HandleImporter::cleanup() {
-    if (!mInitialized) {
         return;
     }
 
-    closeGralloc();
+    mMapper = IMapper::getService();
+    if (mMapper == nullptr) {
+        ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
+        return;
+    }
+
+    mInitialized = true;
+    return;
+}
+
+void HandleImporter::cleanup() {
+    mMapper.clear();
     mInitialized = false;
 }
 
@@ -64,12 +58,37 @@
         return true;
     }
 
-    buffer_handle_t clone = cloneBuffer(handle);
-    if (!clone) {
+    Mutex::Autolock lock(mLock);
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapper == nullptr) {
+        ALOGE("%s: mMapper is null!", __FUNCTION__);
         return false;
     }
 
-    handle = clone;
+    MapperError error;
+    buffer_handle_t importedHandle;
+    auto ret = mMapper->importBuffer(
+        hidl_handle(handle),
+        [&](const auto& tmpError, const auto& tmpBufferHandle) {
+            error = tmpError;
+            importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
+        });
+
+    if (!ret.isOk()) {
+        ALOGE("%s: mapper importBuffer failed: %s",
+                __FUNCTION__, ret.description().c_str());
+        return false;
+    }
+
+    if (error != MapperError::NONE) {
+        return false;
+    }
+
+    handle = importedHandle;
+
     return true;
 }
 
@@ -78,10 +97,20 @@
         return;
     }
 
-    releaseBuffer(handle);
+    Mutex::Autolock lock(mLock);
+    if (mMapper == nullptr) {
+        ALOGE("%s: mMapper is null!", __FUNCTION__);
+        return;
+    }
+
+    auto ret = mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
+    if (!ret.isOk()) {
+        ALOGE("%s: mapper freeBuffer failed: %s",
+                __FUNCTION__, ret.description().c_str());
+    }
 }
 
-bool HandleImporter::importFence(const native_handle_t* handle, int& fd) {
+bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
     if (handle == nullptr || handle->numFds == 0) {
         fd = -1;
     } else if (handle->numFds == 1) {
@@ -99,89 +128,12 @@
     return true;
 }
 
-void HandleImporter::closeFence(int fd) {
+void HandleImporter::closeFence(int fd) const {
     if (fd >= 0) {
         close(fd);
     }
 }
 
-bool HandleImporter::openGralloc() {
-    const hw_module_t* module;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGE("failed to get gralloc module");
-        return false;
-    }
-
-    uint8_t major = (module->module_api_version >> 8) & 0xff;
-    if (major > 1) {
-        ALOGE("unknown gralloc module major version %d", major);
-        return false;
-    }
-
-    if (major == 1) {
-        err = gralloc1_open(module, &mDevice);
-        if (err) {
-            ALOGE("failed to open gralloc1 device");
-            return false;
-        }
-
-        mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
-                mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
-        mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
-                mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
-        if (!mRetain || !mRelease) {
-            ALOGE("invalid gralloc1 device");
-            gralloc1_close(mDevice);
-            return false;
-        }
-    } else {
-        mModule = reinterpret_cast<const gralloc_module_t*>(module);
-    }
-
-    return true;
-}
-
-void HandleImporter::closeGralloc() {
-    if (mDevice) {
-        gralloc1_close(mDevice);
-    }
-}
-
-buffer_handle_t HandleImporter::cloneBuffer(buffer_handle_t handle) {
-    native_handle_t* clone = native_handle_clone(handle);
-    if (!clone) {
-        ALOGE("failed to clone buffer %p", handle);
-        return nullptr;
-    }
-
-    bool err;
-    if (mDevice) {
-        err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
-    } else {
-        err = (mModule->registerBuffer(mModule, clone) != 0);
-    }
-
-    if (err) {
-        ALOGE("failed to retain/register buffer %p", clone);
-        native_handle_close(clone);
-        native_handle_delete(clone);
-        return nullptr;
-    }
-
-    return clone;
-}
-
-void HandleImporter::releaseBuffer(buffer_handle_t handle) {
-    if (mDevice) {
-        mRelease(mDevice, handle);
-    } else {
-        mModule->unregisterBuffer(mModule, handle);
-    }
-    native_handle_close(handle);
-    native_handle_delete(const_cast<native_handle_t*>(handle));
-}
-
 } // namespace helper
 } // namespace V1_0
 } // namespace common
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index def8982..c68cfc0 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -17,9 +17,11 @@
 #ifndef CAMERA_COMMON_1_0_HANDLEIMPORTED_H
 #define CAMERA_COMMON_1_0_HANDLEIMPORTED_H
 
-#include <hardware/gralloc.h>
-#include <hardware/gralloc1.h>
 #include <system/window.h>
+#include <utils/Mutex.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
 
 namespace android {
 namespace hardware {
@@ -31,36 +33,24 @@
 // Borrowed from graphics HAL. Use this until gralloc mapper HAL is working
 class HandleImporter {
 public:
-    static HandleImporter& getInstance();
+    HandleImporter();
 
     // In IComposer, any buffer_handle_t is owned by the caller and we need to
     // make a clone for hwcomposer2.  We also need to translate empty handle
     // to nullptr.  This function does that, in-place.
     bool importBuffer(buffer_handle_t& handle);
     void freeBuffer(buffer_handle_t handle);
-    bool importFence(const native_handle_t* handle, int& fd);
-    void closeFence(int fd);
+    bool importFence(const native_handle_t* handle, int& fd) const;
+    void closeFence(int fd) const;
 
 private:
-
-    HandleImporter() : mInitialized(false) {}
-    bool initialize();
+    void initializeLocked();
     void cleanup();
-    bool openGralloc();
-    void closeGralloc();
-    buffer_handle_t cloneBuffer(buffer_handle_t handle);
-    void releaseBuffer(buffer_handle_t handle);
 
-    static HandleImporter sHandleImporter;
+    Mutex mLock;
     bool mInitialized;
+    sp<IMapper> mMapper;
 
-    // gralloc1
-    gralloc1_device_t* mDevice;
-    GRALLOC1_PFN_RETAIN mRetain;
-    GRALLOC1_PFN_RELEASE mRelease;
-
-    // gralloc0
-    const gralloc_module_t* mModule;
 };
 
 } // namespace helper
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index af94b0f..686521b 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -14,6 +14,7 @@
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.common@1.0",
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.base@1.0",
@@ -26,6 +27,9 @@
     static_libs: [
         "android.hardware.camera.common@1.0-helper"
     ],
+    include_dirs: [
+        "frameworks/native/include/media/openmax"
+    ],
     export_include_dirs: ["."]
 }
 
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index cb20fec..4f26c54 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -21,6 +21,7 @@
 #include <log/log.h>
 #include <utils/Trace.h>
 
+#include <media/hardware/HardwareAPI.h> // For VideoNativeHandleMetadata
 #include "CameraDevice_1_0.h"
 
 namespace android {
@@ -33,7 +34,7 @@
 using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
 
-HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance();
+HandleImporter CameraDevice::sHandleImporter;
 
 Status CameraDevice::getHidlStatus(const int& status) {
     switch (status) {
@@ -500,7 +501,7 @@
         if (mem->mBufSize == sizeof(VideoNativeHandleMetadata)) {
             VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*)
                     ((uint8_t*) mem->mHidlHeapMemData + index * mem->mBufSize);
-            if (md->eType == VideoNativeHandleMetadata::kMetadataBufferTypeNativeHandleSource) {
+            if (md->eType == kMetadataBufferTypeNativeHandleSource) {
                 handle = md->pHandle;
             }
         }
@@ -837,7 +838,7 @@
         void *data = ((uint8_t *) camMemory->mHidlHeapMemData) + bufferIndex * camMemory->mBufSize;
         if (handle) {
             VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) data;
-            if (md->eType == VideoNativeHandleMetadata::kMetadataBufferTypeNativeHandleSource) {
+            if (md->eType == kMetadataBufferTypeNativeHandleSource) {
                 // Input handle will be closed by HIDL transport later, so clone it
                 // HAL implementation is responsible to close/delete the clone
                 native_handle_t* clone = native_handle_clone(handle);
diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h
index a9f55c2..0e5a49b 100644
--- a/camera/device/1.0/default/CameraDevice_1_0.h
+++ b/camera/device/1.0/default/CameraDevice_1_0.h
@@ -133,17 +133,6 @@
     };
     sp<IAllocator> mAshmemAllocator;
 
-
-    // TODO: b/35625849
-    // Meta data buffer layout for passing a native_handle to codec
-    // matching frameworks/native/include/media/hardware/MetadataBufferType.h and
-    //          frameworks/native/include/media/hardware/HardwareAPI.h
-    struct VideoNativeHandleMetadata {
-        static const uint32_t kMetadataBufferTypeNativeHandleSource = 3;
-        uint32_t eType; // must be kMetadataBufferTypeNativeHandleSource
-        native_handle_t* pHandle;
-    };
-
     const sp<CameraModule> mModule;
     const std::string mCameraId;
     // const after ctor
@@ -170,7 +159,7 @@
     // Set by provider (when external camera is connected/disconnected)
     bool  mDisconnected;
 
-    static HandleImporter& sHandleImporter;
+    static HandleImporter sHandleImporter;
 
     const SortedVector<std::pair<std::string, std::string>>& mCameraDeviceNames;
 
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index d95f8f4..325c008 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -12,6 +12,7 @@
         "libcutils",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.provider@2.4",
+        "android.hardware.graphics.mapper@2.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 2499b1a..61be82d 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -35,7 +35,7 @@
 // Size of result metadata fast message queue. Change to 0 to always use hwbinder buffer.
 static constexpr size_t CAMERA_RESULT_METADATA_QUEUE_SIZE  = 1 << 20 /* 1MB */;
 
-HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
+HandleImporter CameraDeviceSession::sHandleImporter;
 const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
 
 CameraDeviceSession::CameraDeviceSession(
@@ -44,16 +44,33 @@
     const sp<ICameraDeviceCallback>& callback) :
         camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
         mDevice(device),
+        mDeviceVersion(device->common.version),
+        mIsAELockAvailable(false),
+        mDerivePostRawSensKey(false),
+        mNumPartialResults(1),
         mResultBatcher(callback) {
 
     mDeviceInfo = deviceInfo;
-    uint32_t numPartialResults = 1;
     camera_metadata_entry partialResultsCount =
             mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
     if (partialResultsCount.count > 0) {
-        numPartialResults = partialResultsCount.data.i32[0];
+        mNumPartialResults = partialResultsCount.data.i32[0];
     }
-    mResultBatcher.setNumPartialResults(numPartialResults);
+    mResultBatcher.setNumPartialResults(mNumPartialResults);
+
+    camera_metadata_entry aeLockAvailableEntry = mDeviceInfo.find(
+            ANDROID_CONTROL_AE_LOCK_AVAILABLE);
+    if (aeLockAvailableEntry.count > 0) {
+        mIsAELockAvailable = (aeLockAvailableEntry.data.u8[0] ==
+                ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
+    }
+
+    // Determine whether we need to derive sensitivity boost values for older devices.
+    // If post-RAW sensitivity boost range is listed, so should post-raw sensitivity control
+    // be listed (as the default value 100)
+    if (mDeviceInfo.exists(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE)) {
+        mDerivePostRawSensKey = true;
+    }
 
     mInitFail = initialize();
 }
@@ -130,6 +147,77 @@
     }
 }
 
+/**
+ * For devices <= CAMERA_DEVICE_API_VERSION_3_2, AE_PRECAPTURE_TRIGGER_CANCEL is not supported so
+ * we need to override AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE and AE_LOCK_OFF
+ * to AE_LOCK_ON to start cancelling AE precapture. If AE lock is not available, it still overrides
+ * AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE but doesn't add AE_LOCK_ON to the
+ * request.
+ */
+bool CameraDeviceSession::handleAePrecaptureCancelRequestLocked(
+        const camera3_capture_request_t &halRequest,
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/,
+         AETriggerCancelOverride *override /*out*/) {
+    if ((mDeviceVersion > CAMERA_DEVICE_API_VERSION_3_2) ||
+            (nullptr == halRequest.settings) || (nullptr == settings) ||
+            (0 == get_camera_metadata_entry_count(halRequest.settings))) {
+        return false;
+    }
+
+    settings->clear();
+    settings->append(halRequest.settings);
+    camera_metadata_entry_t aePrecaptureTrigger =
+            settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
+    if (aePrecaptureTrigger.count > 0 &&
+            aePrecaptureTrigger.data.u8[0] ==
+                    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) {
+        // Always override CANCEL to IDLE
+        uint8_t aePrecaptureTrigger =
+                ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
+        settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+                &aePrecaptureTrigger, 1);
+        *override = { false, ANDROID_CONTROL_AE_LOCK_OFF,
+                true, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL };
+
+        if (mIsAELockAvailable == true) {
+            camera_metadata_entry_t aeLock = settings->find(
+                    ANDROID_CONTROL_AE_LOCK);
+            if (aeLock.count == 0 || aeLock.data.u8[0] ==
+                    ANDROID_CONTROL_AE_LOCK_OFF) {
+                uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_ON;
+                settings->update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
+                override->applyAeLock = true;
+                override->aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
+            }
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * Override result metadata for cancelling AE precapture trigger applied in
+ * handleAePrecaptureCancelRequestLocked().
+ */
+void CameraDeviceSession::overrideResultForPrecaptureCancelLocked(
+        const AETriggerCancelOverride &aeTriggerCancelOverride,
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/) {
+    if (aeTriggerCancelOverride.applyAeLock) {
+        // Only devices <= v3.2 should have this override
+        assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
+        settings->update(ANDROID_CONTROL_AE_LOCK, &aeTriggerCancelOverride.aeLock, 1);
+    }
+
+    if (aeTriggerCancelOverride.applyAePrecaptureTrigger) {
+        // Only devices <= v3.2 should have this override
+        assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
+        settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+                &aeTriggerCancelOverride.aePrecaptureTrigger, 1);
+    }
+}
+
 Status CameraDeviceSession::importRequest(
         const CaptureRequest& request,
         hidl_vec<buffer_handle_t*>& allBufPtrs,
@@ -612,13 +700,58 @@
                   __FUNCTION__, type);
             status = Status::ILLEGAL_ARGUMENT;
         } else {
-            convertToHidl(rawRequest, &outMetadata);
+            mOverridenRequest.clear();
+            mOverridenRequest.append(rawRequest);
+            // Derive some new keys for backward compatibility
+            if (mDerivePostRawSensKey && !mOverridenRequest.exists(
+                    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
+                int32_t defaultBoost[1] = {100};
+                mOverridenRequest.update(
+                        ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
+                        defaultBoost, 1);
+                const camera_metadata_t *metaBuffer =
+                        mOverridenRequest.getAndLock();
+                convertToHidl(metaBuffer, &outMetadata);
+                mOverridenRequest.unlock(metaBuffer);
+            } else {
+                convertToHidl(rawRequest, &outMetadata);
+            }
         }
     }
     _hidl_cb(status, outMetadata);
     return Void();
 }
 
+/**
+ * Map Android N dataspace definitions back to Android M definitions, for
+ * use with HALv3.3 or older.
+ *
+ * Only map where correspondences exist, and otherwise preserve the value.
+ */
+android_dataspace CameraDeviceSession::mapToLegacyDataspace(
+        android_dataspace dataSpace) const {
+    if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
+        switch (dataSpace) {
+            case HAL_DATASPACE_V0_SRGB_LINEAR:
+                return HAL_DATASPACE_SRGB_LINEAR;
+            case HAL_DATASPACE_V0_SRGB:
+                return HAL_DATASPACE_SRGB;
+            case HAL_DATASPACE_V0_JFIF:
+                return HAL_DATASPACE_JFIF;
+            case HAL_DATASPACE_V0_BT601_625:
+                return HAL_DATASPACE_BT601_625;
+            case HAL_DATASPACE_V0_BT601_525:
+                return HAL_DATASPACE_BT601_525;
+            case HAL_DATASPACE_V0_BT709:
+                return HAL_DATASPACE_BT709;
+            default:
+                return dataSpace;
+        }
+    }
+
+   return dataSpace;
+}
+
 Return<void> CameraDeviceSession::configureStreams(
         const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb)  {
     Status status = initStatus();
@@ -634,6 +767,22 @@
         return Void();
     }
 
+    if (!mInflightAETriggerOverrides.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight"
+                " trigger overrides!", __FUNCTION__,
+                mInflightAETriggerOverrides.size());
+        _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+        return Void();
+    }
+
+    if (!mInflightRawBoostPresent.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight"
+                " boost overrides!", __FUNCTION__,
+                mInflightRawBoostPresent.size());
+        _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+        return Void();
+    }
+
     if (status != Status::OK) {
         _hidl_cb(status, outStreams);
         return Void();
@@ -654,6 +803,8 @@
             Camera3Stream stream;
             convertFromHidl(requestedConfiguration.streams[i], &stream);
             mStreamMap[id] = stream;
+            mStreamMap[id].data_space = mapToLegacyDataspace(
+                    mStreamMap[id].data_space);
             mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
         } else {
             // width/height/format must not change, but usage/rotation might need to change
@@ -662,8 +813,9 @@
                     mStreamMap[id].width != requestedConfiguration.streams[i].width ||
                     mStreamMap[id].height != requestedConfiguration.streams[i].height ||
                     mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
-                    mStreamMap[id].data_space != (android_dataspace_t)
-                            requestedConfiguration.streams[i].dataSpace) {
+                    mStreamMap[id].data_space !=
+                            mapToLegacyDataspace( static_cast<android_dataspace_t> (
+                                    requestedConfiguration.streams[i].dataSpace))) {
                 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
                 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
                 return Void();
@@ -837,6 +989,8 @@
 
     hidl_vec<camera3_stream_buffer_t> outHalBufs;
     outHalBufs.resize(numOutputBufs);
+    bool aeCancelTriggerNeeded = false;
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
     {
         Mutex::Autolock _l(mInflightLock);
         if (hasInputBuf) {
@@ -862,12 +1016,24 @@
             outHalBufs[i] = bufCache;
         }
         halRequest.output_buffers = outHalBufs.data();
+
+        AETriggerCancelOverride triggerOverride;
+        aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
+                halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
+        if (aeCancelTriggerNeeded) {
+            mInflightAETriggerOverrides[halRequest.frame_number] =
+                    triggerOverride;
+            halRequest.settings = settingsOverride.getAndLock();
+        }
     }
 
     ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
     ATRACE_BEGIN("camera3->process_capture_request");
     status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
     ATRACE_END();
+    if (aeCancelTriggerNeeded) {
+        settingsOverride.unlock(halRequest.settings);
+    }
     if (ret != OK) {
         Mutex::Autolock _l(mInflightLock);
         ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
@@ -881,6 +1047,9 @@
             auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
             mInflightBuffers.erase(key);
         }
+        if (aeCancelTriggerNeeded) {
+            mInflightAETriggerOverrides.erase(request.frameNumber);
+        }
         return Status::INTERNAL_ERROR;
     }
 
@@ -908,6 +1077,17 @@
                 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
                         __FUNCTION__, mInflightBuffers.size());
             }
+            if (!mInflightAETriggerOverrides.empty()) {
+                ALOGE("%s: trying to close while there are still %zu inflight "
+                        "trigger overrides!", __FUNCTION__,
+                        mInflightAETriggerOverrides.size());
+            }
+            if (!mInflightRawBoostPresent.empty()) {
+                ALOGE("%s: trying to close while there are still %zu inflight "
+                        " RAW boost overrides!", __FUNCTION__,
+                        mInflightRawBoostPresent.size());
+            }
+
         }
 
         ATRACE_BEGIN("camera3->close");
@@ -971,6 +1151,61 @@
     result.fmqResultSize = 0;
     result.partialResult = hal_result->partial_result;
     convertToHidl(hal_result->result, &result.result);
+    if (nullptr != hal_result->result) {
+        bool resultOverriden = false;
+        Mutex::Autolock _l(d->mInflightLock);
+
+        // Derive some new keys for backward compatibility
+        if (d->mDerivePostRawSensKey) {
+            camera_metadata_ro_entry entry;
+            if (find_camera_metadata_ro_entry(hal_result->result,
+                    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
+                d->mInflightRawBoostPresent[frameNumber] = true;
+            } else {
+                auto entry = d->mInflightRawBoostPresent.find(frameNumber);
+                if (d->mInflightRawBoostPresent.end() == entry) {
+                    d->mInflightRawBoostPresent[frameNumber] = false;
+                }
+            }
+
+            if ((hal_result->partial_result == d->mNumPartialResults)) {
+                if (!d->mInflightRawBoostPresent[frameNumber]) {
+                    if (!resultOverriden) {
+                        d->mOverridenResult.clear();
+                        d->mOverridenResult.append(hal_result->result);
+                        resultOverriden = true;
+                    }
+                    int32_t defaultBoost[1] = {100};
+                    d->mOverridenResult.update(
+                            ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
+                            defaultBoost, 1);
+                }
+
+                d->mInflightRawBoostPresent.erase(frameNumber);
+            }
+        }
+
+        auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
+        if (d->mInflightAETriggerOverrides.end() != entry) {
+            if (!resultOverriden) {
+                d->mOverridenResult.clear();
+                d->mOverridenResult.append(hal_result->result);
+                resultOverriden = true;
+            }
+            d->overrideResultForPrecaptureCancelLocked(entry->second,
+                    &d->mOverridenResult);
+            if (hal_result->partial_result == d->mNumPartialResults) {
+                d->mInflightAETriggerOverrides.erase(frameNumber);
+            }
+        }
+
+        if (resultOverriden) {
+            const camera_metadata_t *metaBuffer =
+                    d->mOverridenResult.getAndLock();
+            convertToHidl(metaBuffer, &result.result);
+            d->mOverridenResult.unlock(metaBuffer);
+        }
+    }
     if (hasInputBuf) {
         result.inputBuffer.streamId =
                 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
@@ -1046,6 +1281,36 @@
             return;
         }
     }
+
+    if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
+        switch (hidlMsg.msg.error.errorCode) {
+            case ErrorCode::ERROR_DEVICE:
+            case ErrorCode::ERROR_REQUEST:
+            case ErrorCode::ERROR_RESULT: {
+                Mutex::Autolock _l(d->mInflightLock);
+                auto entry = d->mInflightAETriggerOverrides.find(
+                        hidlMsg.msg.error.frameNumber);
+                if (d->mInflightAETriggerOverrides.end() != entry) {
+                    d->mInflightAETriggerOverrides.erase(
+                            hidlMsg.msg.error.frameNumber);
+                }
+
+                auto boostEntry = d->mInflightRawBoostPresent.find(
+                        hidlMsg.msg.error.frameNumber);
+                if (d->mInflightRawBoostPresent.end() != boostEntry) {
+                    d->mInflightRawBoostPresent.erase(
+                            hidlMsg.msg.error.frameNumber);
+                }
+
+            }
+                break;
+            case ErrorCode::ERROR_BUFFER:
+            default:
+                break;
+        }
+
+    }
+
     d->mResultBatcher.notify(hidlMsg);
 }
 
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 7682165..d559c48 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -111,7 +111,18 @@
     // Set by CameraDevice (when external camera is disconnected)
     bool mDisconnected = false;
 
+    struct AETriggerCancelOverride {
+        bool applyAeLock;
+        uint8_t aeLock;
+        bool applyAePrecaptureTrigger;
+        uint8_t aePrecaptureTrigger;
+    };
+
     camera3_device_t* mDevice;
+    uint32_t mDeviceVersion;
+    bool mIsAELockAvailable;
+    bool mDerivePostRawSensKey;
+    uint32_t mNumPartialResults;
     // Stream ID -> Camera3Stream cache
     std::map<int, Camera3Stream> mStreamMap;
 
@@ -119,6 +130,12 @@
     // (streamID, frameNumber) -> inflight buffer cache
     std::map<std::pair<int, uint32_t>, camera3_stream_buffer_t>  mInflightBuffers;
 
+    // (frameNumber, AETriggerOverride) -> inflight request AETriggerOverrides
+    std::map<uint32_t, AETriggerCancelOverride> mInflightAETriggerOverrides;
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenResult;
+    std::map<uint32_t, bool> mInflightRawBoostPresent;
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest;
+
     // buffers currently ciculating between HAL and camera service
     // key: bufferId sent via HIDL interface
     // value: imported buffer_handle_t
@@ -128,7 +145,7 @@
     // Stream ID -> circulating buffers map
     std::map<int, CirculatingBuffers> mCirculatingBuffers;
 
-    static HandleImporter& sHandleImporter;
+    static HandleImporter sHandleImporter;
 
     bool mInitFail;
 
@@ -258,6 +275,18 @@
 
     void updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove);
 
+    android_dataspace mapToLegacyDataspace(
+            android_dataspace dataSpace) const;
+
+    bool handleAePrecaptureCancelRequestLocked(
+            const camera3_capture_request_t &halRequest,
+            android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/,
+            AETriggerCancelOverride *override /*out*/);
+
+    void overrideResultForPrecaptureCancelLocked(
+            const AETriggerCancelOverride &aeTriggerCancelOverride,
+            ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/);
+
     Status processOneCaptureRequest(const CaptureRequest& request);
     /**
      * Static callback forwarding methods from HAL to instance
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index f7074ac..f2a2d2e 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -15,6 +15,7 @@
         "camera.device@3.2-impl",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "liblog",
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 9f4d188..791b93c 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -207,6 +207,20 @@
 
     mNumberOfLegacyCameras = mModule->getNumberOfCameras();
     for (int i = 0; i < mNumberOfLegacyCameras; i++) {
+        struct camera_info info;
+        auto rc = mModule->getCameraInfo(i, &info);
+        if (rc != NO_ERROR) {
+            ALOGE("%s: Camera info query failed!", __func__);
+            mModule.clear();
+            return true;
+        }
+
+        if (checkCameraVersion(i, info) != OK) {
+            ALOGE("%s: Camera version check failed!", __func__);
+            mModule.clear();
+            return true;
+        }
+
         char cameraId[kMaxCameraIdLen];
         snprintf(cameraId, sizeof(cameraId), "%d", i);
         std::string cameraIdStr(cameraId);
@@ -242,6 +256,40 @@
     return false; // mInitFailed
 }
 
+/**
+ * Check that the device HAL version is still in supported.
+ */
+int CameraProvider::checkCameraVersion(int id, camera_info info) {
+    if (mModule == nullptr) {
+        return NO_INIT;
+    }
+
+    // device_version undefined in CAMERA_MODULE_API_VERSION_1_0,
+    // All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible
+    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
+        // Verify the device version is in the supported range
+        switch (info.device_version) {
+            case CAMERA_DEVICE_API_VERSION_1_0:
+            case CAMERA_DEVICE_API_VERSION_3_2:
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_4:
+                // in support
+                break;
+            case CAMERA_DEVICE_API_VERSION_2_0:
+            case CAMERA_DEVICE_API_VERSION_2_1:
+            case CAMERA_DEVICE_API_VERSION_3_0:
+            case CAMERA_DEVICE_API_VERSION_3_1:
+                // no longer supported
+            default:
+                ALOGE("%s: Device %d has HAL version %x, which is not supported",
+                        __FUNCTION__, id, info.device_version);
+                return NO_INIT;
+        }
+    }
+
+    return OK;
+}
+
 bool CameraProvider::setUpVendorTags() {
     ATRACE_CALL();
     vendor_tag_ops_t vOps = vendor_tag_ops_t();
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index d7b0ea6..75971fa 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -89,6 +89,7 @@
 
     hidl_vec<VendorTagSection> mVendorTagSections;
     bool setUpVendorTags();
+    int checkCameraVersion(int id, camera_info info);
 
     // extract legacy camera ID/device version from a HIDL device name
     static std::string getLegacyCameraId(const hidl_string& deviceName);
diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp
index 2c8aad6..a4cad66 100644
--- a/configstore/utils/Android.bp
+++ b/configstore/utils/Android.bp
@@ -16,6 +16,7 @@
 
 cc_library_shared {
     name: "android.hardware.configstore-utils",
+    vendor_available: true,
     defaults: ["hidl_defaults"],
 
     srcs: [ "ConfigStoreUtils.cpp" ],
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 7602399..4c05da8 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -41,8 +41,9 @@
 
 # TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
 # migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on ENABLE_MEDIADRM_64 to build this service as 64-bit.
-ifneq ($(ENABLE_MEDIADRM_64), true)
+# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
+# 64-bit.
+ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
 LOCAL_32_BIT_ONLY := true
 endif
 
@@ -80,8 +81,9 @@
 
 # TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
 # 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on ENABLE_MEDIADRM_64 to build this impl as 64-bit.
-ifneq ($(ENABLE_MEDIADRM_64), true)
+# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this impl as
+# 64-bit.
+ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
 LOCAL_32_BIT_ONLY := true
 endif
 
diff --git a/keymaster/3.0/default/KeymasterDevice.cpp b/keymaster/3.0/default/KeymasterDevice.cpp
index 9c7c860..219f419 100644
--- a/keymaster/3.0/default/KeymasterDevice.cpp
+++ b/keymaster/3.0/default/KeymasterDevice.cpp
@@ -603,7 +603,13 @@
         return ErrorCode::UNIMPLEMENTED;
     }
     auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
-    return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
+    auto rc = legacy_enum_conversion(
+        keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
+    // Keymaster 3.0 requires deleteKey to return ErrorCode::OK if the key
+    // blob is unusable after the call. This is equally true if the key blob was
+    // unusable before.
+    if (rc == ErrorCode::INVALID_KEY_BLOB) return ErrorCode::OK;
+    return rc;
 }
 
 Return<ErrorCode> KeymasterDevice::deleteAllKeys() {
diff --git a/nfc/1.0/default/Android.bp b/nfc/1.0/default/Android.bp
index a157f86..d7f7203 100644
--- a/nfc/1.0/default/Android.bp
+++ b/nfc/1.0/default/Android.bp
@@ -16,3 +16,24 @@
         "android.hardware.nfc@1.0",
     ],
 }
+
+cc_binary {
+    name: "android.hardware.nfc@1.0-service",
+    relative_install_path: "hw",
+    proprietary: true,
+    init_rc: ["android.hardware.nfc@1.0-service.rc"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.nfc@1.0",
+    ],
+
+}
diff --git a/nfc/1.0/default/Android.mk b/nfc/1.0/default/Android.mk
deleted file mode 100644
index 4afad74..0000000
--- a/nfc/1.0/default/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE := android.hardware.nfc@1.0-service
-LOCAL_INIT_RC := android.hardware.nfc@1.0-service.rc
-LOCAL_SRC_FILES := \
-	service.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libcutils \
-	libdl \
-	libbase \
-	libutils \
-	libhardware \
-
-LOCAL_SHARED_LIBRARIES += \
-	libhidlbase \
-	libhidltransport \
-	android.hardware.nfc@1.0 \
-
-
-include $(BUILD_EXECUTABLE)
diff --git a/tetheroffload/Android.bp b/tetheroffload/Android.bp
new file mode 100644
index 0000000..4b50f11
--- /dev/null
+++ b/tetheroffload/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "config/1.0",
+    "control/1.0",
+]
diff --git a/tetheroffload/config/1.0/Android.bp b/tetheroffload/config/1.0/Android.bp
new file mode 100644
index 0000000..7eac6b0
--- /dev/null
+++ b/tetheroffload/config/1.0/Android.bp
@@ -0,0 +1,60 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.tetheroffload.config@1.0_hal",
+    srcs: [
+        "IOffloadConfig.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tetheroffload.config@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tetheroffload.config@1.0",
+    srcs: [
+        ":android.hardware.tetheroffload.config@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tetheroffload/config/1.0/OffloadConfigAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tetheroffload.config@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tetheroffload.config@1.0",
+    srcs: [
+        ":android.hardware.tetheroffload.config@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tetheroffload/config/1.0/IOffloadConfig.h",
+        "android/hardware/tetheroffload/config/1.0/IHwOffloadConfig.h",
+        "android/hardware/tetheroffload/config/1.0/BnHwOffloadConfig.h",
+        "android/hardware/tetheroffload/config/1.0/BpHwOffloadConfig.h",
+        "android/hardware/tetheroffload/config/1.0/BsOffloadConfig.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tetheroffload.config@1.0",
+    generated_sources: ["android.hardware.tetheroffload.config@1.0_genc++"],
+    generated_headers: ["android.hardware.tetheroffload.config@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tetheroffload.config@1.0_genc++_headers"],
+    vendor_available: true,
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/tetheroffload/config/1.0/IOffloadConfig.hal b/tetheroffload/config/1.0/IOffloadConfig.hal
new file mode 100644
index 0000000..4d285da
--- /dev/null
+++ b/tetheroffload/config/1.0/IOffloadConfig.hal
@@ -0,0 +1,36 @@
+/*
+ * 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.tetheroffload.config@1.0;
+
+
+/**
+ * Interface used for configuring the hardware management process
+ */
+interface IOffloadConfig {
+  /**
+   * Provides bound netlink file descriptors for use in the management process
+   *
+   * @param fd1   A file descriptor bound to the following netlink groups
+   *              (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
+   * @param fd2   A file descriptor bound to the following netlink groups
+   *              (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
+   *
+   * @return success true if successful, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   */
+  setHandles(handle fd1, handle fd2) generates (bool success, string errMsg);
+};
diff --git a/tetheroffload/control/1.0/Android.bp b/tetheroffload/control/1.0/Android.bp
new file mode 100644
index 0000000..1d94ec8
--- /dev/null
+++ b/tetheroffload/control/1.0/Android.bp
@@ -0,0 +1,71 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.tetheroffload.control@1.0_hal",
+    srcs: [
+        "types.hal",
+        "IOffloadControl.hal",
+        "ITetheringOffloadCallback.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tetheroffload.control@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tetheroffload.control@1.0",
+    srcs: [
+        ":android.hardware.tetheroffload.control@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tetheroffload/control/1.0/types.cpp",
+        "android/hardware/tetheroffload/control/1.0/OffloadControlAll.cpp",
+        "android/hardware/tetheroffload/control/1.0/TetheringOffloadCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tetheroffload.control@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tetheroffload.control@1.0",
+    srcs: [
+        ":android.hardware.tetheroffload.control@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tetheroffload/control/1.0/types.h",
+        "android/hardware/tetheroffload/control/1.0/hwtypes.h",
+        "android/hardware/tetheroffload/control/1.0/IOffloadControl.h",
+        "android/hardware/tetheroffload/control/1.0/IHwOffloadControl.h",
+        "android/hardware/tetheroffload/control/1.0/BnHwOffloadControl.h",
+        "android/hardware/tetheroffload/control/1.0/BpHwOffloadControl.h",
+        "android/hardware/tetheroffload/control/1.0/BsOffloadControl.h",
+        "android/hardware/tetheroffload/control/1.0/ITetheringOffloadCallback.h",
+        "android/hardware/tetheroffload/control/1.0/IHwTetheringOffloadCallback.h",
+        "android/hardware/tetheroffload/control/1.0/BnHwTetheringOffloadCallback.h",
+        "android/hardware/tetheroffload/control/1.0/BpHwTetheringOffloadCallback.h",
+        "android/hardware/tetheroffload/control/1.0/BsTetheringOffloadCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tetheroffload.control@1.0",
+    generated_sources: ["android.hardware.tetheroffload.control@1.0_genc++"],
+    generated_headers: ["android.hardware.tetheroffload.control@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tetheroffload.control@1.0_genc++_headers"],
+    vendor_available: true,
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/tetheroffload/control/1.0/Android.mk b/tetheroffload/control/1.0/Android.mk
new file mode 100644
index 0000000..6e52c87
--- /dev/null
+++ b/tetheroffload/control/1.0/Android.mk
@@ -0,0 +1,274 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tetheroffload.control-V1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base-V1.0-java \
+
+
+#
+# Build types.hal (IPv4AddrPortPair)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/IPv4AddrPortPair.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.IPv4AddrPortPair
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NatTimeoutUpdate)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/NatTimeoutUpdate.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.NatTimeoutUpdate
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NetworkProtocol)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/NetworkProtocol.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.NetworkProtocol
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (OffloadCallbackEvent)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/OffloadCallbackEvent.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.OffloadCallbackEvent
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IOffloadControl.hal
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/IOffloadControl.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IOffloadControl.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+$(GEN): $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::IOffloadControl
+
+$(GEN): $(LOCAL_PATH)/IOffloadControl.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ITetheringOffloadCallback.hal
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/ITetheringOffloadCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::ITetheringOffloadCallback
+
+$(GEN): $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tetheroffload.control-V1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base-V1.0-java-static \
+
+
+#
+# Build types.hal (IPv4AddrPortPair)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/IPv4AddrPortPair.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.IPv4AddrPortPair
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NatTimeoutUpdate)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/NatTimeoutUpdate.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.NatTimeoutUpdate
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NetworkProtocol)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/NetworkProtocol.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.NetworkProtocol
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (OffloadCallbackEvent)
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/OffloadCallbackEvent.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::types.OffloadCallbackEvent
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IOffloadControl.hal
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/IOffloadControl.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IOffloadControl.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+$(GEN): $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::IOffloadControl
+
+$(GEN): $(LOCAL_PATH)/IOffloadControl.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ITetheringOffloadCallback.hal
+#
+GEN := $(intermediates)/android/hardware/tetheroffload/control/V1_0/ITetheringOffloadCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tetheroffload.control@1.0::ITetheringOffloadCallback
+
+$(GEN): $(LOCAL_PATH)/ITetheringOffloadCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tetheroffload/control/1.0/IOffloadControl.hal b/tetheroffload/control/1.0/IOffloadControl.hal
new file mode 100644
index 0000000..334f4ca
--- /dev/null
+++ b/tetheroffload/control/1.0/IOffloadControl.hal
@@ -0,0 +1,221 @@
+/*
+ * 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.tetheroffload.control@1.0;
+
+import ITetheringOffloadCallback;
+
+
+/**
+ * Interface used to control the lifecycle of tethering offload
+ */
+interface IOffloadControl {
+  /**
+   * Indicates intent to start offload for tethering in immediate future.
+   *
+   * This API must be called exactly once the first time that Tethering is requested by
+   * the user.
+   *
+   * If this API is called multiple times without first calling stopOffload, then the subsequent
+   * calls must fail without changing the state of the server.
+   *
+   * If for some reason, the hardware is currently unable to support offload, this call must fail.
+   *
+   * @param cb Assuming success, this callback must provide unsolicited updates of offload status.
+   *           It is assumed to be valid until stopOffload is called.
+   *
+   * @return success true if initialization is successful, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   *
+   * Remarks: Initializing offload does not imply that any upstreams or downstreams have yet been,
+   * or even will be, chosen.  This API is symmetrical with stopOffload.
+   */
+  @entry
+  @callflow(next={"*"})
+  initOffload(ITetheringOffloadCallback cb) generates (bool success, string errMsg);
+
+  /**
+   * Indicate desire to tear down all tethering offload.
+   *
+   * Called after tethering is no longer requested by the user. Any remaining offload must
+   * be subsequently torn down by the management process.  Upon success, the callback registered
+   * in initOffload must be released, and offload must be stopped.
+   *
+   * @return success true if offload is stopped, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   *
+   * Remarks: Statistics must be reset by this API.
+   */
+  @exit
+  stopOffload() generates (bool success, string errMsg);
+
+  /**
+   * Instruct management process not to forward traffic destined to or from the specified prefixes.
+   *
+   * This API may only be called after initOffload and before stopOffload.
+   *
+   * @param prefixes List containing fully specified prefixes. For e.g. 192.168.1.12/24
+                     or 2001:4860:0684:0:0:0:0:0:1002/64
+   *
+   * @return success true if success, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   *
+   * Remarks: This list overrides any previously specified list
+   */
+  setLocalPrefixes(vec<string> prefixes) generates (bool success, string errMsg);
+
+  /**
+   * Query offloaded traffic statistics forwarded to an upstream address.
+   *
+   * Return statistics that have transpired since the last query.  This would include
+   * statistics from all offloaded downstream tether interfaces that have been forwarded to this
+   * upstream interface.  After returning the statistics, the counters are reset to zero.
+   *
+   * Only offloaded statistics must be returned by this API, software stats must not be
+   * returned.
+   *
+   * @param upstream Upstream interface on which traffic exited/entered
+   *
+   * @return rxBytes values depicting the received bytes
+   * @return txBytes values depicting the transmitted bytes
+   */
+  getForwardedStats(string upstream) generates (uint64_t rxBytes, uint64_t txBytes);
+
+  /**
+   * Instruct hardware to stop forwarding traffic and send a callback after limit bytes have been
+   * transferred in either direction on this upstream interface.
+   *
+   * The limit must be applied to all traffic on the given upstream interface.  This
+   * includes hardware forwarded traffic, software forwarded traffic, and AP-originated traffic.
+   * IPv4 and IPv6 traffic both count towards the same limit.  IP headers are included in the
+   * byte count limit, but, link-layer headers are not.
+   *
+   * This API may only be called while offload is occurring on this upstream.  The hardware
+   * management process is not expected to cache the value and apply the quota once offload is
+   * started.  This cache is not expected, because the limit value would likely become stale over
+   * time and would not reflect any new traffic that has occurred.
+   *
+   * This limit must replace any previous limit.  It may be interpreted as "tell me when
+   * <limit> bytes have been transferred (in either direction) on <upstream>, starting
+   * now and counting from zero."
+   *
+   * Once the limit is reached, the callback registered in initOffload must be called to indicate
+   * this event and all offload must be stopped.  If offload is desired again, the hardware
+   * management process must be completely reprogrammed by calling setUpstreamParameters and
+   * addDownstream again.  Note that it is not necessary to call initOffload again to resume offload
+   * if stopOffload was not called by the client.
+   *
+   * @param upstream Upstream interface name that limit must apply to
+   * @param limit    Bytes limit that can occur before action must be taken
+   *
+   * @return success true if limit is applied, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   */
+  setDataLimit(string upstream, uint64_t limit) generates (bool success, string errMsg);
+
+  /**
+   * Instruct hardware to start forwarding traffic to the specified upstream.
+   *
+   * When iface, v4Addr, and v4Gw are all non-null, the management process may begin forwarding
+   * any currently configured or future configured IPv4 downstreams to this upstream interface.
+   *
+   * If any of the previously three mentioned parameters are null, then any current IPv4 offload
+   * must be stopped.
+   *
+   * When iface and v6Gws are both non-null, and in the case of v6Gws, are not empty, the
+   * management process may begin forwarding any currently configured or future configured IPv6
+   * downstreams to this upstream interface.
+   *
+   * If either of the two above parameters are null, or no V6 Gateways are provided, then IPv6
+   * offload must be stopped.
+   *
+   * This API may only be called after initOffload and before stopOffload.
+   *
+   * @param iface  Upstream interface name.  Note that only one is needed because IPv4 and IPv6
+   *               interfaces cannot be different (only known that this can occur during software
+   *               xlat, which cannot be offloaded through hardware anyways).  If the iface is
+   *               null, offload must be stopped.
+   * @param v4Addr The local IPv4 address assigned to the provided upstream interface, i.e. the
+   *               IPv4 address the packets are NATed to. For e.g. 192.168.1.12.
+   * @param v4Gw   The IPv4 address of the IPv4 gateway on the upstream interface.
+   *               For e.g. 192.168.1.1
+   * @param v6Gws  A list of IPv6 addresses (for e.g. 2001:4860:0684:0:0:0:0:0:1002) for possible
+   *               IPv6 gateways on the upstream interface.
+   *
+   * @return success true if success, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   *
+   * Remarks: This overrides any previously configured parameters.
+   */
+  setUpstreamParameters(string iface, string v4Addr, string v4Gw, vec<string> v6Gws)
+          generates (bool success, string errMsg);
+
+  /**
+   * Configure a downstream interface and prefix in the hardware management process that may be
+   * forwarded.
+   *
+   * The prefix may be an IPv4 or an IPv6 address to signify which family can be offloaded from the
+   * specified tether interface.  The list of IPv4 and IPv6 downstreams that are configured may
+   * differ.
+   *
+   * If the given protocol, as determined by the prefix, has an upstream set,
+   * the hardware may begin forwarding traffic between the upstream and any devices on the
+   * downstream interface that have IP addresses within the specified prefix. Traffic from the same
+   * downstream interfaces is unaffected and must be forwarded if and only if it was already
+   * being forwarded.
+   *
+   * If no upstream is currently configured, then these downstream interface and prefixes must be
+   * preserved so that offload may begin in the future when an upstream is set.
+   *
+   * This API does not replace any previously configured downstreams and must be explictly removed
+   * by calling removeDownstream.
+   *
+   * This API may only be called after initOffload and before stopOffload.
+   *
+   * @param iface  Tether interface
+   * @param prefix Downstream prefix depicting addresses that may be offloaded.
+   *               For e.g. 192.168.1.12/24 or 2001:4860:0684::/64)
+   *
+   * @return success true if success, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   *
+   * Remarks: The hardware management process may fail this call in a normal situation.  This can
+   *          happen because the hardware cannot support the current number of prefixes, the
+   *          hardware cannot support concurrent offload on multiple interfaces, the hardware
+   *          cannot currently support offload on the tether interface for some reason, or any
+   *          other dynamic configuration issues which may occur.  In this case,
+   *          traffic must remain unaffected and must be forwarded if and only if it was already
+   *          being forwarded.
+   */
+  addDownstream(string iface, string prefix) generates (bool success, string errMsg);
+
+  /**
+   * Remove a downstream prefix that may be forwarded from the hardware management process.
+   *
+   * The prefix may be an IPv4 or an IPv6 address. If it was not previously configured using
+   * addDownstream, then this must be a no-op.
+   *
+   * This API may only be called after initOffload and before stopOffload.
+   *
+   * @param iface  Tether interface
+   * @param prefix Downstream prefix depicting address that must no longer be offloaded
+   *               For e.g. 192.168.1.12/24 or 2001:4860:0684::/64)
+   *
+   * @return success true if success, false otherwise
+   * @return errMsg a human readable string if eror has occured.
+   */
+  removeDownstream(string iface, string prefix) generates (bool success, string errMsg);
+};
diff --git a/tetheroffload/control/1.0/ITetheringOffloadCallback.hal b/tetheroffload/control/1.0/ITetheringOffloadCallback.hal
new file mode 100644
index 0000000..397667f
--- /dev/null
+++ b/tetheroffload/control/1.0/ITetheringOffloadCallback.hal
@@ -0,0 +1,38 @@
+/*
+ * 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.tetheroffload.control@1.0;
+
+/**
+ * Callback providing information about status of hardware management process
+ * as well as providing a way to keep offloaded connections from timing out.
+ */
+interface ITetheringOffloadCallback {
+  /**
+   * Called when an asynchronous event is generated by the hardware management
+   * process.
+   */
+  oneway onEvent(OffloadCallbackEvent event);
+
+  /**
+   *  Provide a way for the management process to request that a connections
+   *  timeout be updated in kernel.
+   *
+   *  This is necessary to ensure that offloaded traffic is not cleaned up
+   *  by the kernel connection tracking module for IPv4.
+   */
+   oneway updateTimeout(NatTimeoutUpdate params);
+};
diff --git a/tetheroffload/control/1.0/types.hal b/tetheroffload/control/1.0/types.hal
new file mode 100644
index 0000000..e2576ac
--- /dev/null
+++ b/tetheroffload/control/1.0/types.hal
@@ -0,0 +1,72 @@
+/*
+ * 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.tetheroffload.control@1.0;
+
+enum OffloadCallbackEvent : uint32_t {
+    /**
+     * Indicate that a working configuration has been programmed and the
+     * hardware management process has begun forwarding traffic.
+     */
+    OFFLOAD_STARTED = 1,
+    /**
+     * Indicate that an error has occurred which has disrupted hardware
+     * acceleration.  Software routing may still be attempted; however,
+     * statistics may be temporarily unavailable.  Statistics may be recovered
+     * after OFFLOAD_SUPPORT_AVAILABLE event is fired.
+     */
+    OFFLOAD_STOPPED_ERROR = 2,
+    /**
+     * Indicate that the device has moved to a RAT on which hardware
+     * acceleration is not supported.  Subsequent calls to setUpstreamParameters
+     * and add/removeDownstream will likely fail and cannot be presumed to be
+     * saved inside of the hardware management process.  Upon receiving
+     * OFFLOAD_SUPPORT_AVAIALBLE, the client may reprogram the hardware
+     * management process to begin offload again.
+     */
+    OFFLOAD_STOPPED_UNSUPPORTED = 3,
+    /**
+     * Indicate that the hardware management process is willing and able to
+     * provide support for hardware acceleration at this time.  If applicable,
+     * the client may query for statistics.  If offload is desired, the client
+     * must reprogram the hardware management process.
+     */
+    OFFLOAD_SUPPORT_AVAILABLE = 4,
+    /**
+     * Hardware acceleration is no longer in effect and must be reprogrammed
+     * in order to resume.  This event is fired when the limit, applied in
+     * setDataLimit, has expired.  It is recommended that the client query for
+     * statistics immediately after receiving this event.
+     */
+    OFFLOAD_STOPPED_LIMIT_REACHED = 5
+};
+
+enum NetworkProtocol : uint32_t {
+    TCP = 6,
+    UDP = 17
+};
+
+struct IPv4AddrPortPair {
+    /** IPv4 Address and Port */
+    string addr; // for e.g. 192.168.1.12
+    uint16_t port; // for e.g. 8080
+};
+
+struct NatTimeoutUpdate {
+    IPv4AddrPortPair src;
+    IPv4AddrPortPair dst;
+    NetworkProtocol proto;
+};
diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk
index 13f6cc1..7603b8b 100644
--- a/wifi/1.0/default/Android.mk
+++ b/wifi/1.0/default/Android.mk
@@ -46,7 +46,7 @@
     libnl \
     libutils \
     libwifi-hal \
-    libwifi-system \
+    libwifi-system-iface \
     libcld80211
 LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
 include $(BUILD_EXECUTABLE)
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index 32206d8..661cd78 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -26,6 +26,16 @@
 namespace implementation {
 namespace hidl_struct_util {
 
+hidl_string safeConvertChar(const char* str, size_t max_len) {
+  const char* c = str;
+  size_t size = 0;
+  while (*c && (unsigned char)*c < 128 && size < max_len) {
+    ++size;
+    ++c;
+  }
+  return hidl_string(str, size);
+}
+
 IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(
     uint32_t feature) {
   using HidlChipCaps = IWifiChip::ChipCapabilityMask;
@@ -134,7 +144,8 @@
     return false;
   }
   *hidl_status = {};
-  hidl_status->ringName = reinterpret_cast<const char*>(legacy_status.name);
+  hidl_status->ringName = safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
+        sizeof(legacy_status.name));
   hidl_status->flags = 0;
   for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES,
                           WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
@@ -449,7 +460,8 @@
   hidl_scan_result->timeStampInUs = legacy_scan_result.ts;
   hidl_scan_result->ssid = std::vector<uint8_t>(
       legacy_scan_result.ssid,
-      legacy_scan_result.ssid + strlen(legacy_scan_result.ssid));
+      legacy_scan_result.ssid + strnlen(legacy_scan_result.ssid,
+            sizeof(legacy_scan_result.ssid) - 1));
   memcpy(hidl_scan_result->bssid.data(),
          legacy_scan_result.bssid,
          hidl_scan_result->bssid.size());
@@ -882,6 +894,12 @@
   CHECK(false);
 }
 
+void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
+    WifiNanStatus* wifiNanStatus) {
+  wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type);
+  wifiNanStatus->description = safeConvertChar(str, max_len);
+}
+
 bool convertHidlNanEnableRequestToLegacy(
     const NanEnableRequest& hidl_request,
     legacy_hal::NanEnableRequest* legacy_request) {
@@ -1539,8 +1557,8 @@
   }
   *wifiNanStatus = {};
 
-  wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(legacy_response.status);
-  wifiNanStatus->description = legacy_response.nan_error;
+  convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error,
+        sizeof(legacy_response.nan_error), wifiNanStatus);
   return true;
 }
 
diff --git a/wifi/1.0/default/hidl_struct_util.h b/wifi/1.0/default/hidl_struct_util.h
index 41e97b3..c04d92f 100644
--- a/wifi/1.0/default/hidl_struct_util.h
+++ b/wifi/1.0/default/hidl_struct_util.h
@@ -94,7 +94,8 @@
     std::vector<WifiDebugRxPacketFateReport>* hidl_fates);
 
 // NAN iface conversion methods.
-NanStatusType convertLegacyNanStatusTypeToHidl(legacy_hal::NanStatusType type);
+void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
+    WifiNanStatus* wifiNanStatus);
 bool convertHidlNanEnableRequestToLegacy(
     const NanEnableRequest& hidl_request,
     legacy_hal::NanEnableRequest* legacy_request);
diff --git a/wifi/1.0/default/wifi_nan_iface.cpp b/wifi/1.0/default/wifi_nan_iface.cpp
index 6977fc0..1072015 100644
--- a/wifi/1.0/default/wifi_nan_iface.cpp
+++ b/wifi/1.0/default/wifi_nan_iface.cpp
@@ -217,8 +217,8 @@
         return;
       }
       WifiNanStatus status;
-      status.status = hidl_struct_util::convertLegacyNanStatusTypeToHidl(msg.reason);
-      status.description = msg.nan_reason;
+      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
+            &status);
 
       for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
         if (!callback->eventDisabled(status).isOk()) {
@@ -235,8 +235,8 @@
         return;
       }
       WifiNanStatus status;
-      status.status = hidl_struct_util::convertLegacyNanStatusTypeToHidl(msg.reason);
-      status.description = msg.nan_reason;
+      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
+            &status);
 
       for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
         if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) {
@@ -253,8 +253,8 @@
         return;
       }
       WifiNanStatus status;
-      status.status = hidl_struct_util::convertLegacyNanStatusTypeToHidl(msg.reason);
-      status.description = msg.nan_reason;
+      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
+            &status);
 
       for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
         if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) {
@@ -328,8 +328,8 @@
         return;
       }
       WifiNanStatus status;
-      status.status = hidl_struct_util::convertLegacyNanStatusTypeToHidl(msg.reason);
-      status.description = msg.nan_reason;
+      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
+            &status);
 
       for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
         if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
diff --git a/wifi/supplicant/1.0/vts/functional/Android.mk b/wifi/supplicant/1.0/vts/functional/Android.mk
index cfcd4f8..d87d7ef 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.mk
+++ b/wifi/supplicant/1.0/vts/functional/Android.mk
@@ -34,7 +34,8 @@
     liblog \
     libutils \
     libwifi-hal \
-    libwifi-system
+    libwifi-system \
+    libwifi-system-iface
 LOCAL_STATIC_LIBRARIES := \
     libgmock \
     VtsHalHidlTargetTestBase