Temporarily disable 2 unratified Khronos extensions. am: 34a327b710
am: e912144263

Change-Id: I08be797e159ad6d31cf7014748cda9fc8248704d
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..03af56d
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+
+AccessModifierOffset: -4
+AlignOperands: false
+AllowShortFunctionsOnASingleLine: Inline
+AlwaysBreakBeforeMultilineStrings: false
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ConstructorInitializerIndentWidth: 6
+ContinuationIndentWidth: 8
+IndentWidth: 4
+PenaltyBreakBeforeFirstCallParameter: 100000
+SpacesBeforeTrailingComments: 1
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 a407ea2..669e8d2 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/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/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h
index 1f4387d..1c89000 100644
--- a/include/gui/ISurfaceComposerClient.h
+++ b/include/gui/ISurfaceComposerClient.h
@@ -14,55 +14,53 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_GUI_ISURFACE_COMPOSER_CLIENT_H
-#define ANDROID_GUI_ISURFACE_COMPOSER_CLIENT_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
+#pragma once
 
 #include <binder/IInterface.h>
-
-#include <ui/FrameStats.h>
+#include <binder/SafeInterface.h>
 #include <ui/PixelFormat.h>
 
 namespace android {
-// ----------------------------------------------------------------------------
 
+class FrameStats;
 class IGraphicBufferProducer;
 
-class ISurfaceComposerClient : public IInterface
-{
+class ISurfaceComposerClient : public IInterface {
 public:
     DECLARE_META_INTERFACE(SurfaceComposerClient)
 
+    enum class Tag : uint32_t {
+        CreateSurface = IBinder::FIRST_CALL_TRANSACTION,
+        DestroySurface,
+        ClearLayerFrameStats,
+        GetLayerFrameStats,
+        GetTransformToDisplayInverse,
+        Last,
+    };
+
     // flags for createSurface()
     enum { // (keep in sync with Surface.java)
-        eHidden             = 0x00000004,
-        eDestroyBackbuffer  = 0x00000020,
-        eSecure             = 0x00000080,
-        eNonPremultiplied   = 0x00000100,
-        eOpaque             = 0x00000400,
-        eProtectedByApp     = 0x00000800,
-        eProtectedByDRM     = 0x00001000,
-        eCursorWindow       = 0x00002000,
+        eHidden = 0x00000004,
+        eDestroyBackbuffer = 0x00000020,
+        eSecure = 0x00000080,
+        eNonPremultiplied = 0x00000100,
+        eOpaque = 0x00000400,
+        eProtectedByApp = 0x00000800,
+        eProtectedByDRM = 0x00001000,
+        eCursorWindow = 0x00002000,
 
-        eFXSurfaceNormal    = 0x00000000,
-        eFXSurfaceDim       = 0x00020000,
-        eFXSurfaceMask      = 0x000F0000,
+        eFXSurfaceNormal = 0x00000000,
+        eFXSurfaceDim = 0x00020000,
+        eFXSurfaceMask = 0x000F0000,
     };
 
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
      */
-    virtual status_t createSurface(
-            const String8& name, uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t flags,
-            const sp<IBinder>& parent, uint32_t windowType, uint32_t ownerUid,
-            sp<IBinder>* handle,
-            sp<IGraphicBufferProducer>* gbp) = 0;
+    virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
+                                   uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
+                                   uint32_t ownerUid, sp<IBinder>* handle,
+                                   sp<IGraphicBufferProducer>* gbp) = 0;
 
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
@@ -80,19 +78,15 @@
     virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0;
 
     virtual status_t getTransformToDisplayInverse(const sp<IBinder>& handle,
-            bool* outTransformToDisplayInverse) const = 0;
+                                                  bool* outTransformToDisplayInverse) const = 0;
 };
 
-// ----------------------------------------------------------------------------
-
-class BnSurfaceComposerClient: public BnInterface<ISurfaceComposerClient> {
+class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> {
 public:
-    virtual status_t onTransact(uint32_t code, const Parcel& data,
-            Parcel* reply, uint32_t flags = 0);
+    BnSurfaceComposerClient()
+          : SafeBnInterface<ISurfaceComposerClient>("BnSurfaceComposerClient") {}
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
 };
 
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_GUI_ISURFACE_COMPOSER_CLIENT_H
+} // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 93b8684..b225128 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -71,6 +71,10 @@
         "libutils",
     ],
 
+    export_include_dirs: [
+        "include",
+    ],
+
     clang: true,
     sanitize: {
         misc_undefined: ["integer"],
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
new file mode 100644
index 0000000..0e723c5
--- /dev/null
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -0,0 +1,621 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <cutils/compiler.h>
+
+// Set to 1 to enable CallStacks when logging errors
+#define SI_DUMP_CALLSTACKS 0
+#if SI_DUMP_CALLSTACKS
+#include <utils/CallStack.h>
+#endif
+
+#include <functional>
+#include <type_traits>
+
+namespace android {
+namespace SafeInterface {
+
+// ParcelHandler is responsible for writing/reading various types to/from a Parcel in a generic way
+class ParcelHandler {
+public:
+    explicit ParcelHandler(const char* logTag) : mLogTag(logTag) {}
+
+    // Specializations for types with dedicated handling in Parcel
+    status_t read(const Parcel& parcel, bool* b) const {
+        return callParcel("readBool", [&]() { return parcel.readBool(b); });
+    }
+    status_t write(Parcel* parcel, bool b) const {
+        return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
+            const Parcel& parcel, T* t) const {
+        return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type write(
+            Parcel* parcel, const T& t) const {
+        return callParcel("write(LightFlattenable)", [&]() { return parcel->write(t); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
+            const Parcel& parcel, T* t) const {
+        return callParcel("readParcelable", [&]() { return parcel.readParcelable(t); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
+            Parcel* parcel, const T& t) const {
+        return callParcel("writeParcelable", [&]() { return parcel->writeParcelable(t); });
+    }
+    status_t read(const Parcel& parcel, String8* str) const {
+        return callParcel("readString8", [&]() { return parcel.readString8(str); });
+    }
+    status_t write(Parcel* parcel, const String8& str) const {
+        return callParcel("writeString8", [&]() { return parcel->writeString8(str); });
+    }
+    template <typename T>
+    status_t read(const Parcel& parcel, sp<T>* pointer) const {
+        return callParcel("readNullableStrongBinder",
+                          [&]() { return parcel.readNullableStrongBinder(pointer); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type write(
+            Parcel* parcel, const sp<T>& pointer) const {
+        return callParcel("writeStrongBinder",
+                          [&]() { return parcel->writeStrongBinder(pointer); });
+    }
+    template <typename T>
+    typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write(
+            Parcel* parcel, const sp<T>& interface) const {
+        return write(parcel, IInterface::asBinder(interface));
+    }
+
+    // Templates to handle integral types. We use a struct template to require that the called
+    // function exactly matches the signedness and size of the argument (e.g., the argument isn't
+    // silently widened).
+    template <bool isSigned, size_t size, typename I>
+    struct HandleInt;
+    template <typename I>
+    struct HandleInt<true, 4, I> {
+        static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
+            return handler.callParcel("readInt32", [&]() { return parcel.readInt32(i); });
+        }
+        static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
+            return handler.callParcel("writeInt32", [&]() { return parcel->writeInt32(i); });
+        }
+    };
+    template <typename I>
+    struct HandleInt<false, 4, I> {
+        static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
+            return handler.callParcel("readUint32", [&]() { return parcel.readUint32(i); });
+        }
+        static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
+            return handler.callParcel("writeUint32", [&]() { return parcel->writeUint32(i); });
+        }
+    };
+    template <typename I>
+    typename std::enable_if<std::is_integral<I>::value, status_t>::type read(const Parcel& parcel,
+                                                                             I* i) const {
+        return HandleInt<std::is_signed<I>::value, sizeof(I), I>::read(*this, parcel, i);
+    }
+    template <typename I>
+    typename std::enable_if<std::is_integral<I>::value, status_t>::type write(Parcel* parcel,
+                                                                              I i) const {
+        return HandleInt<std::is_signed<I>::value, sizeof(I), I>::write(*this, parcel, i);
+    }
+
+private:
+    const char* const mLogTag;
+
+    // Helper to encapsulate error handling while calling the various Parcel methods
+    template <typename Function>
+    status_t callParcel(const char* name, Function f) const {
+        status_t error = f();
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            ALOG(LOG_ERROR, mLogTag, "Failed to %s, (%d: %s)", name, error, strerror(-error));
+#if SI_DUMP_CALLSTACKS
+            CallStack callStack(mLogTag);
+#endif
+        }
+        return error;
+    }
+};
+
+// Utility struct template which allows us to retrieve the types of the parameters of a member
+// function pointer
+template <typename T>
+struct ParamExtractor;
+template <typename Class, typename Return, typename... Params>
+struct ParamExtractor<Return (Class::*)(Params...)> {
+    using ParamTuple = std::tuple<Params...>;
+};
+template <typename Class, typename Return, typename... Params>
+struct ParamExtractor<Return (Class::*)(Params...) const> {
+    using ParamTuple = std::tuple<Params...>;
+};
+
+} // namespace SafeInterface
+
+template <typename Interface>
+class SafeBpInterface : public BpInterface<Interface> {
+protected:
+    SafeBpInterface(const sp<IBinder>& impl, const char* logTag)
+          : BpInterface<Interface>(impl), mLogTag(logTag) {}
+    ~SafeBpInterface() override = default;
+
+    // callRemote is used to invoke a synchronous procedure call over Binder
+    template <typename Method, typename TagType, typename... Args>
+    status_t callRemote(TagType tag, Args&&... args) const {
+        static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
+
+        // Verify that the arguments are compatible with the parameters
+        using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
+        static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
+                      "Invalid argument type");
+
+        // Write the input arguments to the data Parcel
+        Parcel data;
+        data.writeInterfaceToken(this->getInterfaceDescriptor());
+
+        status_t error = writeInputs(&data, std::forward<Args>(args)...);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by writeInputs
+            return error;
+        }
+
+        // Send the data Parcel to the remote and retrieve the reply parcel
+        Parcel reply;
+        error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
+#if SI_DUMP_CALLSTACKS
+            CallStack callStack(mLogTag);
+#endif
+            return error;
+        }
+
+        // Read the outputs from the reply Parcel into the output arguments
+        error = readOutputs(reply, std::forward<Args>(args)...);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by readOutputs
+            return error;
+        }
+
+        // Retrieve the result code from the reply Parcel
+        status_t result = NO_ERROR;
+        error = reply.readInt32(&result);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            ALOG(LOG_ERROR, mLogTag, "Failed to obtain result");
+#if SI_DUMP_CALLSTACKS
+            CallStack callStack(mLogTag);
+#endif
+            return error;
+        }
+        return result;
+    }
+
+    // callRemoteAsync is used to invoke an asynchronous procedure call over Binder
+    template <typename Method, typename TagType, typename... Args>
+    void callRemoteAsync(TagType tag, Args&&... args) const {
+        static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
+
+        // Verify that the arguments are compatible with the parameters
+        using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
+        static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
+                      "Invalid argument type");
+
+        // Write the input arguments to the data Parcel
+        Parcel data;
+        data.writeInterfaceToken(this->getInterfaceDescriptor());
+        status_t error = writeInputs(&data, std::forward<Args>(args)...);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by writeInputs
+            return;
+        }
+
+        // There will be no data in the reply Parcel since the call is one-way
+        Parcel reply;
+        error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply,
+                                         IBinder::FLAG_ONEWAY);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
+#if SI_DUMP_CALLSTACKS
+            CallStack callStack(mLogTag);
+#endif
+        }
+    }
+
+private:
+    const char* const mLogTag;
+
+    // This struct provides information on whether the decayed types of the elements at Index in the
+    // tuple types T and U (that is, the types after stripping cv-qualifiers, removing references,
+    // and a few other less common operations) are the same
+    template <size_t Index, typename T, typename U>
+    struct DecayedElementsMatch {
+    private:
+        using FirstT = typename std::tuple_element<Index, T>::type;
+        using DecayedT = typename std::decay<FirstT>::type;
+        using FirstU = typename std::tuple_element<Index, U>::type;
+        using DecayedU = typename std::decay<FirstU>::type;
+
+    public:
+        static constexpr bool value = std::is_same<DecayedT, DecayedU>::value;
+    };
+
+    // When comparing whether the argument types match the parameter types, we first decay them (see
+    // DecayedElementsMatch) to avoid falsely flagging, say, T&& against T even though they are
+    // equivalent enough for our purposes
+    template <typename T, typename U>
+    struct ArgsMatchParams {};
+    template <typename... Args, typename... Params>
+    struct ArgsMatchParams<std::tuple<Args...>, std::tuple<Params...>> {
+        static_assert(sizeof...(Args) <= sizeof...(Params), "Too many arguments");
+        static_assert(sizeof...(Args) >= sizeof...(Params), "Not enough arguments");
+
+    private:
+        template <size_t Index>
+        static constexpr typename std::enable_if<(Index < sizeof...(Args)), bool>::type
+        elementsMatch() {
+            if (!DecayedElementsMatch<Index, std::tuple<Args...>, std::tuple<Params...>>::value) {
+                return false;
+            }
+            return elementsMatch<Index + 1>();
+        }
+        template <size_t Index>
+        static constexpr typename std::enable_if<(Index >= sizeof...(Args)), bool>::type
+        elementsMatch() {
+            return true;
+        }
+
+    public:
+        static constexpr bool value = elementsMatch<0>();
+    };
+
+    // Since we assume that pointer arguments are outputs, we can use this template struct to
+    // determine whether or not a given argument is fundamentally a pointer type and thus an output
+    template <typename T>
+    struct IsPointerIfDecayed {
+    private:
+        using Decayed = typename std::decay<T>::type;
+
+    public:
+        static constexpr bool value = std::is_pointer<Decayed>::value;
+    };
+
+    template <typename T>
+    typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
+            Parcel* data, T&& t) const {
+        return SafeInterface::ParcelHandler{mLogTag}.write(data, std::forward<T>(t));
+    }
+    template <typename T>
+    typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
+            Parcel* /*data*/, T&& /*t*/) const {
+        return NO_ERROR;
+    }
+
+    // This method iterates through all of the arguments, writing them to the data Parcel if they
+    // are an input (i.e., if they are not a pointer type)
+    template <typename T, typename... Remaining>
+    status_t writeInputs(Parcel* data, T&& t, Remaining&&... remaining) const {
+        status_t error = writeIfInput(data, std::forward<T>(t));
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by writeIfInput
+            return error;
+        }
+        return writeInputs(data, std::forward<Remaining>(remaining)...);
+    }
+    static status_t writeInputs(Parcel* /*data*/) { return NO_ERROR; }
+
+    template <typename T>
+    typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type readIfOutput(
+            const Parcel& reply, T&& t) const {
+        return SafeInterface::ParcelHandler{mLogTag}.read(reply, std::forward<T>(t));
+    }
+    template <typename T>
+    static typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type readIfOutput(
+            const Parcel& /*reply*/, T&& /*t*/) {
+        return NO_ERROR;
+    }
+
+    // Similar to writeInputs except that it reads output arguments from the reply Parcel
+    template <typename T, typename... Remaining>
+    status_t readOutputs(const Parcel& reply, T&& t, Remaining&&... remaining) const {
+        status_t error = readIfOutput(reply, std::forward<T>(t));
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by readIfOutput
+            return error;
+        }
+        return readOutputs(reply, std::forward<Remaining>(remaining)...);
+    }
+    static status_t readOutputs(const Parcel& /*data*/) { return NO_ERROR; }
+};
+
+template <typename Interface>
+class SafeBnInterface : public BnInterface<Interface> {
+public:
+    explicit SafeBnInterface(const char* logTag) : mLogTag(logTag) {}
+
+protected:
+    template <typename Method>
+    status_t callLocal(const Parcel& data, Parcel* reply, Method method) {
+        CHECK_INTERFACE(this, data, reply);
+
+        // Since we need to both pass inputs into the call as well as retrieve outputs, we create a
+        // "raw" tuple, where the inputs are interleaved with actual, non-pointer versions of the
+        // outputs. When we ultimately call into the method, we will pass the addresses of the
+        // output arguments instead of their tuple members directly, but the storage will live in
+        // the tuple.
+        using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
+        typename RawConverter<std::tuple<>, ParamTuple>::type rawArgs{};
+
+        // Read the inputs from the data Parcel into the argument tuple
+        status_t error = InputReader<ParamTuple>{mLogTag}.readInputs(data, &rawArgs);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by read
+            return error;
+        }
+
+        // Call the local method
+        status_t result = MethodCaller<ParamTuple>::call(this, method, &rawArgs);
+
+        // Extract the outputs from the argument tuple and write them into the reply Parcel
+        error = OutputWriter<ParamTuple>{mLogTag}.writeOutputs(reply, &rawArgs);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by write
+            return error;
+        }
+
+        // Return the result code in the reply Parcel
+        error = reply->writeInt32(result);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            ALOG(LOG_ERROR, mLogTag, "Failed to write result");
+#if SI_DUMP_CALLSTACKS
+            CallStack callStack(mLogTag);
+#endif
+            return error;
+        }
+        return NO_ERROR;
+    }
+
+    template <typename Method>
+    status_t callLocalAsync(const Parcel& data, Parcel* /*reply*/, Method method) {
+        // reply is not actually used by CHECK_INTERFACE
+        CHECK_INTERFACE(this, data, reply);
+
+        // Since we need to both pass inputs into the call as well as retrieve outputs, we create a
+        // "raw" tuple, where the inputs are interleaved with actual, non-pointer versions of the
+        // outputs. When we ultimately call into the method, we will pass the addresses of the
+        // output arguments instead of their tuple members directly, but the storage will live in
+        // the tuple.
+        using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
+        typename RawConverter<std::tuple<>, ParamTuple>::type rawArgs{};
+
+        // Read the inputs from the data Parcel into the argument tuple
+        status_t error = InputReader<ParamTuple>{mLogTag}.readInputs(data, &rawArgs);
+        if (CC_UNLIKELY(error != NO_ERROR)) {
+            // A message will have been logged by read
+            return error;
+        }
+
+        // Call the local method
+        MethodCaller<ParamTuple>::callVoid(this, method, &rawArgs);
+
+        // After calling, there is nothing more to do since asynchronous calls do not return a value
+        // to the caller
+        return NO_ERROR;
+    }
+
+private:
+    const char* const mLogTag;
+
+    // RemoveFirst strips the first element from a tuple.
+    // For example, given T = std::tuple<A, B, C>, RemoveFirst<T>::type = std::tuple<B, C>
+    template <typename T, typename... Args>
+    struct RemoveFirst;
+    template <typename T, typename... Args>
+    struct RemoveFirst<std::tuple<T, Args...>> {
+        using type = std::tuple<Args...>;
+    };
+
+    // RawConverter strips a tuple down to its fundamental types, discarding both pointers and
+    // references. This allows us to allocate storage for both input (non-pointer) arguments and
+    // output (pointer) arguments in one tuple.
+    // For example, given T = std::tuple<const A&, B*>, RawConverter<T>::type = std::tuple<A, B>
+    template <typename Unconverted, typename... Converted>
+    struct RawConverter;
+    template <typename Unconverted, typename... Converted>
+    struct RawConverter<std::tuple<Converted...>, Unconverted> {
+    private:
+        using ElementType = typename std::tuple_element<0, Unconverted>::type;
+        using Decayed = typename std::decay<ElementType>::type;
+        using WithoutPointer = typename std::remove_pointer<Decayed>::type;
+
+    public:
+        using type = typename RawConverter<std::tuple<Converted..., WithoutPointer>,
+                                           typename RemoveFirst<Unconverted>::type>::type;
+    };
+    template <typename... Converted>
+    struct RawConverter<std::tuple<Converted...>, std::tuple<>> {
+        using type = std::tuple<Converted...>;
+    };
+
+    // This provides a simple way to determine whether the indexed element of Args... is a pointer
+    template <size_t I, typename... Args>
+    struct ElementIsPointer {
+    private:
+        using ElementType = typename std::tuple_element<I, std::tuple<Args...>>::type;
+
+    public:
+        static constexpr bool value = std::is_pointer<ElementType>::value;
+    };
+
+    // This class iterates over the parameter types, and if a given parameter is an input
+    // (i.e., is not a pointer), reads the corresponding argument tuple element from the data Parcel
+    template <typename... Params>
+    class InputReader;
+    template <typename... Params>
+    class InputReader<std::tuple<Params...>> {
+    public:
+        explicit InputReader(const char* logTag) : mLogTag(logTag) {}
+
+        // Note that in this case (as opposed to in SafeBpInterface), we iterate using an explicit
+        // index (starting with 0 here) instead of using recursion and stripping the first element.
+        // This is because in SafeBpInterface we aren't actually operating on a real tuple, but are
+        // instead just using a tuple as a convenient container for variadic types, whereas here we
+        // can't modify the argument tuple without causing unnecessary copies or moves of the data
+        // contained therein.
+        template <typename RawTuple>
+        status_t readInputs(const Parcel& data, RawTuple* args) {
+            return dispatchArg<0>(data, args);
+        }
+
+    private:
+        const char* const mLogTag;
+
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<!ElementIsPointer<I, Params...>::value, status_t>::type readIfInput(
+                const Parcel& data, RawTuple* args) {
+            return SafeInterface::ParcelHandler{mLogTag}.read(data, &std::get<I>(*args));
+        }
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<ElementIsPointer<I, Params...>::value, status_t>::type readIfInput(
+                const Parcel& /*data*/, RawTuple* /*args*/) {
+            return NO_ERROR;
+        }
+
+        // Recursively iterate through the arguments
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<(I < sizeof...(Params)), status_t>::type dispatchArg(
+                const Parcel& data, RawTuple* args) {
+            status_t error = readIfInput<I>(data, args);
+            if (CC_UNLIKELY(error != NO_ERROR)) {
+                // A message will have been logged in read
+                return error;
+            }
+            return dispatchArg<I + 1>(data, args);
+        }
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<(I >= sizeof...(Params)), status_t>::type dispatchArg(
+                const Parcel& /*data*/, RawTuple* /*args*/) {
+            return NO_ERROR;
+        }
+    };
+
+    // getForCall uses the types of the parameters to determine whether a given element of the
+    // argument tuple is an input, which should be passed directly into the call, or an output, for
+    // which its address should be passed into the call
+    template <size_t I, typename RawTuple, typename... Params>
+    static typename std::enable_if<
+            ElementIsPointer<I, Params...>::value,
+            typename std::tuple_element<I, std::tuple<Params...>>::type>::type
+    getForCall(RawTuple* args) {
+        return &std::get<I>(*args);
+    }
+    template <size_t I, typename RawTuple, typename... Params>
+    static typename std::enable_if<
+            !ElementIsPointer<I, Params...>::value,
+            typename std::tuple_element<I, std::tuple<Params...>>::type>::type&
+    getForCall(RawTuple* args) {
+        return std::get<I>(*args);
+    }
+
+    // This template class uses std::index_sequence and parameter pack expansion to call the given
+    // method using the elements of the argument tuple (after those arguments are passed through
+    // getForCall to get addresses instead of values for output arguments)
+    template <typename... Params>
+    struct MethodCaller;
+    template <typename... Params>
+    struct MethodCaller<std::tuple<Params...>> {
+    public:
+        // The calls through these to the helper methods are necessary to generate the
+        // std::index_sequences used to unpack the argument tuple into the method call
+        template <typename Class, typename MemberFunction, typename RawTuple>
+        static status_t call(Class* instance, MemberFunction function, RawTuple* args) {
+            return callHelper(instance, function, args, std::index_sequence_for<Params...>{});
+        }
+        template <typename Class, typename MemberFunction, typename RawTuple>
+        static void callVoid(Class* instance, MemberFunction function, RawTuple* args) {
+            callVoidHelper(instance, function, args, std::index_sequence_for<Params...>{});
+        }
+
+    private:
+        template <typename Class, typename MemberFunction, typename RawTuple, std::size_t... I>
+        static status_t callHelper(Class* instance, MemberFunction function, RawTuple* args,
+                                   std::index_sequence<I...> /*unused*/) {
+            return (instance->*function)(getForCall<I, RawTuple, Params...>(args)...);
+        }
+        template <typename Class, typename MemberFunction, typename RawTuple, std::size_t... I>
+        static void callVoidHelper(Class* instance, MemberFunction function, RawTuple* args,
+                                   std::index_sequence<I...> /*unused*/) {
+            (instance->*function)(getForCall<I, RawTuple, Params...>(args)...);
+        }
+    };
+
+    // This class iterates over the parameter types, and if a given parameter is an output
+    // (i.e., is a pointer), writes the corresponding argument tuple element into the reply Parcel
+    template <typename... Params>
+    struct OutputWriter;
+    template <typename... Params>
+    struct OutputWriter<std::tuple<Params...>> {
+    public:
+        explicit OutputWriter(const char* logTag) : mLogTag(logTag) {}
+
+        // See the note on InputReader::readInputs for why this differs from the arguably simpler
+        // RemoveFirst approach in SafeBpInterface
+        template <typename RawTuple>
+        status_t writeOutputs(Parcel* reply, RawTuple* args) {
+            return dispatchArg<0>(reply, args);
+        }
+
+    private:
+        const char* const mLogTag;
+
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<ElementIsPointer<I, Params...>::value, status_t>::type
+        writeIfOutput(Parcel* reply, RawTuple* args) {
+            return SafeInterface::ParcelHandler{mLogTag}.write(reply, std::get<I>(*args));
+        }
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<!ElementIsPointer<I, Params...>::value, status_t>::type
+        writeIfOutput(Parcel* /*reply*/, RawTuple* /*args*/) {
+            return NO_ERROR;
+        }
+
+        // Recursively iterate through the arguments
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<(I < sizeof...(Params)), status_t>::type dispatchArg(
+                Parcel* reply, RawTuple* args) {
+            status_t error = writeIfOutput<I>(reply, args);
+            if (CC_UNLIKELY(error != NO_ERROR)) {
+                // A message will have been logged in read
+                return error;
+            }
+            return dispatchArg<I + 1>(reply, args);
+        }
+        template <std::size_t I, typename RawTuple>
+        typename std::enable_if<(I >= sizeof...(Params)), status_t>::type dispatchArg(
+                Parcel* /*reply*/, RawTuple* /*args*/) {
+            return NO_ERROR;
+        }
+    };
+};
+
+} // namespace android
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 327ecad..1ee4b6f 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -80,3 +80,27 @@
         "libbase",
     ],
 }
+
+cc_test {
+    name: "binderSafeInterfaceTest",
+    srcs: ["binderSafeInterfaceTest.cpp"],
+
+    cppflags: [
+        "-Werror",
+        "-Weverything",
+        "-Wno-c++98-compat",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-global-constructors",
+        "-Wno-padded",
+        "-Wno-weak-vtables",
+    ],
+
+    cpp_std: "experimental",
+    gnu_extensions: false,
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
new file mode 100644
index 0000000..ac2f4d5
--- /dev/null
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -0,0 +1,514 @@
+/*
+ * 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.
+ */
+
+#include <binder/SafeInterface.h>
+
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/ProcessState.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Weverything"
+#include <gtest/gtest.h>
+#pragma clang diagnostic pop
+
+#include <optional>
+
+using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
+
+namespace android {
+namespace tests {
+
+// This class serves two purposes:
+//   1) It ensures that the implementation doesn't require copying or moving the data (for
+//      efficiency purposes)
+//   2) It tests that Parcelables can be passed correctly
+class NoCopyNoMove : public Parcelable {
+public:
+    NoCopyNoMove() = default;
+    explicit NoCopyNoMove(int32_t value) : mValue(value) {}
+    ~NoCopyNoMove() override = default;
+
+    // Not copyable
+    NoCopyNoMove(const NoCopyNoMove&) = delete;
+    NoCopyNoMove& operator=(const NoCopyNoMove&) = delete;
+
+    // Not movable
+    NoCopyNoMove(NoCopyNoMove&&) = delete;
+    NoCopyNoMove& operator=(NoCopyNoMove&&) = delete;
+
+    // Parcelable interface
+    status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
+    status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
+
+    int32_t getValue() const { return mValue; }
+    void setValue(int32_t value) { mValue = value; }
+
+private:
+    int32_t mValue = 0;
+    uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
+};
+
+struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
+    TestLightFlattenable() = default;
+    explicit TestLightFlattenable(int32_t v) : value(v) {}
+    int32_t value = 0;
+};
+
+class ExitOnDeath : public IBinder::DeathRecipient {
+public:
+    ~ExitOnDeath() override = default;
+
+    void binderDied(const wp<IBinder>& /*who*/) override {
+        ALOG(LOG_INFO, "ExitOnDeath", "Exiting");
+        exit(0);
+    }
+};
+
+// This callback class is used to test both one-way transactions and that sp<IInterface> can be
+// passed correctly
+class ICallback : public IInterface {
+public:
+    DECLARE_META_INTERFACE(Callback)
+
+    enum class Tag : uint32_t {
+        OnCallback = IBinder::FIRST_CALL_TRANSACTION,
+        Last,
+    };
+
+    virtual void onCallback(int32_t aPlusOne) = 0;
+};
+
+class BpCallback : public SafeBpInterface<ICallback> {
+public:
+    explicit BpCallback(const sp<IBinder>& impl) : SafeBpInterface<ICallback>(impl, getLogTag()) {}
+
+    void onCallback(int32_t aPlusOne) override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemoteAsync<decltype(&ICallback::onCallback)>(Tag::OnCallback, aPlusOne);
+    }
+
+private:
+    static constexpr const char* getLogTag() { return "BpCallback"; }
+};
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
+IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
+#pragma clang diagnostic pop
+
+class BnCallback : public SafeBnInterface<ICallback> {
+public:
+    BnCallback() : SafeBnInterface("BnCallback") {}
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t /*flags*/) override {
+        EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
+        EXPECT_LT(code, static_cast<uint32_t>(ICallback::Tag::Last));
+        ICallback::Tag tag = static_cast<ICallback::Tag>(code);
+        switch (tag) {
+            case ICallback::Tag::OnCallback: {
+                return callLocalAsync(data, reply, &ICallback::onCallback);
+            }
+            case ICallback::Tag::Last:
+                // Should not be possible because of the asserts at the beginning of the method
+                [&]() { FAIL(); }();
+                return UNKNOWN_ERROR;
+        }
+    }
+};
+
+class ISafeInterfaceTest : public IInterface {
+public:
+    DECLARE_META_INTERFACE(SafeInterfaceTest)
+
+    enum class Tag : uint32_t {
+        SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
+        ReturnsNoMemory,
+        LogicalNot,
+        IncrementLightFlattenable,
+        IncrementNoCopyNoMove,
+        ToUpper,
+        CallMeBack,
+        IncrementInt32,
+        IncrementUint32,
+        IncrementTwo,
+        Last,
+    };
+
+    // This is primarily so that the remote service dies when the test does, but it also serves to
+    // test the handling of sp<IBinder> and non-const methods
+    virtual status_t setDeathToken(const sp<IBinder>& token) = 0;
+
+    // This is the most basic test since it doesn't require parceling any arguments
+    virtual status_t returnsNoMemory() const = 0;
+
+    // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
+    virtual status_t logicalNot(bool a, bool* notA) const = 0;
+    virtual status_t increment(const TestLightFlattenable& a,
+                               TestLightFlattenable* aPlusOne) const = 0;
+    virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
+    virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
+    // As mentioned above, sp<IBinder> is already tested by setDeathToken
+    virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
+    virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
+    virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
+
+    // This tests that input/output parameter interleaving works correctly
+    virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
+                               int32_t* bPlusOne) const = 0;
+};
+
+class BpSafeInterfaceTest : public SafeBpInterface<ISafeInterfaceTest> {
+public:
+    explicit BpSafeInterfaceTest(const sp<IBinder>& impl)
+          : SafeBpInterface<ISafeInterfaceTest>(impl, getLogTag()) {}
+
+    status_t setDeathToken(const sp<IBinder>& token) override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<decltype(&ISafeInterfaceTest::setDeathToken)>(Tag::SetDeathToken, token);
+    }
+    status_t returnsNoMemory() const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<decltype(&ISafeInterfaceTest::returnsNoMemory)>(Tag::ReturnsNoMemory);
+    }
+    status_t logicalNot(bool a, bool* notA) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
+    }
+    status_t increment(const TestLightFlattenable& a,
+                       TestLightFlattenable* aPlusOne) const override {
+        using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
+                                                           TestLightFlattenable*) const;
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
+    }
+    status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
+                                                           NoCopyNoMove* aPlusOne) const;
+        return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
+    }
+    status_t toUpper(const String8& str, String8* upperStr) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
+    }
+    void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemoteAsync<decltype(&ISafeInterfaceTest::callMeBack)>(Tag::CallMeBack, callback,
+                                                                          a);
+    }
+    status_t increment(int32_t a, int32_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
+        return callRemote<Signature>(Tag::IncrementInt32, a, aPlusOne);
+    }
+    status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
+        return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
+    }
+    status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        using Signature =
+                status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t, int32_t*) const;
+        return callRemote<Signature>(Tag::IncrementTwo, a, aPlusOne, b, bPlusOne);
+    }
+
+private:
+    static constexpr const char* getLogTag() { return "BpSafeInterfaceTest"; }
+};
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
+IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
+
+static sp<IBinder::DeathRecipient> getDeathRecipient() {
+    static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
+    return recipient;
+}
+#pragma clang diagnostic pop
+
+class BnSafeInterfaceTest : public SafeBnInterface<ISafeInterfaceTest> {
+public:
+    BnSafeInterfaceTest() : SafeBnInterface(getLogTag()) {}
+
+    status_t setDeathToken(const sp<IBinder>& token) override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        token->linkToDeath(getDeathRecipient());
+        return NO_ERROR;
+    }
+    status_t returnsNoMemory() const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return NO_MEMORY;
+    }
+    status_t logicalNot(bool a, bool* notA) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *notA = !a;
+        return NO_ERROR;
+    }
+    status_t increment(const TestLightFlattenable& a,
+                       TestLightFlattenable* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        aPlusOne->value = a.value + 1;
+        return NO_ERROR;
+    }
+    status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        aPlusOne->setValue(a.getValue() + 1);
+        return NO_ERROR;
+    }
+    status_t toUpper(const String8& str, String8* upperStr) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *upperStr = str;
+        upperStr->toUpper();
+        return NO_ERROR;
+    }
+    void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        callback->onCallback(a + 1);
+    }
+    status_t increment(int32_t a, int32_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *aPlusOne = a + 1;
+        return NO_ERROR;
+    }
+    status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *aPlusOne = a + 1;
+        return NO_ERROR;
+    }
+    status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *aPlusOne = a + 1;
+        *bPlusOne = b + 1;
+        return NO_ERROR;
+    }
+
+    // BnInterface
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t /*flags*/) override {
+        EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
+        EXPECT_LT(code, static_cast<uint32_t>(Tag::Last));
+        ISafeInterfaceTest::Tag tag = static_cast<ISafeInterfaceTest::Tag>(code);
+        switch (tag) {
+            case ISafeInterfaceTest::Tag::SetDeathToken: {
+                return callLocal(data, reply, &ISafeInterfaceTest::setDeathToken);
+            }
+            case ISafeInterfaceTest::Tag::ReturnsNoMemory: {
+                return callLocal(data, reply, &ISafeInterfaceTest::returnsNoMemory);
+            }
+            case ISafeInterfaceTest::Tag::LogicalNot: {
+                return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
+            }
+            case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
+                using Signature =
+                        status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
+                                                         TestLightFlattenable* aPlusOne) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
+                using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
+                                                                   NoCopyNoMove* aPlusOne) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::ToUpper: {
+                return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
+            }
+            case ISafeInterfaceTest::Tag::CallMeBack: {
+                return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
+            }
+            case ISafeInterfaceTest::Tag::IncrementInt32: {
+                using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::IncrementUint32: {
+                using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::IncrementTwo: {
+                using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
+                                                                   int32_t*) const;
+                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+            }
+            case ISafeInterfaceTest::Tag::Last:
+                // Should not be possible because of the asserts at the beginning of the method
+                [&]() { FAIL(); }();
+                return UNKNOWN_ERROR;
+        }
+    }
+
+private:
+    static constexpr const char* getLogTag() { return "BnSafeInterfaceTest"; }
+};
+
+class SafeInterfaceTest : public ::testing::Test {
+public:
+    SafeInterfaceTest() : mSafeInterfaceTest(getRemoteService()) {
+        ProcessState::self()->startThreadPool();
+    }
+    ~SafeInterfaceTest() override = default;
+
+protected:
+    sp<ISafeInterfaceTest> mSafeInterfaceTest;
+
+private:
+    static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }
+
+    sp<ISafeInterfaceTest> getRemoteService() {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
+        static std::mutex sMutex;
+        static sp<ISafeInterfaceTest> sService;
+        static sp<IBinder> sDeathToken = new BBinder;
+#pragma clang diagnostic pop
+
+        std::unique_lock<decltype(sMutex)> lock;
+        if (sService == nullptr) {
+            ALOG(LOG_INFO, getLogTag(), "Forking remote process");
+            pid_t forkPid = fork();
+            EXPECT_NE(forkPid, -1);
+
+            const String16 serviceName("SafeInterfaceTest");
+
+            if (forkPid == 0) {
+                ALOG(LOG_INFO, getLogTag(), "Remote process checking in");
+                sp<ISafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
+                defaultServiceManager()->addService(serviceName,
+                                                    IInterface::asBinder(nativeService));
+                ProcessState::self()->startThreadPool();
+                IPCThreadState::self()->joinThreadPool();
+                // We shouldn't get to this point
+                [&]() { FAIL(); }();
+            }
+
+            sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
+            sService = interface_cast<ISafeInterfaceTest>(binder);
+            EXPECT_TRUE(sService != nullptr);
+
+            sService->setDeathToken(sDeathToken);
+        }
+
+        return sService;
+    }
+};
+
+TEST_F(SafeInterfaceTest, TestReturnsNoMemory) {
+    status_t result = mSafeInterfaceTest->returnsNoMemory();
+    ASSERT_EQ(NO_MEMORY, result);
+}
+
+TEST_F(SafeInterfaceTest, TestLogicalNot) {
+    const bool a = true;
+    bool notA = true;
+    status_t result = mSafeInterfaceTest->logicalNot(a, &notA);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(!a, notA);
+    // Test both since we don't want to accidentally catch a default false somewhere
+    const bool b = false;
+    bool notB = false;
+    result = mSafeInterfaceTest->logicalNot(b, &notB);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(!b, notB);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
+    const TestLightFlattenable a{1};
+    TestLightFlattenable aPlusOne{0};
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a.value + 1, aPlusOne.value);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
+    const NoCopyNoMove a{1};
+    NoCopyNoMove aPlusOne{0};
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
+}
+
+TEST_F(SafeInterfaceTest, TestToUpper) {
+    const String8 str{"Hello, world!"};
+    String8 upperStr;
+    status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
+}
+
+TEST_F(SafeInterfaceTest, TestCallMeBack) {
+    class CallbackReceiver : public BnCallback {
+    public:
+        void onCallback(int32_t aPlusOne) override {
+            ALOG(LOG_INFO, "CallbackReceiver", "%s", __PRETTY_FUNCTION__);
+            std::unique_lock<decltype(mMutex)> lock(mMutex);
+            mValue = aPlusOne;
+            mCondition.notify_one();
+        }
+
+        std::optional<int32_t> waitForCallback() {
+            std::unique_lock<decltype(mMutex)> lock(mMutex);
+            bool success =
+                    mCondition.wait_for(lock, 100ms, [&]() { return static_cast<bool>(mValue); });
+            return success ? mValue : std::nullopt;
+        }
+
+    private:
+        std::mutex mMutex;
+        std::condition_variable mCondition;
+        std::optional<int32_t> mValue;
+    };
+
+    sp<CallbackReceiver> receiver = new CallbackReceiver;
+    const int32_t a = 1;
+    mSafeInterfaceTest->callMeBack(receiver, a);
+    auto result = receiver->waitForCallback();
+    ASSERT_TRUE(result);
+    ASSERT_EQ(a + 1, *result);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementInt32) {
+    const int32_t a = 1;
+    int32_t aPlusOne = 0;
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a + 1, aPlusOne);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementUint32) {
+    const uint32_t a = 1;
+    uint32_t aPlusOne = 0;
+    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a + 1, aPlusOne);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementTwo) {
+    const int32_t a = 1;
+    int32_t aPlusOne = 0;
+    const int32_t b = 2;
+    int32_t bPlusOne = 0;
+    status_t result = mSafeInterfaceTest->increment(1, &aPlusOne, 2, &bPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(a + 1, aPlusOne);
+    ASSERT_EQ(b + 1, bPlusOne);
+}
+
+} // namespace tests
+} // namespace android
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index db8a517..853e23a 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -17,116 +17,64 @@
 // tag as surfaceflinger
 #define LOG_TAG "SurfaceFlinger"
 
-#include <stdio.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <sys/types.h>
 
-#include <binder/Parcel.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/SafeInterface.h>
 
+#include <ui/FrameStats.h>
 #include <ui/Point.h>
 #include <ui/Rect.h>
 
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/ISurfaceComposerClient.h>
-#include <private/gui/LayerState.h>
-
-// ---------------------------------------------------------------------------
 
 namespace android {
 
-enum {
-    CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
-    DESTROY_SURFACE,
-    CLEAR_LAYER_FRAME_STATS,
-    GET_LAYER_FRAME_STATS,
-    GET_TRANSFORM_TO_DISPLAY_INVERSE
-};
-
-class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
-{
+class BpSurfaceComposerClient : public SafeBpInterface<ISurfaceComposerClient> {
 public:
     explicit BpSurfaceComposerClient(const sp<IBinder>& impl)
-        : BpInterface<ISurfaceComposerClient>(impl) {
+          : SafeBpInterface<ISurfaceComposerClient>(impl, "BpSurfaceComposerClient") {}
+
+    ~BpSurfaceComposerClient() override;
+
+    status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
+                           uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
+                           uint32_t ownerUid, sp<IBinder>* handle,
+                           sp<IGraphicBufferProducer>* gbp) override {
+        return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CreateSurface,
+                                                                            name, width, height,
+                                                                            format, flags, parent,
+                                                                            windowType, ownerUid,
+                                                                            handle, gbp);
     }
 
-    virtual ~BpSurfaceComposerClient();
-
-    virtual status_t createSurface(const String8& name, uint32_t width,
-            uint32_t height, PixelFormat format, uint32_t flags,
-            const sp<IBinder>& parent, uint32_t windowType, uint32_t ownerUid,
-            sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeString8(name);
-        data.writeUint32(width);
-        data.writeUint32(height);
-        data.writeInt32(static_cast<int32_t>(format));
-        data.writeUint32(flags);
-        data.writeUint32(windowType);
-        data.writeUint32(ownerUid);
-        if (parent != nullptr) {
-            data.writeStrongBinder(parent);
-        }
-        remote()->transact(CREATE_SURFACE, data, &reply);
-        *handle = reply.readStrongBinder();
-        *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
-        return reply.readInt32();
+    status_t destroySurface(const sp<IBinder>& handle) override {
+        return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DestroySurface,
+                                                                             handle);
     }
 
-    virtual status_t destroySurface(const sp<IBinder>& handle) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(handle);
-        remote()->transact(DESTROY_SURFACE, data, &reply);
-        return reply.readInt32();
+    status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
+        return callRemote<decltype(
+                &ISurfaceComposerClient::clearLayerFrameStats)>(Tag::ClearLayerFrameStats, handle);
     }
 
-    virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(handle);
-        remote()->transact(CLEAR_LAYER_FRAME_STATS, data, &reply);
-        return reply.readInt32();
+    status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const override {
+        return callRemote<decltype(
+                &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GetLayerFrameStats, handle,
+                                                              outStats);
     }
 
-    virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(handle);
-        remote()->transact(GET_LAYER_FRAME_STATS, data, &reply);
-        reply.read(*outStats);
-        return reply.readInt32();
-    }
-
-    virtual status_t getTransformToDisplayInverse(const sp<IBinder>& handle,
-            bool* outTransformToDisplayInverse) const {
-        Parcel data, reply;
-        status_t result =
-                data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        if (result != NO_ERROR) {
-            return result;
-        }
-        result = data.writeStrongBinder(handle);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        result = remote()->transact(GET_TRANSFORM_TO_DISPLAY_INVERSE, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        int transformInverse;
-        result = reply.readInt32(&transformInverse);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        *outTransformToDisplayInverse = transformInverse != 0 ? true : false;
-        status_t result2 = reply.readInt32(&result);
-        if (result2 != NO_ERROR) {
-            return result2;
-        }
-        return result;
+    status_t getTransformToDisplayInverse(const sp<IBinder>& handle,
+                                          bool* outTransformToDisplayInverse) const override {
+        return callRemote<decltype(
+                &ISurfaceComposerClient::
+                        getTransformToDisplayInverse)>(Tag::GetTransformToDisplayInverse, handle,
+                                                       outTransformToDisplayInverse);
     }
 };
 
@@ -138,75 +86,32 @@
 
 // ----------------------------------------------------------------------
 
-status_t BnSurfaceComposerClient::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-     switch(code) {
-        case CREATE_SURFACE: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            String8 name = data.readString8();
-            uint32_t width = data.readUint32();
-            uint32_t height = data.readUint32();
-            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
-            uint32_t createFlags = data.readUint32();
-            uint32_t windowType = data.readUint32();
-            uint32_t ownerUid = data.readUint32();
-            sp<IBinder> parent = nullptr;
-            if (data.dataAvail() > 0) {
-                parent = data.readStrongBinder();
-            }
-            sp<IBinder> handle;
-            sp<IGraphicBufferProducer> gbp;
-            status_t result = createSurface(name, width, height, format,
-                    createFlags, parent, windowType, ownerUid, &handle, &gbp);
-            reply->writeStrongBinder(handle);
-            reply->writeStrongBinder(IInterface::asBinder(gbp));
-            reply->writeInt32(result);
-            return NO_ERROR;
+status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                             uint32_t flags) {
+    if (code < IBinder::FIRST_CALL_TRANSACTION || code >= static_cast<uint32_t>(Tag::Last)) {
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+    auto tag = static_cast<Tag>(code);
+    switch (tag) {
+        case Tag::CreateSurface: {
+            return callLocal(data, reply, &ISurfaceComposerClient::createSurface);
         }
-        case DESTROY_SURFACE: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            reply->writeInt32(destroySurface( data.readStrongBinder() ) );
-            return NO_ERROR;
+        case Tag::DestroySurface: {
+            return callLocal(data, reply, &ISurfaceComposerClient::destroySurface);
         }
-       case CLEAR_LAYER_FRAME_STATS: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            sp<IBinder> handle = data.readStrongBinder();
-            status_t result = clearLayerFrameStats(handle);
-            reply->writeInt32(result);
-            return NO_ERROR;
+        case Tag::ClearLayerFrameStats: {
+            return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
         }
-        case GET_LAYER_FRAME_STATS: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            sp<IBinder> handle = data.readStrongBinder();
-            FrameStats stats;
-            status_t result = getLayerFrameStats(handle, &stats);
-            reply->write(stats);
-            reply->writeInt32(result);
-            return NO_ERROR;
+        case Tag::GetLayerFrameStats: {
+            return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats);
         }
-        case GET_TRANSFORM_TO_DISPLAY_INVERSE: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            sp<IBinder> handle;
-            status_t result = data.readStrongBinder(&handle);
-            if (result != NO_ERROR) {
-                return result;
-            }
-            bool transformInverse = false;
-            result = getTransformToDisplayInverse(handle, &transformInverse);
-            if (result != NO_ERROR) {
-                return result;
-            }
-            result = reply->writeInt32(transformInverse ? 1 : 0);
-            if (result != NO_ERROR) {
-                return result;
-            }
-            result = reply->writeInt32(NO_ERROR);
-            return result;
+        case Tag::GetTransformToDisplayInverse: {
+            return callLocal(data, reply, &ISurfaceComposerClient::getTransformToDisplayInverse);
         }
-        default:
+        case Tag::Last:
+            // Should not be possible because of the check at the beginning of the method
             return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
-}; // namespace android
+} // namespace android
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/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 32a2160..f9c7462 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -91,6 +91,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";
   }
@@ -418,7 +422,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
@@ -446,13 +451,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;
+      }
 
       // IMU driver gives timestamps on its own clock, but we need monotonic
       // clock. Subtract 5ms to account for estimated IMU sample latency.
@@ -460,6 +477,26 @@
                       pose_state.timestamp_ns + 5000000);
       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");
@@ -467,6 +504,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;
+}
+
 int PoseService::HandleMessage(pdx::Message& msg) {
   int ret = 0;
   const pdx::MessageInfo& info = msg.GetInfo();
@@ -646,6 +690,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 899d5fb..517334a 100644
--- a/services/vr/sensord/pose_service.h
+++ b/services/vr/sensord/pose_service.h
@@ -99,6 +99,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_;