Merge "binder_parcel_fuzzer: split out random_parcel.h"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 0473bb8..9cab9b4 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -8,6 +8,7 @@
                include/input/
                libs/binder/fuzzer/
                libs/binder/ndk/
+               libs/binder/tests/fuzzers/
                libs/binderthreadstate/
                libs/graphicsenv/
                libs/gui/
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index bbc724c..3091f6b 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -69,7 +69,7 @@
 
     static const std::vector<std::string> group_names{
         "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats",
-            "readproc", "bluetooth", "wakelock"};
+            "readproc", "bluetooth", "wakelock", "nfc"};
     std::vector<gid_t> groups(group_names.size(), 0);
     for (size_t i = 0; i < group_names.size(); ++i) {
         grp = getgrnam(group_names[i].c_str());
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index edad3fd..84de9f3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1507,6 +1507,8 @@
 
     /* Dump Bluetooth HCI logs */
     ds.AddDir("/data/misc/bluetooth/logs", true);
+    /* Dump Nfc NCI logs */
+    ds.AddDir("/data/misc/nfc/logs", true);
 
     if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
         MYLOGI("taking late screenshot\n");
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 9964888..ba6cdf1 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -479,8 +479,7 @@
 }
 
 TEST_F(ListTest, DumpVintf) {
-    const std::string expected = "<manifest version=\"2.0\" type=\"device\">\n"
-                                 "    <hal format=\"hidl\">\n"
+    const std::string expected = "    <hal format=\"hidl\">\n"
                                  "        <name>a.h.foo1</name>\n"
                                  "        <transport>hwbinder</transport>\n"
                                  "        <fqname>@1.0::IFoo/1</fqname>\n"
@@ -499,8 +498,7 @@
                                  "        <name>a.h.foo4</name>\n"
                                  "        <transport arch=\"32\">passthrough</transport>\n"
                                  "        <fqname>@4.0::IFoo/4</fqname>\n"
-                                 "    </hal>\n"
-                                 "</manifest>";
+                                 "    </hal>\n";
 
     optind = 1; // mimic Lshal::parseArg()
     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--init-vintf"})));
diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h
index b6814aa..5da2515 100644
--- a/libs/binder/include/binder/ParcelableHolder.h
+++ b/libs/binder/include/binder/ParcelableHolder.h
@@ -103,7 +103,7 @@
         return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
     }
 
-    Stability getStability() const override { return mStability; };
+    Stability getStability() const override { return mStability; }
 
     inline bool operator!=(const ParcelableHolder& rhs) const {
         return std::tie(mParcelable, mParcelPtr, mStability) !=
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 09949ea..054aebe 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -45,7 +45,7 @@
     std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
     if (static_cast<size_t>(length) > vec->max_size()) return false;
 
-    vec->resize(length);
+    vec->resize(static_cast<size_t>(length));
     *outBuffer = vec->data();
     return true;
 }
@@ -66,7 +66,7 @@
     *vec = std::optional<std::vector<T>>(std::vector<T>{});
 
     if (static_cast<size_t>(length) > (*vec)->max_size()) return false;
-    (*vec)->resize(length);
+    (*vec)->resize(static_cast<size_t>(length));
 
     *outBuffer = (*vec)->data();
     return true;
@@ -90,7 +90,7 @@
     std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
     if (static_cast<size_t>(length) > vec->max_size()) return false;
 
-    vec->resize(length);
+    vec->resize(static_cast<size_t>(length));
     return true;
 }
 
@@ -117,7 +117,7 @@
     *vec = std::optional<std::vector<T>>(std::vector<T>{});
 
     if (static_cast<size_t>(length) > (*vec)->max_size()) return false;
-    (*vec)->resize(length);
+    (*vec)->resize(static_cast<size_t>(length));
 
     return true;
 }
@@ -257,7 +257,7 @@
     if (length <= 0) return false;
 
     std::string* str = static_cast<std::string*>(stringData);
-    str->resize(length - 1);
+    str->resize(static_cast<size_t>(length) - 1);
     *buffer = &(*str)[0];
     return true;
 }
@@ -279,7 +279,7 @@
     }
 
     *str = std::optional<std::string>(std::string{});
-    (*str)->resize(length - 1);
+    (*str)->resize(static_cast<size_t>(length) - 1);
     *buffer = &(**str)[0];
     return true;
 }
@@ -303,7 +303,7 @@
     const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData);
     const std::string& element = vec->at(index);
 
-    *outLength = element.size();
+    *outLength = static_cast<int32_t>(element.size());
     return element.c_str();
 }
 
@@ -337,7 +337,7 @@
         return nullptr;
     }
 
-    *outLength = element->size();
+    *outLength = static_cast<int32_t>(element->size());
     return element->c_str();
 }
 
@@ -345,7 +345,7 @@
  * Convenience API for writing a std::string.
  */
 static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
-    return AParcel_writeString(parcel, str.c_str(), str.size());
+    return AParcel_writeString(parcel, str.c_str(), static_cast<int32_t>(str.size()));
 }
 
 /**
@@ -365,7 +365,7 @@
         return AParcel_writeString(parcel, nullptr, -1);
     }
 
-    return AParcel_writeString(parcel, str->c_str(), str->size());
+    return AParcel_writeString(parcel, str->c_str(), static_cast<int32_t>(str->size()));
 }
 
 /**
@@ -383,7 +383,7 @@
 static inline binder_status_t AParcel_writeVector(AParcel* parcel,
                                                   const std::vector<std::string>& vec) {
     const void* vectorData = static_cast<const void*>(&vec);
-    return AParcel_writeStringArray(parcel, vectorData, vec.size(),
+    return AParcel_writeStringArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
                                     AParcel_stdVectorStringElementGetter);
 }
 
@@ -404,7 +404,8 @@
 static inline binder_status_t AParcel_writeVector(
         AParcel* parcel, const std::optional<std::vector<std::optional<std::string>>>& vec) {
     const void* vectorData = static_cast<const void*>(&vec);
-    return AParcel_writeStringArray(parcel, vectorData, (vec ? vec->size() : -1),
+    return AParcel_writeStringArray(parcel, vectorData,
+                                    (vec ? static_cast<int32_t>(vec->size()) : -1),
                                     AParcel_nullableStdVectorStringElementGetter);
 }
 
@@ -545,7 +546,7 @@
 template <typename P>
 static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) {
     const void* vectorData = static_cast<const void*>(&vec);
-    return AParcel_writeParcelableArray(parcel, vectorData, vec.size(),
+    return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
                                         AParcel_writeStdVectorParcelableElement<P>);
 }
 
@@ -564,7 +565,7 @@
  * Writes a vector of int32_t to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
-    return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
+    return AParcel_writeInt32Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -597,7 +598,7 @@
  * Writes a vector of uint32_t to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
-    return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
+    return AParcel_writeUint32Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -631,7 +632,7 @@
  * Writes a vector of int64_t to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
-    return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
+    return AParcel_writeInt64Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -664,7 +665,7 @@
  * Writes a vector of uint64_t to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
-    return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
+    return AParcel_writeUint64Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -698,7 +699,7 @@
  * Writes a vector of float to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
-    return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
+    return AParcel_writeFloatArray(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -731,7 +732,7 @@
  * Writes a vector of double to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) {
-    return AParcel_writeDoubleArray(parcel, vec.data(), vec.size());
+    return AParcel_writeDoubleArray(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -764,8 +765,8 @@
  * Writes a vector of bool to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) {
-    return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec), vec.size(),
-                                  AParcel_stdVectorGetter<bool>);
+    return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec),
+                                  static_cast<int32_t>(vec.size()), AParcel_stdVectorGetter<bool>);
 }
 
 /**
@@ -801,7 +802,7 @@
  * Writes a vector of char16_t to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) {
-    return AParcel_writeCharArray(parcel, vec.data(), vec.size());
+    return AParcel_writeCharArray(parcel, vec.data(), static_cast<int32_t>(vec.size()));
 }
 
 /**
@@ -834,7 +835,8 @@
  * Writes a vector of uint8_t to the next location in a non-null parcel.
  */
 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint8_t>& vec) {
-    return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()), vec.size());
+    return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()),
+                                  static_cast<int32_t>(vec.size()));
 }
 
 /**
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/parcel_fuzzer/binder.cpp
index c2d4a3f..e5c6333 100644
--- a/libs/binder/parcel_fuzzer/binder.cpp
+++ b/libs/binder/parcel_fuzzer/binder.cpp
@@ -137,6 +137,7 @@
 
     PARCEL_READ_WITH_STATUS(std::string, readUtf8FromUtf16),
     PARCEL_READ_WITH_STATUS(std::unique_ptr<std::string>, readUtf8FromUtf16),
+    PARCEL_READ_WITH_STATUS(std::optional<std::string>, readUtf8FromUtf16),
     [] (const ::android::Parcel& p, uint8_t /*data*/) {
         FUZZ_LOG() << "about to read c-str";
         const char* str = p.readCString();
@@ -145,6 +146,7 @@
     PARCEL_READ_OPT_STATUS(android::String8, readString8),
     PARCEL_READ_OPT_STATUS(android::String16, readString16),
     PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16),
+    PARCEL_READ_WITH_STATUS(std::optional<android::String16>, readString16),
     [] (const ::android::Parcel& p, uint8_t /*data*/) {
         FUZZ_LOG() << "about to readString16Inplace";
         size_t outLen = 0;
@@ -158,17 +160,22 @@
     // TODO(b/131868573): can force read of arbitrarily sized vector
     // PARCEL_READ_WITH_STATUS(std::vector<ByteEnum>, readEnumVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<ByteEnum>>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<ByteEnum>>, readEnumVector),
     // PARCEL_READ_WITH_STATUS(std::vector<IntEnum>, readEnumVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<IntEnum>>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<IntEnum>>, readEnumVector),
     // PARCEL_READ_WITH_STATUS(std::vector<LongEnum>, readEnumVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<LongEnum>>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<LongEnum>>, readEnumVector),
 
     // only reading one parcelable type for now
     // TODO(b/131868573): can force read of arbitrarily sized vector
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<ExampleParcelable>>>, readParcelableVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<ExampleParcelable>>>, readParcelableVector),
     // PARCEL_READ_WITH_STATUS(std::vector<ExampleParcelable>, readParcelableVector),
     PARCEL_READ_WITH_STATUS(ExampleParcelable, readParcelable),
     PARCEL_READ_WITH_STATUS(std::unique_ptr<ExampleParcelable>, readParcelable),
+    PARCEL_READ_WITH_STATUS(std::optional<ExampleParcelable>, readParcelable),
 
     // only reading one binder type for now
     PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder),
@@ -176,30 +183,42 @@
 
     // TODO(b/131868573): can force read of arbitrarily sized vector
     // PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
+    // PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
     // PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::IBinder>>, readStrongBinderVector),
 
     // TODO(b/131868573): can force read of arbitrarily sized vector
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int8_t>>, readByteVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<int8_t>>, readByteVector),
     // PARCEL_READ_WITH_STATUS(std::vector<int8_t>, readByteVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, readByteVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint8_t>>, readByteVector),
     // PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, readByteVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int32_t>>, readInt32Vector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<int32_t>>, readInt32Vector),
     // PARCEL_READ_WITH_STATUS(std::vector<int32_t>, readInt32Vector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int64_t>>, readInt64Vector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<int64_t>>, readInt64Vector),
     // PARCEL_READ_WITH_STATUS(std::vector<int64_t>, readInt64Vector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint64_t>>, readUint64Vector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint64_t>>, readUint64Vector),
     // PARCEL_READ_WITH_STATUS(std::vector<uint64_t>, readUint64Vector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<float>>, readFloatVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<float>>, readFloatVector),
     // PARCEL_READ_WITH_STATUS(std::vector<float>, readFloatVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<double>>, readDoubleVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<double>>, readDoubleVector),
     // PARCEL_READ_WITH_STATUS(std::vector<double>, readDoubleVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<bool>>, readBoolVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<bool>>, readBoolVector),
     // PARCEL_READ_WITH_STATUS(std::vector<bool>, readBoolVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<char16_t>>, readCharVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<char16_t>>, readCharVector),
     // PARCEL_READ_WITH_STATUS(std::vector<char16_t>, readCharVector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<android::String16>>>, readString16Vector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<android::String16>>>, readString16Vector),
     // PARCEL_READ_WITH_STATUS(std::vector<android::String16>, readString16Vector),
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<std::string>>>, readUtf8VectorFromUtf16Vector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<std::string>>>, readUtf8VectorFromUtf16Vector),
     // PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
 
     [] (const android::Parcel& p, uint8_t /*len*/) {
@@ -236,6 +255,7 @@
 
     // TODO(b/131868573): can force read of arbitrarily sized vector
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
+    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
     // PARCEL_READ_WITH_STATUS(std::vector<android::base::unique_fd>, readUniqueFileDescriptorVector),
 
     [] (const android::Parcel& p, uint8_t len) {
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/fuzzers/Android.bp
new file mode 100644
index 0000000..46379fc
--- /dev/null
+++ b/libs/binder/tests/fuzzers/Android.bp
@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+    name: "binder_fuzz_defaults",
+    host_supported: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libbase",
+    ],
+}
+
+cc_fuzz {
+    name: "binder_binderFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["BinderFuzz.cpp"],
+}
+
+cc_fuzz {
+    name: "binder_bpBinderFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    host_supported: false,
+    srcs: ["BpBinderFuzz.cpp"],
+}
+
+cc_fuzz {
+    name: "binder_persistableBundleFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["PersistableBundleFuzz.cpp"],
+}
+
+cc_fuzz {
+    name: "binder_stabilityFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["StabilityFuzz.cpp"],
+}
+
+cc_fuzz {
+    name: "binder_statusFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["StatusFuzz.cpp"],
+}
+
+cc_fuzz {
+    name: "binder_textOutputFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["TextOutputFuzz.cpp"],
+}
diff --git a/libs/binder/tests/fuzzers/BinderFuzz.cpp b/libs/binder/tests/fuzzers/BinderFuzz.cpp
new file mode 100644
index 0000000..1e5d80a
--- /dev/null
+++ b/libs/binder/tests/fuzzers/BinderFuzz.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 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 <BinderFuzzFunctions.h>
+#include <IBinderFuzzFunctions.h>
+#include <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/Binder.h>
+
+namespace android {
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+    sp<BBinder> bbinder = new BBinder();
+
+    // To prevent memory from running out from calling too many add item operations.
+    const uint32_t MAX_RUNS = 2048;
+    uint32_t count = 0;
+
+    while (fdp.remaining_bytes() > 0 && count++ < MAX_RUNS) {
+        if (fdp.ConsumeBool()) {
+            callArbitraryFunction(&fdp, gBBinderOperations, bbinder);
+        } else {
+            callArbitraryFunction(&fdp, gIBinderOperations,
+                                  reinterpret_cast<IBinder *>(bbinder.get()));
+        }
+    }
+
+    return 0;
+}
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/BinderFuzzFunctions.h b/libs/binder/tests/fuzzers/BinderFuzzFunctions.h
new file mode 100644
index 0000000..9ac65bb
--- /dev/null
+++ b/libs/binder/tests/fuzzers/BinderFuzzFunctions.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 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 <IBinderFuzzFunctions.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <stdint.h>
+#include <atomic>
+
+namespace android {
+
+/* This is a vector of lambda functions the fuzzer will pull from.
+ *  This is done so new functions can be added to the fuzzer easily
+ *  without requiring modifications to the main fuzzer file. This also
+ *  allows multiple fuzzers to include this file, if functionality is needed.
+ */
+static const std::vector<std::function<void(FuzzedDataProvider*, const sp<BBinder>&)>>
+        gBBinderOperations = {[](FuzzedDataProvider*, const sp<BBinder>& bbinder) -> void {
+                                  bbinder->isRequestingSid();
+                              },
+                              [](FuzzedDataProvider* fdp, const sp<BBinder>& bbinder) -> void {
+                                  bool request_sid = fdp->ConsumeBool();
+                                  bbinder->setRequestingSid(request_sid);
+                              },
+                              [](FuzzedDataProvider*, const sp<BBinder>& bbinder) -> void {
+                                  bbinder->getExtension();
+                              },
+                              [](FuzzedDataProvider*, const sp<BBinder>& bbinder) -> void {
+                                  static IBinder* extension = nullptr;
+                                  bbinder->setExtension(extension);
+                              },
+                              [](FuzzedDataProvider* fdp, const sp<BBinder>& bbinder) -> void {
+                                  int priority;
+                                  int policy = fdp->ConsumeIntegralInRange<int>(0, 2);
+                                  if (policy == 0) {
+                                      priority = fdp->ConsumeIntegralInRange<int>(-20, 19);
+                                  } else {
+                                      priority = fdp->ConsumeIntegralInRange<int>(1, 99);
+                                  }
+                                  bbinder->setMinSchedulerPolicy(policy, priority);
+                              },
+                              [](FuzzedDataProvider*, const sp<BBinder>& bbinder) -> void {
+                                  bbinder->getMinSchedulerPolicy();
+                              },
+                              [](FuzzedDataProvider*, const sp<BBinder>& bbinder) -> void {
+                                  bbinder->getMinSchedulerPriority();
+                              },
+                              [](FuzzedDataProvider*, const sp<BBinder>& bbinder) -> void {
+                                  bbinder->getDebugPid();
+                              }};
+
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/fuzzers/BpBinderFuzz.cpp
new file mode 100644
index 0000000..c50279b
--- /dev/null
+++ b/libs/binder/tests/fuzzers/BpBinderFuzz.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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 <BpBinderFuzzFunctions.h>
+#include <IBinderFuzzFunctions.h>
+#include <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/BpBinder.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+
+    // TODO: In the future it would be more effective to fork a new process and then pass a BBinder
+    // to your process. Right now this is not implemented because it would involved fuzzing IPC on a
+    // forked process, and libfuzzer will not be able to handle code coverage. This would lead to
+    // crashes that are not easy to diagnose.
+    int32_t handle = fdp.ConsumeIntegralInRange<int32_t>(0, 1024);
+    sp<BpBinder> bpbinder = BpBinder::create(handle);
+    if (bpbinder == nullptr) return 0;
+
+    // To prevent memory from running out from calling too many add item operations.
+    const uint32_t MAX_RUNS = 2048;
+    uint32_t count = 0;
+    sp<IBinder::DeathRecipient> s_recipient = new FuzzDeathRecipient();
+
+    while (fdp.remaining_bytes() > 0 && count++ < MAX_RUNS) {
+        if (fdp.ConsumeBool()) {
+            callArbitraryFunction(&fdp, gBPBinderOperations, bpbinder, s_recipient);
+        } else {
+            callArbitraryFunction(&fdp, gIBinderOperations, bpbinder.get());
+        }
+    }
+
+    return 0;
+}
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h
new file mode 100644
index 0000000..c685b41
--- /dev/null
+++ b/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2020 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 <IBinderFuzzFunctions.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/BpBinder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+#include <cutils/compiler.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/threads.h>
+
+#include <stdio.h>
+
+namespace android {
+
+// Static variable to reference so we don't consume a bunch of memory to link and
+// unlink DeathRecipients.
+static int8_t kBpBinderCookie = 0;
+
+/* This is a vector of lambda functions the fuzzer will pull from.
+ *  This is done so new functions can be added to the fuzzer easily
+ *  without requiring modifications to the main fuzzer file. This also
+ *  allows multiple fuzzers to include this file, if functionality is needed.
+ */
+static const std::vector<std::function<void(FuzzedDataProvider*, const sp<BpBinder>&,
+                                            const sp<IBinder::DeathRecipient>&)>>
+        gBPBinderOperations =
+                {[](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void { bpbinder->handle(); },
+                 [](FuzzedDataProvider* fdp, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>& s_recipient) -> void {
+                     // Clean up possible leftover memory.
+                     wp<IBinder::DeathRecipient> outRecipient(nullptr);
+                     bpbinder->sendObituary();
+                     bpbinder->unlinkToDeath(nullptr, reinterpret_cast<void*>(&kBpBinderCookie), 0,
+                                             &outRecipient);
+
+                     uint32_t flags = fdp->ConsumeIntegral<uint32_t>();
+                     kBpBinderCookie = fdp->ConsumeIntegral<int8_t>();
+                     bpbinder->linkToDeath(s_recipient.get(),
+                                           reinterpret_cast<void*>(&kBpBinderCookie), flags);
+                 },
+                 [](FuzzedDataProvider* fdp, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void {
+                     wp<IBinder::DeathRecipient> out_recipient(nullptr);
+                     uint32_t flags = fdp->ConsumeIntegral<uint32_t>();
+                     int8_t random_cookie = fdp->ConsumeIntegral<int8_t>();
+                     bpbinder->unlinkToDeath(nullptr, reinterpret_cast<void*>(&random_cookie),
+                                             flags, &out_recipient);
+                 },
+                 [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void { bpbinder->remoteBinder(); },
+                 [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void { bpbinder->sendObituary(); },
+                 [](FuzzedDataProvider* fdp, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void {
+                     uint32_t uid = fdp->ConsumeIntegral<uint32_t>();
+                     bpbinder->getBinderProxyCount(uid);
+                 },
+                 [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void { bpbinder->enableCountByUid(); },
+                 [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void { bpbinder->disableCountByUid(); },
+                 [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void {
+                     Vector<uint32_t> uids;
+                     Vector<uint32_t> counts;
+                     bpbinder->getCountByUid(uids, counts);
+                 },
+                 [](FuzzedDataProvider* fdp, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void {
+                     bool enable = fdp->ConsumeBool();
+                     bpbinder->setCountByUidEnabled(enable);
+                 },
+                 [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void {
+                     binder_proxy_limit_callback cb = binder_proxy_limit_callback();
+                     bpbinder->setLimitCallback(cb);
+                 },
+                 [](FuzzedDataProvider* fdp, const sp<BpBinder>& bpbinder,
+                    const sp<IBinder::DeathRecipient>&) -> void {
+                     int high = fdp->ConsumeIntegral<int>();
+                     int low = fdp->ConsumeIntegral<int>();
+                     bpbinder->setBinderProxyCountWatermarks(high, low);
+                 }};
+
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h
new file mode 100644
index 0000000..626b758
--- /dev/null
+++ b/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+#include <cutils/compiler.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class FuzzDeathRecipient : public IBinder::DeathRecipient {
+private:
+    virtual void binderDied(const wp<IBinder>& who) { (void)who; };
+};
+
+// Allow objects to be attached that aren't stack locals
+static uint32_t objectID = 0;
+static uint32_t object = 0;
+static uint32_t cleanup_cookie = 0;
+
+/* This is a vector of lambda functions the fuzzer will pull from.
+ *  This is done so new functions can be added to the fuzzer easily
+ *  without requiring modifications to the main fuzzer file. This also
+ *  allows multiple fuzzers to include this file, if functionality is needed.
+ */
+static const std::vector<std::function<void(FuzzedDataProvider*, IBinder*)>> gIBinderOperations =
+        {[](FuzzedDataProvider*, IBinder* ibinder) -> void { ibinder->getInterfaceDescriptor(); },
+         [](FuzzedDataProvider*, IBinder* ibinder) -> void { ibinder->isBinderAlive(); },
+         [](FuzzedDataProvider*, IBinder* ibinder) -> void { ibinder->pingBinder(); },
+         [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
+             int fd = STDOUT_FILENO;
+             std::string rand_str = fdp->ConsumeRandomLengthString(fdp->remaining_bytes());
+             Vector<String16> args;
+             args.push(String16(rand_str.c_str()));
+             ibinder->dump(fd, args);
+         },
+         [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
+             objectID = fdp->ConsumeIntegral<uint32_t>();
+             object = fdp->ConsumeIntegral<uint32_t>();
+             cleanup_cookie = fdp->ConsumeIntegral<uint32_t>();
+             IBinder::object_cleanup_func func = IBinder::object_cleanup_func();
+             ibinder->attachObject(fdp->ConsumeBool() ? reinterpret_cast<void*>(&objectID)
+                                                      : nullptr,
+                                   fdp->ConsumeBool() ? reinterpret_cast<void*>(&object) : nullptr,
+                                   fdp->ConsumeBool() ? reinterpret_cast<void*>(&cleanup_cookie)
+                                                      : nullptr,
+                                   func);
+         },
+         [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
+             uint32_t id = fdp->ConsumeIntegral<uint32_t>();
+             ibinder->findObject(reinterpret_cast<void*>(&id));
+         },
+         [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
+             uint32_t id = fdp->ConsumeIntegral<uint32_t>();
+             ibinder->detachObject(reinterpret_cast<void*>(&id));
+         },
+         [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void {
+             uint32_t code = fdp->ConsumeIntegral<uint32_t>();
+             Parcel p_data;
+             Parcel reply;
+             uint32_t flags = fdp->ConsumeIntegral<uint32_t>();
+             ibinder->transact(code, p_data, &reply, flags);
+         }};
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp b/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp
new file mode 100644
index 0000000..4843c46
--- /dev/null
+++ b/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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 <PersistableBundleFuzzFunctions.h>
+#include <binder/PersistableBundle.h>
+#include <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String16.h>
+
+namespace android {
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+    std::shared_ptr<os::PersistableBundle> p_bundle(new os::PersistableBundle());
+
+    while (fdp.remaining_bytes() > 0) {
+        String16 key(fdp.ConsumeRandomLengthString(fdp.remaining_bytes()).c_str());
+        callArbitraryFunction(&fdp, gPersistableBundleOperations, p_bundle, &key);
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h b/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h
new file mode 100644
index 0000000..820e9e8
--- /dev/null
+++ b/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2020 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/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+#include <map>
+#include <set>
+#include <vector>
+
+namespace android {
+
+/* This is a vector of lambda functions the fuzzer will pull from.
+ *  This is done so new functions can be added to the fuzzer easily
+ *  without requiring modifications to the main fuzzer file. This also
+ *  allows multiple fuzzers to include this file, if functionality is needed.
+ */
+static const std::vector<std::function<
+        void(FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const&, String16*)>>
+        gPersistableBundleOperations =
+                {[](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16*) -> void { p_bundle->empty(); },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16*) -> void {
+                     Parcel parcel;
+                     p_bundle->writeToParcel(&parcel);
+                 },
+                 [](FuzzedDataProvider* fdp, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16*) -> void {
+                     Parcel parcel;
+                     std::vector<uint8_t> buf = fdp->ConsumeBytes<uint8_t>(
+                             fdp->ConsumeIntegralInRange<size_t>(0, fdp->remaining_bytes() - 1));
+                     parcel.write(buf.data(), buf.size());
+                     p_bundle->readFromParcel(&parcel);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16*) -> void { p_bundle->size(); },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void { p_bundle->erase(*key); },
+                 [](FuzzedDataProvider* fdp, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     bool value = fdp->ConsumeBool();
+                     p_bundle->putBoolean(*key, value);
+                 },
+                 [](FuzzedDataProvider* fdp, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     int32_t value = fdp->ConsumeIntegral<int32_t>();
+                     p_bundle->putInt(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     os::PersistableBundle value = os::PersistableBundle();
+                     p_bundle->putPersistableBundle(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<String16> value;
+                     p_bundle->putStringVector(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<double> value;
+                     p_bundle->putDoubleVector(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<int64_t> value;
+                     p_bundle->putLongVector(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<int32_t> value;
+                     p_bundle->putIntVector(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<bool> value;
+                     p_bundle->putBooleanVector(*key, value);
+                 },
+                 [](FuzzedDataProvider* fdp, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     String16 value(fdp->ConsumeRandomLengthString(fdp->remaining_bytes()).c_str());
+                     p_bundle->putString(*key, value);
+                 },
+                 [](FuzzedDataProvider* fdp, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     int64_t value = fdp->ConsumeIntegral<int64_t>();
+                     p_bundle->putLong(*key, value);
+                 },
+                 [](FuzzedDataProvider* fdp, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     double value = fdp->ConsumeFloatingPoint<double>();
+                     p_bundle->putDouble(*key, value);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     bool out;
+                     p_bundle->getBoolean(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     os::PersistableBundle out;
+                     p_bundle->getPersistableBundle(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<String16> out;
+                     p_bundle->getStringVector(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<double> out;
+                     p_bundle->getDoubleVector(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<int64_t> out;
+                     p_bundle->getLongVector(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<int32_t> out;
+                     p_bundle->getIntVector(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     std::vector<bool> out;
+                     p_bundle->getBooleanVector(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     String16 out;
+                     p_bundle->getString(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     double out;
+                     p_bundle->getDouble(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     int64_t out;
+                     p_bundle->getLong(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16* key) -> void {
+                     int32_t out;
+                     p_bundle->getInt(*key, &out);
+                 },
+                 [](FuzzedDataProvider*, std::shared_ptr<os::PersistableBundle> const& p_bundle,
+                    String16*) -> void {
+                     p_bundle->getBooleanKeys();
+                     p_bundle->getIntKeys();
+                     p_bundle->getLongKeys();
+                     p_bundle->getDoubleKeys();
+                     p_bundle->getStringKeys();
+                     p_bundle->getBooleanVectorKeys();
+                     p_bundle->getIntVectorKeys();
+                     p_bundle->getLongVectorKeys();
+                     p_bundle->getDoubleVectorKeys();
+                     p_bundle->getStringVectorKeys();
+                     p_bundle->getPersistableBundleKeys();
+                 }};
+
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/StabilityFuzz.cpp b/libs/binder/tests/fuzzers/StabilityFuzz.cpp
new file mode 100644
index 0000000..8ad9b44
--- /dev/null
+++ b/libs/binder/tests/fuzzers/StabilityFuzz.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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 <StabilityFuzzFunctions.h>
+#include <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    // Init our wrapper
+    FuzzedDataProvider dataProvider(data, size);
+    android::sp<android::IBinder> bbinder = new android::BBinder();
+
+    // Call some functions
+    while (dataProvider.remaining_bytes() > 0) {
+        callArbitraryFunction(&dataProvider, gStabilityOperations, bbinder);
+    }
+
+    return 0;
+}
diff --git a/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h
new file mode 100644
index 0000000..8b4ed70
--- /dev/null
+++ b/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2020 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/Binder.h>
+#include <binder/Stability.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#define STABILITY_MAX_TAG_LENGTH 2048
+static bool marked = false;
+
+/* This is a vector of lambda functions the fuzzer will pull from.
+ *  This is done so new functions can be added to the fuzzer easily
+ *  without requiring modifications to the main fuzzer file. This also
+ *  allows multiple fuzzers to include this file, if functionality is needed.
+ */
+static const std::vector<
+        std::function<void(FuzzedDataProvider*, android::sp<android::IBinder> const&)>>
+        gStabilityOperations = {
+                // markCompilationUnit(IBinder* binder)
+                [](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
+                    if (!marked) {
+                        android::internal::Stability::markCompilationUnit(bbinder.get());
+                        marked = true;
+                    }
+                },
+
+                // markVintf(IBinder* binder)
+                [](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
+                    if (!marked) {
+                        android::internal::Stability::markVintf(bbinder.get());
+                        marked = true;
+                    }
+                },
+
+                // debugLogStability(const std::string& tag, const sp<IBinder>& binder)
+                [](FuzzedDataProvider* fdp, android::sp<android::IBinder> const& bbinder) -> void {
+                    std::string tag = fdp->ConsumeRandomLengthString(STABILITY_MAX_TAG_LENGTH);
+                    android::internal::Stability::debugLogStability(tag, bbinder);
+                },
+
+                // markVndk(IBinder* binder)
+                [](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
+                    if (!marked) {
+                        android::internal::Stability::markVndk(bbinder.get());
+                        marked = true;
+                    }
+                },
+
+                // requiresVintfDeclaration(const sp<IBinder>& binder)
+                [](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
+                    android::internal::Stability::requiresVintfDeclaration(bbinder);
+                }};
diff --git a/libs/binder/tests/fuzzers/StatusFuzz.cpp b/libs/binder/tests/fuzzers/StatusFuzz.cpp
new file mode 100644
index 0000000..4f6ad6f
--- /dev/null
+++ b/libs/binder/tests/fuzzers/StatusFuzz.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 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 <StatusFuzzFunctions.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String8.h>
+#include <cstdint>
+#include <sstream>
+#include <string>
+
+namespace android {
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+
+    int32_t exceptionCode = fdp.ConsumeIntegral<int32_t>();
+    std::string message_str = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+    String8 message(message_str.c_str());
+
+    Parcel parcel;
+    std::vector<uint8_t> buf = fdp.ConsumeBytes<uint8_t>(
+            fdp.ConsumeIntegralInRange<size_t>(0, fdp.remaining_bytes() - 1));
+    parcel.write(buf.data(), buf.size());
+    binder::Status status = binder::Status::fromExceptionCode(exceptionCode, message);
+
+    while (fdp.remaining_bytes() > 0) {
+        callArbitraryFunction(&fdp, gStatusOperations, &status, &parcel);
+    }
+    return 0;
+}
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/StatusFuzzFunctions.h b/libs/binder/tests/fuzzers/StatusFuzzFunctions.h
new file mode 100644
index 0000000..bc8d17a
--- /dev/null
+++ b/libs/binder/tests/fuzzers/StatusFuzzFunctions.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <stdio.h>
+#include <utils/String8.h>
+#include <cstdint>
+#include <sstream>
+#include <string>
+
+namespace android {
+/* This is a vector of lambda functions the fuzzer will pull from.
+ *  This is done so new functions can be added to the fuzzer easily
+ *  without requiring modifications to the main fuzzer file. This also
+ *  allows multiple fuzzers to include this file, if functionality is needed.
+ */
+static const std::vector<std::function<void(FuzzedDataProvider*, binder::Status*, Parcel*)>>
+        gStatusOperations = {
+                [](FuzzedDataProvider*, binder::Status* status, Parcel* parcel) -> void {
+                    parcel->setDataPosition(0);
+                    status->readFromParcel(*parcel);
+                },
+                [](FuzzedDataProvider*, binder::Status* status, Parcel* parcel) -> void {
+                    status->writeToParcel(parcel);
+                },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    std::string message_str =
+                            fdp->ConsumeRandomLengthString(fdp->remaining_bytes());
+                    String8 message(message_str.c_str());
+                    status->setServiceSpecificError(fdp->ConsumeIntegral<int32_t>(), message);
+                },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    std::string message_str =
+                            fdp->ConsumeRandomLengthString(fdp->remaining_bytes());
+                    String8 message(message_str.c_str());
+                    status->setException(fdp->ConsumeIntegral<int32_t>(), message);
+                },
+                [](FuzzedDataProvider*, binder::Status* status, Parcel*) -> void { status->ok(); },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    std::string message_str =
+                            fdp->ConsumeRandomLengthString(fdp->remaining_bytes());
+                    String8 message(message_str.c_str());
+                    *status = binder::Status::fromExceptionCode(fdp->ConsumeIntegral<int32_t>(),
+                                                                message);
+                },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    *status = binder::Status::fromServiceSpecificError(
+                            fdp->ConsumeIntegral<int32_t>());
+                },
+                [](FuzzedDataProvider* fdp, binder::Status*, Parcel*) -> void {
+                    binder::Status::exceptionToString(fdp->ConsumeIntegral<int32_t>());
+                },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    std::string message_str =
+                            fdp->ConsumeRandomLengthString(fdp->remaining_bytes());
+                    String8 message(message_str.c_str());
+                    *status = binder::Status::fromServiceSpecificError(fdp->ConsumeIntegral<
+                                                                               int32_t>(),
+                                                                       message);
+                },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    *status = binder::Status::fromStatusT(fdp->ConsumeIntegral<status_t>());
+                },
+                [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void {
+                    status->setFromStatusT(fdp->ConsumeIntegral<status_t>());
+                },
+                [](FuzzedDataProvider*, binder::Status* status, Parcel*) -> void {
+                    std::stringstream ss;
+                    ss << *status;
+                },
+};
+
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp
new file mode 100644
index 0000000..c950020
--- /dev/null
+++ b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 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 <fuzzer/FuzzedDataProvider.h>
+
+#include <binder/Debug.h>
+#include <binder/Parcel.h>
+#include <binder/TextOutput.h>
+#include "android-base/file.h"
+#include "android-base/test_utils.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <cstddef>
+#include <limits>
+
+// Fuzzer for the TextOutput class. These were lifted from the existing
+// test suite.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+    CapturedStderr cap;
+
+    while (fdp.remaining_bytes() > 1) {
+        switch (fdp.ConsumeIntegral<uint8_t>() % 3) {
+            case 0: {
+                std::string input = fdp.ConsumeBytesAsString(
+                        fdp.ConsumeIntegralInRange<size_t>(0, fdp.remaining_bytes()));
+                android::aerr << input << android::endl;
+                break;
+            }
+            case 1: {
+                std::string str = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+                android::HexDump input(str.c_str(), sizeof(str.c_str()));
+                android::aerr << input << android::endl;
+                break;
+            }
+            case 2: {
+                android::TypeCode input(fdp.ConsumeIntegral<uint32_t>());
+                android::aerr << input << android::endl;
+            }
+        }
+    }
+    cap.Stop();
+
+    return 0;
+}
diff --git a/libs/binder/tests/fuzzers/commonFuzzHelpers.h b/libs/binder/tests/fuzzers/commonFuzzHelpers.h
new file mode 100644
index 0000000..d58d9b6
--- /dev/null
+++ b/libs/binder/tests/fuzzers/commonFuzzHelpers.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>
+#include <vector>
+
+// Calls a function from the ops_vector
+template <class F, class T, class... Types>
+void callArbitraryFunction(F* fdp, T const& ops_vector, Types... args) {
+    // Choose which function we'll be calling
+    uint8_t function_id = fdp->template ConsumeIntegralInRange<uint8_t>(0, ops_vector.size() - 1);
+
+    // Call the function we've chosen
+    ops_vector[function_id](fdp, args...);
+}
+
+template <class T>
+T getArbitraryVectorElement(FuzzedDataProvider* fdp, std::vector<T> const& vect, bool allow_null) {
+    // If we're allowing null, give it a 50:50 shot at returning a nullptr
+    if (vect.empty() || (allow_null && fdp->ConsumeBool())) {
+        return nullptr;
+    }
+
+    // Otherwise, return an element from our vector
+    return vect.at(fdp->ConsumeIntegralInRange<size_t>(0, vect.size() - 1));
+}
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 97dc0f1..f82c2a4 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -29,9 +29,13 @@
 #include <graphicsenv/GraphicsEnv.h>
 #include <time.h>
 #include <log/log.h>
+#include <vndksupport/linker.h>
 
 namespace angle {
 
+constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so";
+constexpr int kAngleDlFlags = RTLD_LOCAL | RTLD_NOW;
+
 static GetDisplayPlatformFunc angleGetDisplayPlatform = nullptr;
 static ResetDisplayPlatformFunc angleResetDisplayPlatform = nullptr;
 
@@ -101,11 +105,22 @@
 bool initializeAnglePlatform(EGLDisplay dpy) {
     // Since we're inside libEGL, use dlsym to lookup fptr for ANGLEGetDisplayPlatform
     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
-    const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-            .library_namespace = ns,
-    };
-    void* so = android_dlopen_ext("libGLESv2_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+    void* so = nullptr;
+    if (ns) {
+        const android_dlextinfo dlextinfo = {
+                .flags = ANDROID_DLEXT_USE_NAMESPACE,
+                .library_namespace = ns,
+        };
+        so = android_dlopen_ext(kAngleEs2Lib, kAngleDlFlags, &dlextinfo);
+    } else {
+        // If we are here, ANGLE is loaded as built-in gl driver in the sphal.
+        so = android_load_sphal_library(kAngleEs2Lib, kAngleDlFlags);
+    }
+    if (!so) {
+        ALOGE("%s failed to dlopen %s!", __FUNCTION__, kAngleEs2Lib);
+        return false;
+    }
+
     angleGetDisplayPlatform =
             reinterpret_cast<GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
 
diff --git a/services/surfaceflinger/Scheduler/TimeKeeper.h b/services/surfaceflinger/Scheduler/TimeKeeper.h
index da2195c..40dd841 100644
--- a/services/surfaceflinger/Scheduler/TimeKeeper.h
+++ b/services/surfaceflinger/Scheduler/TimeKeeper.h
@@ -43,10 +43,10 @@
     virtual ~TimeKeeper();
 
     /*
-     * Arms callback to fired in time nanoseconds.
+     * Arms callback to fired when time is current based on CLOCK_MONOTONIC
      * There is only one timer, and subsequent calls will reset the callback function and the time.
      */
-    virtual void alarmIn(std::function<void()> const& callback, nsecs_t time) = 0;
+    virtual void alarmAt(std::function<void()> const& callback, nsecs_t time) = 0;
 
     /*
      * Cancels an existing pending callback
diff --git a/services/surfaceflinger/Scheduler/Timer.cpp b/services/surfaceflinger/Scheduler/Timer.cpp
index 7c5058e..59c336a 100644
--- a/services/surfaceflinger/Scheduler/Timer.cpp
+++ b/services/surfaceflinger/Scheduler/Timer.cpp
@@ -88,7 +88,7 @@
     return systemTime(SYSTEM_TIME_MONOTONIC);
 }
 
-void Timer::alarmIn(std::function<void()> const& cb, nsecs_t fireIn) {
+void Timer::alarmAt(std::function<void()> const& cb, nsecs_t time) {
     std::lock_guard<decltype(mMutex)> lk(mMutex);
     using namespace std::literals;
     static constexpr int ns_per_s =
@@ -99,11 +99,11 @@
     struct itimerspec old_timer;
     struct itimerspec new_timer {
         .it_interval = {.tv_sec = 0, .tv_nsec = 0},
-        .it_value = {.tv_sec = static_cast<long>(fireIn / ns_per_s),
-                     .tv_nsec = static_cast<long>(fireIn % ns_per_s)},
+        .it_value = {.tv_sec = static_cast<long>(time / ns_per_s),
+                     .tv_nsec = static_cast<long>(time % ns_per_s)},
     };
 
-    if (timerfd_settime(mTimerFd, 0, &new_timer, &old_timer)) {
+    if (timerfd_settime(mTimerFd, TFD_TIMER_ABSTIME, &new_timer, &old_timer)) {
         ALOGW("Failed to set timerfd %s (%i)", strerror(errno), errno);
     }
 }
diff --git a/services/surfaceflinger/Scheduler/Timer.h b/services/surfaceflinger/Scheduler/Timer.h
index a8e2d5a..69ce079 100644
--- a/services/surfaceflinger/Scheduler/Timer.h
+++ b/services/surfaceflinger/Scheduler/Timer.h
@@ -30,9 +30,9 @@
     ~Timer();
     nsecs_t now() const final;
 
-    // NB: alarmIn and alarmCancel are threadsafe; with the last-returning function being effectual
+    // NB: alarmAt and alarmCancel are threadsafe; with the last-returning function being effectual
     //     Most users will want to serialize thes calls so as to be aware of the timer state.
-    void alarmIn(std::function<void()> const& cb, nsecs_t fireIn) final;
+    void alarmAt(std::function<void()> const& cb, nsecs_t time) final;
     void alarmCancel() final;
     void dump(std::string& result) const final;
 
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index a596bce..ef92680 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -180,10 +180,10 @@
     mTimeKeeper->alarmCancel();
 }
 
-void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t now) {
+void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
     mIntendedWakeupTime = targetTime;
-    mTimeKeeper->alarmIn(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
-                         targetTime - now);
+    mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
+                         mIntendedWakeupTime);
     mLastTimerSchedule = mTimeKeeper->now();
 }
 
@@ -243,7 +243,8 @@
     std::vector<Invocation> invocations;
     {
         std::lock_guard<decltype(mMutex)> lk(mMutex);
-        mLastTimerCallback = mTimeKeeper->now();
+        auto const now = mTimeKeeper->now();
+        mLastTimerCallback = now;
         for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
             auto& callback = it->second;
             auto const wakeupTime = callback->wakeupTime();
@@ -251,7 +252,8 @@
                 continue;
             }
 
-            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack) {
+            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
+            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                 callback->executing();
                 invocations.emplace_back(
                         Invocation{callback, *callback->lastExecutedVsyncTarget(), *wakeupTime});
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 3c4a791..1bbc3f8 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -58,6 +58,7 @@
         "RegionSamplingTest.cpp",
         "TimeStatsTest.cpp",
         "FrameTracerTest.cpp",
+        "TimerTest.cpp",
         "TransactionApplicationTest.cpp",
         "StrongTypingTest.cpp",
         "VSyncDispatchTimerQueueTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/TimerTest.cpp b/services/surfaceflinger/tests/unittests/TimerTest.cpp
new file mode 100644
index 0000000..cda6bbf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/TimerTest.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 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 "AsyncCallRecorder.h"
+#include "Scheduler/TimeKeeper.h"
+#include "Scheduler/Timer.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace testing;
+using namespace std::literals;
+
+namespace android::scheduler {
+
+struct TimerTest : testing::Test {
+    static constexpr int mIterations = 20;
+
+    AsyncCallRecorder<void (*)()> mCallbackRecorder;
+    Timer mTimer;
+
+    void timerCallback() { mCallbackRecorder.recordCall(); }
+};
+
+TEST_F(TimerTest, callsCallbackIfScheduledInPast) {
+    for (int i = 0; i < mIterations; i++) {
+        mTimer.alarmAt(std::bind(&TimerTest::timerCallback, this), systemTime() - 10'000'00);
+        EXPECT_TRUE(mCallbackRecorder.waitForCall().has_value());
+        EXPECT_FALSE(mCallbackRecorder.waitForUnexpectedCall().has_value());
+    }
+}
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index d940dc5..fa5cc32 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -63,19 +63,19 @@
 class ControllableClock : public TimeKeeper {
 public:
     ControllableClock() {
-        ON_CALL(*this, alarmIn(_, _))
-                .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
+        ON_CALL(*this, alarmAt(_, _))
+                .WillByDefault(Invoke(this, &ControllableClock::alarmAtDefaultBehavior));
         ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
     }
 
     MOCK_CONST_METHOD0(now, nsecs_t());
-    MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
+    MOCK_METHOD2(alarmAt, void(std::function<void()> const&, nsecs_t time));
     MOCK_METHOD0(alarmCancel, void());
     MOCK_CONST_METHOD1(dump, void(std::string&));
 
-    void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
+    void alarmAtDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
         mCallback = callback;
-        mNextCallbackTime = time + mCurrentTime;
+        mNextCallbackTime = time;
     }
 
     nsecs_t fakeTime() const { return mCurrentTime; }
@@ -115,11 +115,15 @@
 
     operator VSyncDispatch::CallbackToken() const { return mToken; }
 
-    void counter(nsecs_t time, nsecs_t) { mCalls.push_back(time); }
+    void counter(nsecs_t time, nsecs_t wakeup_time) {
+        mCalls.push_back(time);
+        mWakeupTime.push_back(wakeup_time);
+    }
 
     VSyncDispatch& mDispatch;
     VSyncDispatch::CallbackToken mToken;
     std::vector<nsecs_t> mCalls;
+    std::vector<nsecs_t> mWakeupTime;
 };
 
 class PausingCallback {
@@ -187,8 +191,8 @@
         class TimeKeeperWrapper : public TimeKeeper {
         public:
             TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
-            void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
-                mControllableClock.alarmIn(callback, time);
+            void alarmAt(std::function<void()> const& callback, nsecs_t time) final {
+                mControllableClock.alarmAt(callback, time);
             }
             void alarmCancel() final { mControllableClock.alarmCancel(); }
             nsecs_t now() const final { return mControllableClock.now(); }
@@ -217,7 +221,7 @@
 };
 
 TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
+    EXPECT_CALL(mMockClock, alarmAt(_, 900));
     EXPECT_CALL(mMockClock, alarmCancel());
     {
         VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
@@ -229,7 +233,7 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
     auto intended = mPeriod - 230;
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
+    EXPECT_CALL(mMockClock, alarmAt(_, 900));
 
     CountingCallback cb(mDispatch);
     EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
@@ -241,7 +245,7 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
-    EXPECT_CALL(mMockClock, alarmIn(_, 1050));
+    EXPECT_CALL(mMockClock, alarmAt(_, 1050));
 
     CountingCallback cb(mDispatch);
     mDispatch.schedule(cb, 100, mPeriod);
@@ -257,14 +261,14 @@
     auto const workDuration = 10 * mPeriod;
     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
             .WillOnce(Return(mPeriod * 11));
-    EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
+    EXPECT_CALL(mMockClock, alarmAt(_, mPeriod));
 
     CountingCallback cb(mDispatch);
     EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
+    EXPECT_CALL(mMockClock, alarmAt(_, 900));
     EXPECT_CALL(mMockClock, alarmCancel());
 
     CountingCallback cb(mDispatch);
@@ -273,7 +277,7 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
+    EXPECT_CALL(mMockClock, alarmAt(_, 900));
     EXPECT_CALL(mMockClock, alarmCancel());
 
     CountingCallback cb(mDispatch);
@@ -283,7 +287,7 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
+    EXPECT_CALL(mMockClock, alarmAt(_, 900));
     EXPECT_CALL(mMockClock, alarmCancel());
 
     PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
@@ -297,7 +301,7 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
+    EXPECT_CALL(mMockClock, alarmAt(_, 900));
     EXPECT_CALL(mMockClock, alarmCancel());
 
     auto resource = std::make_shared<int>(110);
@@ -327,9 +331,9 @@
             .WillOnce(Return(1075));
 
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 955)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 813)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 975)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     CountingCallback cb1(mDispatch);
@@ -355,9 +359,9 @@
             .WillOnce(Return(10000));
 
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 750)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     CountingCallback cb1(mDispatch);
@@ -369,8 +373,8 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 700)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     CountingCallback cb1(mDispatch);
@@ -383,9 +387,9 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     CountingCallback cb1(mDispatch);
@@ -398,10 +402,10 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1590)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
 
     auto offset = 400;
     auto closeOffset = offset + mDispatchGroupThreshold - 1;
@@ -432,9 +436,10 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 900));
-    EXPECT_CALL(mMockClock, alarmIn(_, 800));
-    EXPECT_CALL(mMockClock, alarmIn(_, 100));
+    Sequence seq;
+    EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 800)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
     EXPECT_CALL(mMockClock, alarmCancel());
 
     CountingCallback cb0(mDispatch);
@@ -472,8 +477,8 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
 
     VSyncDispatch::CallbackToken tmp;
     tmp = mDispatch.registerCallback([&](auto, auto) { mDispatch.schedule(tmp, 100, 2000); },
@@ -507,10 +512,10 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1000)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 950)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1950)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
 
     CountingCallback cb(mDispatch);
     mDispatch.schedule(cb, 0, 1000);
@@ -527,10 +532,10 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 850)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1800)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     CountingCallback cb1(mDispatch);
@@ -548,7 +553,7 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     CountingCallback cb1(mDispatch);
@@ -558,9 +563,9 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
     EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
 
     CountingCallback cb0(mDispatch);
     mDispatch.schedule(cb0, 500, 1000);
@@ -582,7 +587,7 @@
 
 // b/1450138150
 TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 500));
+    EXPECT_CALL(mMockClock, alarmAt(_, 500));
     CountingCallback cb(mDispatch);
     EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
     mMockClock.advanceBy(400);
@@ -612,8 +617,8 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1100)).InSequence(seq);
     CountingCallback cb0(mDispatch);
     EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
     advanceToNextCallback();
@@ -621,7 +626,7 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 600));
+    EXPECT_CALL(mMockClock, alarmAt(_, 600));
 
     CountingCallback cb(mDispatch);
     EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
@@ -632,7 +637,7 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
     EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
 
     VSyncCallbackRegistration cb(
@@ -646,7 +651,7 @@
 }
 
 TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
-    EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
+    EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
     EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
 
     VSyncCallbackRegistration cb(
@@ -664,8 +669,8 @@
 // b/154303580
 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 1200)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
     CountingCallback cb1(mDispatch);
     CountingCallback cb2(mDispatch);
 
@@ -686,8 +691,8 @@
 // update later, as opposed to blocking the calling thread.
 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminentSameCallback) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 930)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1630)).InSequence(seq);
     CountingCallback cb(mDispatch);
 
     EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
@@ -704,7 +709,7 @@
 // b/154303580.
 TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
     EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
     CountingCallback cb1(mDispatch);
     CountingCallback cb2(mDispatch);
@@ -725,8 +730,8 @@
 
 TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) {
     Sequence seq;
-    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
-    EXPECT_CALL(mMockClock, alarmIn(_, 1280)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
     EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
     CountingCallback cb1(mDispatch);
     CountingCallback cb2(mDispatch);
@@ -747,6 +752,31 @@
     EXPECT_THAT(cb2.mCalls.size(), Eq(1));
 }
 
+TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) {
+    CountingCallback cb1(mDispatch);
+    CountingCallback cb2(mDispatch);
+
+    Sequence seq;
+    EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
+            .InSequence(seq)
+            .WillOnce(Return(1000));
+    EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+    EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
+            .InSequence(seq)
+            .WillOnce(Return(1000));
+
+    EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled);
+    EXPECT_EQ(mDispatch.schedule(cb2, 390, 1000), ScheduleResult::Scheduled);
+
+    mMockClock.setLag(100);
+    mMockClock.advanceBy(700);
+
+    ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1));
+    EXPECT_THAT(cb1.mWakeupTime[0], Eq(600));
+    ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1));
+    EXPECT_THAT(cb2.mWakeupTime[0], Eq(610));
+}
+
 class VSyncDispatchTimerQueueEntryTest : public testing::Test {
 protected:
     nsecs_t const mPeriod = 1000;