Fix enforcement of sensor's slowest rate am: 663720b29f
am: 6528410dbd

Change-Id: I3026783f4b9442d59939b2e2bf1755971a517b15
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
index 880bc75..10dda56 100644
--- a/cmds/bugreportz/Android.mk
+++ b/cmds/bugreportz/Android.mk
@@ -25,6 +25,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := bugreportz_test
+LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_CFLAGS := -Werror -Wall
diff --git a/cmds/bugreportz/AndroidTest.xml b/cmds/bugreportz/AndroidTest.xml
new file mode 100644
index 0000000..38b6276
--- /dev/null
+++ b/cmds/bugreportz/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for bugreportz_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="bugreportz_test->/data/local/tmp/bugreportz_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="bugreportz_test" />
+    </test>
+</configuration>
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 18a4078..a1b6a51 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -138,7 +138,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := dumpstate_test_fixture
-
+LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
diff --git a/cmds/dumpstate/AndroidTest.xml b/cmds/dumpstate/AndroidTest.xml
new file mode 100644
index 0000000..f189489
--- /dev/null
+++ b/cmds/dumpstate/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for dumpstate_test_fixture">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="dumpstate_test_fixture->/data/local/tmp/dumpstate_test_fixture" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="dumpstate_test_fixture" />
+    </test>
+</configuration>
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index d8a754c..6a81cfc 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -38,23 +38,21 @@
  * frameworks/base/services/core/java/com/android/server/pm/Installer.java
  ***************************************************************************/
 constexpr int DEXOPT_PUBLIC         = 1 << 1;
-constexpr int DEXOPT_SAFEMODE       = 1 << 2;
-constexpr int DEXOPT_DEBUGGABLE     = 1 << 3;
-constexpr int DEXOPT_BOOTCOMPLETE   = 1 << 4;
-constexpr int DEXOPT_PROFILE_GUIDED = 1 << 5;
-constexpr int DEXOPT_SECONDARY_DEX  = 1 << 6;
+constexpr int DEXOPT_DEBUGGABLE     = 1 << 2;
+constexpr int DEXOPT_BOOTCOMPLETE   = 1 << 3;
+constexpr int DEXOPT_PROFILE_GUIDED = 1 << 4;
+constexpr int DEXOPT_SECONDARY_DEX  = 1 << 5;
 // DEXOPT_FORCE, DEXOPT_STORAGE_CE, DEXOPT_STORAGE_DE are exposed for secondary
 // dex files only. Primary apks are analyzed in PackageManager and installd
 // does not need to know if the compilation is forced or on what kind of storage
 // the dex files are.
-constexpr int DEXOPT_FORCE          = 1 << 7;
-constexpr int DEXOPT_STORAGE_CE     = 1 << 8;
-constexpr int DEXOPT_STORAGE_DE     = 1 << 9;
+constexpr int DEXOPT_FORCE          = 1 << 6;
+constexpr int DEXOPT_STORAGE_CE     = 1 << 7;
+constexpr int DEXOPT_STORAGE_DE     = 1 << 8;
 
 /* all known values for dexopt flags */
 constexpr int DEXOPT_MASK =
     DEXOPT_PUBLIC
-    | DEXOPT_SAFEMODE
     | DEXOPT_DEBUGGABLE
     | DEXOPT_BOOTCOMPLETE
     | DEXOPT_PROFILE_GUIDED
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index ff838ce..299ea17 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -472,7 +472,8 @@
                 case 6: {
                     // Version 1 had:
                     constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
-                    constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
+                    // Note: DEXOPT_SAFEMODE has been removed.
+                    // constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
                     constexpr int OLD_DEXOPT_DEBUGGABLE     = 1 << 3;
                     constexpr int OLD_DEXOPT_BOOTCOMPLETE   = 1 << 4;
                     constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
@@ -480,7 +481,6 @@
                     int input = atoi(param);
                     package_parameters_.dexopt_flags =
                             ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
-                            ReplaceMask(input, OLD_DEXOPT_SAFEMODE, DEXOPT_SAFEMODE) |
                             ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
                             ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
                             ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 39d92a7..d3d396f 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -46,7 +46,6 @@
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    shared_libs: ["libcutils"],
-    static_libs: ["libselinux"],
+    shared_libs: ["libcutils", "libselinux_vendor"],
     init_rc: ["vndservicemanager.rc"],
 }
diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp
new file mode 100644
index 0000000..d4c037a
--- /dev/null
+++ b/cmds/surfacereplayer/Android.bp
@@ -0,0 +1,4 @@
+subdirs = [
+    "proto",
+    "replayer",
+]
\ No newline at end of file
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
new file mode 100644
index 0000000..dda80bb
--- /dev/null
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -0,0 +1,10 @@
+cc_library_static {
+    name: "libtrace_proto",
+    srcs: [
+        "src/trace.proto",
+    ],
+    proto: {
+        type: "lite",
+        export_proto_headers: true,
+    },
+}
diff --git a/cmds/surfacereplayer/proto/Android.mk b/cmds/surfacereplayer/proto/Android.mk
deleted file mode 100644
index 3cf1148..0000000
--- a/cmds/surfacereplayer/proto/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-proto-files-under, src)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-
-LOCAL_MODULE := libtrace_proto
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
new file mode 100644
index 0000000..5caceec
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -0,0 +1,66 @@
+cc_library_shared {
+    name: "libsurfacereplayer",
+    clang: true,
+    srcs: [
+        "BufferQueueScheduler.cpp",
+        "Event.cpp",
+        "Replayer.cpp",
+    ],
+    cppflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wno-format",
+	"-Wno-c++98-compat-pedantic",
+	"-Wno-float-conversion",
+	"-Wno-disabled-macro-expansion",
+	"-Wno-float-equal",
+	"-Wno-sign-conversion",
+	"-Wno-padded",
+	"-std=c++14",
+    ],
+    static_libs: [
+        "libtrace_proto",
+    ],
+    shared_libs: [
+        "libEGL",
+        "libGLESv2",
+        "libbinder",
+        "liblog",
+        "libcutils",
+        "libgui",
+        "libui",
+        "libutils",
+        "libprotobuf-cpp-lite",
+        "libbase",
+        "libnativewindow",
+    ],
+    export_include_dirs: [
+        ".",
+    ],
+}
+
+cc_binary {
+    name: "surfacereplayer",
+    clang: true,
+    srcs: [
+        "Main.cpp",
+    ],
+    shared_libs: [
+        "libprotobuf-cpp-lite",
+        "libsurfacereplayer",
+        "libutils",
+        "libgui",
+    ],
+    static_libs: [
+        "libtrace_proto",
+    ],
+    cppflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+	"-Wno-c++98-compat-pedantic",
+	"-Wno-float-conversion",
+	"-Wno-disabled-macro-expansion",
+	"-Wno-float-equal",
+	"-std=c++14",
+    ],
+}
diff --git a/cmds/surfacereplayer/replayer/Android.mk b/cmds/surfacereplayer/replayer/Android.mk
deleted file mode 100644
index 1dd926c..0000000
--- a/cmds/surfacereplayer/replayer/Android.mk
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 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.
-
-LOCAL_TARGET_DIR := $(TARGET_OUT_DATA)/local/tmp
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(call first-makefiles-under, /frameworks/native/cmds/surfacereplayer/proto)
-
-include $(CLEAR_VARS)
-
-LOCAL_CPPFLAGS := -Weverything -Werror
-LOCAL_CPPFLAGS := -Wno-unused-parameter
-LOCAL_CPPFLAGS := -Wno-format
-
-LOCAL_MODULE := libsurfacereplayer
-
-LOCAL_SRC_FILES := \
-    BufferQueueScheduler.cpp \
-    Event.cpp \
-    Replayer.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    libEGL \
-    libGLESv2 \
-    libbinder \
-    liblog \
-    libcutils \
-    libgui \
-    libui \
-    libutils \
-    libprotobuf-cpp-lite \
-    libbase \
-    libnativewindow \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtrace_proto \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/..
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := surfacereplayer
-
-LOCAL_SRC_FILES := \
-    Main.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    libprotobuf-cpp-lite \
-    libsurfacereplayer \
-    libutils \
-    libgui \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtrace_proto \
-
-LOCAL_CPPFLAGS := -Weverything -Werror
-LOCAL_CPPFLAGS := -Wno-unused-parameter
-
-LOCAL_MODULE_PATH := $(LOCAL_TARGET_DIR)
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/surfacereplayer/replayer/Main.cpp b/cmds/surfacereplayer/replayer/Main.cpp
index dd1dd7d..7090bdb 100644
--- a/cmds/surfacereplayer/replayer/Main.cpp
+++ b/cmds/surfacereplayer/replayer/Main.cpp
@@ -24,7 +24,7 @@
  * 5. Exit successfully or print error statement
  */
 
-#include <replayer/Replayer.h>
+#include <Replayer.h>
 
 #include <csignal>
 #include <iostream>
diff --git a/cmds/vr/pose/pose.cpp b/cmds/vr/pose/pose.cpp
index 2288a86..faceb67 100644
--- a/cmds/vr/pose/pose.cpp
+++ b/cmds/vr/pose/pose.cpp
@@ -28,7 +28,7 @@
                " px, py, pz as position (0,0,0 if omitted).\n"
             << "  --mode=mode: sets mode to one of normal, head_turn:slow, "
                "head_turn:fast, rotate:slow, rotate:medium, rotate:fast, "
-               "circle_strafe.\n"
+               "circle_strafe, float, motion_sickness.\n"
             << "  --unfreeze: sets the mode to normal.\n"
             << "  --log_controller=[true|false]: starts and stops controller"
                " logs\n"
@@ -150,6 +150,12 @@
   } else if (value == "circle_strafe") {
     *mode = DVR_POSE_MODE_MOCK_CIRCLE_STRAFE;
     return true;
+  } else if (value == "float") {
+    *mode = DVR_POSE_MODE_FLOAT;
+    return true;
+  } else if (value == "motion_sickness") {
+    *mode = DVR_POSE_MODE_MOCK_MOTION_SICKNESS;
+    return true;
   } else {
     return false;
   }
diff --git a/data/etc/android.hardware.radio.xml b/data/etc/android.hardware.radio.xml
new file mode 100644
index 0000000..f718c47
--- /dev/null
+++ b/data/etc/android.hardware.radio.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard set of features for a broadcast radio. -->
+<permissions>
+    <feature name="android.hardware.radio" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.euicc.xml b/data/etc/android.hardware.telephony.euicc.xml
new file mode 100644
index 0000000..167ed6a
--- /dev/null
+++ b/data/etc/android.hardware.telephony.euicc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices with an eUICC. -->
+<permissions>
+    <feature name="android.hardware.telephony.euicc" />
+</permissions>
diff --git a/include/ui/DebugUtils.h b/include/ui/DebugUtils.h
index 8483808..30f4a59 100644
--- a/include/ui/DebugUtils.h
+++ b/include/ui/DebugUtils.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <system/graphics.h>
+#include <ui/PixelFormat.h>
 
 #include <string>
 
@@ -25,3 +26,4 @@
 std::string decodeRange(android_dataspace dataspace);
 std::string dataspaceDetails(android_dataspace dataspace);
 std::string decodeColorMode(android_color_mode colormode);
+std::string decodePixelFormat(android::PixelFormat format);
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 0d25176..a20154f 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -23,5 +23,6 @@
 cc_library_static {
     name: "libarect",
     host_supported: true,
+    vendor_available: true,
     export_include_dirs: ["include"],
 }
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 3ef8b4a..693bace 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -15,6 +15,7 @@
 cc_library_static {
     name: "libmath",
     host_supported: true,
+    vendor_available: true,
     export_include_dirs: ["include"],
 }
 
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index d759acb..938d426 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -63,4 +63,11 @@
     ],
 }
 
+llndk_library {
+    name: "libnativewindow",
+    symbol_file: "libnativewindow.map.vndk.txt",
+    unversioned: true,
+    export_include_dirs: ["include"],
+}
+
 subdirs = ["tests"]
diff --git a/libs/nativewindow/libnativewindow.map.vndk.txt b/libs/nativewindow/libnativewindow.map.vndk.txt
new file mode 100644
index 0000000..eed4e19
--- /dev/null
+++ b/libs/nativewindow/libnativewindow.map.vndk.txt
@@ -0,0 +1,44 @@
+LIBNATIVEWINDOW {
+  global:
+    AHardwareBuffer_acquire;
+    AHardwareBuffer_allocate;
+    AHardwareBuffer_describe;
+    AHardwareBuffer_fromHardwareBuffer;
+    AHardwareBuffer_getNativeHandle;
+    AHardwareBuffer_lock;
+    AHardwareBuffer_recvHandleFromUnixSocket;
+    AHardwareBuffer_release;
+    AHardwareBuffer_sendHandleToUnixSocket;
+    AHardwareBuffer_toHardwareBuffer;
+    AHardwareBuffer_unlock;
+    ANativeWindowBuffer_getHardwareBuffer;
+    ANativeWindow_OemStorageGet;
+    ANativeWindow_OemStorageSet;
+    ANativeWindow_acquire;
+    ANativeWindow_cancelBuffer;
+    ANativeWindow_dequeueBuffer;
+    ANativeWindow_fromSurface;
+    ANativeWindow_fromSurfaceTexture;
+    ANativeWindow_getFormat;
+    ANativeWindow_getHeight;
+    ANativeWindow_getWidth;
+    ANativeWindow_lock;
+    ANativeWindow_query;
+    ANativeWindow_queryf;
+    ANativeWindow_queueBuffer;
+    ANativeWindow_release;
+    ANativeWindow_setAutoRefresh;
+    ANativeWindow_setBufferCount;
+    ANativeWindow_setBufferDataSpace;
+    ANativeWindow_setBuffersDimensions;
+    ANativeWindow_setBuffersFormat;
+    ANativeWindow_setBuffersGeometry;
+    ANativeWindow_setBuffersTimestamp;
+    ANativeWindow_setBuffersTransform;
+    ANativeWindow_setSharedBufferMode;
+    ANativeWindow_setSwapInterval;
+    ANativeWindow_setUsage;
+    ANativeWindow_unlockAndPost;
+  local:
+    *;
+};
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 5ccf178..ab48a7f 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -65,7 +65,7 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.configstore@1.0",
-	"android.hardware.configstore-utils",
+        "android.hardware.configstore-utils",
         "libbase",
         "libnativeloader",
         "libcutils",
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 882bd7c..94b68e7 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <ui/DebugUtils.h>
+#include <ui/PixelFormat.h>
 
 #include <android-base/stringprintf.h>
 #include <string>
@@ -145,6 +146,9 @@
 }
 
 std::string dataspaceDetails(android_dataspace dataspace) {
+    if (dataspace == 0) {
+        return "Default (0)";
+    }
     return android::base::StringPrintf("%s %s %s", decodeStandard(dataspace).c_str(),
                                        decodeTransfer(dataspace).c_str(),
                                        decodeRange(dataspace).c_str());
@@ -185,3 +189,36 @@
 
     return android::base::StringPrintf("Unknown color mode %d", colorMode);
 }
+
+// Converts a PixelFormat to a human-readable string.  Max 11 chars.
+// (Could use a table of prefab String8 objects.)
+std::string decodePixelFormat(android::PixelFormat format) {
+    switch (format) {
+        case android::PIXEL_FORMAT_UNKNOWN:
+            return std::string("Unknown/None");
+        case android::PIXEL_FORMAT_CUSTOM:
+            return std::string("Custom");
+        case android::PIXEL_FORMAT_TRANSLUCENT:
+            return std::string("Translucent");
+        case android::PIXEL_FORMAT_TRANSPARENT:
+            return std::string("Transparent");
+        case android::PIXEL_FORMAT_OPAQUE:
+            return std::string("Opaque");
+        case android::PIXEL_FORMAT_RGBA_8888:
+            return std::string("RGBA_8888");
+        case android::PIXEL_FORMAT_RGBX_8888:
+            return std::string("RGBx_8888");
+        case android::PIXEL_FORMAT_RGBA_FP16:
+            return std::string("RGBA_FP16");
+        case android::PIXEL_FORMAT_RGBA_1010102:
+            return std::string("RGBA_1010102");
+        case android::PIXEL_FORMAT_RGB_888:
+            return std::string("RGB_888");
+        case android::PIXEL_FORMAT_RGB_565:
+            return std::string("RGB_565");
+        case android::PIXEL_FORMAT_BGRA_8888:
+            return std::string("BGRA_8888");
+        default:
+            return android::base::StringPrintf("Unknown %#08x", format);
+    }
+}
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index ed75f84..6802fa9 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -105,6 +105,8 @@
   DVR_POSE_MODE_MOCK_ROTATE_MEDIUM,
   DVR_POSE_MODE_MOCK_ROTATE_FAST,
   DVR_POSE_MODE_MOCK_CIRCLE_STRAFE,
+  DVR_POSE_MODE_FLOAT,
+  DVR_POSE_MODE_MOCK_MOTION_SICKNESS,
 
   // Always last.
   DVR_POSE_MODE_COUNT,
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index d0996f0..7de8c62 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -625,6 +625,11 @@
 #define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
 #endif
 
+#ifndef EGL_KHR_no_config_context
+#define EGL_KHR_no_config_context 1
+#define EGL_NO_CONFIG_KHR                 EGL_CAST(EGLConfig,0)
+#endif /* EGL_KHR_no_config_context */
+
 #ifndef EGL_ANDROID_get_frame_timestamps
 #define EGL_ANDROID_get_frame_timestamps 1
 #define EGL_TIMESTAMPS_ANDROID 0x3430
@@ -667,6 +672,16 @@
 #define EGL_GL_COLORSPACE_BT2020_PQ_EXT   0x3340
 #endif /* EGL_EXT_gl_colorspace_bt2020_pq */
 
+#ifndef EGL_EXT_gl_colorspace_display_p3
+#define EGL_EXT_gl_colorspace_display_p3 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363
+#endif /* EGL_EXT_gl_colorspace_display_p3 */
+
+#ifndef EGL_EXT_gl_colorspace_display_p3_linear
+#define EGL_EXT_gl_colorspace_display_p3_linear 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
+#endif /* EGL_EXT_gl_colorspace_display_p3_linear */
+
 #ifndef EGL_EXT_gl_colorspace_scrgb_linear
 #define EGL_EXT_gl_colorspace_scrgb_linear 1
 #define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 9de15d0..7c4bdf9 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -79,6 +79,7 @@
 extern char const * const gBuiltinExtensionString;
 extern char const * const gExtensionString;
 
+// clang-format off
 char const * const gBuiltinExtensionString =
         "EGL_KHR_get_all_proc_addresses "
         "EGL_ANDROID_presentation_time "
@@ -86,6 +87,9 @@
         "EGL_ANDROID_get_native_client_buffer "
         "EGL_ANDROID_front_buffer_auto_refresh "
         "EGL_ANDROID_get_frame_timestamps "
+        "EGL_EXT_gl_colorspace_scrgb_linear "
+        "EGL_EXT_gl_colorspace_display_p3_linear "
+        "EGL_EXT_gl_colorspace_display_p3 "
         ;
 
 char const * const gExtensionString  =
@@ -123,6 +127,7 @@
         "EGL_IMG_context_priority "
         "EGL_KHR_no_config_context "
         ;
+// clang-format on
 
 // extensions not exposed to applications but used by the ANDROID system
 //      "EGL_ANDROID_blob_cache "               // strongly recommended
@@ -458,10 +463,55 @@
         return HAL_DATASPACE_SRGB_LINEAR;
     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
         return HAL_DATASPACE_SRGB;
+    } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
+        return HAL_DATASPACE_DISPLAY_P3_LINEAR;
+    } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
+        return HAL_DATASPACE_V0_SCRGB_LINEAR;
     }
     return dataSpace;
 }
 
+static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
+                                         EGLint& colorSpace, android_dataspace& dataSpace) {
+    colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
+    dataSpace = HAL_DATASPACE_UNKNOWN;
+    if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+        for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
+            if (*attr == EGL_GL_COLORSPACE_KHR) {
+                colorSpace = attr[1];
+                bool found = false;
+                // Verify that color space is allowed
+                if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
+                    colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
+                    found = true;
+                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
+                    found = true;
+                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
+                    found = true;
+                }
+                if (!found) {
+                    return false;
+                }
+            }
+        }
+        dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
+    }
+    return true;
+}
+
 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
                                     NativeWindowType window,
                                     const EGLint *attrib_list)
@@ -502,7 +552,8 @@
                                     &componentType);
 
         EGLint format;
-        android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+        EGLint colorSpace;
+        android_dataspace dataSpace;
         EGLint a = 0;
         EGLint r, g, b;
         r = g = b = 0;
@@ -539,12 +590,9 @@
         }
 
         // now select a corresponding sRGB format if needed
-        if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
-            for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
-                if (*attr == EGL_GL_COLORSPACE_KHR) {
-                    dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
-                }
-            }
+        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+            ALOGE("error invalid colorspace: %d", colorSpace);
+            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
         }
 
         if (format != 0) {
@@ -575,8 +623,8 @@
         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                 iDpy, config, window, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
-                    surface, cnx);
+            egl_surface_t* s =
+                    new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
             return s;
         }
 
@@ -595,12 +643,19 @@
 
     egl_connection_t* cnx = NULL;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
+    EGLint colorSpace;
+    android_dataspace dataSpace;
     if (dp) {
+        // now select a corresponding sRGB format if needed
+        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+            ALOGE("error invalid colorspace: %d", colorSpace);
+            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+        }
+
         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
                 dp->disp.dpy, config, pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
-                    surface, cnx);
+            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
             return s;
         }
     }
@@ -614,12 +669,19 @@
 
     egl_connection_t* cnx = NULL;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
+    EGLint colorSpace;
+    android_dataspace dataSpace;
     if (dp) {
+        // now select a corresponding sRGB format if needed
+        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+            ALOGE("error invalid colorspace: %d", colorSpace);
+            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+        }
+
         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
                 dp->disp.dpy, config, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
-                    surface, cnx);
+            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
             return s;
         }
     }
@@ -658,6 +720,10 @@
         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
 
     egl_surface_t const * const s = get_surface(surface);
+    if (attribute == EGL_GL_COLORSPACE_KHR) {
+        *value = s->getColorSpace();
+        return EGL_TRUE;
+    }
     return s->cnx->egl.eglQuerySurface(
             dp->disp.dpy, s->surface, attribute, value);
 }
@@ -1697,13 +1763,22 @@
     egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_SURFACE;
 
+    EGLint colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
+    android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+    // TODO: Probably need to update EGL_KHR_stream_producer_eglsurface to
+    // indicate support for EGL_GL_COLORSPACE_KHR.
+    // now select a corresponding sRGB format if needed
+    if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+        ALOGE("error invalid colorspace: %d", colorSpace);
+        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+    }
+
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
         EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
                 dp->disp.dpy, config, stream, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
-                    surface, cnx);
+            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
             return s;
         }
     }
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 6238780..837cfa9 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -55,12 +55,15 @@
 
 // ----------------------------------------------------------------------------
 
-egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config,
-        EGLNativeWindowType win, EGLSurface surface,
-        egl_connection_t const* cnx) :
-    egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
-    connected(true)
-{
+egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win,
+                             EGLSurface surface, EGLint colorSpace, egl_connection_t const* cnx)
+      : egl_object_t(dpy),
+        surface(surface),
+        config(config),
+        win(win),
+        cnx(cnx),
+        connected(true),
+        colorSpace(colorSpace) {
     if (win) {
         win->incStrong(this);
     }
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 8988905..7c3075c 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -131,12 +131,12 @@
 public:
     typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
 
-    egl_surface_t(egl_display_t* dpy, EGLConfig config,
-            EGLNativeWindowType win, EGLSurface surface,
-            egl_connection_t const* cnx);
+    egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
+                  EGLint colorSpace, egl_connection_t const* cnx);
 
     ANativeWindow* getNativeWindow() { return win; }
     ANativeWindow* getNativeWindow() const { return win; }
+    EGLint getColorSpace() const { return colorSpace; }
 
     // Try to keep the order of these fields and size unchanged. It's not public API, but
     // it's not hard to imagine native games accessing them.
@@ -149,6 +149,7 @@
 private:
     bool connected;
     void disconnect();
+    EGLint colorSpace;
 };
 
 class egl_context_t: public egl_object_t {
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 94de5af..4c13dc8 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -28,18 +28,17 @@
 #include <gui/IGraphicBufferConsumer.h>
 #include <gui/BufferQueue.h>
 
-#define PIXEL_FORMAT_FLOAT "EGL_EXT_pixel_format_float"
-
-bool hasEglPixelFormatFloat() {
-    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
-    size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
+    size_t cropExtLen = strlen(extensionName);
     size_t extsLen = strlen(exts);
-    bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
-    bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
+    bool equal = !strcmp(extensionName, exts);
+    android::String8 extString(extensionName);
+    android::String8 space(" ");
+    bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
     bool atEnd = (cropExtLen + 1) < extsLen &&
-            !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
-    bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
+            !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
+    bool inMiddle = strstr(exts, space + extString + space);
     return equal || atStart || atEnd || inMiddle;
 }
 
@@ -193,6 +192,176 @@
     EXPECT_GE(components[3], 8);
 }
 
+TEST_F(EGLTest, EGLDisplayP3) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        return;
+    }
+
+    // Test that display-p3 extensions exist
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+
+    // Use 8-bit to keep forcus on Display-P3 aspect
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+            EGL_RED_SIZE,                 8,
+            EGL_GREEN_SIZE,               8,
+            EGL_BLUE_SIZE,                8,
+            EGL_ALPHA_SIZE,               8,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+    EGLint value;
+    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(components[0], 8);
+    EXPECT_EQ(components[1], 8);
+    EXPECT_EQ(components[2], 8);
+    EXPECT_EQ(components[3], 8);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    // Create a EGLSurface
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+    EGLint winAttrs[] = {
+            // clang-format off
+            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+            EGL_NONE,              EGL_NONE
+            // clang-format on
+    };
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLDisplayP31010102) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        return;
+    }
+
+    // Test that display-p3 extensions exist
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+
+    // Use 8-bit to keep forcus on Display-P3 aspect
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+            EGL_RED_SIZE,                 10,
+            EGL_GREEN_SIZE,               10,
+            EGL_BLUE_SIZE,                10,
+            EGL_ALPHA_SIZE,               2,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+    EGLint value;
+    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(components[0], 10);
+    EXPECT_EQ(components[1], 10);
+    EXPECT_EQ(components[2], 10);
+    EXPECT_EQ(components[3], 2);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    // Create a EGLSurface
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+    EGLint winAttrs[] = {
+            // clang-format off
+            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+            EGL_NONE,              EGL_NONE
+            // clang-format on
+    };
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
 TEST_F(EGLTest, EGLConfigFP16) {
     EGLint numConfigs;
     EGLConfig config;
@@ -203,23 +372,20 @@
         return;
     }
 
-    ASSERT_TRUE(hasEglPixelFormatFloat());
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
 
-    EGLint attrs[] = {EGL_SURFACE_TYPE,
-                      EGL_WINDOW_BIT,
-                      EGL_RENDERABLE_TYPE,
-                      EGL_OPENGL_ES2_BIT,
-                      EGL_RED_SIZE,
-                      16,
-                      EGL_GREEN_SIZE,
-                      16,
-                      EGL_BLUE_SIZE,
-                      16,
-                      EGL_ALPHA_SIZE,
-                      16,
-                      EGL_COLOR_COMPONENT_TYPE_EXT,
-                      EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
-                      EGL_NONE};
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE,                 16,
+            EGL_GREEN_SIZE,               16,
+            EGL_BLUE_SIZE,                16,
+            EGL_ALPHA_SIZE,               16,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
     success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
     ASSERT_EQ(1, numConfigs);
@@ -250,6 +416,108 @@
         void onSidebandStreamChanged() override {}
     };
 
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGL_KHR_no_config_context) {
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        return;
+    }
+
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    std::vector<EGLint> contextAttributes;
+    contextAttributes.reserve(4);
+    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+    contextAttributes.push_back(2);
+    contextAttributes.push_back(EGL_NONE);
+    contextAttributes.push_back(EGL_NONE);
+
+    EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
+                                             contextAttributes.data());
+    EXPECT_NE(EGL_NO_CONTEXT, eglContext);
+    EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+    if (eglContext != EGL_NO_CONTEXT) {
+        eglDestroyContext(mEglDisplay, eglContext);
+    }
+}
+
+// Emulate what a native application would do to create a
+// 10:10:10:2 surface.
+TEST_F(EGLTest, EGLConfig1010102) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        return;
+    }
+
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+            EGL_RED_SIZE,                 10,
+            EGL_GREEN_SIZE,               10,
+            EGL_BLUE_SIZE,                10,
+            EGL_ALPHA_SIZE,               2,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+    EGLint value;
+    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(components[0], 10);
+    EXPECT_EQ(components[1], 10);
+    EXPECT_EQ(components[2], 10);
+    EXPECT_EQ(components[3], 2);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
     // Create a EGLSurface
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
diff --git a/opengl/tests/configdump/configdump.cpp b/opengl/tests/configdump/configdump.cpp
index 2a94598..c423105 100644
--- a/opengl/tests/configdump/configdump.cpp
+++ b/opengl/tests/configdump/configdump.cpp
@@ -66,8 +66,7 @@
 };
 // clang-format on
 
-int main(int argc, char** argv)
-{
+int main(int /*argc*/, char** /*argv*/) {
     EGLConfig* configs;
     EGLint n;
 
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index 9f8d166..ee88667 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -30,6 +30,7 @@
 #include <EGLUtils.h>
 
 using namespace android;
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 static void printGLString(const char *name, GLenum s) {
     // fprintf(stderr, "printGLString %s, %d\n", name, s);
@@ -46,7 +47,8 @@
 
 static void printEGLString(EGLDisplay dpy, const char *name, GLenum s) {
     const char *v = (const char *) eglQueryString(dpy, s);
-    fprintf(stderr, "GL %s = %s\n", name, v);
+    const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s);
+    fprintf(stderr, "GL %s = %s\nImplementationANDROID: %s\n", name, v, va);
 }
 
 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
@@ -263,7 +265,7 @@
     return true;
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
index 98d8aa8..22128ab 100644
--- a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
+++ b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
@@ -331,7 +331,7 @@
     printf("\n");
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
index c923b07..fad26a6 100644
--- a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
+++ b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
@@ -221,7 +221,7 @@
     printf("\n");
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml
index af13395..c2d3494 100755
--- a/opengl/tools/glgen2/registry/egl.xml
+++ b/opengl/tools/glgen2/registry/egl.xml
@@ -191,6 +191,7 @@
         <enum value="((EGLSync)0)" name="EGL_NO_SYNC"/>
         <enum value="((EGLSyncKHR)0)" name="EGL_NO_SYNC_KHR" alias="EGL_NO_SYNC"/>
         <enum value="((EGLSyncNV)0)" name="EGL_NO_SYNC_NV" alias="EGL_NO_SYNC"/>
+        <enum value="EGL_CAST(EGLConfig,0)" name="EGL_NO_CONFIG_KHR"/>
         <enum value="10000" name="EGL_DISPLAY_SCALING"/>
         <enum value="0xFFFFFFFFFFFFFFFF" name="EGL_FOREVER" type="ull"/>
         <enum value="0xFFFFFFFFFFFFFFFF" name="EGL_FOREVER_KHR" type="ull" alias="EGL_FOREVER"/>
@@ -739,7 +740,10 @@
         <enum value="50000"  name="EGL_METADATA_SCALING_EXT"/>
             <unused start="0x334B" end="0x334F"/>
         <enum value="0x3350" name="EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT"/>
-            <unused start="0x3351" end="0x339F"/>
+            <unused start="0x3351" end="0x3361"/>
+        <enum value="0x3362" name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/>
+        <enum value="0x3363" name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
+            <unused start="0x3364" end="0x339F"/>
     </enums>
 
     <enums namespace="EGL" start="0x33A0" end="0x33AF" vendor="ANGLE" comment="Reserved for Shannon Woods (Bug 13175)">
@@ -1891,6 +1895,16 @@
                 <enum name="EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_gl_colorspace_display_p3_linear" supported="egl">
+            <require>
+                <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_gl_colorspace_display_p3" supported="egl">
+            <require>
+                <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_image_dma_buf_import" supported="egl">
             <require>
                 <enum name="EGL_LINUX_DMA_BUF_EXT"/>
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index d2f8995..50589b4 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -150,7 +150,8 @@
         fd(fd), id(id), path(path), identifier(identifier),
         classes(0), configuration(NULL), virtualKeyMap(NULL),
         ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
-        timestampOverrideSec(0), timestampOverrideUsec(0) {
+        timestampOverrideSec(0), timestampOverrideUsec(0), enabled(true),
+        isVirtual(fd < 0) {
     memset(keyBitmask, 0, sizeof(keyBitmask));
     memset(absBitmask, 0, sizeof(absBitmask));
     memset(relBitmask, 0, sizeof(relBitmask));
@@ -173,6 +174,25 @@
     }
 }
 
+status_t EventHub::Device::enable() {
+    fd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+    if(fd < 0) {
+        ALOGE("could not open %s, %s\n", path.string(), strerror(errno));
+        return -errno;
+    }
+    enabled = true;
+    return OK;
+}
+
+status_t EventHub::Device::disable() {
+    close();
+    enabled = false;
+    return OK;
+}
+
+bool EventHub::Device::hasValidFd() {
+    return !isVirtual && enabled;
+}
 
 // --- EventHub ---
 
@@ -286,7 +306,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
+        if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
             struct input_absinfo info;
             if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -337,7 +357,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) {
+        if (device && device->hasValidFd() && test_bit(scanCode, device->keyBitmask)) {
             uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
             memset(keyState, 0, sizeof(keyState));
             if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
@@ -352,7 +372,7 @@
     AutoMutex _l(mLock);
 
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) {
+    if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
         Vector<int32_t> scanCodes;
         device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
         if (scanCodes.size() != 0) {
@@ -377,7 +397,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) {
+        if (device && device->hasValidFd() && test_bit(sw, device->swBitmask)) {
             uint8_t swState[sizeof_bit_array(SW_MAX + 1)];
             memset(swState, 0, sizeof(swState));
             if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) {
@@ -395,7 +415,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
+        if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
             struct input_absinfo info;
             if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -532,7 +552,7 @@
 
 void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
     int32_t sc;
-    if (device && !device->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
+    if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
         struct input_event ev;
         ev.time.tv_sec = 0;
         ev.time.tv_usec = 0;
@@ -636,7 +656,7 @@
 void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual()) {
+    if (device && device->hasValidFd()) {
         ff_effect effect;
         memset(&effect, 0, sizeof(effect));
         effect.type = FF_RUMBLE;
@@ -670,7 +690,7 @@
 void EventHub::cancelVibrate(int32_t deviceId) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual()) {
+    if (device && device->hasValidFd()) {
         if (device->ffEffectPlaying) {
             device->ffEffectPlaying = false;
 
@@ -1065,12 +1085,37 @@
         AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
 };
 
+status_t EventHub::registerDeviceForEpollLocked(Device* device) {
+    struct epoll_event eventItem;
+    memset(&eventItem, 0, sizeof(eventItem));
+    eventItem.events = EPOLLIN;
+    if (mUsingEpollWakeup) {
+        eventItem.events |= EPOLLWAKEUP;
+    }
+    eventItem.data.u32 = device->id;
+    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, device->fd, &eventItem)) {
+        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
+        return -errno;
+    }
+    return OK;
+}
+
+status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
+    if (device->hasValidFd()) {
+        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
+            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
+            return -errno;
+        }
+    }
+    return OK;
+}
+
 status_t EventHub::openDeviceLocked(const char *devicePath) {
     char buffer[80];
 
     ALOGV("Opening device: %s", devicePath);
 
-    int fd = open(devicePath, O_RDWR | O_CLOEXEC);
+    int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
     if(fd < 0) {
         ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
         return -1;
@@ -1135,13 +1180,6 @@
     // Fill in the descriptor.
     assignDescriptorLocked(identifier);
 
-    // Make file descriptor non-blocking for use with poll().
-    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
-        ALOGE("Error %d making device file descriptor non-blocking.", errno);
-        close(fd);
-        return -1;
-    }
-
     // Allocate device.  (The device object takes ownership of the fd at this point.)
     int32_t deviceId = mNextDeviceId++;
     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
@@ -1303,12 +1341,6 @@
                 break;
             }
         }
-
-        // Disable kernel key repeat since we handle it ourselves
-        unsigned int repeatRate[] = {0,0};
-        if (ioctl(fd, EVIOCSREP, repeatRate)) {
-            ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
-        }
     }
 
     // If the device isn't recognized as something we handle, don't monitor it.
@@ -1332,23 +1364,41 @@
     if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
             && device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
         device->controllerNumber = getNextControllerNumberLocked(device);
-        setLedForController(device);
+        setLedForControllerLocked(device);
     }
 
-    // Register with epoll.
-    struct epoll_event eventItem;
-    memset(&eventItem, 0, sizeof(eventItem));
-    eventItem.events = EPOLLIN;
-    if (mUsingEpollWakeup) {
-        eventItem.events |= EPOLLWAKEUP;
-    }
-    eventItem.data.u32 = deviceId;
-    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
-        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
+
+    if (registerDeviceForEpollLocked(device) != OK) {
         delete device;
         return -1;
     }
 
+    configureFd(device);
+
+    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
+            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
+         deviceId, fd, devicePath, device->identifier.name.string(),
+         device->classes,
+         device->configurationFile.string(),
+         device->keyMap.keyLayoutFile.string(),
+         device->keyMap.keyCharacterMapFile.string(),
+         toString(mBuiltInKeyboardId == deviceId));
+
+    addDeviceLocked(device);
+    return OK;
+}
+
+void EventHub::configureFd(Device* device) {
+    // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
+    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+        // Disable kernel key repeat since we handle it ourselves
+        unsigned int repeatRate[] = {0, 0};
+        if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
+            ALOGW("Unable to disable kernel key repeat for %s: %s",
+                  device->path.string(), strerror(errno));
+        }
+    }
+
     String8 wakeMechanism("EPOLLWAKEUP");
     if (!mUsingEpollWakeup) {
 #ifndef EVIOCSSUSPENDBLOCK
@@ -1357,44 +1407,67 @@
         // this feature, we need to be prepared to define the ioctl ourselves.
 #define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
 #endif
-        if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) {
+        if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
             wakeMechanism = "<none>";
         } else {
             wakeMechanism = "EVIOCSSUSPENDBLOCK";
         }
     }
-
     // Tell the kernel that we want to use the monotonic clock for reporting timestamps
     // associated with input events.  This is important because the input system
     // uses the timestamps extensively and assumes they were recorded using the monotonic
     // clock.
-    //
-    // In older kernel, before Linux 3.4, there was no way to tell the kernel which
-    // clock to use to input event timestamps.  The standard kernel behavior was to
-    // record a real time timestamp, which isn't what we want.  Android kernels therefore
-    // contained a patch to the evdev_event() function in drivers/input/evdev.c to
-    // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
-    // clock to be used instead of the real time clock.
-    //
-    // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
-    // Therefore, we no longer require the Android-specific kernel patch described above
-    // as long as we make sure to set select the monotonic clock.  We do that here.
     int clockId = CLOCK_MONOTONIC;
-    bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
+    bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
+    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
+          toString(usingClockIoctl));
+}
 
-    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
-            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
-            "wakeMechanism=%s, usingClockIoctl=%s",
-         deviceId, fd, devicePath, device->identifier.name.string(),
-         device->classes,
-         device->configurationFile.string(),
-         device->keyMap.keyLayoutFile.string(),
-         device->keyMap.keyCharacterMapFile.string(),
-         toString(mBuiltInKeyboardId == deviceId),
-         wakeMechanism.string(), toString(usingClockIoctl));
+bool EventHub::isDeviceEnabled(int32_t deviceId) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) {
+        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+        return false;
+    }
+    return device->enabled;
+}
 
-    addDeviceLocked(device);
-    return 0;
+status_t EventHub::enableDevice(int32_t deviceId) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) {
+        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+        return BAD_VALUE;
+    }
+    if (device->enabled) {
+        ALOGW("Duplicate call to %s, input device %" PRId32 " already enabled", __func__, deviceId);
+        return OK;
+    }
+    status_t result = device->enable();
+    if (result != OK) {
+        ALOGE("Failed to enable device %" PRId32, deviceId);
+        return result;
+    }
+
+    configureFd(device);
+
+    return registerDeviceForEpollLocked(device);
+}
+
+status_t EventHub::disableDevice(int32_t deviceId) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) {
+        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+        return BAD_VALUE;
+    }
+    if (!device->enabled) {
+        ALOGW("Duplicate call to %s, input device already disabled", __func__);
+        return OK;
+    }
+    unregisterDeviceFromEpollLocked(device);
+    return device->disable();
 }
 
 void EventHub::createVirtualKeyboardLocked() {
@@ -1490,7 +1563,7 @@
     mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
 }
 
-void EventHub::setLedForController(Device* device) {
+void EventHub::setLedForControllerLocked(Device* device) {
     for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
         setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
     }
@@ -1500,7 +1573,7 @@
     if (!device->keyMap.haveKeyLayout()) {
         return false;
     }
-    
+
     Vector<int32_t> scanCodes;
     device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
     const size_t N = scanCodes.size();
@@ -1510,7 +1583,7 @@
             return true;
         }
     }
-    
+
     return false;
 }
 
@@ -1556,11 +1629,7 @@
         mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
     }
 
-    if (!device->isVirtual()) {
-        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
-            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
-        }
-    }
+    unregisterDeviceFromEpollLocked(device);
 
     releaseControllerNumberLocked(device);
 
@@ -1691,6 +1760,7 @@
             }
             dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
             dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
+            dump.appendFormat(INDENT3 "Enabled: %s\n", toString(device->enabled));
             dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
             dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
             dump.appendFormat(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 6869253..727b73a 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -25,9 +25,8 @@
 #include <input/KeyCharacterMap.h>
 #include <input/VirtualKeyMap.h>
 #include <utils/String8.h>
-#include <utils/threads.h>
+#include <utils/Mutex.h>
 #include <utils/Log.h>
-#include <utils/threads.h>
 #include <utils/List.h>
 #include <utils/Errors.h>
 #include <utils/PropertyMap.h>
@@ -267,6 +266,15 @@
 
     /* Called by the heatbeat to ensures that the reader has not deadlocked. */
     virtual void monitor() = 0;
+
+    /* Return true if the device is enabled. */
+    virtual bool isDeviceEnabled(int32_t deviceId) = 0;
+
+    /* Enable an input device */
+    virtual status_t enableDevice(int32_t deviceId) = 0;
+
+    /* Disable an input device. Closes file descriptor to that device. */
+    virtual status_t disableDevice(int32_t deviceId) = 0;
 };
 
 class EventHub : public EventHubInterface
@@ -335,7 +343,7 @@
     struct Device {
         Device* next;
 
-        int fd; // may be -1 if device is virtual
+        int fd; // may be -1 if device is closed
         const int32_t id;
         const String8 path;
         const InputDeviceIdentifier identifier;
@@ -371,7 +379,11 @@
 
         void close();
 
-        inline bool isVirtual() const { return fd < 0; }
+        bool enabled; // initially true
+        status_t enable();
+        status_t disable();
+        bool hasValidFd();
+        const bool isVirtual; // set if fd < 0 is passed to constructor
 
         const sp<KeyCharacterMap>& getKeyCharacterMap() const {
             if (combinedKeyMap != NULL) {
@@ -390,6 +402,14 @@
     void closeDeviceLocked(Device* device);
     void closeAllDevicesLocked();
 
+    void configureFd(Device* device);
+
+    bool isDeviceEnabled(int32_t deviceId);
+    status_t enableDevice(int32_t deviceId);
+    status_t disableDevice(int32_t deviceId);
+    status_t registerDeviceForEpollLocked(Device* device);
+    status_t unregisterDeviceFromEpollLocked(Device* device);
+
     status_t scanDirLocked(const char *dirname);
     void scanDevicesLocked();
     status_t readNotifyLocked();
@@ -409,7 +429,7 @@
 
     int32_t getNextControllerNumberLocked(Device* device);
     void releaseControllerNumberLocked(Device* device);
-    void setLedForController(Device* device);
+    void setLedForControllerLocked(Device* device);
 
     status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
     void setLedStateLocked(Device* device, int32_t led, bool on);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 2705e13..8af9038 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -788,6 +788,18 @@
     }
 }
 
+bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex >= 0) {
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        return device->isEnabled();
+    }
+    ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+    return false;
+}
+
 void InputReader::dump(String8& dump) {
     AutoMutex _l(mLock);
 
@@ -961,6 +973,26 @@
     mMappers.clear();
 }
 
+bool InputDevice::isEnabled() {
+    return getEventHub()->isDeviceEnabled(mId);
+}
+
+void InputDevice::setEnabled(bool enabled, nsecs_t when) {
+    if (isEnabled() == enabled) {
+        return;
+    }
+
+    if (enabled) {
+        getEventHub()->enableDevice(mId);
+        reset(when);
+    } else {
+        reset(when);
+        getEventHub()->disableDevice(mId);
+    }
+    // Must change generation to flag this device as changed
+    bumpGeneration();
+}
+
 void InputDevice::dump(String8& dump) {
     InputDeviceInfo deviceInfo;
     getDeviceInfo(& deviceInfo);
@@ -1032,6 +1064,12 @@
             }
         }
 
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
+            ssize_t index = config->disabledDevices.indexOf(mId);
+            bool enabled = index < 0;
+            setEnabled(enabled, when);
+        }
+
         size_t numMappers = mMappers.size();
         for (size_t i = 0; i < numMappers; i++) {
             InputMapper* mapper = mMappers[i];
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 3171526..647f271 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -26,11 +26,14 @@
 #include <input/VelocityTracker.h>
 #include <ui/DisplayInfo.h>
 #include <utils/KeyedVector.h>
-#include <utils/threads.h>
+#include <utils/Condition.h>
+#include <utils/Thread.h>
+#include <utils/Mutex.h>
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/BitSet.h>
+#include <utils/SortedVector.h>
 
 #include <stddef.h>
 #include <unistd.h>
@@ -147,6 +150,9 @@
         // The pointer capture mode has changed.
         CHANGE_POINTER_CAPTURE = 1 << 8,
 
+        // The set of disabled input devices (disabledDevices) has changed.
+        CHANGE_ENABLED_STATE = 1 << 9,
+
         // All devices must be reopened.
         CHANGE_MUST_REOPEN = 1 << 31,
     };
@@ -237,6 +243,9 @@
     // True if pointer capture is enabled.
     bool pointerCapture;
 
+    // The set of currently disabled input devices.
+    SortedVector<int32_t> disabledDevices;
+
     InputReaderConfiguration() :
             virtualKeyQuietTime(0),
             pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
@@ -344,6 +353,9 @@
     /* Called by the heatbeat to ensures that the reader has not deadlocked. */
     virtual void monitor() = 0;
 
+    /* Returns true if the input device is enabled. */
+    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
+
     /* Runs a single iteration of the processing loop.
      * Nominally reads and processes one incoming message from the EventHub.
      *
@@ -463,6 +475,8 @@
 
     virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);
 
+    virtual bool isInputDeviceEnabled(int32_t deviceId);
+
     virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
             int32_t scanCode);
     virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
@@ -608,6 +622,9 @@
 
     inline bool isIgnored() { return mMappers.isEmpty(); }
 
+    bool isEnabled();
+    void setEnabled(bool enabled, nsecs_t when);
+
     void dump(String8& dump);
     void addMapper(InputMapper* mapper);
     void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 2e0bcd1..7082fe1 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -16,6 +16,7 @@
 
 #include "../InputReader.h"
 
+#include <inttypes.h>
 #include <utils/List.h>
 #include <gtest/gtest.h>
 #include <math.h>
@@ -161,6 +162,22 @@
         mConfig.excludedDeviceNames.push(deviceName);
     }
 
+    void addDisabledDevice(int32_t deviceId) {
+        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
+        bool currentlyEnabled = index < 0;
+        if (currentlyEnabled) {
+            mConfig.disabledDevices.add(deviceId);
+        }
+    }
+
+    void removeDisabledDevice(int32_t deviceId) {
+        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
+        bool currentlyEnabled = index < 0;
+        if (!currentlyEnabled) {
+            mConfig.disabledDevices.remove(deviceId);
+        }
+    }
+
     void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
         mPointerControllers.add(deviceId, controller);
     }
@@ -236,6 +253,11 @@
         mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin());
     }
 
+    void assertNotifyConfigurationChangedWasNotCalled() {
+        ASSERT_TRUE(mNotifyConfigurationChangedArgsQueue.empty())
+                << "Expected notifyConfigurationChanged() to not have been called.";
+    }
+
     void assertNotifyDeviceResetWasCalled(
             NotifyDeviceResetArgs* outEventArgs = NULL) {
         ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty())
@@ -246,6 +268,11 @@
         mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin());
     }
 
+    void assertNotifyDeviceResetWasNotCalled() {
+        ASSERT_TRUE(mNotifyDeviceResetArgsQueue.empty())
+                << "Expected notifyDeviceReset() to not have been called.";
+    }
+
     void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) {
         ASSERT_FALSE(mNotifyKeyArgsQueue.empty())
                 << "Expected notifyKey() to have been called.";
@@ -328,9 +355,20 @@
         KeyedVector<int32_t, KeyInfo> keysByUsageCode;
         KeyedVector<int32_t, bool> leds;
         Vector<VirtualKeyDefinition> virtualKeys;
+        bool enabled;
+
+        status_t enable() {
+            enabled = true;
+            return OK;
+        }
+
+        status_t disable() {
+            enabled = false;
+            return OK;
+        }
 
         explicit Device(uint32_t classes) :
-                classes(classes) {
+                classes(classes), enabled(true) {
         }
     };
 
@@ -363,6 +401,43 @@
         enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
     }
 
+    bool isDeviceEnabled(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == NULL) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return false;
+        }
+        return device->enabled;
+    }
+
+    status_t enableDevice(int32_t deviceId) {
+        status_t result;
+        Device* device = getDevice(deviceId);
+        if (device == NULL) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
+            return OK;
+        }
+        result = device->enable();
+        return result;
+    }
+
+    status_t disableDevice(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == NULL) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (!device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
+            return OK;
+        }
+        return device->disable();
+    }
+
     void finishDeviceScan() {
         enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
     }
@@ -1020,6 +1095,20 @@
         mFakeEventHub->assertQueueIsEmpty();
     }
 
+    void disableDevice(int32_t deviceId, InputDevice* device) {
+        mFakePolicy->addDisabledDevice(deviceId);
+        configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE, device);
+    }
+
+    void enableDevice(int32_t deviceId, InputDevice* device) {
+        mFakePolicy->removeDisabledDevice(deviceId);
+        configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE, device);
+    }
+
+    void configureDevice(uint32_t changes, InputDevice* device) {
+        device->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
+    }
+
     FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
             const String8& name, uint32_t classes, uint32_t sources,
             const PropertyMap* configuration) {
@@ -1058,6 +1147,46 @@
     ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
 }
 
+TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
+    constexpr int32_t deviceId = 1;
+    constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+    InputDevice* device = mReader->newDevice(deviceId, 0, String8("fake"), deviceClass);
+    // Must add at least one mapper or the device will be ignored!
+    FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD);
+    device->addMapper(mapper);
+    mReader->setNextDevice(device);
+    addDevice(deviceId, String8("fake"), deviceClass, NULL);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(NULL));
+
+    NotifyDeviceResetArgs resetArgs;
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+
+    ASSERT_EQ(device->isEnabled(), true);
+    disableDevice(deviceId, device);
+    mReader->loopOnce();
+
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_EQ(device->isEnabled(), false);
+
+    disableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasNotCalled();
+    mFakeListener->assertNotifyConfigurationChangedWasNotCalled();
+    ASSERT_EQ(device->isEnabled(), false);
+
+    enableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_EQ(device->isEnabled(), true);
+}
+
 TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
     FakeInputMapper* mapper = NULL;
     ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
@@ -1255,6 +1384,10 @@
     ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
 }
 
+TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsTrue) {
+    ASSERT_EQ(mDevice->isEnabled(), true);
+}
+
 TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
     // Configuration.
     InputReaderConfiguration config;
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 8c2300e..8d381b1 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -1,3 +1,73 @@
 subdirs = [
     "hidl"
 ]
+cc_library_shared {
+    name: "libsensorservice",
+
+    srcs: [
+        "BatteryService.cpp",
+        "CorrectedGyroSensor.cpp",
+        "Fusion.cpp",
+        "GravitySensor.cpp",
+        "LinearAccelerationSensor.cpp",
+        "OrientationSensor.cpp",
+        "RecentEventLogger.cpp",
+        "RotationVectorSensor.cpp",
+        "SensorDevice.cpp",
+        "SensorDirectConnection.cpp",
+        "SensorEventConnection.cpp",
+        "SensorFusion.cpp",
+        "SensorInterface.cpp",
+        "SensorList.cpp",
+        "SensorRecord.cpp",
+        "SensorService.cpp",
+        "SensorServiceUtils.cpp",
+    ],
+
+    cflags: [
+        "-DLOG_TAG=\"SensorService\"",
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+        "-fvisibility=hidden"
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "libhardware",
+        "libhardware_legacy",
+        "libutils",
+        "liblog",
+        "libbinder",
+        "libsensor",
+        "libcrypto",
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "android.hardware.sensors@1.0",
+    ],
+
+    static_libs: ["android.hardware.sensors@1.0-convert"],
+
+    // our public headers depend on libsensor
+    export_shared_lib_headers: ["libsensor"],
+}
+
+cc_binary {
+    name: "sensorservice",
+
+    srcs: ["main_sensorservice.cpp"],
+
+    shared_libs: [
+        "libsensorservice",
+        "libbinder",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
deleted file mode 100644
index cfb7231..0000000
--- a/services/sensorservice/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    BatteryService.cpp \
-    CorrectedGyroSensor.cpp \
-    Fusion.cpp \
-    GravitySensor.cpp \
-    LinearAccelerationSensor.cpp \
-    OrientationSensor.cpp \
-    RecentEventLogger.cpp \
-    RotationVectorSensor.cpp \
-    SensorDevice.cpp \
-    SensorDirectConnection.cpp \
-    SensorEventConnection.cpp \
-    SensorFusion.cpp \
-    SensorInterface.cpp \
-    SensorList.cpp \
-    SensorRecord.cpp \
-    SensorService.cpp \
-    SensorServiceUtils.cpp \
-
-LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-
-LOCAL_CFLAGS += -Wall -Werror -Wextra
-
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libhardware \
-    libhardware_legacy \
-    libutils \
-    liblog \
-    libbinder \
-    libsensor \
-    libcrypto \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    android.hardware.sensors@1.0
-
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.sensors@1.0-convert
-
-# our public headers depend on libsensor
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
-    libsensor \
-
-LOCAL_MODULE:= libsensorservice
-
-include $(BUILD_SHARED_LIBRARY)
-
-#####################################################################
-# build executable
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    main_sensorservice.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libsensorservice \
-    libbinder \
-    libutils
-
-LOCAL_CFLAGS := -Wall -Werror -Wextra
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sensorservice
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index d60768c..b5baba8 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -394,6 +394,7 @@
             }
         } else if (!mSensors.hasAnySensor()) {
             result.append("No Sensors on the device\n");
+            result.append("devInitCheck : %d\n", SensorDevice::getInstance().initCheck());
         } else {
             // Default dump the sensor list and debugging information.
             //
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b5ffc60..4d0c085 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -121,7 +121,8 @@
     ANativeWindow* const window = mNativeWindow.get();
 
 #ifdef USE_HWC2
-    mActiveColorMode = static_cast<android_color_mode_t>(-1);
+    // Set defaultColorMode to SRGB if this device supports wide-color
+    mActiveColorMode = (supportWideColor) ? HAL_COLOR_MODE_SRGB : HAL_COLOR_MODE_NATIVE;
     mDisplayHasWideColor = supportWideColor;
 #else
     (void) supportWideColor;
@@ -610,23 +611,25 @@
 
 void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
-    result.appendFormat(
-        "+ DisplayDevice: %s\n"
-        "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
-        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
-        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
-        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
-        mDisplayName.string(), mType, mHwcDisplayId,
-        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
-        mOrientation, tr.getType(), getPageFlipCount(),
-        mIsSecure, mPowerMode, mActiveConfig,
-        mVisibleLayersSortedByZ.size(),
-        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
-        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
-        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
-        tr[0][0], tr[1][0], tr[2][0],
-        tr[0][1], tr[1][1], tr[2][1],
-        tr[0][2], tr[1][2], tr[2][2]);
+    EGLint redSize, greenSize, blueSize, alphaSize;
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &redSize);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &greenSize);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &blueSize);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &alphaSize);
+    result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
+    result.appendFormat("   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
+                        "(%d:%d:%d:%d), orient=%2d (type=%08x), "
+                        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+                        mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight,
+                        mNativeWindow.get(), redSize, greenSize, blueSize, alphaSize, mOrientation,
+                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        mVisibleLayersSortedByZ.size());
+    result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
+                        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
+                        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
+                        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
+                        mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
+                        tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
 
     String8 surfaceDump;
     mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8220d0a..ae731f7 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -34,6 +34,7 @@
 #include <utils/StopWatch.h>
 #include <utils/Trace.h>
 
+#include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 
@@ -873,9 +874,6 @@
     }
 }
 
-android_dataspace Layer::getDataSpace() const {
-    return mCurrentState.dataSpace;
-}
 #else
 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer) {
@@ -1886,6 +1884,10 @@
     return true;
 }
 
+android_dataspace Layer::getDataSpace() const {
+    return mCurrentState.dataSpace;
+}
+
 uint32_t Layer::getLayerStack() const {
     auto p = getParent();
     if (p == nullptr) {
@@ -2331,11 +2333,17 @@
     visibleRegion.dump(result, "visibleRegion");
     surfaceDamageRegion.dump(result, "surfaceDamageRegion");
     sp<Client> client(mClientRef.promote());
+    PixelFormat pf = PIXEL_FORMAT_UNKNOWN;
+    const sp<GraphicBuffer>& buffer(getActiveBuffer());
+    if (buffer != NULL) {
+        pf = buffer->getPixelFormat();
+    }
 
     result.appendFormat(            "      "
             "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), "
             "crop=(%4d,%4d,%4d,%4d), finalCrop=(%4d,%4d,%4d,%4d), "
             "isOpaque=%1d, invalidate=%1d, "
+            "dataspace=%s, pixelformat=%s "
 #ifdef USE_HWC2
             "alpha=%.3f, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
 #else
@@ -2350,6 +2358,7 @@
             s.finalCrop.left, s.finalCrop.top,
             s.finalCrop.right, s.finalCrop.bottom,
             isOpaque(s), contentDirty,
+            dataspaceDetails(getDataSpace()).c_str(), decodePixelFormat(pf).c_str(),
             s.alpha, s.flags,
             s.active.transform[0][0], s.active.transform[0][1],
             s.active.transform[1][0], s.active.transform[1][1],
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9f45435..92353ae 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -192,6 +192,7 @@
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setLayerStack(uint32_t layerStack);
     bool setDataSpace(android_dataspace dataSpace);
+    android_dataspace getDataSpace() const;
     uint32_t getLayerStack() const;
     void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber);
     void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber);
@@ -275,8 +276,6 @@
     void forceClientComposition(int32_t hwcId);
     void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
 
-    android_dataspace getDataSpace() const;
-
     // callIntoHwc exists so we can update our local state and call
     // acceptDisplayChanges without unnecessarily updating the device's state
     void setCompositionType(int32_t hwcId, HWC2::Composition type,
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 7564269..f8785db 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -54,12 +54,16 @@
     // both a 16-bit primary display framebuffer and a 32-bit virtual display
     // framebuffer.
     //
+    // EGL_KHR_no_config_context is official extension to allow creating a
+    // context that works with any surface of a display.
+    //
     // The code assumes that ES2 or later is available if this extension is
     // supported.
     EGLConfig config = EGL_NO_CONFIG;
-    if (!findExtension(
-            eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
-            "EGL_ANDROIDX_no_config_context")) {
+    if (!findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+                       "EGL_ANDROIDX_no_config_context") &&
+        !findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+                       "EGL_KHR_no_config_context")) {
         config = chooseEglConfig(display, hwcFormat);
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 45cac6f..1456429 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2641,6 +2641,8 @@
     {
         Mutex::Autolock _l(mStateLock);
         if (mNumLayers >= MAX_LAYERS) {
+            ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
+                  MAX_LAYERS);
             return NO_MEMORY;
         }
         if (parent == nullptr) {
@@ -3206,6 +3208,22 @@
         getHwComposer().setPowerMode(type, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
+    } else if (mode == HWC_POWER_MODE_DOZE) {
+        // Update display while dozing
+        getHwComposer().setPowerMode(type, mode);
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenAcquired();
+            resyncToHardwareVsync(true);
+        }
+    } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+        // Leave display going to doze
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            disableHardwareVsync(true); // also cancels any in-progress resync
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenReleased();
+        }
+        getHwComposer().setPowerMode(type, mode);
     } else {
         getHwComposer().setPowerMode(type, mode);
     }
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 7070b97..290d31e 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2877,6 +2877,22 @@
         getHwComposer().setPowerMode(type, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
+    } else if (mode == HWC_POWER_MODE_DOZE) {
+        // Update display while dozing
+        getHwComposer().setPowerMode(type, mode);
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenAcquired();
+            resyncToHardwareVsync(true);
+        }
+    } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+        // Leave display going to doze
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            disableHardwareVsync(true); // also cancels any in-progress resync
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenReleased();
+        }
+        getHwComposer().setPowerMode(type, mode);
     } else {
         getHwComposer().setPowerMode(type, mode);
     }
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index 16041da..43e22a0 100644
--- a/services/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
@@ -4,7 +4,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_MODULE := SurfaceFlinger_test
-
+LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
diff --git a/services/surfaceflinger/tests/AndroidTest.xml b/services/surfaceflinger/tests/AndroidTest.xml
new file mode 100644
index 0000000..8315037
--- /dev/null
+++ b/services/surfaceflinger/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for SurfaceFlinger_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="SurfaceFlinger_test->/data/local/tmp/SurfaceFlinger_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="SurfaceFlinger_test" />
+    </test>
+</configuration>
diff --git a/services/surfaceflinger/tests/vsync/Android.mk b/services/surfaceflinger/tests/vsync/Android.mk
index 9181760..8e41617 100644
--- a/services/surfaceflinger/tests/vsync/Android.mk
+++ b/services/surfaceflinger/tests/vsync/Android.mk
@@ -15,4 +15,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_CFLAGS := -Werror
+
 include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp
index aa72c79..a1b45e6 100644
--- a/services/surfaceflinger/tests/vsync/vsync.cpp
+++ b/services/surfaceflinger/tests/vsync/vsync.cpp
@@ -20,7 +20,7 @@
 
 using namespace android;
 
-int receiver(int fd, int events, void* data)
+int receiver(int /*fd*/, int /*events*/, void* data)
 {
     DisplayEventReceiver* q = (DisplayEventReceiver*)data;
 
@@ -47,7 +47,7 @@
     return 1;
 }
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     DisplayEventReceiver myDisplayEvent;
 
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.mk b/services/surfaceflinger/tests/waitforvsync/Android.mk
index c25f5ab..932d2be 100644
--- a/services/surfaceflinger/tests/waitforvsync/Android.mk
+++ b/services/surfaceflinger/tests/waitforvsync/Android.mk
@@ -11,4 +11,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_CFLAGS := -Werror
+
 include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
index b88b04a..65eaae5 100644
--- a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
+++ b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
@@ -29,7 +29,7 @@
 #define FBIO_WAITFORVSYNC   _IOW('F', 0x20, __u32)
 #endif
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     int fd = open("/dev/graphics/fb0", O_RDWR);
     if (fd >= 0) {
         do {
diff --git a/services/vr/sensord/pose_service.cpp b/services/vr/sensord/pose_service.cpp
index 75423bb..edf4998 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -93,6 +93,10 @@
       return "DVR_POSE_MODE_MOCK_ROTATE_FAST";
     case DVR_POSE_MODE_MOCK_CIRCLE_STRAFE:
       return "DVR_POSE_MODE_MOCK_CIRCLE_STRAFE";
+    case DVR_POSE_MODE_FLOAT:
+      return "DVR_POSE_MODE_FLOAT";
+    case DVR_POSE_MODE_MOCK_MOTION_SICKNESS:
+      return "DVR_POSE_MODE_MOCK_MOTION_SICKNESS";
     default:
       return "Unknown pose mode";
   }
@@ -421,7 +425,8 @@
                       current_time_ns);
       break;
     }
-    case DVR_POSE_MODE_3DOF: {
+    case DVR_POSE_MODE_3DOF:
+    case DVR_POSE_MODE_FLOAT: {
       // Sensor fusion provides IMU-space data, transform to world space.
 
       // Constants to perform IMU orientation adjustments. Note that these
@@ -458,13 +463,25 @@
       }
       start_from_head_rotation.normalize();
 
-      // Neck / head model code procedure for when no 6dof is available.
-      // To apply the neck model, first translate the head pose to the new
-      // center of eyes, then rotate around the origin (the original head
-      // pos).
-      Vector3d position =
-          start_from_head_rotation * Vector3d(0.0, kDefaultNeckVerticalOffset,
-                                              -kDefaultNeckHorizontalOffset);
+      Vector3d position;
+      switch (pose_mode_) {
+        default:
+        case DVR_POSE_MODE_3DOF:
+          // Neck / head model code procedure for when no 6dof is available.
+          // To apply the neck model, first translate the head pose to the new
+          // center of eyes, then rotate around the origin (the original head
+          // pos).
+          position = start_from_head_rotation *
+                     Vector3d(0.0, kDefaultNeckVerticalOffset,
+                              -kDefaultNeckHorizontalOffset);
+          break;
+        case DVR_POSE_MODE_FLOAT:
+          // Change position a bit in facing direction.
+          mock_pos_offset_ += start_from_head_rotation.toRotationMatrix() * Vector3d(0, 0, -0.01);
+          ResetMockDeviatedPosition();
+          position = mock_pos_offset_;
+          break;
+      }
 
       // Update the current latency model.
       if (pose_state.timestamp_ns != 0) {
@@ -478,6 +495,26 @@
           pose_state.timestamp_ns + sensor_latency_.CurrentLatencyEstimate());
       break;
     }
+    case DVR_POSE_MODE_MOCK_MOTION_SICKNESS: {
+      double phase = std::sin(current_time_ns / 1e9) + 1;
+      // Randomize 3rd order rotation axis on phase minimum.
+      if (phase > mock_prev_phase_ && mock_diff_phase_ < 0)
+        mock_rot_axis_2_ = RandVector();
+      mock_diff_phase_ = phase - mock_prev_phase_;
+      mock_prev_phase_ = phase;
+
+      // Rotate axes all the way down.
+      mock_rot_axis_2_ = AngleAxisd(0.004 * phase, mock_rot_axis_3_) * mock_rot_axis_2_;
+      mock_rot_axis_1_ = AngleAxisd(0.002 * (std::sin(current_time_ns / 5e8 + M_PI / 2) + 1), mock_rot_axis_2_) * mock_rot_axis_1_;
+      Rotationd rotation = Rotationd(AngleAxisd(fmod(current_time_ns / 2e9, kTwoPi), mock_rot_axis_1_));
+
+      // Change position a bit.
+      mock_pos_offset_ += rotation.toRotationMatrix() * Vector3d(0, 0, 0.003 * (std::sin(current_time_ns / 6e8) + 1));
+      ResetMockDeviatedPosition();
+
+      WriteAsyncPoses(mock_pos_offset_, rotation, current_time_ns);
+      break;
+    }
     default:
     case DVR_POSE_MODE_6DOF:
       ALOGE("ERROR: invalid pose mode");
@@ -485,6 +522,13 @@
   }
 }
 
+void PoseService::ResetMockDeviatedPosition() {
+  if (mock_pos_offset_[1] < -1) mock_pos_offset_[1] = 2;
+  if (mock_pos_offset_[1] > 30) mock_pos_offset_[1] = 2;
+  if (abs(mock_pos_offset_[0]) > 30) mock_pos_offset_[0] = mock_pos_offset_[2] = 0;
+  if (abs(mock_pos_offset_[2]) > 30) mock_pos_offset_[0] = mock_pos_offset_[2] = 0;
+}
+
 pdx::Status<void> PoseService::HandleMessage(pdx::Message& msg) {
   pdx::Status<void> ret;
   const pdx::MessageInfo& info = msg.GetInfo();
@@ -638,6 +682,10 @@
   if (mode == DVR_POSE_MODE_6DOF) {
     // Only 3DoF is currently supported.
     mode = DVR_POSE_MODE_3DOF;
+  } else if (mode == DVR_POSE_MODE_MOCK_MOTION_SICKNESS) {
+    mock_rot_axis_1_ = RandVector();
+    mock_rot_axis_2_ = RandVector();
+    mock_rot_axis_3_ = RandVector();
   }
 
   pose_mode_ = mode;
diff --git a/services/vr/sensord/pose_service.h b/services/vr/sensord/pose_service.h
index 7b7adec..acf4124 100644
--- a/services/vr/sensord/pose_service.h
+++ b/services/vr/sensord/pose_service.h
@@ -102,6 +102,25 @@
   // Last known pose.
   DvrPoseAsync last_known_pose_;
 
+  // Position offset for use in pose modes.
+  Eigen::Vector3d mock_pos_offset_;
+
+  // Phase data for DVR_POSE_MODE_MOCK_MOTION_SICKNESS.
+  double mock_prev_phase_, mock_diff_phase_;
+
+  // Axis data for DVR_POSE_MODE_MOCK_MOTION_SICKNESS.
+  Eigen::Vector3d mock_rot_axis_1_, mock_rot_axis_2_, mock_rot_axis_3_;
+
+  // Return a random normalized 3d vector.
+  static Eigen::Vector3d RandVector() {
+    Eigen::Vector3d vec = Eigen::Vector3d::Random();
+    vec.normalize();
+    return vec;
+  }
+
+  // Reset mock_pos_offset_ if strayed too far
+  void ResetMockDeviatedPosition();
+
   // If this flag is true, the pose published includes a small prediction of
   // where it'll be when it's consumed.
   bool enable_pose_prediction_;