Merge "Patch cec@1.0 hal to add two Cec message types"
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index b04adf7..6498289 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -22,6 +22,7 @@
         "libaudiopolicycomponents",
         "libicuuc",
         "libicuuc_stubdata",
+        "libandroidicu",
         "libmedia_helper",
         "libxml2",
     ],
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 88d49d8..de6cad9 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -28,6 +28,7 @@
         "libeffectsconfig",
         "libicuuc",
         "libicuuc_stubdata",
+        "libandroidicu",
         "libxml2",
     ],
     header_libs: [
diff --git a/automotive/OWNERS b/automotive/OWNERS
new file mode 100644
index 0000000..4a94494
--- /dev/null
+++ b/automotive/OWNERS
@@ -0,0 +1,3 @@
+randolphs@google.com
+pirozzoj@google.com
+twasilczyk@google.com
diff --git a/automotive/vehicle/2.0/default/OWNERS b/automotive/vehicle/2.0/default/OWNERS
deleted file mode 100644
index d5d9d4c..0000000
--- a/automotive/vehicle/2.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-egranata@google.com
-pavelm@google.com
-spaik@google.com
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 4751a76..e874146 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -131,6 +131,9 @@
  * When a property's status field is not set to AVAILABLE:
  *  - IVehicle#set may return StatusCode::NOT_AVAILABLE.
  *  - IVehicle#get is not guaranteed to work.
+ *
+ * Properties set to values out of range must be ignored and no action taken
+ * in response to such ill formed requests.
  */
 enum VehicleProperty : int32_t {
 
@@ -243,7 +246,7 @@
      * Fuel door location
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
-     * @data_enum FuelDoorLocationType
+     * @data_enum PortLocationType
      * @access VehiclePropertyAccess:READ
      */
     INFO_FUEL_DOOR_LOCATION = (
@@ -267,6 +270,7 @@
 
     /**
      * Driver's seat location
+     * VHAL implementations must ignore the areaId. Use VehicleArea:GLOBAL.
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @data_enum VehicleAreaSeat
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index b96f574..0f23657 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -378,8 +378,12 @@
     const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
     UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
 
-    // Orientation probably isn't useful for external facing camera?
-    const int32_t orientation = 0;
+    // Orientation is a bit odd for external camera, but consider it as the orientation
+    // between the external camera sensor (which is usually landscape) and the device's
+    // natural display orientation. For devices with natural landscape display (ex: tablet/TV), the
+    // orientation should be 0. For devices with natural portrait display (phone), the orientation
+    // should be 270.
+    const int32_t orientation = mCfg.orientation;
     UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
 
     // android.shading
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 680c95a..0941052 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -160,9 +160,11 @@
 namespace common {
 
 namespace {
-    const int  kDefaultJpegBufSize = 5 << 20; // 5MB
-    const int  kDefaultNumVideoBuffer = 4;
-    const int  kDefaultNumStillBuffer = 2;
+    const int kDefaultJpegBufSize = 5 << 20; // 5MB
+    const int kDefaultNumVideoBuffer = 4;
+    const int kDefaultNumStillBuffer = 2;
+    const int kDefaultOrientation = 0; // suitable for natural landscape displays like tablet/TV
+                                       // For phone devices 270 is better
 } // anonymous namespace
 
 const char* ExternalCameraConfig::kDefaultCfgPath = "/vendor/etc/external_camera_config.xml";
@@ -276,10 +278,17 @@
                 minStreamSize->UnsignedAttribute("height", /*Default*/0)};
     }
 
+    XMLElement *orientation = deviceCfg->FirstChildElement("Orientation");
+    if (orientation == nullptr) {
+        ALOGI("%s: no sensor orientation specified", __FUNCTION__);
+    } else {
+        ret.orientation = orientation->IntAttribute("degree", /*Default*/kDefaultOrientation);
+    }
+
     ALOGI("%s: external camera cfg loaded: maxJpgBufSize %d,"
-            " num video buffers %d, num still buffers %d",
+            " num video buffers %d, num still buffers %d, orientation %d",
             __FUNCTION__, ret.maxJpegBufSize,
-            ret.numVideoBuffers, ret.numStillBuffers);
+            ret.numVideoBuffers, ret.numStillBuffers, ret.orientation);
     for (const auto& limit : ret.fpsLimits) {
         ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__,
                 limit.size.width, limit.size.height, limit.fpsUpperBound);
@@ -292,7 +301,8 @@
 ExternalCameraConfig::ExternalCameraConfig() :
         maxJpegBufSize(kDefaultJpegBufSize),
         numVideoBuffers(kDefaultNumVideoBuffer),
-        numStillBuffers(kDefaultNumStillBuffer) {
+        numStillBuffers(kDefaultNumStillBuffer),
+        orientation(kDefaultOrientation) {
     fpsLimits.push_back({/*Size*/{ 640,  480}, /*FPS upper bound*/30.0});
     fpsLimits.push_back({/*Size*/{1280,  720}, /*FPS upper bound*/7.5});
     fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0});
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 5754ccb..3b1ac96 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -80,6 +80,9 @@
     // Minimum output stream size
     Size minStreamSize;
 
+    // The value of android.sensor.orientation
+    int32_t orientation;
+
 private:
     ExternalCameraConfig();
 };
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index d4c422d..42ac921 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -240,6 +240,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.input.classifier</name>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.keymaster</name>
         <version>3.0</version>
@@ -367,6 +375,7 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.sensors</name>
         <version>1.0</version>
+        <version>2.0</version>
         <interface>
             <name>ISensors</name>
             <instance>default</instance>
@@ -439,7 +448,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0-2</version>
+        <version>1.0-3</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 99773be..d66f377 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -19,39 +19,23 @@
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/common_default_service.mk
 LOCAL_MODULE := android.hardware.drm@1.0-service
 LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-  service.cpp \
+LOCAL_SRC_FILES := service.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-  android.hardware.drm@1.0 \
-  android.hidl.memory@1.0 \
-  libhidlbase \
-  libhidltransport \
-  libhardware \
-  liblog \
-  libutils \
-  libbinder \
+include $(BUILD_EXECUTABLE)
 
-LOCAL_STATIC_LIBRARIES := \
-  android.hardware.drm@1.0-helper \
+############# Build legacy drm lazy service ############
 
-LOCAL_C_INCLUDES := \
-  hardware/interfaces/drm
+include $(CLEAR_VARS)
 
-LOCAL_HEADER_LIBRARIES := \
-  media_plugin_headers
-
-# 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 TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
+include $(LOCAL_PATH)/common_default_service.mk
+LOCAL_MODULE := android.hardware.drm@1.0-service-lazy
+LOCAL_OVERRIDES_MODULES := android.hardware.drm@1.0-service
+LOCAL_INIT_RC := android.hardware.drm@1.0-service-lazy.rc
+LOCAL_SRC_FILES := serviceLazy.cpp
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc b/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
new file mode 100644
index 0000000..4b32f7f
--- /dev/null
+++ b/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
@@ -0,0 +1,10 @@
+service vendor.drm-hal-1-0 /vendor/bin/hw/android.hardware.drm@1.0-service-lazy
+    interface android.hardware.drm@1.0::ICryptoFactory default
+    interface android.hardware.drm@1.0::IDrmFactory default
+    oneshot
+    disabled
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service.rc b/drm/1.0/default/android.hardware.drm@1.0-service.rc
index a3457b5..790eded 100644
--- a/drm/1.0/default/android.hardware.drm@1.0-service.rc
+++ b/drm/1.0/default/android.hardware.drm@1.0-service.rc
@@ -1,4 +1,6 @@
 service vendor.drm-hal-1-0 /vendor/bin/hw/android.hardware.drm@1.0-service
+    interface android.hardware.drm@1.0::ICryptoFactory default
+    interface android.hardware.drm@1.0::IDrmFactory default
     class hal
     user media
     group mediadrm drmrpc
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
new file mode 100644
index 0000000..28db567
--- /dev/null
+++ b/drm/1.0/default/common_default_service.mk
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2019 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 $(CLEAR_VARS)
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_SHARED_LIBRARIES := \
+  android.hardware.drm@1.0 \
+  android.hidl.memory@1.0 \
+  libhidlbase \
+  libhidltransport \
+  libhardware \
+  liblog \
+  libutils \
+  libbinder \
+
+LOCAL_STATIC_LIBRARIES := \
+  android.hardware.drm@1.0-helper \
+
+LOCAL_C_INCLUDES := \
+  hardware/interfaces/drm
+
+LOCAL_HEADER_LIBRARIES := \
+  media_plugin_headers
+
+# 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 TARGET_ENABLE_MEDIADRM_64 to build this service as
+# 64-bit.
+ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
+LOCAL_32_BIT_ONLY := true
+endif
diff --git a/drm/1.0/default/service.cpp b/drm/1.0/default/service.cpp
index 1a44ce2..98d2c3b 100644
--- a/drm/1.0/default/service.cpp
+++ b/drm/1.0/default/service.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "android.hardware.drm@1.0-service"
 
 #include <1.0/default/CryptoFactory.h>
 #include <1.0/default/DrmFactory.h>
@@ -31,15 +30,8 @@
 using android::hardware::drm::V1_0::IDrmFactory;
 
 int main() {
-    ALOGD("android.hardware.drm@1.0-service starting...");
-
-    // The DRM HAL may communicate to other vendor components via
-    // /dev/vndbinder
-    android::ProcessState::initWithDriver("/dev/vndbinder");
-
     configureRpcThreadpool(8, true /* callerWillJoin */);
-    android::status_t status =
-        registerPassthroughServiceImplementation<IDrmFactory>();
+    android::status_t status = registerPassthroughServiceImplementation<IDrmFactory>();
     LOG_ALWAYS_FATAL_IF(
         status != android::OK,
         "Error while registering drm service: %d", status);
diff --git a/drm/1.0/default/serviceLazy.cpp b/drm/1.0/default/serviceLazy.cpp
new file mode 100644
index 0000000..e5068b5
--- /dev/null
+++ b/drm/1.0/default/serviceLazy.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 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 <1.0/default/CryptoFactory.h>
+#include <1.0/default/DrmFactory.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include <binder/ProcessState.h>
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::registerLazyPassthroughServiceImplementation;
+
+using android::hardware::drm::V1_0::ICryptoFactory;
+using android::hardware::drm::V1_0::IDrmFactory;
+
+int main() {
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+    android::status_t status = registerLazyPassthroughServiceImplementation<IDrmFactory>();
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering drm service: %d", status);
+    status = registerLazyPassthroughServiceImplementation<ICryptoFactory>();
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering crypto service: %d",
+                        status);
+    joinRpcThreadpool();
+}
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index 200671e..9b6b076 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -13,6 +13,7 @@
         "IAGnssRil.hal",
         "IGnss.hal",
         "IGnssCallback.hal",
+        "IGnssConfiguration.hal",
         "IGnssMeasurement.hal",
         "IGnssMeasurementCallback.hal",
     ],
diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal
index fb8b040..e1acd6d 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -20,13 +20,14 @@
 import @1.1::IGnss;
 
 import IGnssCallback;
+import IGnssConfiguration;
 import IGnssMeasurement;
 import IAGnss;
 import IAGnssRil;
 
 /** Represents the standard GNSS (Global Navigation Satellite System) interface. */
 interface IGnss extends @1.1::IGnss {
-     /**
+    /**
      * Opens the interface and provides the callback routines to the implementation of this
      * interface.
      *
@@ -37,6 +38,13 @@
     setCallback_2_0(IGnssCallback callback) generates (bool success);
 
     /**
+     * This method returns the IGnssConfiguration interface.
+     *
+     * @return gnssConfigurationIface Handle to the IGnssConfiguration interface.
+     */
+    getExtensionGnssConfiguration_2_0() generates (IGnssConfiguration gnssConfigurationIface);
+
+    /**
      * This method returns the IAGnss Interface.
      *
      * The getExtensionAGnss() must return nullptr as the @1.0::IAGnss interface is
diff --git a/gnss/2.0/IGnssConfiguration.hal b/gnss/2.0/IGnssConfiguration.hal
new file mode 100644
index 0000000..90c376e
--- /dev/null
+++ b/gnss/2.0/IGnssConfiguration.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss@2.0;
+
+import @1.1::IGnssConfiguration;
+
+/**
+ * Extended interface for GNSS Configuration support.
+ *
+ * Due to the introduction of new GNSS HAL package android.hardware.gnss.visibility_control@1.0
+ * the following methods in @1.0::IGnssConfiguration are deprecated in this version and not
+ * called by the framework.
+ *
+ * setGpsLock(bitfield<GpsLock> lock) generates (bool success);
+ * setSuplEs(bool enabled) generates (bool success);
+ */
+interface IGnssConfiguration extends @1.1::IGnssConfiguration {
+    /**
+     * This method sets the emergency session extension duration. The GNSS HAL
+     * implementation must serve emergency SUPL and Control Plane network initiated
+     * location requests for this extra duration after the user initiated emergency
+     * session ends.
+     *
+     * @param emergencyExtensionSeconds Number of seconds to extend the emergency
+     * session duration post emergency call.
+     *
+     * @return success True if the GNSS HAL implementation accepts and supports the
+     * extended duration for emergency SUPL and Control Plane location requests.
+     */
+    setEsExtensionSec(uint32_t emergencyExtensionSeconds) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 9119ee4..92d5c1f 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -21,6 +21,7 @@
     vendor: true,
     vintf_fragments: ["android.hardware.gnss@2.0-service.xml"],
     srcs: [
+        "GnssConfiguration.cpp",
         "AGnss.cpp",
         "AGnssRil.cpp",
         "Gnss.cpp",
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index bde904f..5c752d5 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -20,6 +20,7 @@
 #include <log/log.h>
 #include "AGnss.h"
 #include "AGnssRil.h"
+#include "GnssConfiguration.h"
 #include "GnssMeasurement.h"
 
 using ::android::hardware::Status;
@@ -181,6 +182,10 @@
 }
 
 // Methods from V2_0::IGnss follow.
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+    return new GnssConfiguration{};
+}
+
 Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
     return new AGnss{};
 }
diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h
index 47792cf..e86158f 100644
--- a/gnss/2.0/default/Gnss.h
+++ b/gnss/2.0/default/Gnss.h
@@ -72,6 +72,7 @@
     Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
 
     // Methods from V2_0::IGnss follow.
+    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
     Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
     Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
     Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
diff --git a/gnss/2.0/default/GnssConfiguration.cpp b/gnss/2.0/default/GnssConfiguration.cpp
new file mode 100644
index 0000000..4389dd2
--- /dev/null
+++ b/gnss/2.0/default/GnssConfiguration.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssConfiguration"
+
+#include "GnssConfiguration.h"
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enable) {
+    ALOGD("setSuplEs enable: %d", enable);
+    // Method deprecated in 2.0 and not expected to be called by the framework.
+    return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setSuplMode(hidl_bitfield<SuplMode>) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setGpsLock(hidl_bitfield<GpsLock> gpsLock) {
+    ALOGD("setGpsLock gpsLock: %hhu", static_cast<GpsLock>(gpsLock));
+    // Method deprecated in 2.0 and not expected to be called by the framework.
+    return false;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(hidl_bitfield<LppProfile>) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol>) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool) {
+    // TODO implement
+    return bool{};
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+    const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>&) {
+    // TODO (b/122463906): Reuse 1.1 implementation.
+    return bool{};
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+    ALOGD("setEsExtensionSec emergencyExtensionSeconds: %d", emergencyExtensionSeconds);
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/2.0/default/GnssConfiguration.h b/gnss/2.0/default/GnssConfiguration.h
new file mode 100644
index 0000000..0c02ccd
--- /dev/null
+++ b/gnss/2.0/default/GnssConfiguration.h
@@ -0,0 +1,62 @@
+/*
+ * 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_GNSS_V2_0_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.0/IGnssConfiguration.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssConfiguration : public IGnssConfiguration {
+    // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(hidl_bitfield<SuplMode> mode) override;
+    Return<bool> setGpsLock(hidl_bitfield<GpsLock> lock) override;
+    Return<bool> setLppProfile(hidl_bitfield<LppProfile> lppProfile) override;
+    Return<bool> setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol> protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist(
+        const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+    Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
\ No newline at end of file
diff --git a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
index ae36c50..a8e40ba 100644
--- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
+++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
@@ -23,6 +23,7 @@
     ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GnssHidlEnvironment::Instance()->init(&argc, argv);
+    // TODO (b/122463165): Expand coverage to include 1.1 and 1.0 VTS tests.
     int status = RUN_ALL_TESTS();
     ALOGI("Test result = %d", status);
     return status;
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index ef232c9..cef06a2 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -21,6 +21,7 @@
 
 using android::hardware::hidl_vec;
 
+using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
 using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
 using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
 using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
@@ -60,6 +61,56 @@
 }
 
 /*
+ * TestGnssConfigurationExtension:
+ * Gets the GnssConfigurationExtension and verifies that it returns an actual extension by
+ * calling a method.
+ *
+ * The GNSS HAL 2.0 implementation must support @2.0::IGnssConfiguration interface due to
+ * the deprecation of some methods in @1.0::IGnssConfiguration interface.
+ */
+TEST_F(GnssHalTest, TestGnssConfigurationExtension) {
+    auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    ASSERT_TRUE(gnssConfiguration.isOk());
+    sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
+    ASSERT_NE(iGnssConfiguration, nullptr);
+
+    auto result = iGnssConfiguration->setEsExtensionSec(180);
+    ASSERT_TRUE(result.isOk());
+    // Expected result can be true or false depending on whether HAL implementation supports
+    // detecting emergency sessions without involving the framework.
+}
+
+/*
+ * TestGnssConfiguration_setSuplEs_Deprecation:
+ * Calls setSuplEs and verifies that it returns false.
+ */
+TEST_F(GnssHalTest, TestGnssConfiguration_setSuplEs_Deprecation) {
+    auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    ASSERT_TRUE(gnssConfiguration.isOk());
+    sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
+    ASSERT_NE(iGnssConfiguration, nullptr);
+
+    auto result = iGnssConfiguration->setSuplEs(false);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_FALSE(result);
+}
+
+/*
+ * TestGnssConfiguration_setGpsLock_Deprecation:
+ * Calls setGpsLock and verifies that it returns false.
+ */
+TEST_F(GnssHalTest, TestGnssConfiguration_setGpsLock_Deprecation) {
+    auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    ASSERT_TRUE(gnssConfiguration.isOk());
+    sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
+    ASSERT_NE(iGnssConfiguration, nullptr);
+
+    auto result = iGnssConfiguration->setGpsLock(0);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_FALSE(result);
+}
+
+/*
  * TestAGnssRilExtension:
  * Gets the AGnssRilExtension and verifies that it returns an actual extension.
  *
@@ -76,11 +127,11 @@
 }
 
 /*
- * TestAGnssRilUpdateNetworkState_2_0:
+ * TestAGnssRil_UpdateNetworkState_2_0:
  * 1. Updates GNSS HAL that a network has connected.
  * 2. Updates GNSS HAL that network has disconnected.
  */
-TEST_F(GnssHalTest, TestAGnssRilUpdateNetworkState_2_0) {
+TEST_F(GnssHalTest, TestAGnssRil_UpdateNetworkState_2_0) {
     auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0();
     ASSERT_TRUE(agnssRil.isOk());
     sp<IAGnssRil_2_0> iAGnssRil = agnssRil;
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
new file mode 100644
index 0000000..c3c6fc6
--- /dev/null
+++ b/input/classifier/1.0/Android.bp
@@ -0,0 +1,35 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.input.classifier@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IInputClassifier.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Action",
+        "Axis",
+        "Button",
+        "Classification",
+        "EdgeFlag",
+        "Flag",
+        "Meta",
+        "MotionEvent",
+        "PointerCoords",
+        "PointerProperties",
+        "PolicyFlag",
+        "Source",
+        "SourceClass",
+        "ToolType",
+        "VideoFrame",
+    ],
+    gen_java: true,
+}
+
diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal
new file mode 100644
index 0000000..edc1138
--- /dev/null
+++ b/input/classifier/1.0/IInputClassifier.hal
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 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.input.classifier@1.0;
+
+interface IInputClassifier {
+
+  /**
+   * Returns the classification for the current sequence of input events.
+   */
+  classify(MotionEvent event) generates (Classification classification);
+
+};
diff --git a/input/classifier/1.0/default/Android.bp b/input/classifier/1.0/default/Android.bp
new file mode 100644
index 0000000..ddd883c
--- /dev/null
+++ b/input/classifier/1.0/default/Android.bp
@@ -0,0 +1,23 @@
+cc_binary {
+    name: "android.hardware.input.classifier@1.0-service-example",
+    init_rc: ["android.hardware.input.classifier@1.0-service-example.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    vintf_fragments: ["manifest_input.classifier.xml"],
+    srcs: [
+        "InputClassifier.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.input.classifier@1.0",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp
new file mode 100644
index 0000000..c463361
--- /dev/null
+++ b/input/classifier/1.0/default/InputClassifier.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputClassifierHAL"
+
+#include "InputClassifier.h"
+#include <inttypes.h>
+#include <log/log.h>
+#include <utils/Timers.h>
+
+using namespace android::hardware::input::classifier::V1_0;
+
+namespace android {
+namespace hardware {
+namespace input {
+namespace classifier {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
+Return<Classification> InputClassifier::classify(const MotionEvent& event) {
+    /**
+     * In this example implementation, we will see how many "pixels" inside the video frame
+     * exceed the value of 250. If more than 6 such pixels are present, then treat the event
+     * as a "DEEP_PRESS".
+     */
+    if (event.frames.size() == 0) {
+        return Classification::NONE;
+    }
+    ALOGI("Frame(O) timestamp = %" PRIu64 ", received %zu frame(s)", event.frames[0].timestamp,
+          event.frames.size());
+    for (const VideoFrame& frame : event.frames) {
+        size_t count = 0;
+        for (size_t i = 0; i < frame.data.size(); i++) {
+            if (frame.data[i] > 250) {
+                count++;
+            }
+        }
+        if (count > 6) {
+            return Classification::DEEP_PRESS;
+        }
+    }
+
+    return Classification::NONE;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace classifier
+}  // namespace input
+}  // namespace hardware
+}  // namespace android
diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h
new file mode 100644
index 0000000..0858ecb
--- /dev/null
+++ b/input/classifier/1.0/default/InputClassifier.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
+#define ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
+
+#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace input {
+namespace classifier {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+
+struct InputClassifier : public IInputClassifier {
+    // Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
+    Return<Classification> classify(
+        const ::android::hardware::input::classifier::V1_0::MotionEvent& event) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace classifier
+}  // namespace input
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
diff --git a/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc
new file mode 100644
index 0000000..f799bf4
--- /dev/null
+++ b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc
@@ -0,0 +1,9 @@
+service vendor.input.classifier-1-0 /vendor/bin/hw/android.hardware.input.classifier@1.0-service-example
+    # Must be specified if "disabled" is set. This HAL will only start if requested via getService
+    interface android.hardware.input.classifier@1.0::IInputClassifier default
+    class hal
+    user nobody
+    # will not be restarted if it exits until it is requested to be restarted
+    oneshot
+    # will only be started when requested
+    disabled
diff --git a/input/classifier/1.0/default/manifest_input.classifier.xml b/input/classifier/1.0/default/manifest_input.classifier.xml
new file mode 100644
index 0000000..8634169
--- /dev/null
+++ b/input/classifier/1.0/default/manifest_input.classifier.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.input.classifier</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/input/classifier/1.0/default/service.cpp b/input/classifier/1.0/default/service.cpp
new file mode 100644
index 0000000..6ef2118
--- /dev/null
+++ b/input/classifier/1.0/default/service.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.input.classifier@1.0"
+
+#include <inttypes.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+#include "InputClassifier.h"
+#include "android/hardware/input/classifier/1.0/IInputClassifier.h"
+
+using android::sp;
+using android::status_t;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::input::classifier::V1_0::IInputClassifier;
+using android::hardware::input::classifier::V1_0::implementation::InputClassifier;
+
+int main() {
+    sp<IInputClassifier> classifier = new InputClassifier();
+
+    configureRpcThreadpool(1, true);
+    const status_t status = classifier->registerAsService();
+
+    if (status != android::OK) {
+        ALOGE("Could not register InputClassifier HAL!");
+        return EXIT_FAILURE;  // or handle error
+    }
+
+    joinRpcThreadpool();
+    LOG_ALWAYS_FATAL("Under normal operation, joinRpcThreadpool should never return");
+    return EXIT_FAILURE;
+}
diff --git a/input/classifier/1.0/types.hal b/input/classifier/1.0/types.hal
new file mode 100644
index 0000000..244ecd9
--- /dev/null
+++ b/input/classifier/1.0/types.hal
@@ -0,0 +1,829 @@
+/*
+ * Copyright (C) 2019 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.input.classifier@1.0;
+
+
+/**
+ * Constants that identify each individual axis of a motion event.
+ */
+enum Axis : uint64_t {
+    /**
+     * Axis constant: X axis of a motion event.
+     *
+     * - For a touch screen, reports the absolute X screen position of the center of
+     * the touch contact area.  The units are display pixels.
+     * - For a touch pad, reports the absolute X surface position of the center of the touch
+     * contact area. The units are device-dependent.
+     * - For a mouse, reports the absolute X screen position of the mouse pointer.
+     * The units are display pixels.
+     * - For a trackball, reports the relative horizontal displacement of the trackball.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     * - For a joystick, reports the absolute X position of the joystick.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     */
+    X = 0,
+    /**
+     * Axis constant: Y axis of a motion event.
+     *
+     * - For a touch screen, reports the absolute Y screen position of the center of
+     * the touch contact area.  The units are display pixels.
+     * - For a touch pad, reports the absolute Y surface position of the center of the touch
+     * contact area. The units are device-dependent.
+     * - For a mouse, reports the absolute Y screen position of the mouse pointer.
+     * The units are display pixels.
+     * - For a trackball, reports the relative vertical displacement of the trackball.
+     * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+     * - For a joystick, reports the absolute Y position of the joystick.
+     * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+     */
+    Y = 1,
+    /**
+     * Axis constant: Pressure axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the approximate pressure applied to the surface
+     * by a finger or other tool.  The value is normalized to a range from
+     * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+     * may be generated depending on the calibration of the input device.
+     * - For a trackball, the value is set to 1 if the trackball button is pressed
+     * or 0 otherwise.
+     * - For a mouse, the value is set to 1 if the primary mouse button is pressed
+     * or 0 otherwise.
+     */
+    PRESSURE = 2,
+    /**
+     * Axis constant: Size axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the approximate size of the contact area in
+     * relation to the maximum detectable size for the device.  The value is normalized
+     * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+     * although it is not a linear scale. This value is of limited use.
+     * To obtain calibrated size information, see
+     * {@link TOUCH_MAJOR} or {@link TOOL_MAJOR}.
+     */
+    SIZE = 3,
+    /**
+     * Axis constant: TouchMajor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the major axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are display pixels.
+     * - For a touch pad, reports the length of the major axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are device-dependent.
+     */
+    TOUCH_MAJOR = 4,
+    /**
+     * Axis constant: TouchMinor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the minor axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are display pixels.
+     * - For a touch pad, reports the length of the minor axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     */
+    TOUCH_MINOR = 5,
+    /**
+     * Axis constant: ToolMajor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the major axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * - For a touch pad, reports the length of the major axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     *
+     * The tool size may be larger than the touch size since the tool may not be fully
+     * in contact with the touch sensor.
+     */
+    TOOL_MAJOR = 6,
+    /**
+     * Axis constant: ToolMinor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the minor axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * - For a touch pad, reports the length of the minor axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     *
+     * The tool size may be larger than the touch size since the tool may not be fully
+     * in contact with the touch sensor.
+     */
+    TOOL_MINOR = 7,
+    /**
+     * Axis constant: Orientation axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the orientation of the finger
+     * or tool in radians relative to the vertical plane of the device.
+     * An angle of 0 radians indicates that the major axis of contact is oriented
+     * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+     * indicates that the major axis of contact is oriented to the right.  A negative angle
+     * indicates that the major axis of contact is oriented to the left.
+     * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+     * (finger pointing fully right).
+     * - For a stylus, the orientation indicates the direction in which the stylus
+     * is pointing in relation to the vertical axis of the current orientation of the screen.
+     * The range is from -PI radians to PI radians, where 0 is pointing up,
+     * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+     * is pointing right.  See also {@link TILT}.
+     */
+    ORIENTATION = 8,
+    /**
+     * Axis constant: Vertical Scroll axis of a motion event.
+     *
+     * - For a mouse, reports the relative movement of the vertical scroll wheel.
+     * The value is normalized to a range from -1.0 (down) to 1.0 (up).
+     *
+     * The framework may use this axis to scroll views vertically.
+     */
+    VSCROLL = 9,
+    /**
+     * Axis constant: Horizontal Scroll axis of a motion event.
+     *
+     * - For a mouse, reports the relative movement of the horizontal scroll wheel.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     *
+     * The framework may use this axis to scroll views horizontally.
+     */
+    HSCROLL = 10,
+    /**
+     * Axis constant: Z axis of a motion event.
+     *
+     * - For a joystick, reports the absolute Z position of the joystick.
+     * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+     * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+     * to report the absolute X position of the second joystick instead.</em>
+     */
+    Z = 11,
+    /**
+     * Axis constant: X Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the X axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     */
+    RX = 12,
+    /**
+     * Axis constant: Y Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the Y axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     */
+    RY = 13,
+    /**
+     * Axis constant: Z Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the Z axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     * On game pads with two analog joysticks, this axis is often reinterpreted
+     * to report the absolute Y position of the second joystick instead.
+     */
+    RZ = 14,
+    /**
+     * Axis constant: Hat X axis of a motion event.
+     *
+     * - For a joystick, reports the absolute X position of the directional hat control.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     */
+    HAT_X = 15,
+    /**
+     * Axis constant: Hat Y axis of a motion event.
+     *
+     * - For a joystick, reports the absolute Y position of the directional hat control.
+     * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+     */
+    HAT_Y = 16,
+    /**
+     * Axis constant: Left Trigger axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the left trigger control.
+     * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+     */
+    LTRIGGER = 17,
+    /**
+     * Axis constant: Right Trigger axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the right trigger control.
+     * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+     */
+    RTRIGGER = 18,
+    /**
+     * Axis constant: Throttle axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the throttle control.
+     * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+     */
+    THROTTLE = 19,
+    /**
+     * Axis constant: Rudder axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the rudder control.
+     * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+     */
+    RUDDER = 20,
+    /**
+     * Axis constant: Wheel axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the steering wheel control.
+     * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+     */
+    WHEEL = 21,
+    /**
+     * Axis constant: Gas axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the gas (accelerator) control.
+     * The value is normalized to a range from 0.0 (no acceleration)
+     * to 1.0 (maximum acceleration).
+     */
+    GAS = 22,
+    /**
+     * Axis constant: Brake axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the brake control.
+     * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+     */
+    BRAKE = 23,
+    /**
+     * Axis constant: Distance axis of a motion event.
+     *
+     * - For a stylus, reports the distance of the stylus from the screen.
+     * A value of 0.0 indicates direct contact and larger values indicate increasing
+     * distance from the surface.
+     */
+    DISTANCE = 24,
+    /**
+     * Axis constant: Tilt axis of a motion event.
+     *
+     * - For a stylus, reports the tilt angle of the stylus in radians where
+     * 0 radians indicates that the stylus is being held perpendicular to the
+     * surface, and PI/2 radians indicates that the stylus is being held flat
+     * against the surface.
+     */
+    TILT = 25,
+    /**
+     * Axis constant:  Generic scroll axis of a motion event.
+     *
+     * - This is used for scroll axis motion events that can't be classified as strictly
+     *   vertical or horizontal. The movement of a rotating scroller is an example of this.
+     */
+    SCROLL = 26,
+    /**
+     * Axis constant: The movement of x position of a motion event.
+     *
+     * - For a mouse, reports a difference of x position between the previous position.
+     * This is useful when pointer is captured, in that case the mouse pointer doesn't
+     * change the location but this axis reports the difference which allows the app
+     * to see how the mouse is moved.
+     */
+    RELATIVE_X = 27,
+    /**
+     * Axis constant: The movement of y position of a motion event.
+     *
+     * Same as {@link RELATIVE_X}, but for y position.
+     */
+    RELATIVE_Y = 28,
+    /**
+     * Axis constant: Generic 1 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_1 = 32,
+    /**
+     * Axis constant: Generic 2 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_2 = 33,
+    /**
+     * Axis constant: Generic 3 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_3 = 34,
+    /**
+     * Axis constant: Generic 4 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_4 = 35,
+    /**
+     * Axis constant: Generic 5 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_5 = 36,
+    /**
+     * Axis constant: Generic 6 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_6 = 37,
+    /**
+     * Axis constant: Generic 7 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_7 = 38,
+    /**
+     * Axis constant: Generic 8 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_8 = 39,
+    /**
+     * Axis constant: Generic 9 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_9 = 40,
+    /**
+     * Axis constant: Generic 10 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_10 = 41,
+    /**
+     * Axis constant: Generic 11 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_11 = 42,
+    /**
+     * Axis constant: Generic 12 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_12 = 43,
+    /**
+     * Axis constant: Generic 13 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_13 = 44,
+    /**
+     * Axis constant: Generic 14 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_14 = 45,
+    /**
+     * Axis constant: Generic 15 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_15 = 46,
+    /**
+     * Axis constant: Generic 16 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_16 = 47,
+};
+
+/**
+ * Tool type of a pointer
+ */
+enum ToolType: uint8_t {
+    UNKNOWN = 0,
+    FINGER = 1,
+    STYLUS = 2,
+    MOUSE = 3,
+    ERASER = 4,
+};
+
+/**
+ * Properties of a particular pointer. Analogous to Android's PointerProperties.
+ */
+struct PointerProperties {
+    /**
+     * A number identifying a specific pointer. When a pointer is lifted,
+     * this value may be reused by another new pointer, even during the
+     * same gesture. For example, if there are two pointers touching the screen
+     * at the same time, they might have pointer ID's of 0 and 1. If the
+     * pointer with id = 0 is lifted, while the pointer with id = 1 remains, and
+     * a new pointer is placed on the screen, then the new pointer may receive
+     * an id of 0. While a pointer is active, it is guaranteed to keep the same
+     * id.
+     */
+    int32_t id;
+    /**
+     * Type of tool used to make contact, such as a finger or stylus, if known.
+     */
+    ToolType toolType;
+};
+
+/**
+ * Pointer coordinate data. Analogous to Android's PointerCoords.
+ */
+struct PointerCoords {
+    /**
+     * Bitfield of axes that are present in this structure.
+     */
+    bitfield<Axis> bits;
+    /**
+     * The values corresponding to each non-zero axis. This vector only
+     * contains non-zero entries. If an axis that is not currently specified
+     * in "bits" is requested, a zero value is returned.
+     * There are only as many values stored here
+     * as there are non-zero bits in the "bits" field.
+     * The values are position-packed. So the first non-zero axis will be
+     * at position 0, the next non-zero axis will be at position 1, and so on.
+     */
+    vec<float> values;
+};
+
+enum SourceClass: uint8_t {
+    NONE = 1 << 0,
+    BUTTON = 1 << 1,
+    POINTER = 1 << 2,
+    NAVIGATION = 1 << 3,
+    POSITION = 1 << 4,
+    JOYSTICK = 1 << 5,
+};
+
+/**
+ * Input sources
+ */
+enum Source: uint32_t {
+    UNKNOWN = 0,
+    KEYBOARD = (1 << 8) | SourceClass:BUTTON,
+    DPAD = (1 << 9) | SourceClass:BUTTON,
+    GAMEPAD = (1 << 10) | SourceClass:BUTTON,
+    TOUCHSCREEN = (1 << 12) | SourceClass:POINTER,
+    MOUSE = (1 << 13) | SourceClass:POINTER,
+    STYLUS = (1 << 14) | SourceClass:POINTER,
+    BLUETOOTH_STYLUS = (1 << 15) | STYLUS,
+    TRACKBALL = (1 << 16) | SourceClass:NAVIGATION,
+    MOUSE_RELATIVE = (1 << 17) | SourceClass:NAVIGATION,
+    TOUCHPAD = (1 << 20) | SourceClass:POSITION,
+    TOUCH_NAVIGATION = (1 << 21) | SourceClass:NONE,
+    ROTARY_ENCODER = (1 << 22) | SourceClass:NONE,
+    JOYSTICK = (1 << 24) | SourceClass:JOYSTICK,
+    ANY = 0xFFFFFF00,
+};
+
+/** Motion event actions */
+enum Action: int32_t {
+    /** A pressed gesture has started, the motion contains the initial starting location. */
+    DOWN = 0,
+    /**
+     * A pressed gesture has finished, the motion contains the final release location
+     * as well as any intermediate points since the last down or move event.
+     */
+    UP = 1,
+    /**
+     * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+     * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point.
+     */
+    MOVE = 2,
+    /**
+     * The current gesture has been aborted.
+     * You will not receive any more points in it. You must treat this as
+     * an up event, but not perform any action that you normally would.
+     */
+    CANCEL = 3,
+    /**
+     * A movement has happened outside of the normal bounds of the UI element.
+     * This does not provide a full gesture, but only the initial location of the movement/touch.
+     */
+    OUTSIDE = 4,
+    /**
+     * A non-primary pointer has gone down.
+     */
+    POINTER_DOWN = 5,
+    /**
+     * A non-primary pointer has gone up.
+     */
+    POINTER_UP = 6,
+    /**
+     * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+     * The motion contains the most recent point, as well as any intermediate points since
+     * the last hover move event.
+     */
+    HOVER_MOVE = 7,
+    /**
+     * The motion event contains relative vertical and/or horizontal scroll offsets.
+     * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
+     * and AMOTION_EVENT_AXIS_HSCROLL.
+     * The pointer may or may not be down when this event is dispatched.
+     * The framework will always deliver this action to the window under the pointer, which
+     * may not be the window currently touched.
+     */
+    SCROLL = 8,
+    /**
+     * The pointer is not down but has entered the boundaries of a window or view.
+     */
+    HOVER_ENTER = 9,
+    /**
+     * The pointer is not down but has exited the boundaries of a window or view.
+     */
+    HOVER_EXIT = 10,
+    /**
+     * One or more buttons have been pressed.
+     */
+    BUTTON_PRESS = 11,
+    /**
+     * One or more buttons have been released.
+     */
+    BUTTON_RELEASE = 12,
+};
+
+/** Edge flags */
+enum EdgeFlag : int32_t {
+    /** No edges are intersected */
+    NONE = 0,
+    /** Motion intersected top edge of the screen */
+    TOP = 1 << 0,
+    /** Motion intersected bottom edge of the screen */
+    BOTTOM = 1 << 1,
+    /** Motion intersected left edge of the screen */
+    LEFT = 1 << 2,
+    /** Motion intersected right edge of the screen */
+    RIGHT = 1 << 3,
+};
+
+/** Policy flags */
+enum PolicyFlag : uint32_t {
+    // The following flags originate in RawEvents
+
+    /** Event should wake the device */
+    WAKE = 1 << 0,
+    /** Key is virtual, and should generate haptic feedback */
+    VIRTUAL = 1 << 1,
+    /** Key is the special function modifier */
+    FUNCTION = 1 << 2,
+    /**
+     * Key represents a special gesture that has been detected
+     * by the touch firmware or driver.
+     */
+    GESTURE = 1 << 3,
+
+    // The following flags may be generated here in the InputClassifier HAL
+    // or in later InputListener stages
+
+    /** Event was injected */
+    INJECTED = 1 << 24,
+    /**
+     * Event comes from a trusted source, such as a directly attached input
+     * device or an application with system-wide event injection permission.
+     */
+    TRUSTED = 1 << 25,
+    /** Event has passed through an input filter. */
+    FILTERED = 1 << 26,
+    /** Disable automatic key repeating behaviour. */
+    DISABLE_KEY_REPEAT = 1 << 27,
+
+    // The following flags are set by the input reader policy as it intercepts each event
+
+    /** Device was in an interactive state when the event was intercepted */
+    INTERACTIVE = 1 << 29,
+    /** Event should be dispatched to applications */
+    PASS_TO_USER = 1 << 30,
+};
+
+/**
+ * Buttons that are associated with motion events.
+ */
+enum Button : int32_t {
+    NONE = 0,
+    PRIMARY = 1 << 0,
+    SECONDARY = 1 << 1,
+    TERTIARY = 1 << 2,
+    BACK = 1 << 3,
+    FORWARD = 1 << 4,
+    STYLUS_PRIMARY = 1 << 5,
+    STYLUS_SECONDARY = 1 << 6,
+};
+
+/**
+ * Meta key / modifier state
+ */
+enum Meta : int32_t {
+    NONE = 0,
+
+    /** One of the ALT meta keys is pressed. */
+    ALT_ON = 1 << 1, // 0x02
+
+    /** The left ALT meta key is pressed. */
+    ALT_LEFT_ON = 1 << 4, // 0x10
+
+    /** The right ALT meta key is pressed. */
+    ALT_RIGHT_ON = 1 << 5, // 0x20
+
+    /** One of the SHIFT meta keys is pressed. */
+    SHIFT_ON = 1 << 0, // 0x01
+
+    /** The left SHIFT meta key is pressed. */
+    SHIFT_LEFT_ON = 1 << 6, // 0x40
+
+    /** The right SHIFT meta key is pressed. */
+    SHIFT_RIGHT_ON = 1 << 7, // 0x80
+
+    /** The SYM meta key is pressed. */
+    SYM_ON = 1 << 2, // 0x04
+
+    /** The FUNCTION meta key is pressed. */
+    FUNCTION_ON = 1 << 3, // 0x08
+
+    /** One of the CTRL meta keys is pressed. */
+    CTRL_ON = 1 << 12, // 0x1000
+
+    /** The left CTRL meta key is pressed. */
+    CTRL_LEFT_ON = 1 << 13, // 0x2000
+
+    /** The right CTRL meta key is pressed. */
+    CTRL_RIGHT_ON = 1 << 14, // 0x4000
+
+    /** One of the META meta keys is pressed. */
+    META_ON = 1 << 16, // 0x10000
+
+    /** The left META meta key is pressed. */
+    META_LEFT_ON = 1 << 17, // 0x20000
+
+    /** The right META meta key is pressed. */
+    META_RIGHT_ON = 1 << 18, //0x40000
+
+    /** The CAPS LOCK meta key is on. */
+    CAPS_LOCK_ON = 1 << 20, // 0x100000
+
+    /** The NUM LOCK meta key is on. */
+    NUM_LOCK_ON = 1 << 21, // 0x200000
+
+    /** The SCROLL LOCK meta key is on. */
+    SCROLL_LOCK_ON = 1 << 22, // 0x400000
+};
+
+/**
+ * Motion event flags
+ */
+enum Flag : int32_t {
+    /**
+     * Indicates that the window that received this motion event is partly
+     * or wholly obscured by another visible window above it. This flag is set to true
+     * even if the event did not directly pass through the obscured area.
+     * A security sensitive application can check this flag to identify situations in which
+     * a malicious application may have covered up part of its content for the purpose
+     * of misleading the user or hijacking touches. An appropriate response might be
+     * to drop the suspect touches or to take additional precautions to confirm the user's
+     * actual intent.
+     */
+    WINDOW_IS_OBSCURED = 1 << 0,
+    /**
+     * This flag indicates that the event has been generated by a gesture generator. It
+     * could be used, for example, to determine whether touch slop should be applied.
+     */
+    IS_GENERATED_GESTURE = 1 << 3, // 0x8
+    /**
+     * Motion event is inconsistent with previously sent motion events.
+     */
+    TAINTED = 1 << 31, // 0x80000000
+};
+
+/**
+ * Touch heatmap.
+ *
+ * The array is a 2-D row-major matrix with dimensions (height, width).
+ * The heatmap data does not rotate when device orientation changes.
+ *
+ * Example:
+ *
+ * If the data in the array is:
+ * data[i] = i for i in 0 .. 59,
+ * then it can be represented as follows:
+ *
+ *  <--    width   -- >
+ *   0  1  2  3  4  5   ^
+ *   6  7  8  9 10 11   |
+ *  12 12 14 15 16 17   |
+ *  18    ...      23   | height
+ *  24    ...      29   |
+ *  30    ...      35   |
+ *  36    ...      41   |
+ *  42    ...      47   |
+ *  48    ...      53   |
+ *  54    ...      59   v
+ *
+ * Looking at the device in standard portrait orientation,
+ * the element "0" is the top left of the screen,
+ * "5" is at the top right, and "59" is the bottom right.
+ * Here width=6, and height=10.
+ */
+struct VideoFrame {
+    /**
+     * Video frame data.
+     * Size of the data is width * height.
+     */
+    vec<int16_t> data;
+    uint32_t width;
+    uint32_t height;
+    /**
+     * Time at which the frame was collected, in nanoseconds.
+     * Measured with the same clock that is used to populate MotionEvent times.
+     */
+    uint64_t timestamp;
+};
+
+/**
+ * Analogous to Android's native MotionEvent / NotifyMotionArgs.
+ * Stores the basic information about pointer movements.
+ */
+struct MotionEvent {
+    // InputEvent fields
+    /**
+     * The id of the device which produced this event.
+     */
+    int32_t deviceId;
+    /**
+     * The source type of this event.
+     */
+    Source source;
+    /**
+     * The display id associated with this event.
+     */
+    int32_t displayId;
+
+    // NotifyMotionArgs fields
+    /**
+     * Time when the initial touch down occurred, in nanoseconds.
+     */
+    int64_t downTime;
+    /**
+     * Time when this event occurred, in nanoseconds.
+     */
+    int64_t eventTime;
+    /**
+     * The kind of action being performed.
+     */
+    Action action;
+    /**
+     * For ACTION_POINTER_DOWN or ACTION_POINTER_UP, this contains the associated pointer index.
+     * The index may be used to get information about the pointer that has gone down or up.
+     */
+    uint8_t actionIndex;
+    /**
+     * The button that has been modified during a press or release action.
+     */
+    Button actionButton;
+    /**
+     * The motion event flags.
+     */
+    bitfield<Flag> flags;
+    /**
+     * The motion event policy flags.
+     */
+    bitfield<PolicyFlag> policyFlags;
+    /**
+     * The edges, if any, that were touched by this motion event.
+     */
+    bitfield<EdgeFlag> edgeFlags;
+    /**
+     * The state of any meta / modifier keys that were in effect when the event was generated.
+     */
+    bitfield<Meta> metaState;
+    /**
+     * The state of buttons that are pressed.
+     */
+    bitfield<Button> buttonState;
+    /**
+     * The precision of the X coordinate being reported.
+     */
+    float xPrecision;
+    /**
+     * The precision of the Y coordinate being reported.
+     */
+    float yPrecision;
+    /**
+     * The properties of each pointer present in this motion event.
+     */
+    vec<PointerProperties> pointerProperties;
+    /**
+     * The coordinates of each pointer.
+     */
+    vec<PointerCoords> pointerCoords;
+
+    // Additional fields from NotifyMotionArgs
+    /**
+     * Device time at which the event occurred, in microseconds.
+     * Will wrap after a little over an hour.
+     */
+    uint32_t deviceTimestamp;
+    /**
+     * The video frames, if any, associated with the current or previous motion events.
+     */
+    vec<VideoFrame> frames;
+};
+
+
+enum Classification : uint8_t {
+    NONE = 0,
+    /**
+     * Too early to classify the gesture, need more events.
+     */
+    AMBIGUOUS_GESTURE = 1,
+    /**
+     * User is force-pressing the screen.
+     */
+    DEEP_PRESS = 2,
+};
diff --git a/keymaster/3.0/vts/functional/keymaster_tags.h b/keymaster/3.0/vts/functional/keymaster_tags.h
index f241ef1..8544bf7 100644
--- a/keymaster/3.0/vts/functional/keymaster_tags.h
+++ b/keymaster/3.0/vts/functional/keymaster_tags.h
@@ -274,7 +274,10 @@
  */
 template <typename ValueT> class NullOr {
     template <typename T> struct reference_initializer {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+#pragma GCC diagnostic pop
     };
     template <typename T> struct pointer_initializer {
         static T init() { return nullptr; }
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 61c444c..97dab68 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -282,7 +282,10 @@
 class NullOr {
     template <typename T>
     struct reference_initializer {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+#pragma GCC diagnostic pop
     };
     template <typename T>
     struct pointer_initializer {
diff --git a/radio/1.4/Android.bp b/radio/1.4/Android.bp
index ad114f3..32f9712 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -30,6 +30,7 @@
         "DataConnActiveStatus",
         "DataProfileInfo",
         "DataRegStateResult",
+        "EmergencyCallRouting",
         "EmergencyNumber",
         "EmergencyNumberSource",
         "EmergencyServiceCategory",
diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal
index 8438777..b0810a4 100644
--- a/radio/1.4/IRadio.hal
+++ b/radio/1.4/IRadio.hal
@@ -18,9 +18,11 @@
 
 import @1.0::Dial;
 import @1.2::DataRequestReason;
+import @1.2::NetworkScanRequest;
 import @1.3::IRadio;
 import @1.4::AccessNetwork;
 import @1.4::DataProfileInfo;
+import @1.4::EmergencyCallRouting;
 import @1.4::EmergencyServiceCategory;
 import @1.4::RadioAccessFamily;
 
@@ -101,21 +103,26 @@
     oneway setDataProfile_1_4(int32_t serial, vec<DataProfileInfo> profiles);
 
     /**
-     * Initiate emergency voice call, with zero or more emergency service category(s).
+     * Initiate emergency voice call, with zero or more emergency service category(s) and routing
+     * information for handling the call. Android uses this request to make its emergency call
+     * instead of using @1.0::IRadio.dial if the 'address' in the 'dialInfo' field is identified
+     * as an emergency number by Android.
      *
-     * Note this API is the same as IRadio.dial except using the
-     * @1.4::EmergencyServiceCategory as the input param.
+     * In multi-sim senario, this radio request is sent through the IRadio service that serves
+     * the subscription the emergency number belongs to, no matter of the PUK/PIN state of the
+     * subscription and the service state.
      *
-     * If the number in the 'dialInfo' field is identified as an emergency number in Android,
-     * Android use this request for its emergency call instead of @1.0::IRadio.dial. The
-     * implementation decides how to handle the call (e.g. emergency routing or normal
-     * routing).
+     * Some countries or carriers require some emergency numbers that must be handled with normal
+     * call routing or emergency routing. If the 'routing' field is specified as
+     * @1.4::EmergencyNumberRouting#NORMAL, the implementation must use normal call routing to
+     * handle the call; if it is specified as @1.4::EmergencyNumberRouting#EMERGENCY, the
+     * implementation must use emergency routing to handle the call; if it is
+     * @1.4::EmergencyNumberRouting#UNKNOWN, Android does not know how to handle the call.
      *
      * If the dialed emergency number does not have a specified emergency service category, the
-     * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED; iff either the
-     * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED or the underlying
+     * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED; if the underlying
      * technology used to request emergency services does not support the emergency service
-     * category, the interpretation of the categories is defined by implementation.
+     * category, the categories may be ignored.
      *
      * Reference: 3gpp TS 22.101, Section 10 - Emergency Calls
      *
@@ -123,11 +130,23 @@
      * @param dialInfo the same @1.0::Dial information used by @1.0::IRadio.dial.
      * @param categories bitfield<@1.4::EmergencyServiceCategory> the Emergency Service Category(s)
      *     of the call.
+     * @param routing @1.4::EmergencyCallRouting the emergency call routing information.
      *
      * Response function is IRadioResponse.emergencyDialResponse()
      */
     oneway emergencyDial(int32_t serial, Dial dialInfo,
-            bitfield<EmergencyServiceCategory> categories);
+            bitfield<EmergencyServiceCategory> categories, EmergencyCallRouting routing);
+
+    /**
+     * Starts a network scan
+     *
+     * @param serial Serial number of request.
+     * @param request Defines the radio networks/bands/channels which need to be scanned.
+     *
+     * Same API as @1.2::IRadio.startNetworkScan_1_2, except using the
+     * @1.4::IRadioResponse.startNetworkScanResponse_1_4 as the response.
+     */
+    oneway startNetworkScan_1_4(int32_t serial, NetworkScanRequest request);
 
     /**
      * Query the preferred network type bitmap.
diff --git a/radio/1.4/IRadioIndication.hal b/radio/1.4/IRadioIndication.hal
index 626b494..a58d19c 100644
--- a/radio/1.4/IRadioIndication.hal
+++ b/radio/1.4/IRadioIndication.hal
@@ -27,17 +27,17 @@
      * Report the current list of emergency numbers
      *
      * Each emergency number (@1.4::EmergencyNumber) in the emergency number list contains a
-     * dialing number, zero or more service category(s), mobile country code, and source(s) that
-     * indicate where it comes from.
+     * dialing number, zero or more service category(s), mobile country code, mobile network code,
+     * and source(s) that indicate where it comes from.
      *
-     * Radio must report all the valid emergency numbers with known mobile country code and
-     * emergency service categories from all available sources including network signaling, sim,
-     * modem/oem configuration, and default configuration (112 and 911 must be always available;
-     * additionally, 000, 08, 110, 999, 118 and 119 must be available when sim is not present).
-     * Radio shall not report emergency numbers that are invalid in the current locale. The
-     * reported emergency number list must not have duplicate @1.4::EmergencyNumber entries. Please
-     * refer the documentation of @1.4::EmergencyNumber to construct each emergency number to
-     * report.
+     * Radio must report all the valid emergency numbers with known mobile country code, mobile
+     * network code and emergency service categories from all available sources including network
+     * signaling, sim, modem/oem configuration, and default configuration (112 and 911 must be
+     * always available; additionally, 000, 08, 110, 999, 118 and 119 must be available when sim
+     * is not present). Radio shall not report emergency numbers that are invalid in the current
+     * locale. The reported emergency number list must not have duplicate @1.4::EmergencyNumber
+     * entries. Please refer the documentation of @1.4::EmergencyNumber to construct each
+     * emergency number to report.
      *
      * Radio must report the complete list of emergency numbers whenever the emergency numbers in
      * the list are changed or whenever the client and the radio server are connected.
diff --git a/radio/1.4/IRadioResponse.hal b/radio/1.4/IRadioResponse.hal
index df40969..a58a5c1 100644
--- a/radio/1.4/IRadioResponse.hal
+++ b/radio/1.4/IRadioResponse.hal
@@ -50,6 +50,23 @@
 
     /**
      * @param info Response info struct containing response type, serial no. and error
+     *
+     * Same API as @1.1::IRadioResponse.startNetworkScanResponse, except disallowing error codes
+     * OPERATION_NOT_ALLOWED and REQUEST_NOT_SUPPORTED.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway startNetworkScanResponse_1_4(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
      * @param cellInfo List of current cell information known to radio
      *
      * Valid errors returned:
diff --git a/radio/1.4/types.hal b/radio/1.4/types.hal
index d0eb0ac..74613af 100644
--- a/radio/1.4/types.hal
+++ b/radio/1.4/types.hal
@@ -53,7 +53,7 @@
 
 /**
  * Emergency number contains information of number, one or more service category(s), mobile country
- * code (mcc), and source(s) that indicate where it comes from.
+ * code (mcc), mobile network country (mnc) and source(s) that indicate where it comes from.
  *
  * If the source of the emergency number is associated with country, field ‘mcc’ must be provided;
  * otherwise the field ‘mcc’ must be an empty string.
@@ -155,6 +155,25 @@
     DEFAULT = 1 << 3,
 };
 
+/**
+ * Indicates how the implementation should handle the emergency call if it is required by Android.
+ */
+enum EmergencyCallRouting : int32_t {
+    /**
+     * Indicates Android does not require how to handle the corresponding emergency call; it is
+     * decided by implementation.
+     */
+    UNKNOWN = 0,
+    /**
+     * Indicates the implementation must handle the call through emergency routing.
+     */
+    EMERGENCY = 1,
+    /**
+     * Indicates the implementation must handle the call through normal call routing.
+     */
+    NORMAL = 2,
+};
+
 enum RadioTechnology : @1.0::RadioTechnology {
     /** 5G NR. */
     NR = 20,
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index 37b7349..be7415b 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -24,10 +24,12 @@
 
 using ::android::hardware::EventFlag;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
 using ::android::hardware::sensors::V1_0::Result;
 using ::android::hardware::sensors::V1_0::SensorInfo;
 using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
 using ::android::hardware::sensors::V2_0::ISensors;
+using ::android::hardware::sensors::V2_0::ISensorsCallback;
 
 template <typename EnumType>
 constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
@@ -36,6 +38,16 @@
 
 constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
 
+struct SensorsCallback : ISensorsCallback {
+    Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& /* sensorInfos */) {
+        return Return<void>();
+    }
+
+    Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& /* sensorHandles */) {
+        return Return<void>();
+    }
+};
+
 bool SensorsHidlEnvironmentV2_0::resetHal() {
     bool succeed = false;
     do {
@@ -63,7 +75,7 @@
         }
 
         mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(),
-                             nullptr /* TODO: callback */);
+                             new SensorsCallback());
 
         std::vector<SensorInfo> sensorList;
         if (!mSensors->getSensorsList([&](const hidl_vec<SensorInfo>& list) { sensorList = list; })
diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp
new file mode 100644
index 0000000..28370d6
--- /dev/null
+++ b/vibrator/1.3/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.vibrator@1.3",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IVibrator.hal",
+    ],
+    interfaces: [
+        "android.hardware.vibrator@1.0",
+        "android.hardware.vibrator@1.1",
+        "android.hardware.vibrator@1.2",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/vibrator/1.3/IVibrator.hal b/vibrator/1.3/IVibrator.hal
new file mode 100644
index 0000000..01c2801
--- /dev/null
+++ b/vibrator/1.3/IVibrator.hal
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator@1.3;
+
+import @1.0::Status;
+import @1.2::IVibrator;
+
+interface IVibrator extends @1.2::IVibrator {
+  /**
+   * Returns whether the vibrator supports control through an alternate interface.
+   */
+  supportsExternalControl() generates (bool supports);
+
+  /**
+   * Enables/disables control override of vibrator to audio.
+   *
+   * When this API is set, the vibrator control should be ceded to audio system
+   * for haptic audio. While this is enabled, issuing of other commands to control
+   * the vibrator is unsupported and the resulting behavior is undefined. Amplitude
+   * control may or may not be supported and is reflected in the return value of
+   * supportsAmplitudeControl() while this is enabled. When this is disabled, the
+   * vibrator should resume to an off state.
+   *
+   * @param enabled Whether external control should be enabled or disabled.
+   * @return status Whether the command was successful or not. Must return
+   *                Status::UNSUPPORTED_OPERATION if external control is
+   *                not supported by the device.
+   */
+  setExternalControl(bool enabled) generates (Status status);
+};
diff --git a/vibrator/1.3/vts/functional/Android.bp b/vibrator/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..5b4c893
--- /dev/null
+++ b/vibrator/1.3/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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: "VtsHalVibratorV1_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalVibratorV1_3TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.vibrator@1.0",
+        "android.hardware.vibrator@1.1",
+        "android.hardware.vibrator@1.2",
+        "android.hardware.vibrator@1.3",
+    ],
+    test_suites: ["general-tests"],
+}
+
diff --git a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
new file mode 100644
index 0000000..a67d1dc
--- /dev/null
+++ b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "vibrator_hidl_hal_test"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/vibrator/1.0/types.h>
+#include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <unistd.h>
+
+using ::android::sp;
+using ::android::hardware::vibrator::V1_0::Status;
+using ::android::hardware::vibrator::V1_3::IVibrator;
+
+// Test environment for Vibrator HIDL HAL.
+class VibratorHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static VibratorHidlEnvironment* Instance() {
+        static VibratorHidlEnvironment* instance = new VibratorHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IVibrator>(); }
+
+   private:
+    VibratorHidlEnvironment() {}
+};
+
+// The main test class for VIBRATOR HIDL HAL 1.3.
+class VibratorHidlTest_1_3 : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        vibrator = ::testing::VtsHalHidlTargetTestBase::getService<IVibrator>(
+            VibratorHidlEnvironment::Instance()->getServiceName<IVibrator>());
+        ASSERT_NE(vibrator, nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+    sp<IVibrator> vibrator;
+};
+
+TEST_F(VibratorHidlTest_1_3, ChangeVibrationalExternalControl) {
+    if (vibrator->supportsExternalControl()) {
+        EXPECT_EQ(Status::OK, vibrator->setExternalControl(true));
+        sleep(1);
+        EXPECT_EQ(Status::OK, vibrator->setExternalControl(false));
+        sleep(1);
+    }
+}
+
+TEST_F(VibratorHidlTest_1_3, SetExternalControlReturnUnsupportedOperationIfNotSupported) {
+    if (!vibrator->supportsExternalControl()) {
+        EXPECT_EQ(Status::UNSUPPORTED_OPERATION, vibrator->setExternalControl(true));
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(VibratorHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    VibratorHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 3189db4..397ad17 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -45,6 +45,7 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
     ],
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index a3fdf27..3555c2e 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -87,7 +88,19 @@
 
     uint32_t configureChipForStaIfaceAndGetCapabilities() {
         configureChipForIfaceType(IfaceType::STA, true);
-        const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+
+        sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted =
+            ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_);
+
+        std::pair<WifiStatus, uint32_t> status_and_caps;
+
+        if (chip_converted != nullptr) {
+            // Call the newer HAL version
+            status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3);
+        } else {
+            status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+        }
+
         if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
             EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status_and_caps.first.code);
             return 0;
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 78d7a85..6662314 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -24,6 +24,8 @@
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
index d3a983c..6323547 100644
--- a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/wifi/1.1/IWifi.h>
 #include <android/hardware/wifi/1.1/IWifiChip.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -58,7 +59,19 @@
         ChipModeId mode_id;
         EXPECT_TRUE(configureChipToSupportIfaceType(
             wifi_chip_, IfaceType::STA, &mode_id));
-        const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+
+        sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted =
+            ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_);
+
+        std::pair<WifiStatus, uint32_t> status_and_caps;
+
+        if (chip_converted != nullptr) {
+            // Call the newer HAL version
+            status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3);
+        } else {
+            status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+        }
+
         EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
         return status_and_caps.second;
     }
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index a969f65..b2956ce 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -27,6 +27,7 @@
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
index a5457b7..9d567fe 100644
--- a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/wifi/1.2/IWifiChip.h>
 #include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
@@ -104,7 +105,19 @@
     ChipModeId mode_id;
     EXPECT_TRUE(
         configureChipToSupportIfaceType(wifi_chip_, IfaceType::STA, &mode_id));
-    const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+
+    sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted =
+        ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_);
+
+    std::pair<WifiStatus, uint32_t> status_and_caps;
+
+    if (chip_converted != nullptr) {
+        // Call the newer HAL version
+        status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3);
+    } else {
+        status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+    }
+
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
     return status_and_caps.second;
   }
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 32ba760..3fcc39e 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <cutils/properties.h>
 #include <gmock/gmock.h>
 
 #undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
@@ -117,6 +118,19 @@
             .WillRepeatedly(testing::Return(modes));
     }
 
+    void setup_MultiIfaceCombination() {
+        // clang-format off
+        const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = {
+            {{{{IfaceType::STA}, 3}}}
+        };
+        const std::vector<V1_0::IWifiChip::ChipMode> modes = {
+            {feature_flags::chip_mode_ids::kV3, combinations}
+        };
+        // clang-format on
+        EXPECT_CALL(*feature_flags_, getChipModes())
+            .WillRepeatedly(testing::Return(modes));
+    }
+
     void assertNumberOfModes(uint32_t num_modes) {
         chip_->getAvailableModes(
             [num_modes](const WifiStatus& status,
@@ -655,6 +669,58 @@
     ASSERT_TRUE(createIface(IfaceType::AP).empty());
 }
 
+class WifiChip_MultiIfaceTest : public WifiChipTest {
+   public:
+    void SetUp() override {
+        setup_MultiIfaceCombination();
+        WifiChipTest::SetUp();
+    }
+};
+
+TEST_F(WifiChip_MultiIfaceTest, Create3Sta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithDefaultNames) {
+    property_set("wifi.interface.0", "");
+    property_set("wifi.interface.1", "");
+    property_set("wifi.interface.2", "");
+    property_set("wifi.interface", "");
+    property_set("wifi.concurrent.interface", "");
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan1");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomNames) {
+    property_set("wifi.interface.0", "test0");
+    property_set("wifi.interface.1", "test1");
+    property_set("wifi.interface.2", "test2");
+    property_set("wifi.interface", "bad0");
+    property_set("wifi.concurrent.interface", "bad1");
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "test0");
+    ASSERT_EQ(createIface(IfaceType::STA), "test1");
+    ASSERT_EQ(createIface(IfaceType::STA), "test2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomAltNames) {
+    property_set("wifi.interface.0", "");
+    property_set("wifi.interface.1", "");
+    property_set("wifi.interface.2", "");
+    property_set("wifi.interface", "testA0");
+    property_set("wifi.concurrent.interface", "testA1");
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "testA0");
+    ASSERT_EQ(createIface(IfaceType::STA), "testA1");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+}
+
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace wifi
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index 1f1aa95..e7ebc3b 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -41,6 +41,7 @@
 constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
 constexpr uint32_t kMaxRingBufferFileNum = 20;
 constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
+constexpr unsigned kMaxWlanIfaces = 100;
 
 template <typename Iface>
 void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@@ -78,16 +79,25 @@
     return nullptr;
 }
 
-std::string getWlan0IfaceName() {
-    std::array<char, PROPERTY_VALUE_MAX> buffer;
-    property_get("wifi.interface", buffer.data(), "wlan0");
-    return buffer.data();
-}
+std::string getWlanIfaceName(unsigned idx) {
+    if (idx >= kMaxWlanIfaces) {
+        CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces;
+        return {};
+    }
 
-std::string getWlan1IfaceName() {
     std::array<char, PROPERTY_VALUE_MAX> buffer;
-    property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
-    return buffer.data();
+    std::string propName = "wifi.interface." + std::to_string(idx);
+    auto res = property_get(propName.c_str(), buffer.data(), nullptr);
+    if (res > 0) return buffer.data();
+
+    if (idx == 0 || idx == 1) {
+        const char* altPropName =
+            (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
+        res = property_get(altPropName, buffer.data(), nullptr);
+        if (res > 0) return buffer.data();
+    }
+
+    return "wlan" + std::to_string(idx);
 }
 
 std::string getP2pIfaceName() {
@@ -636,13 +646,14 @@
     legacy_hal::wifi_error legacy_status;
     uint32_t legacy_feature_set;
     uint32_t legacy_logger_feature_set;
+    const auto ifname = getWlanIfaceName(0);
     std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(getWlan0IfaceName());
+        legacy_hal_.lock()->getSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), 0};
     }
     std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         // some devices don't support querying logger feature set
         legacy_logger_feature_set = 0;
@@ -703,8 +714,9 @@
     IWifiChip::ChipDebugInfo result;
     legacy_hal::wifi_error legacy_status;
     std::string driver_desc;
+    const auto ifname = getWlanIfaceName(0);
     std::tie(legacy_status, driver_desc) =
-        legacy_hal_.lock()->getDriverVersion(getWlan0IfaceName());
+        legacy_hal_.lock()->getDriverVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver version: "
                    << legacyErrorToString(legacy_status);
@@ -716,7 +728,7 @@
 
     std::string firmware_desc;
     std::tie(legacy_status, firmware_desc) =
-        legacy_hal_.lock()->getFirmwareVersion(getWlan0IfaceName());
+        legacy_hal_.lock()->getFirmwareVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware version: "
                    << legacyErrorToString(legacy_status);
@@ -734,7 +746,7 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> driver_dump;
     std::tie(legacy_status, driver_dump) =
-        legacy_hal_.lock()->requestDriverMemoryDump(getWlan0IfaceName());
+        legacy_hal_.lock()->requestDriverMemoryDump(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -749,7 +761,7 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> firmware_dump;
     std::tie(legacy_status, firmware_dump) =
-        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlan0IfaceName());
+        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -809,7 +821,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     // These are still assumed to be based on wlan0.
-    std::string ifname = getWlan0IfaceName();
+    std::string ifname = getWlanIfaceName(0);
     sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -952,7 +964,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     sp<WifiRttController> rtt =
-        new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
+        new WifiRttController(getWlanIfaceName(0), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);
     return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
 }
@@ -963,7 +975,7 @@
     std::vector<legacy_hal::wifi_ring_buffer_status>
         legacy_ring_buffer_status_vec;
     std::tie(legacy_status, legacy_ring_buffer_status_vec) =
-        legacy_hal_.lock()->getRingBuffersStatus(getWlan0IfaceName());
+        legacy_hal_.lock()->getRingBuffersStatus(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -985,7 +997,7 @@
     }
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->startRingBufferLogging(
-            getWlan0IfaceName(), ring_name,
+            getWlanIfaceName(0), ring_name,
             static_cast<
                 std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
                 verbose_level),
@@ -1002,7 +1014,7 @@
         return status;
     }
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
+        legacy_hal_.lock()->getRingBufferData(getWlanIfaceName(0), ring_name);
 
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1018,7 +1030,7 @@
 WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
-            getWlan0IfaceName());
+            getWlanIfaceName(0));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1027,7 +1039,7 @@
     legacy_hal::wifi_error legacy_status;
     legacy_hal::WakeReasonStats legacy_stats;
     std::tie(legacy_status, legacy_stats) =
-        legacy_hal_.lock()->getWakeReasonStats(getWlan0IfaceName());
+        legacy_hal_.lock()->getWakeReasonStats(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -1059,10 +1071,10 @@
             }
         };
         legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
-            getWlan0IfaceName(), on_alert_callback);
+            getWlanIfaceName(0), on_alert_callback);
     } else {
         legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
-            getWlan0IfaceName());
+            getWlanIfaceName(0));
     }
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1070,20 +1082,20 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal(
     V1_1::IWifiChip::TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::resetTxPowerScenarioInternal() {
     auto legacy_status =
-        legacy_hal_.lock()->resetTxPowerScenario(getWlan0IfaceName());
+        legacy_hal_.lock()->resetTxPowerScenario(getWlanIfaceName(0));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
     auto legacy_status = legacy_hal_.lock()->setLatencyMode(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1099,7 +1111,7 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
     TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1179,7 +1191,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRingBufferCallbackHandler(
-            getWlan0IfaceName(), on_ring_buffer_data_callback);
+            getWlanIfaceName(0), on_ring_buffer_data_callback);
 
     if (legacy_status == legacy_hal::WIFI_SUCCESS) {
         debug_ring_buffer_cb_registered_ = true;
@@ -1213,7 +1225,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
-            getWlan0IfaceName(), on_radio_mode_change_callback);
+            getWlanIfaceName(0), on_radio_mode_change_callback);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1330,22 +1342,17 @@
     return false;
 }
 
-// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
-// This is based on the assumption that we'll have a max of 2 concurrent
-// AP/STA ifaces.
+// Return the first wlan (wlan0, wlan1 etc.) not already in use.
+// This doesn't check the actual presence of these interfaces.
 std::string WifiChip::allocateApOrStaIfaceName() {
-    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
-    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
-    if (!ap_iface.get() && !sta_iface.get()) {
-        return getWlan0IfaceName();
-    }
-    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
-    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
-    if (!ap_iface.get() && !sta_iface.get()) {
-        return getWlan1IfaceName();
+    for (unsigned i = 0; i < kMaxWlanIfaces; i++) {
+        const auto ifname = getWlanIfaceName(i);
+        if (findUsingName(ap_ifaces_, ifname)) continue;
+        if (findUsingName(sta_ifaces_, ifname)) continue;
+        return ifname;
     }
     // This should never happen. We screwed up somewhere if it did.
-    CHECK(0) << "wlan0 and wlan1 in use already!";
+    CHECK(false) << "All wlan interfaces in use already!";
     return {};
 }
 
diff --git a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
index e195ade..71e90ac 100644
--- a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -43,6 +43,13 @@
     virtual void TearDown() override { stopWifi(); }
 
    protected:
+    bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
+        const auto& status_and_caps =
+            HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+        return (status_and_caps.second & cap_mask) != 0;
+    }
+
     sp<IWifiStaIface> wifi_sta_iface_;
 };
 
@@ -61,3 +68,30 @@
         EXPECT_NE(0, status_and_mac.second[i]);
     }
 }
+
+/*
+ * GetLinkLayerStats_1_3
+ * Ensures that calls to get link layer stats V1_3 will retrieve a non-empty
+ * StaLinkLayerStats after link layer stats collection is enabled.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
+        // No-op if link layer stats is not supported.
+        return;
+    }
+
+    // Enable link layer stats collection.
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
+                  .code);
+    // Retrieve link layer stats.
+    const auto& status_and_stats =
+        HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats_1_3);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code);
+    EXPECT_GT(status_and_stats.second.timeStampInMs, 0u);
+    // Disable link layer stats collection.
+    EXPECT_EQ(
+        WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
+}