Merge "SF: Move/refactor presentation loop to CompositionEngine"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index a8e6738..b781da3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2328,9 +2328,6 @@
             // clang-format off
             case 'd': do_add_date = true;            break;
             case 'z': do_zip_file = true;            break;
-            // o=use_outfile not supported anymore.
-            // TODO(b/111441001): Remove when all callers have migrated.
-            case 'o': break;
             case 's': use_socket = true;             break;
             case 'S': use_control_socket = true;     break;
             case 'v': show_header_only = true;       break;
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 14937b8..e491a4b 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -11,8 +11,7 @@
 
 # dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
 # it is finished.
-service dumpstatez /system/bin/dumpstate -S -d -z \
-        -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+service dumpstatez /system/bin/dumpstate -S -d -z
     socket dumpstate stream 0660 shell log
     class main
     disabled
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 181046a..dbbcdff 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -201,9 +201,7 @@
             (char*)"dumpstate",
             (char*)"-d",
             (char*)"-z",
-            (char*)"-B",
-            (char*)"-o",
-            (char*)dirname(android::base::GetExecutablePath().c_str())
+            (char*)"-B"
         };
         // clang-format on
         sp<DumpstateListener> listener(new DumpstateListener(dup(fileno(stdout)), sections));
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 3ada153..cbac839 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -53,7 +53,7 @@
     MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&));
     MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int));
     MOCK_METHOD1(listServices, Vector<String16>(int));
-
+    MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 119e4c3..b3aa342 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -28,6 +28,13 @@
 ServiceManager::~ServiceManager() {
     // this should only happen in tests
 
+    for (const auto& [name, callbacks] : mNameToCallback) {
+        CHECK(!callbacks.empty()) << name;
+        for (const auto& callback : callbacks) {
+            CHECK(callback != nullptr) << name;
+        }
+    }
+
     for (const auto& [name, service] : mNameToService) {
         CHECK(service.binder != nullptr) << name;
     }
@@ -117,6 +124,14 @@
         .dumpPriority = dumpPriority,
     };
 
+    auto it = mNameToCallback.find(name);
+    if (it != mNameToCallback.end()) {
+        for (const sp<IServiceCallback>& cb : it->second) {
+            // permission checked in registerForNotifications
+            cb->onRegistration(name, binder);
+        }
+    }
+
     return Status::ok();
 }
 
@@ -146,6 +161,84 @@
     return Status::ok();
 }
 
+Status ServiceManager::registerForNotifications(
+        const std::string& name, const sp<IServiceCallback>& callback) {
+    auto ctx = mAccess->getCallingContext();
+
+    if (!mAccess->canFind(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    if (!isValidServiceName(name)) {
+        LOG(ERROR) << "Invalid service name: " << name;
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (callback == nullptr) {
+        return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+    }
+
+    if (OK != IInterface::asBinder(callback)->linkToDeath(this)) {
+        LOG(ERROR) << "Could not linkToDeath when adding " << name;
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+    }
+
+    mNameToCallback[name].push_back(callback);
+
+    if (auto it = mNameToService.find(name); it != mNameToService.end()) {
+        const sp<IBinder>& binder = it->second.binder;
+
+        // never null if an entry exists
+        CHECK(binder != nullptr) << name;
+        callback->onRegistration(name, binder);
+    }
+
+    return Status::ok();
+}
+Status ServiceManager::unregisterForNotifications(
+        const std::string& name, const sp<IServiceCallback>& callback) {
+    auto ctx = mAccess->getCallingContext();
+
+    if (!mAccess->canFind(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    bool found = false;
+
+    auto it = mNameToCallback.find(name);
+    if (it != mNameToCallback.end()) {
+        removeCallback(IInterface::asBinder(callback), &it, &found);
+    }
+
+    if (!found) {
+        LOG(ERROR) << "Trying to unregister callback, but none exists " << name;
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+    }
+
+    return Status::ok();
+}
+
+void ServiceManager::removeCallback(const wp<IBinder>& who,
+                                    CallbackMap::iterator* it,
+                                    bool* found) {
+    std::vector<sp<IServiceCallback>>& listeners = (*it)->second;
+
+    for (auto lit = listeners.begin(); lit != listeners.end();) {
+        if (IInterface::asBinder(*lit) == who) {
+            if(found) *found = true;
+            lit = listeners.erase(lit);
+        } else {
+            ++lit;
+        }
+    }
+
+    if (listeners.empty()) {
+        *it = mNameToCallback.erase(*it);
+    } else {
+        it++;
+    }
+}
+
 void ServiceManager::binderDied(const wp<IBinder>& who) {
     for (auto it = mNameToService.begin(); it != mNameToService.end();) {
         if (who == it->second.binder) {
@@ -154,6 +247,10 @@
             ++it;
         }
     }
+
+    for (auto it = mNameToCallback.begin(); it != mNameToCallback.end();) {
+        removeCallback(who, &it, nullptr /*found*/);
+    }
 }
 
 }  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 43723c5..fcc5124 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -17,11 +17,14 @@
 #pragma once
 
 #include <android/os/BnServiceManager.h>
+#include <android/os/IServiceCallback.h>
 
 #include "Access.h"
 
 namespace android {
 
+using os::IServiceCallback;
+
 class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
 public:
     ServiceManager(std::unique_ptr<Access>&& access);
@@ -29,19 +32,35 @@
 
     binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
     binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
-    binder::Status addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) override;
+    binder::Status addService(const std::string& name, const sp<IBinder>& binder,
+                              bool allowIsolated, int32_t dumpPriority) override;
     binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
+    binder::Status registerForNotifications(const std::string& name,
+                                            const sp<IServiceCallback>& callback) override;
+    binder::Status unregisterForNotifications(const std::string& name,
+                                              const sp<IServiceCallback>& callback) override;
 
     void binderDied(const wp<IBinder>& who) override;
 
 private:
     struct Service {
-        sp<IBinder> binder;
+        sp<IBinder> binder; // not null
         bool allowIsolated;
         int32_t dumpPriority;
     };
 
-    std::map<std::string, Service> mNameToService;
+    using CallbackMap = std::map<std::string, std::vector<sp<IServiceCallback>>>;
+    using ServiceMap = std::map<std::string, Service>;
+
+    // removes a callback from mNameToCallback, removing it if the vector is empty
+    // this updates iterator to the next location
+    void removeCallback(const wp<IBinder>& who,
+                        CallbackMap::iterator* it,
+                        bool* found);
+
+    CallbackMap mNameToCallback;
+    ServiceMap mNameToService;
+
     std::unique_ptr<Access> mAccess;
 };
 
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 91485e4..3c211d2 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+#include <android/os/BnServiceCallback.h>
+#include <binder/Binder.h>
 #include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
 #include <cutils/android_filesystem_config.h>
 #include <gtest/gtest.h>
 #include <gmock/gmock.h>
@@ -24,8 +27,11 @@
 
 using android::sp;
 using android::Access;
+using android::BBinder;
 using android::IBinder;
 using android::ServiceManager;
+using android::binder::Status;
+using android::os::BnServiceCallback;
 using android::os::IServiceManager;
 using testing::_;
 using testing::ElementsAre;
@@ -33,9 +39,14 @@
 using testing::Return;
 
 static sp<IBinder> getBinder() {
-    // It doesn't matter what remote binder it is, we just need one so that linkToDeath will work.
-    // The context manager (servicemanager) is easy to get and is in another process.
-    return android::ProcessState::self()->getContextObject(nullptr);
+    class LinkableBinder : public BBinder {
+        android::status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
+            // let SM linkToDeath
+            return android::OK;
+        }
+    };
+
+    return new LinkableBinder;
 }
 
 class MockAccess : public Access {
@@ -132,12 +143,14 @@
 
 TEST(GetService, HappyHappy) {
     auto sm = getPermissiveServiceManager();
-    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+    sp<IBinder> service = getBinder();
+
+    EXPECT_TRUE(sm->addService("foo", service, false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
     sp<IBinder> out;
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(getBinder(), out);
+    EXPECT_EQ(service, out);
 }
 
 TEST(GetService, NonExistant) {
@@ -181,12 +194,13 @@
 
     sp<ServiceManager> sm = new ServiceManager(std::move(access));
 
-    EXPECT_TRUE(sm->addService("foo", getBinder(), true /*allowIsolated*/,
+    sp<IBinder> service = getBinder();
+    EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
     sp<IBinder> out;
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(getBinder(), out.get());
+    EXPECT_EQ(service, out.get());
 }
 
 TEST(GetService, NotAllowedFromIsolated) {
@@ -265,3 +279,145 @@
     // all there and in the right order
     EXPECT_THAT(out, ElementsAre("sa"));
 }
+
+class CallbackHistorian : public BnServiceCallback {
+    Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
+        registrations.push_back(name);
+        binders.push_back(binder);
+        return Status::ok();
+    }
+
+    android::status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
+        // let SM linkToDeath
+        return android::OK;
+    }
+
+public:
+    std::vector<std::string> registrations;
+    std::vector<sp<IBinder>> binders;
+};
+
+TEST(ServiceNotifications, NoPermissionsRegister) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    EXPECT_EQ(sm->registerForNotifications("foofoo", cb).exceptionCode(),
+        Status::EX_SECURITY);
+}
+
+TEST(ServiceNotifications, NoPermissionsUnregister) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    // should always hit security error first
+    EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
+        Status::EX_SECURITY);
+}
+
+TEST(ServiceNotifications, InvalidName) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    EXPECT_EQ(sm->registerForNotifications("foo@foo", cb).exceptionCode(),
+        Status::EX_ILLEGAL_ARGUMENT);
+}
+
+TEST(ServiceNotifications, NullCallback) {
+    auto sm = getPermissiveServiceManager();
+
+    EXPECT_EQ(sm->registerForNotifications("foofoo", nullptr).exceptionCode(),
+        Status::EX_NULL_POINTER);
+}
+
+TEST(ServiceNotifications, Unregister) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
+    EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(), 0);
+}
+
+TEST(ServiceNotifications, UnregisterWhenNoRegistrationExists) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
+        Status::EX_ILLEGAL_STATE);
+}
+
+TEST(ServiceNotifications, NoNotification) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
+    EXPECT_TRUE(sm->addService("otherservice", getBinder(),
+        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    EXPECT_THAT(cb->registrations, ElementsAre());
+    EXPECT_THAT(cb->binders, ElementsAre());
+}
+
+TEST(ServiceNotifications, GetNotification) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    sp<IBinder> service = getBinder();
+
+    EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
+    EXPECT_TRUE(sm->addService("asdfasdf", service,
+        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf"));
+    EXPECT_THAT(cb->binders, ElementsAre(service));
+}
+
+TEST(ServiceNotifications, GetNotificationForAlreadyRegisteredService) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    sp<IBinder> service = getBinder();
+
+    EXPECT_TRUE(sm->addService("asdfasdf", service,
+        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
+
+    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf"));
+    EXPECT_THAT(cb->binders, ElementsAre(service));
+}
+
+TEST(ServiceNotifications, GetMultipleNotification) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<CallbackHistorian> cb = new CallbackHistorian;
+
+    sp<IBinder> binder1 = getBinder();
+    sp<IBinder> binder2 = getBinder();
+
+    EXPECT_TRUE(sm->registerForNotifications("asdfasdf", cb).isOk());
+    EXPECT_TRUE(sm->addService("asdfasdf", binder1,
+        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("asdfasdf", binder2,
+        false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf", "asdfasdf"));
+    EXPECT_THAT(cb->registrations, ElementsAre("asdfasdf", "asdfasdf"));
+}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 027418a..6ece4a2 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -86,10 +86,8 @@
         vendor: {
             exclude_srcs: [
                 "ActivityManager.cpp",
-                "AppOpsManager.cpp",
                 "IActivityManager.cpp",
                 "IAppOpsCallback.cpp",
-                "IAppOpsService.cpp",
                 "IBatteryStats.cpp",
                 "IMediaResourceMonitor.cpp",
                 "IPermissionController.cpp",
@@ -145,6 +143,7 @@
     name: "libbinder_aidl",
     srcs: [
         "aidl/android/content/pm/IPackageManagerNative.aidl",
+        "aidl/android/os/IServiceCallback.aidl",
         "aidl/android/os/IServiceManager.aidl",
     ],
     path: "aidl",
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 525685c..e2af01c 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -21,10 +21,18 @@
 
 #include <utils/SystemClock.h>
 
+#include <sys/types.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "AppOpsManager"
+
 namespace android {
 
 namespace {
 
+#ifndef __ANDROID_VNDK__
 #if defined(__BRILLO__)
 // Because Brillo has no application model, security policy is managed
 // statically (at build time) with SELinux controls.
@@ -33,13 +41,17 @@
 #else
 const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
 #endif  // defined(__BRILLO__)
+#endif // __ANDROID_VNDK__
 
 }  // namespace
 
 static String16 _appops("appops");
+#ifndef __ANDROID_VNDK__
 static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
+#endif // __ANDROID_VNDK__
 static sp<IBinder> gToken;
 
+#ifndef __ANDROID_VNDK__
 static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
     pthread_mutex_lock(&gTokenMutex);
     if (gToken == nullptr || gToken->pingBinder() != NO_ERROR) {
@@ -48,6 +60,17 @@
     pthread_mutex_unlock(&gTokenMutex);
     return gToken;
 }
+#endif // __ANDROID_VNDK__
+
+thread_local uint64_t notedAppOpsInThisBinderTransaction[2];
+thread_local int32_t uidOfThisBinderTransaction = -1;
+
+// Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
+#ifndef __ANDROID_VNDK__
+uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
+#else
+uint8_t appOpsToNote[128] = {0};
+#endif // __ANDROID_VNDK__
 
 AppOpsManager::AppOpsManager()
 {
@@ -85,6 +108,7 @@
 }
 #endif  // defined(__BRILLO__)
 
+#ifndef __ANDROID_VNDK__
 int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
 {
     sp<IAppOpsService> service = getService();
@@ -102,18 +126,41 @@
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
+    return noteOp(op, uid, callingPackage, String16("noteOp from native code"));
+}
+
+int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
+        const String16& message) {
     sp<IAppOpsService> service = getService();
-    return service != nullptr
+    int32_t mode = service != nullptr
             ? service->noteOperation(op, uid, callingPackage)
             : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+
+    if (mode == AppOpsManager::MODE_ALLOWED) {
+        markAppOpNoted(uid, callingPackage, op, message);
+    }
+
+    return mode;
 }
 
 int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
         bool startIfModeDefault) {
+    return startOpNoThrow(op, uid, callingPackage, startIfModeDefault,
+            String16("startOpNoThrow from native code"));
+}
+
+int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+        bool startIfModeDefault, const String16& message) {
     sp<IAppOpsService> service = getService();
-    return service != nullptr
+    int32_t mode = service != nullptr
             ? service->startOperation(getToken(service), op, uid, callingPackage,
                     startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+
+    if (mode == AppOpsManager::MODE_ALLOWED) {
+        markAppOpNoted(uid, callingPackage, op, message);
+    }
+
+    return mode;
 }
 
 void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
@@ -146,5 +193,47 @@
     return -1;
 }
 
+void AppOpsManager::setCameraAudioRestriction(int32_t mode) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        service->setCameraAudioRestriction(mode);
+    }
+}
+
+#endif // __ANDROID_VNDK__
+
+bool AppOpsManager::shouldCollectNotes(int32_t opcode) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        return service->shouldCollectNotes(opcode);
+    }
+    return false;
+}
+
+void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
+         const String16& message) {
+    // check it the appops needs to be collected and cache result
+    if (appOpsToNote[opCode] == 0) {
+        if (shouldCollectNotes(opCode)) {
+            appOpsToNote[opCode] = 2;
+        } else {
+            appOpsToNote[opCode] = 1;
+        }
+    }
+
+    if (appOpsToNote[opCode] != 2) {
+        return;
+    }
+
+    noteAsyncOp(String16(), uid, packageName, opCode, message);
+}
+
+void AppOpsManager::noteAsyncOp(const String16& callingPackageName, int32_t uid,
+         const String16& packageName, int32_t opCode, const String16& message) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+    }
+}
 
 }; // namespace android
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index c426f3a..b6360cb 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -34,6 +34,7 @@
     {
     }
 
+#ifndef __ANDROID_VNDK__
     virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -111,7 +112,6 @@
         return reply.readStrongBinder();
     }
 
-
     virtual int32_t permissionToOpCode(const String16& permission) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -137,6 +137,52 @@
         }
         return reply.readInt32();
     }
+
+    virtual void setCameraAudioRestriction(int32_t mode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION, data, &reply);
+    }
+
+#endif
+    virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
+            const String16& packageName, int32_t opCode, const String16& message) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+
+        // Convert empty callingPackage into null string
+        if (callingPackageName.size() != 0) {
+            data.writeString16(callingPackageName);
+        } else {
+            data.writeString16(nullptr, 0);
+        }
+
+        data.writeInt32(uid);
+
+        // Convert empty packageName into null string
+        if (packageName.size() != 0) {
+            data.writeString16(packageName);
+        } else {
+            data.writeString16(nullptr, 0);
+        }
+
+        data.writeInt32(opCode);
+        data.writeString16(message);
+        remote()->transact(NOTE_ASYNC_OP_TRANSACTION, data, &reply);
+    }
+
+    virtual bool shouldCollectNotes(int32_t opCode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(opCode);
+        remote()->transact(SHOULD_COLLECT_NOTES_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) {
+            return false;
+        }
+        return reply.readBool();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
@@ -149,6 +195,7 @@
 {
     //printf("AppOpsService received: "); data.print();
     switch(code) {
+#ifndef __ANDROID_VNDK__
         case CHECK_OPERATION_TRANSACTION: {
             CHECK_INTERFACE(IAppOpsService, data, reply);
             int32_t code = data.readInt32();
@@ -234,6 +281,33 @@
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
+        case SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            const int32_t mode = data.readInt32();
+            setCameraAudioRestriction(mode);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+#endif // __ANDROID_VNDK__
+        case NOTE_ASYNC_OP_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            String16 callingPackageName = data.readString16();
+            int32_t uid = data.readInt32();
+            String16 packageName = data.readString16();
+            int32_t opCode = data.readInt32();
+            String16 message = data.readString16();
+            noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case SHOULD_COLLECT_NOTES_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            int32_t opCode = data.readInt32();
+            bool shouldCollect = shouldCollectNotes(opCode);
+            reply->writeNoException();
+            reply->writeBool(shouldCollect);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 74f1f47..715a460 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,6 +18,7 @@
 
 #include <binder/IServiceManager.h>
 
+#include <android/os/BnServiceCallback.h>
 #include <android/os/IServiceManager.h>
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
@@ -212,6 +213,64 @@
         return res;
     }
 
+    sp<IBinder> waitForService(const String16& name16) override {
+        class Waiter : public android::os::BnServiceCallback {
+            Status onRegistration(const std::string& /*name*/,
+                                  const sp<IBinder>& binder) override {
+                std::unique_lock<std::mutex> lock(mMutex);
+                mBinder = binder;
+                lock.unlock();
+                mCv.notify_one();
+                return Status::ok();
+            }
+        public:
+            sp<IBinder> mBinder;
+            std::mutex mMutex;
+            std::condition_variable mCv;
+        };
+
+        const std::string name = String8(name16).c_str();
+
+        sp<IBinder> out;
+        if(!mTheRealServiceManager->checkService(name, &out).isOk()) {
+            return nullptr;
+        }
+        if(out != nullptr) return out;
+
+        sp<Waiter> waiter = new Waiter;
+        if (!mTheRealServiceManager->registerForNotifications(
+                name, waiter).isOk()) {
+            return nullptr;
+        }
+
+        while(true) {
+            {
+                std::unique_lock<std::mutex> lock(waiter->mMutex);
+                using std::literals::chrono_literals::operator""s;
+                waiter->mCv.wait_for(lock, 1s, [&] {
+                    return waiter->mBinder != nullptr;
+                });
+                if (waiter->mBinder != nullptr) return waiter->mBinder;
+            }
+
+            // Handle race condition for lazy services. Here is what can happen:
+            // - the service dies (not processed by init yet).
+            // - sm processes death notification.
+            // - sm gets checkService and calls init to start service.
+            // - init gets the start signal, but the service already appears
+            //   started, so it does nothing.
+            // - init gets death signal, but doesn't know it needs to restart
+            //   the service
+            // - we need to request service again to get it to start
+            if(!mTheRealServiceManager->checkService(name, &out).isOk()) {
+                return nullptr;
+            }
+            if(out != nullptr) return out;
+
+            ALOGW("Waited one second for %s", name.c_str());
+        }
+    }
+
 private:
     sp<AidlServiceManager> mTheRealServiceManager;
 };
diff --git a/libs/binder/aidl/android/os/IServiceCallback.aidl b/libs/binder/aidl/android/os/IServiceCallback.aidl
new file mode 100644
index 0000000..b29dfed
--- /dev/null
+++ b/libs/binder/aidl/android/os/IServiceCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * @hide
+ */
+oneway interface IServiceCallback {
+    /**
+     * Called when a service is registered.
+     *
+     * @param name the service name that has been registered with
+     * @param binder the binder that is registered
+     */
+    void onRegistration(@utf8InCpp String name, IBinder binder);
+}
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 50a72aa..60c2cce 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.os.IServiceCallback;
+
 /**
  * Basic interface for finding and publishing system services.
  *
@@ -77,4 +79,14 @@
      * Return a list of all currently running services.
      */
     @utf8InCpp String[] listServices(int dumpPriority);
+
+    /**
+     * Request a callback when a service is registered.
+     */
+    void registerForNotifications(@utf8InCpp String name, IServiceCallback callback);
+
+    /**
+     * Unregisters all requests for notifications for a specific callback.
+     */
+    void unregisterForNotifications(@utf8InCpp String name, IServiceCallback callback);
 }
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 17493b4..dff4d49 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_APP_OPS_MANAGER_H
 #define ANDROID_APP_OPS_MANAGER_H
 
-#ifndef __ANDROID_VNDK__
-
 #include <binder/IAppOpsService.h>
 
 #include <utils/threads.h>
@@ -35,6 +33,7 @@
         MODE_ERRORED = IAppOpsService::MODE_ERRORED
     };
 
+#ifndef __ANDROID_VNDK__
     enum {
         OP_NONE = -1,
         OP_COARSE_LOCATION = 0,
@@ -109,34 +108,60 @@
         OP_START_FOREGROUND = 76,
         OP_BLUETOOTH_SCAN = 77,
         OP_USE_BIOMETRIC = 78,
+        OP_ACTIVITY_RECOGNITION = 79,
+        OP_SMS_FINANCIAL_TRANSACTIONS = 80,
+        OP_READ_MEDIA_AUDIO = 81,
+        OP_WRITE_MEDIA_AUDIO = 82,
+        OP_READ_MEDIA_VIDEO = 83,
+        OP_WRITE_MEDIA_VIDEO = 84,
+        OP_READ_MEDIA_IMAGES = 85,
+        OP_WRITE_MEDIA_IMAGES = 86,
+        OP_LEGACY_STORAGE = 87,
+        OP_ACCESS_ACCESSIBILITY = 88,
+        OP_READ_DEVICE_IDENTIFIERS = 89,
+        _NUM_OP = 90
     };
+#endif // __ANDROID_VNDK__
 
     AppOpsManager();
 
+#ifndef __ANDROID_VNDK__
     int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
     int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
             const String16& callingPackage);
+    // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&) instead
     int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
+    int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage,
+            const String16& message);
+    // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&)
+    // instead
     int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
             bool startIfModeDefault);
+    int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+            bool startIfModeDefault, const String16& message);
     void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
     void startWatchingMode(int32_t op, const String16& packageName,
             const sp<IAppOpsCallback>& callback);
     void stopWatchingMode(const sp<IAppOpsCallback>& callback);
     int32_t permissionToOpCode(const String16& permission);
+    void setCameraAudioRestriction(int32_t mode);
+#endif // __ANDROID_VNDK__
+    void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName,
+            int32_t opCode, const String16& message);
 
 private:
     Mutex mLock;
     sp<IAppOpsService> mService;
 
     sp<IAppOpsService> getService();
+    void markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
+            const String16& message);
+    bool shouldCollectNotes(int32_t opCode);
 };
 
 
 }; // namespace android
+
 // ---------------------------------------------------------------------------
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
 
 #endif // ANDROID_APP_OPS_MANAGER_H
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 3dbd0d9..009ef6c 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -19,8 +19,8 @@
 #define ANDROID_IAPP_OPS_SERVICE_H
 
 #ifndef __ANDROID_VNDK__
-
 #include <binder/IAppOpsCallback.h>
+#endif
 #include <binder/IInterface.h>
 
 namespace android {
@@ -32,6 +32,7 @@
 public:
     DECLARE_META_INTERFACE(AppOpsService)
 
+#ifndef __ANDROID_VNDK__
     virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
     virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
     virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
@@ -45,8 +46,14 @@
     virtual int32_t permissionToOpCode(const String16& permission) = 0;
     virtual int32_t checkAudioOperation(int32_t code, int32_t usage,int32_t uid,
             const String16& packageName) = 0;
+    virtual void setCameraAudioRestriction(int32_t mode) = 0;
+#endif // __ANDROID_VNDK__
+    virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
+            const String16& packageName, int32_t opCode, const String16& message) = 0;
+    virtual bool shouldCollectNotes(int32_t opCode) = 0;
 
     enum {
+#ifndef __ANDROID_VNDK__
         CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
         START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
@@ -56,6 +63,13 @@
         GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
         PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
         CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
+#endif // __ANDROID_VNDK__
+        NOTE_ASYNC_OP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9,
+        SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+10,
+#ifndef __ANDROID_VNDK__
+        SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+11,
+#endif // __ANDROID_VNDK__
+
     };
 
     enum {
@@ -81,8 +95,4 @@
 
 }; // namespace android
 
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
-
 #endif // ANDROID_IAPP_OPS_SERVICE_H
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 30786fa..8ae860d 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -71,11 +71,24 @@
      */
     // NOLINTNEXTLINE(google-default-arguments)
     virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
+
+    /**
+     * Efficiently wait for a service.
+     *
+     * Returns nullptr only for permission problem or fatal error.
+     */
+    virtual sp<IBinder> waitForService(const String16& name) = 0;
 };
 
 sp<IServiceManager> defaultServiceManager();
 
 template<typename INTERFACE>
+sp<INTERFACE> waitForService(const String16& name) {
+    const sp<IServiceManager> sm = defaultServiceManager();
+    return interface_cast<INTERFACE>(sm->waitForService(name));
+}
+
+template<typename INTERFACE>
 status_t getService(const String16& name, sp<INTERFACE>* outService)
 {
     const sp<IServiceManager> sm = defaultServiceManager();
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 438f8f3..51bf78a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -139,6 +139,7 @@
         "DisplayHardware/VirtualDisplaySurface.cpp",
         "Effects/Daltonizer.cpp",
         "EventLog/EventLog.cpp",
+        "FrameTracer/FrameTracer.cpp",
         "FrameTracker.cpp",
         "Layer.cpp",
         "LayerProtoHelper.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a8bdb79..90a02b3 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -51,6 +51,7 @@
 
 #include "Colorizer.h"
 #include "DisplayDevice.h"
+#include "FrameTracer/FrameTracer.h"
 #include "LayerRejecter.h"
 #include "TimeStats/TimeStats.h"
 
@@ -71,7 +72,9 @@
 
 BufferLayer::~BufferLayer() {
     mFlinger->deleteTextureAsync(mTextureName);
-    mFlinger->mTimeStats->onDestroy(getSequence());
+    const int32_t layerID = getSequence();
+    mFlinger->mTimeStats->onDestroy(layerID);
+    mFlinger->mFrameTracer->onDestroy(layerID);
 }
 
 void BufferLayer::useSurfaceDamage() {
@@ -314,17 +317,17 @@
 
     if (presentFence->isValid()) {
         mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence);
-        mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber,
-                                         presentFence, TimeStats::FrameEvent::PRESENT_FENCE);
+        mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber,
+                                           presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
         mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
     } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
         const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
         mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime);
-        mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber,
-                                             actualPresentTime,
-                                             TimeStats::FrameEvent::PRESENT_FENCE);
+        mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber,
+                                               actualPresentTime,
+                                               FrameTracer::FrameEvent::PRESENT_FENCE);
         mFrameTracker.setActualPresentTime(actualPresentTime);
     }
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 6cad3c7..4da39e4 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -29,6 +29,7 @@
 #include "LayerRejecter.h"
 #include "SurfaceInterceptor.h"
 
+#include "FrameTracer/FrameTracer.h"
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -48,9 +49,9 @@
 
     // Prevent tracing the same release multiple times.
     if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
-        mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
-                                         std::make_shared<FenceTime>(releaseFence),
-                                         TimeStats::FrameEvent::RELEASE_FENCE);
+        mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+                                           std::make_shared<FenceTime>(releaseFence),
+                                           FrameTracer::FrameEvent::RELEASE_FENCE);
         mPreviousReleasedFrameNumber = mPreviousFrameNumber;
     }
 }
@@ -337,6 +338,7 @@
             mQueueItems.clear();
             mQueuedFrames = 0;
             mFlinger->mTimeStats->onDestroy(layerID);
+            mFlinger->mFrameTracer->onDestroy(layerID);
         }
 
         // Once we have hit this state, the shadow queue may no longer
@@ -366,12 +368,12 @@
         uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
         mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber,
                                               mQueueItems[0].mFenceTime);
-        mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber,
-                                         mQueueItems[0].mFenceTime,
-                                         TimeStats::FrameEvent::ACQUIRE_FENCE);
+        mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber,
+                                           mQueueItems[0].mFenceTime,
+                                           FrameTracer::FrameEvent::ACQUIRE_FENCE);
         mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime);
-        mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime,
-                                             TimeStats::FrameEvent::LATCH);
+        mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime,
+                                               FrameTracer::FrameEvent::LATCH);
 
         mQueueItems.removeAt(0);
     }
@@ -429,9 +431,9 @@
 
 void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
     const int32_t layerID = getSequence();
-    mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str());
-    mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber,
-                                         systemTime(), TimeStats::FrameEvent::POST);
+    mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str());
+    mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber,
+                                           systemTime(), FrameTracer::FrameEvent::POST);
 
     ATRACE_CALL();
     // Add this buffer from our internal queue tracker
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 4a8261d..e7d1b63 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -32,6 +32,7 @@
 
 #include "BufferStateLayer.h"
 #include "ColorLayer.h"
+#include "FrameTracer/FrameTracer.h"
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -90,9 +91,9 @@
 
     // Prevent tracing the same release multiple times.
     if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
-        mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
-                                         std::make_shared<FenceTime>(releaseFence),
-                                         TimeStats::FrameEvent::RELEASE_FENCE);
+        mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+                                           std::make_shared<FenceTime>(releaseFence),
+                                           FrameTracer::FrameEvent::RELEASE_FENCE);
         mPreviousReleasedFrameNumber = mPreviousFrameNumber;
     }
 }
@@ -236,9 +237,9 @@
 
     const int32_t layerID = getSequence();
     mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime);
-    mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str());
-    mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime,
-                                         TimeStats::FrameEvent::POST);
+    mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str());
+    mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime,
+                                           FrameTracer::FrameEvent::POST);
     mCurrentState.desiredPresentTime = desiredPresentTime;
 
     if (mFlinger->mUseSmart90ForVideo) {
@@ -569,17 +570,18 @@
         status_t err = bindTextureImage();
         if (err != NO_ERROR) {
             mFlinger->mTimeStats->onDestroy(layerID);
+            mFlinger->mFrameTracer->onDestroy(layerID);
             return BAD_VALUE;
         }
     }
 
     const uint64_t bufferID = getCurrentBufferId();
     mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime());
-    mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
-                                     TimeStats::FrameEvent::ACQUIRE_FENCE);
+    mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
+                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);
     mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime);
-    mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
-                                         TimeStats::FrameEvent::LATCH);
+    mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
+                                           FrameTracer::FrameEvent::LATCH);
 
     mCurrentStateModified = false;
 
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
new file mode 100644
index 0000000..7cbb8d8
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "FrameTracer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "FrameTracer.h"
+
+#include <android-base/stringprintf.h>
+
+#include <algorithm>
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
+
+namespace android {
+
+void FrameTracer::initialize() {
+    perfetto::TracingInitArgs args;
+    args.backends = perfetto::kSystemBackend;
+    perfetto::Tracing::Initialize(args);
+    registerDataSource();
+}
+
+void FrameTracer::registerDataSource() {
+    perfetto::DataSourceDescriptor dsd;
+    dsd.set_name(kFrameTracerDataSource);
+    FrameTracerDataSource::Register(dsd);
+}
+
+void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) {
+    FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) {
+        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+            std::lock_guard<std::mutex> lock(mTraceMutex);
+            mTraceTracker[layerID].layerName = layerName;
+        }
+    });
+}
+
+void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+                                 nsecs_t timestamp, FrameEvent::BufferEventType type,
+                                 nsecs_t duration) {
+    FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
+                                  duration](FrameTracerDataSource::TraceContext ctx) {
+        std::lock_guard<std::mutex> lock(mTraceMutex);
+        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+            return;
+        }
+
+        // Handle any pending fences for this buffer.
+        tracePendingFencesLocked(ctx, layerID, bufferID);
+
+        // Complete current trace.
+        traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
+    });
+}
+
+void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+                             const std::shared_ptr<FenceTime>& fence,
+                             FrameEvent::BufferEventType type, nsecs_t startTime) {
+    FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
+                                  startTime](FrameTracerDataSource::TraceContext ctx) {
+        const nsecs_t signalTime = fence->getSignalTime();
+        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
+            std::lock_guard<std::mutex> lock(mTraceMutex);
+            if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+                return;
+            }
+
+            // Handle any pending fences for this buffer.
+            tracePendingFencesLocked(ctx, layerID, bufferID);
+
+            if (signalTime != Fence::SIGNAL_TIME_PENDING) {
+                traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
+            } else {
+                mTraceTracker[layerID].pendingFences[bufferID].push_back(
+                        {.frameNumber = frameNumber,
+                         .type = type,
+                         .fence = fence,
+                         .startTime = startTime});
+            }
+        }
+    });
+}
+
+void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
+                                           int32_t layerID, uint64_t bufferID) {
+    if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
+        auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
+        for (size_t i = 0; i < pendingFences.size(); ++i) {
+            auto& pendingFence = pendingFences[i];
+
+            nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
+            if (pendingFence.fence && pendingFence.fence->isValid()) {
+                signalTime = pendingFence.fence->getSignalTime();
+                if (signalTime == Fence::SIGNAL_TIME_PENDING) {
+                    continue;
+                }
+            }
+
+            if (signalTime != Fence::SIGNAL_TIME_INVALID &&
+                systemTime() - signalTime < kFenceSignallingDeadline) {
+                traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
+                                pendingFence.startTime, signalTime);
+            }
+
+            pendingFences.erase(pendingFences.begin() + i);
+            --i;
+        }
+    }
+}
+
+void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                              uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
+                              FrameEvent::BufferEventType type, nsecs_t duration) {
+    auto packet = ctx.NewTracePacket();
+    packet->set_timestamp(timestamp);
+    auto* event = packet->set_graphics_frame_event()->set_buffer_event();
+    event->set_buffer_id(static_cast<uint32_t>(bufferID));
+    event->set_frame_number(frameNumber);
+    event->set_type(type);
+
+    if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
+        !mTraceTracker[layerID].layerName.empty()) {
+        const std::string& layerName = mTraceTracker[layerID].layerName;
+        event->set_layer_name(layerName.c_str(), layerName.size());
+    }
+
+    if (duration > 0) {
+        event->set_duration_ns(duration);
+    }
+}
+
+void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                                  uint64_t bufferID, uint64_t frameNumber,
+                                  FrameEvent::BufferEventType type, nsecs_t startTime,
+                                  nsecs_t endTime) {
+    nsecs_t timestamp = endTime;
+    nsecs_t duration = 0;
+    if (startTime > 0 && startTime < endTime) {
+        timestamp = startTime;
+        duration = endTime - startTime;
+    }
+    traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
+}
+
+void FrameTracer::onDestroy(int32_t layerID) {
+    std::lock_guard<std::mutex> traceLock(mTraceMutex);
+    mTraceTracker.erase(layerID);
+}
+
+std::string FrameTracer::miniDump() {
+    std::string result = "FrameTracer miniDump:\n";
+    std::lock_guard<std::mutex> lock(mTraceMutex);
+    android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
+                                 mTraceTracker.size());
+    return result;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h
new file mode 100644
index 0000000..d34ad81
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <perfetto/trace/android/graphics_frame_event.pbzero.h>
+#include <perfetto/tracing.h>
+#include <ui/FenceTime.h>
+
+#include <mutex>
+#include <unordered_map>
+
+namespace android {
+
+class FrameTracer {
+public:
+    class FrameTracerDataSource : public perfetto::DataSource<FrameTracerDataSource> {
+        virtual void OnSetup(const SetupArgs&) override{};
+        virtual void OnStart(const StartArgs&) override{};
+        virtual void OnStop(const StopArgs&) override{};
+    };
+
+    using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
+
+    ~FrameTracer() = default;
+
+    // Sets up the perfetto tracing backend and data source.
+    void initialize();
+    // Registers the data source with the perfetto backend. Called as part of initialize()
+    // and should not be called manually outside of tests. Public to allow for substituting a
+    // perfetto::kInProcessBackend in tests.
+    void registerDataSource();
+    // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
+    // traceFence() for each layer.
+    void traceNewLayer(int32_t layerID, const std::string& layerName);
+    // Creates a trace point at the timestamp provided.
+    void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
+                        FrameEvent::BufferEventType type, nsecs_t duration = 0);
+    // Creates a trace point after the provided fence has been signalled. If a startTime is provided
+    // the trace will have be timestamped from startTime until fence signalling time. If no
+    // startTime is provided, a durationless trace point will be created timestamped at fence
+    // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
+    // time after signalling a trace call for this buffer occurs.
+    void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+                    const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
+                    nsecs_t startTime = 0);
+
+    // Takes care of cleanup when a layer is destroyed.
+    void onDestroy(int32_t layerID);
+
+    std::string miniDump();
+
+    static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame";
+
+    // The maximum amount of time a fence has to signal before it is discarded.
+    // Used to avoid fences from previous traces generating new trace points in later ones.
+    // Public for testing.
+    static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
+
+private:
+    struct PendingFence {
+        uint64_t frameNumber;
+        FrameEvent::BufferEventType type;
+        std::shared_ptr<FenceTime> fence;
+        nsecs_t startTime;
+    };
+
+    struct TraceRecord {
+        std::string layerName;
+        using BufferID = uint64_t;
+        std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
+    };
+
+    // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
+    // trace points for them.
+    void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                                  uint64_t bufferID);
+    // Creates a trace point by translating a start time and an end time to a timestamp and
+    // duration. If startTime is later than end time it sets end time as the timestamp and the
+    // duration to 0. Used by traceFence().
+    void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+                         uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type,
+                         nsecs_t startTime, nsecs_t endTime);
+    void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
+                     uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
+                     nsecs_t duration = 0);
+
+    std::mutex mTraceMutex;
+    std::unordered_map<int32_t, TraceRecord> mTraceTracker;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 557d0bb..79ee827 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -22,6 +22,7 @@
 #include "Layer.h"
 
 #include <android-base/stringprintf.h>
+#include <binder/IPCThreadState.h>
 #include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerFECompositionState.h>
@@ -57,6 +58,7 @@
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "DisplayHardware/HWComposer.h"
+#include "FrameTracer/FrameTracer.h"
 #include "LayerProtoHelper.h"
 #include "LayerRejecter.h"
 #include "MonitoredProducer.h"
@@ -121,7 +123,8 @@
     mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);
 
     mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType);
-
+    mCallingPid = args.callingPid;
+    mCallingUid = args.callingUid;
     mFlinger->onLayerCreated();
 }
 
@@ -135,6 +138,21 @@
     mFlinger->onLayerDestroyed(this);
 }
 
+LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client,
+                                     const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+                                     LayerMetadata metadata)
+      : flinger(flinger),
+        client(client),
+        name(name),
+        w(w),
+        h(h),
+        flags(flags),
+        metadata(std::move(metadata)) {
+    IPCThreadState* ipc = IPCThreadState::self();
+    callingPid = ipc->getCallingPid();
+    callingUid = ipc->getCallingUid();
+}
+
 // ---------------------------------------------------------------------------
 // callbacks
 // ---------------------------------------------------------------------------
@@ -1323,10 +1341,17 @@
     mFrameEventHistory.dump(result);
 }
 
+void Layer::dumpCallingUidPid(std::string& result) const {
+    StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(),
+                  mCallingPid, mCallingUid);
+}
+
 void Layer::onDisconnect() {
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     mFrameEventHistory.onDisconnect();
-    mFlinger->mTimeStats->onDestroy(getSequence());
+    const int32_t layerID = getSequence();
+    mFlinger->mTimeStats->onDestroy(layerID);
+    mFlinger->mFrameTracer->onDestroy(layerID);
 }
 
 void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 23763d2..32be980 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -80,9 +80,7 @@
 
 struct LayerCreationArgs {
     LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
-                      uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata)
-          : flinger(flinger), client(client), name(name), w(w), h(h), flags(flags),
-            metadata(std::move(metadata)) {}
+                      uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata);
 
     SurfaceFlinger* flinger;
     const sp<Client>& client;
@@ -91,6 +89,8 @@
     uint32_t h;
     uint32_t flags;
     LayerMetadata metadata;
+    pid_t callingPid;
+    uid_t callingUid;
 };
 
 class Layer : public virtual compositionengine::LayerFE {
@@ -608,6 +608,7 @@
     void miniDump(std::string& result, const sp<DisplayDevice>& display) const;
     void dumpFrameStats(std::string& result) const;
     void dumpFrameEvents(std::string& result);
+    void dumpCallingUidPid(std::string& result) const;
     void clearFrameStats();
     void logFrameStats();
     void getFrameStats(FrameStats* outStats) const;
@@ -932,6 +933,11 @@
     bool mGetHandleCalled = false;
 
     void removeRemoteSyncPoints();
+
+    // Tracks the process and user id of the caller when creating this layer
+    // to help debugging.
+    pid_t mCallingPid;
+    uid_t mCallingUid;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e0d1609..55835f3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -98,6 +98,7 @@
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
 #include "Effects/Daltonizer.h"
+#include "FrameTracer/FrameTracer.h"
 #include "RegionSamplingThread.h"
 #include "Scheduler/DispSync.h"
 #include "Scheduler/DispSyncSource.h"
@@ -257,6 +258,7 @@
       : mFactory(factory),
         mInterceptor(mFactory.createSurfaceInterceptor(this)),
         mTimeStats(mFactory.createTimeStats()),
+        mFrameTracer(std::make_unique<FrameTracer>()),
         mEventQueue(mFactory.createMessageQueue()),
         mCompositionEngine(mFactory.createCompositionEngine()),
         mPhaseOffsets(mFactory.createPhaseOffsets()) {}
@@ -513,7 +515,7 @@
     const nsecs_t duration = now - mBootTime;
     ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
 
-    mTimeStats->initializeTracing();
+    mFrameTracer->initialize();
 
     // wait patiently for the window manager death
     const String16 name("window");
@@ -2720,32 +2722,31 @@
 
 void SurfaceFlinger::commitTransaction()
 {
-    if (!mLayersPendingRemoval.isEmpty()) {
-        // Notify removed layers now that they can't be drawn from
-        for (const auto& l : mLayersPendingRemoval) {
-            recordBufferingStats(l->getName().string(),
-                    l->getOccupancyHistory(true));
-
-            // Ensure any buffers set to display on any children are released.
-            if (l->isRemovedFromCurrentState()) {
-                l->latchAndReleaseBuffer();
-            }
-
-            // If the layer has been removed and has no parent, then it will not be reachable
-            // when traversing layers on screen. Add the layer to the offscreenLayers set to
-            // ensure we can copy its current to drawing state.
-            if (!l->getParent()) {
-                mOffscreenLayers.emplace(l.get());
-            }
-        }
-        mLayersPendingRemoval.clear();
-    }
-
-    // If this transaction is part of a window animation then the next frame
-    // we composite should be considered an animation as well.
-    mAnimCompositionPending = mAnimTransactionPending;
-
     withTracingLock([&]() {
+        if (!mLayersPendingRemoval.isEmpty()) {
+            // Notify removed layers now that they can't be drawn from
+            for (const auto& l : mLayersPendingRemoval) {
+                recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true));
+
+                // Ensure any buffers set to display on any children are released.
+                if (l->isRemovedFromCurrentState()) {
+                    l->latchAndReleaseBuffer();
+                }
+
+                // If the layer has been removed and has no parent, then it will not be reachable
+                // when traversing layers on screen. Add the layer to the offscreenLayers set to
+                // ensure we can copy its current to drawing state.
+                if (!l->getParent()) {
+                    mOffscreenLayers.emplace(l.get());
+                }
+            }
+            mLayersPendingRemoval.clear();
+        }
+
+        // If this transaction is part of a window animation then the next frame
+        // we composite should be considered an animation as well.
+        mAnimCompositionPending = mAnimTransactionPending;
+
         mDrawingState = mCurrentState;
         // clear the "changed" flags in current state
         mCurrentState.colorMatrixChanged = false;
@@ -4114,9 +4115,11 @@
             if (asProto) {
                 result.append(layersProto.SerializeAsString());
             } else {
+                // Dump info that we need to access from the main thread
                 const auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
                 result.append(LayerProtoParser::layerTreeToString(layerTree));
                 result.append("\n");
+                dumpOffscreenLayers(result);
             }
         }
     }
@@ -4374,12 +4377,54 @@
     return layersProto;
 }
 
+void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const {
+    // Add a fake invisible root layer to the proto output and parent all the offscreen layers to
+    // it.
+    LayerProto* rootProto = layersProto.add_layers();
+    const int32_t offscreenRootLayerId = INT32_MAX - 2;
+    rootProto->set_id(offscreenRootLayerId);
+    rootProto->set_name("Offscreen Root");
+
+    for (Layer* offscreenLayer : mOffscreenLayers) {
+        // Add layer as child of the fake root
+        rootProto->add_children(offscreenLayer->sequence);
+
+        // Add layer
+        LayerProto* layerProto = layersProto.add_layers();
+        offscreenLayer->writeToProtoDrawingState(layerProto, traceFlags);
+        offscreenLayer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing,
+                                                traceFlags);
+        layerProto->set_parent(offscreenRootLayerId);
+
+        // Add children
+        offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+            if (layer == offscreenLayer) {
+                return;
+            }
+            LayerProto* childProto = layersProto.add_layers();
+            layer->writeToProtoDrawingState(childProto, traceFlags);
+            layer->writeToProtoCommonState(childProto, LayerVector::StateSet::Drawing, traceFlags);
+        });
+    }
+}
+
 LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
     LayersProto layersProto;
     postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
     return layersProto;
 }
 
+void SurfaceFlinger::dumpOffscreenLayers(std::string& result) {
+    result.append("Offscreen Layers:\n");
+    postMessageSync(new LambdaMessage([&]() {
+        for (Layer* offscreenLayer : mOffscreenLayers) {
+            offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+                layer->dumpCallingUidPid(result);
+            });
+        }
+    }));
+}
+
 void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const {
     const bool colorize = !args.empty() && args[0] == String16("--color");
     Colorizer colorizer(colorize);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1aa99fc..f6df33a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -95,6 +95,7 @@
 class RefreshRateOverlay;
 class RegionSamplingThread;
 class TimeStats;
+class FrameTracer;
 
 namespace compositionengine {
 class DisplaySurface;
@@ -863,8 +864,11 @@
     void dumpDisplayIdentificationData(std::string& result) const;
     void dumpWideColorInfo(std::string& result) const;
     LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+    void dumpOffscreenLayersProto(LayersProto& layersProto,
+                                  uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
     LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
             EXCLUDES(mStateLock);
+    void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock);
     void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
 
     bool isLayerTripleBufferingDisabled() const {
@@ -983,6 +987,7 @@
     bool mTracingEnabled = false;
     bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
     const std::shared_ptr<TimeStats> mTimeStats;
+    const std::unique_ptr<FrameTracer> mFrameTracer;
     bool mUseHwcVirtualDisplays = false;
     std::atomic<uint32_t> mFrameMissedCount = 0;
     std::atomic<uint32_t> mHwcFrameMissedCount = 0;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 9053f2c..eb26cd0 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -163,6 +163,7 @@
     entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
     entry.set_where(where);
     LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
+    mFlinger.dumpOffscreenLayersProto(layers);
     entry.mutable_layers()->Swap(&layers);
 
     return entry;
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 9e1d503..2080a38 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -2,12 +2,9 @@
     name: "libtimestats",
     defaults: ["surfaceflinger_defaults"],
     srcs: [
-      "TimeStats.cpp"
+      "TimeStats.cpp",
     ],
     export_include_dirs: ["."],
-    static_libs: [
-      "libperfetto_client_experimental",
-    ],
     shared_libs: [
       "libtimestats_proto",
       "libui",
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index b66e4cf..b01fa81 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -30,141 +30,10 @@
 #include <algorithm>
 #include <regex>
 
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource);
-
 namespace android {
 
 namespace impl {
 
-void TimeStats::initializeTracing() {
-    perfetto::TracingInitArgs args;
-    args.backends = perfetto::kSystemBackend;
-    perfetto::Tracing::Initialize(args);
-    registerTracingDataSource();
-}
-
-void TimeStats::registerTracingDataSource() {
-    perfetto::DataSourceDescriptor dsd;
-    dsd.set_name(kTimeStatsDataSource);
-    TimeStatsDataSource::Register(dsd);
-}
-
-void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) {
-    TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) {
-        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
-            std::lock_guard<std::mutex> lock(mTraceMutex);
-            mTraceTracker[layerID].layerName = layerName;
-        }
-    });
-}
-
-void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                               nsecs_t timestamp, FrameEvent::BufferEventType type,
-                               nsecs_t duration) {
-    TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
-                                duration](TimeStatsDataSource::TraceContext ctx) {
-        std::lock_guard<std::mutex> lock(mTraceMutex);
-        if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
-            return;
-        }
-
-        // Handle any pending fences for this buffer.
-        tracePendingFencesLocked(ctx, layerID, bufferID);
-
-        // Complete current trace.
-        traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
-    });
-}
-
-void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                           const std::shared_ptr<FenceTime>& fence,
-                           FrameEvent::BufferEventType type, nsecs_t startTime) {
-    TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
-                                startTime](TimeStatsDataSource::TraceContext ctx) {
-        const nsecs_t signalTime = fence->getSignalTime();
-        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
-            std::lock_guard<std::mutex> lock(mTraceMutex);
-            if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
-                return;
-            }
-
-            // Handle any pending fences for this buffer.
-            tracePendingFencesLocked(ctx, layerID, bufferID);
-
-            if (signalTime != Fence::SIGNAL_TIME_PENDING) {
-                traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
-            } else {
-                mTraceTracker[layerID].pendingFences[bufferID].push_back(
-                        {.frameNumber = frameNumber,
-                         .type = type,
-                         .fence = fence,
-                         .startTime = startTime});
-            }
-        }
-    });
-}
-
-void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                                         uint64_t bufferID) {
-    if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
-        auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
-        for (size_t i = 0; i < pendingFences.size(); ++i) {
-            auto& pendingFence = pendingFences[i];
-
-            nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
-            if (pendingFence.fence && pendingFence.fence->isValid()) {
-                signalTime = pendingFence.fence->getSignalTime();
-                if (signalTime == Fence::SIGNAL_TIME_PENDING) {
-                    continue;
-                }
-            }
-
-            if (signalTime != Fence::SIGNAL_TIME_INVALID &&
-                systemTime() - signalTime < kFenceSignallingDeadline) {
-                traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
-                                pendingFence.startTime, signalTime);
-            }
-
-            pendingFences.erase(pendingFences.begin() + i);
-            --i;
-        }
-    }
-}
-
-void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                            uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
-                            FrameEvent::BufferEventType type, nsecs_t duration) {
-    auto packet = ctx.NewTracePacket();
-    packet->set_timestamp(timestamp);
-    auto* event = packet->set_graphics_frame_event()->set_buffer_event();
-    event->set_buffer_id(static_cast<uint32_t>(bufferID));
-    event->set_frame_number(frameNumber);
-    event->set_type(type);
-
-    if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
-        !mTraceTracker[layerID].layerName.empty()) {
-        const std::string& layerName = mTraceTracker[layerID].layerName;
-        event->set_layer_name(layerName.c_str(), layerName.size());
-    }
-
-    if (duration > 0) {
-        event->set_duration_ns(duration);
-    }
-}
-
-void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                                uint64_t bufferID, uint64_t frameNumber,
-                                FrameEvent::BufferEventType type, nsecs_t startTime,
-                                nsecs_t endTime) {
-    nsecs_t timestamp = endTime;
-    nsecs_t duration = 0;
-    if (startTime > 0 && startTime < endTime) {
-        timestamp = startTime;
-        duration = endTime - startTime;
-    }
-    traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
-}
-
 void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::string& result) {
     ATRACE_CALL();
 
@@ -207,8 +76,6 @@
                                  mTimeStatsTracker.size());
     android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n",
                                  mTimeStats.stats.size());
-    android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
-                                 mTraceTracker.size());
     return result;
 }
 
@@ -542,15 +409,8 @@
 void TimeStats::onDestroy(int32_t layerID) {
     ATRACE_CALL();
     ALOGV("[%d]-onDestroy", layerID);
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        mTimeStatsTracker.erase(layerID);
-    }
-
-    {
-        std::lock_guard<std::mutex> traceLock(mTraceMutex);
-        mTraceTracker.erase(layerID);
-    }
+    std::lock_guard<std::mutex> lock(mMutex);
+    mTimeStatsTracker.erase(layerID);
 }
 
 void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) {
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 470137a..9ebc1ad 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -17,8 +17,6 @@
 #pragma once
 
 #include <hardware/hwcomposer_defs.h>
-#include <perfetto/trace/android/graphics_frame_event.pbzero.h>
-#include <perfetto/tracing.h>
 #include <timestatsproto/TimeStatsHelper.h>
 #include <timestatsproto/TimeStatsProtoHeader.h>
 #include <ui/FenceTime.h>
@@ -36,32 +34,8 @@
 
 class TimeStats {
 public:
-    using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
-
     virtual ~TimeStats() = default;
 
-    // Sets up the perfetto tracing backend and data source.
-    virtual void initializeTracing() = 0;
-    // Registers the data source with the perfetto backend. Called as part of initializeTracing()
-    // and should not be called manually outside of tests. Public to allow for substituting a
-    // perfetto::kInProcessBackend in tests.
-    virtual void registerTracingDataSource() = 0;
-    // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
-    // traceFence() for each layer.
-    virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0;
-    // Creates a trace point at the timestamp provided.
-    virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                                nsecs_t timestamp, FrameEvent::BufferEventType type,
-                                nsecs_t duration = 0) = 0;
-    // Creates a trace point after the provided fence has been signalled. If a startTime is provided
-    // the trace will have be timestamped from startTime until fence signalling time. If no
-    // startTime is provided, a durationless trace point will be created timestamped at fence
-    // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
-    // time after signalling a trace call for this buffer occurs.
-    virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                            const std::shared_ptr<FenceTime>& fence,
-                            FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0;
-
     virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
     virtual bool isEnabled() = 0;
     virtual std::string miniDump() = 0;
@@ -89,13 +63,6 @@
     // Source of truth is RefrehRateStats.
     virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0;
     virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0;
-
-    static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats";
-
-    // The maximum amount of time a fence has to signal before it is discarded.
-    // Used to avoid fence's from previous traces generating new trace points in later ones.
-    // Public for testing.
-    static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
 };
 
 namespace impl {
@@ -117,13 +84,6 @@
         std::shared_ptr<FenceTime> presentFence;
     };
 
-    struct PendingFence {
-        uint64_t frameNumber;
-        FrameEvent::BufferEventType type;
-        std::shared_ptr<FenceTime> fence;
-        nsecs_t startTime;
-    };
-
     struct LayerRecord {
         std::string layerName;
         // This is the index in timeRecords, at which the timestamps for that
@@ -135,12 +95,6 @@
         std::deque<TimeRecord> timeRecords;
     };
 
-    struct TraceRecord {
-        std::string layerName;
-        using BufferID = uint64_t;
-        std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
-    };
-
     struct PowerTime {
         int32_t powerMode = HWC_POWER_MODE_OFF;
         nsecs_t prevTime = 0;
@@ -152,23 +106,8 @@
     };
 
 public:
-    class TimeStatsDataSource : public perfetto::DataSource<TimeStatsDataSource> {
-        virtual void OnSetup(const SetupArgs&) override{};
-        virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); };
-        virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); };
-    };
-
     TimeStats() = default;
 
-    void initializeTracing() override;
-    void registerTracingDataSource() override;
-    void traceNewLayer(int32_t layerID, const std::string& layerName) override;
-    void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
-                        FrameEvent::BufferEventType type, nsecs_t duration = 0) override;
-    void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
-                    const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
-                    nsecs_t startTime = 0) override;
-
     void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
     bool isEnabled() override;
     std::string miniDump() override;
@@ -200,20 +139,6 @@
     static const size_t MAX_NUM_TIME_RECORDS = 64;
 
 private:
-    // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
-    // trace points for them.
-    void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
-                                  uint64_t bufferID);
-    // Creates a trace point by translating a start time and an end time to a timestamp and
-    // duration. If startTime is later than end time it sets end time as the timestamp and the
-    // duration to 0. Used by traceFence().
-    void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
-                         uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime,
-                         nsecs_t endTime);
-    void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
-                     uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
-                     nsecs_t duration = 0);
-
     bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord);
     void flushAvailableRecordsToStatsLocked(int32_t layerID);
     void flushPowerTimeLocked();
@@ -232,9 +157,6 @@
     PowerTime mPowerTime;
     GlobalRecord mGlobalRecord;
 
-    std::mutex mTraceMutex;
-    std::unordered_map<int32_t, TraceRecord> mTraceTracker;
-
     static const size_t MAX_NUM_LAYER_RECORDS = 200;
     static const size_t MAX_NUM_LAYER_STATS = 200;
 };
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 0eedf9b..8d98af6 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -51,6 +51,7 @@
         "RefreshRateStatsTest.cpp",
         "RegionSamplingTest.cpp",
         "TimeStatsTest.cpp",
+        "FrameTracerTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
         "mock/DisplayHardware/MockDisplay.cpp",
         "mock/DisplayHardware/MockPowerAdvisor.cpp",
@@ -63,6 +64,7 @@
         "mock/MockNativeWindowSurface.cpp",
         "mock/MockSurfaceInterceptor.cpp",
         "mock/MockTimeStats.cpp",
+        "mock/MockFrameTracer.cpp",
         "mock/system/window/MockNativeWindow.cpp",
     ],
     static_libs: [
diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
new file mode 100644
index 0000000..b5af591
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include <FrameTracer/FrameTracer.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <perfetto/trace/trace.pb.h>
+
+#include "libsurfaceflinger_unittest_main.h"
+
+using namespace google::protobuf;
+
+namespace android {
+namespace {
+
+class FrameTracerTest : public testing::Test {
+public:
+    FrameTracerTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+
+        // Need to initialize tracing in process for testing, and only once per test suite.
+        static bool wasInitialized = false;
+        if (!wasInitialized) {
+            perfetto::TracingInitArgs args;
+            args.backends = perfetto::kInProcessBackend;
+            perfetto::Tracing::Initialize(args);
+            wasInitialized = true;
+        }
+    }
+
+    ~FrameTracerTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+
+    void SetUp() override {
+        mFrameTracer = std::make_unique<FrameTracer>();
+        mFrameTracer->registerDataSource();
+    }
+
+    void TearDown() override { mFrameTracer.reset(); }
+
+    // Each tracing session can be used for a single block of Start -> Stop.
+    static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
+        perfetto::TraceConfig cfg;
+        cfg.set_duration_ms(500);
+        cfg.add_buffers()->set_size_kb(1024);
+        auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+        ds_cfg->set_name(FrameTracer::kFrameTracerDataSource);
+
+        auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+        tracingSession->Setup(cfg);
+        return tracingSession;
+    }
+
+    std::unique_ptr<FrameTracer> mFrameTracer;
+    FenceToFenceTimeMap fenceFactory;
+};
+
+TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) {
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    mFrameTracer->traceNewLayer(layerID, layerName);
+
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+    auto tracingSession = getTracingSessionForTest();
+    tracingSession->StartBlocking();
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+    mFrameTracer->traceNewLayer(layerID, layerName);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+    tracingSession->StopBlocking();
+}
+
+TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) {
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const int32_t secondLayerID = 6;
+
+    auto tracingSession = getTracingSessionForTest();
+    tracingSession->StartBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+    mFrameTracer->traceNewLayer(secondLayerID, layerName);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n");
+    tracingSession->StopBlocking();
+
+    mFrameTracer->onDestroy(layerID);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+    mFrameTracer->onDestroy(layerID);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+    mFrameTracer->onDestroy(secondLayerID);
+    EXPECT_EQ(mFrameTracer->miniDump(),
+              "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+}
+
+TEST_F(FrameTracerTest, canTraceAfterAddingLayer) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 1;
+    const uint32_t bufferID = 2;
+    const uint64_t frameNumber = 3;
+    const nsecs_t timestamp = 4;
+    const nsecs_t duration = 5;
+    const auto type = FrameTracer::FrameEvent::POST;
+
+    {
+        auto tracingSession = getTracingSessionForTest();
+
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+
+        mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
+        // Create second trace packet to finalize the previous one.
+        mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        EXPECT_EQ(raw_trace.size(), 0);
+    }
+
+    {
+        auto tracingSession = getTracingSessionForTest();
+
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+
+        mFrameTracer->traceNewLayer(layerID, layerName);
+        mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
+        // Create second trace packet to finalize the previous one.
+        mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        ASSERT_GT(raw_trace.size(), 0);
+
+        perfetto::protos::Trace trace;
+        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+        ASSERT_FALSE(trace.packet().empty());
+        EXPECT_EQ(trace.packet().size(), 1);
+
+        const auto& packet = trace.packet().Get(0);
+        ASSERT_TRUE(packet.has_timestamp());
+        EXPECT_EQ(packet.timestamp(), timestamp);
+        ASSERT_TRUE(packet.has_graphics_frame_event());
+        const auto& frame_event = packet.graphics_frame_event();
+        ASSERT_TRUE(frame_event.has_buffer_event());
+        const auto& buffer_event = frame_event.buffer_event();
+        ASSERT_TRUE(buffer_event.has_buffer_id());
+        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
+        ASSERT_TRUE(buffer_event.has_frame_number());
+        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
+        ASSERT_TRUE(buffer_event.has_type());
+        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
+        ASSERT_TRUE(buffer_event.has_duration_ns());
+        EXPECT_EQ(buffer_event.duration_ns(), duration);
+    }
+}
+
+TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+
+    {
+        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+        fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
+        auto tracingSession = getTracingSessionForTest();
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+        // Trace.
+        mFrameTracer->traceNewLayer(layerID, layerName);
+        mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
+        // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
+        mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        EXPECT_EQ(raw_trace.size(), 0);
+    }
+
+    {
+        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+        auto tracingSession = getTracingSessionForTest();
+        tracingSession->StartBlocking();
+        // Clean up irrelevant traces.
+        tracingSession->ReadTraceBlocking();
+        mFrameTracer->traceNewLayer(layerID, layerName);
+        mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
+        const nsecs_t timestamp = systemTime();
+        fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
+        // Create extra trace packet to trigger and finalize fence trace packets.
+        mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+        tracingSession->StopBlocking();
+
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        ASSERT_GT(raw_trace.size(), 0);
+
+        perfetto::protos::Trace trace;
+        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+        ASSERT_FALSE(trace.packet().empty());
+        EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
+
+        const auto& packet = trace.packet().Get(1);
+        ASSERT_TRUE(packet.has_timestamp());
+        EXPECT_EQ(packet.timestamp(), timestamp);
+        ASSERT_TRUE(packet.has_graphics_frame_event());
+        const auto& frame_event = packet.graphics_frame_event();
+        ASSERT_TRUE(frame_event.has_buffer_event());
+        const auto& buffer_event = frame_event.buffer_event();
+        ASSERT_TRUE(buffer_event.has_buffer_id());
+        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
+        ASSERT_TRUE(buffer_event.has_frame_number());
+        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
+        ASSERT_TRUE(buffer_event.has_type());
+        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
+        EXPECT_FALSE(buffer_event.has_duration_ns());
+    }
+}
+
+TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+
+    auto tracingSession = getTracingSessionForTest();
+
+    tracingSession->StartBlocking();
+    // Clean up irrelevant traces.
+    tracingSession->ReadTraceBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+
+    // traceFence called after fence signalled.
+    const nsecs_t signalTime1 = systemTime();
+    const nsecs_t startTime1 = signalTime1 + 100000;
+    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
+
+    // traceFence called before fence signalled.
+    const nsecs_t signalTime2 = systemTime();
+    const nsecs_t startTime2 = signalTime2 + 100000;
+    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
+
+    // Create extra trace packet to trigger and finalize fence trace packets.
+    mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+    tracingSession->StopBlocking();
+
+    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+    ASSERT_GT(raw_trace.size(), 0);
+
+    perfetto::protos::Trace trace;
+    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+    ASSERT_FALSE(trace.packet().empty());
+    EXPECT_EQ(trace.packet().size(), 2);
+
+    const auto& packet1 = trace.packet().Get(0);
+    ASSERT_TRUE(packet1.has_timestamp());
+    EXPECT_EQ(packet1.timestamp(), signalTime1);
+    ASSERT_TRUE(packet1.has_graphics_frame_event());
+    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
+    ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
+
+    const auto& packet2 = trace.packet().Get(1);
+    ASSERT_TRUE(packet2.has_timestamp());
+    EXPECT_EQ(packet2.timestamp(), signalTime2);
+    ASSERT_TRUE(packet2.has_graphics_frame_event());
+    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
+    ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
+}
+
+TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+    const nsecs_t signalTime = systemTime() - FrameTracer::kFenceSignallingDeadline;
+
+    auto tracingSession = getTracingSessionForTest();
+    auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+
+    tracingSession->StartBlocking();
+    // Clean up irrelevant traces.
+    tracingSession->ReadTraceBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
+    // Create extra trace packet to trigger and finalize any previous fence packets.
+    mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+    tracingSession->StopBlocking();
+
+    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+    EXPECT_EQ(raw_trace.size(), 0);
+}
+
+TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
+    const std::string layerName = "co.layername#0";
+    const int32_t layerID = 5;
+    const uint32_t bufferID = 4;
+    const uint64_t frameNumber = 3;
+    const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+    const nsecs_t duration = 1234;
+
+    auto tracingSession = getTracingSessionForTest();
+
+    tracingSession->StartBlocking();
+    // Clean up irrelevant traces.
+    tracingSession->ReadTraceBlocking();
+    mFrameTracer->traceNewLayer(layerID, layerName);
+
+    // traceFence called after fence signalled.
+    const nsecs_t signalTime1 = systemTime();
+    const nsecs_t startTime1 = signalTime1 - duration;
+    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
+
+    // traceFence called before fence signalled.
+    const nsecs_t signalTime2 = systemTime();
+    const nsecs_t startTime2 = signalTime2 - duration;
+    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+    mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
+    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
+
+    // Create extra trace packet to trigger and finalize fence trace packets.
+    mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+    tracingSession->StopBlocking();
+
+    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+    ASSERT_GT(raw_trace.size(), 0);
+
+    perfetto::protos::Trace trace;
+    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+    ASSERT_FALSE(trace.packet().empty());
+    EXPECT_EQ(trace.packet().size(), 2);
+
+    const auto& packet1 = trace.packet().Get(0);
+    ASSERT_TRUE(packet1.has_timestamp());
+    EXPECT_EQ(packet1.timestamp(), startTime1);
+    ASSERT_TRUE(packet1.has_graphics_frame_event());
+    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
+    ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
+    const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
+    EXPECT_EQ(buffer_event1.duration_ns(), duration);
+
+    const auto& packet2 = trace.packet().Get(1);
+    ASSERT_TRUE(packet2.has_timestamp());
+    EXPECT_EQ(packet2.timestamp(), startTime2);
+    ASSERT_TRUE(packet2.has_graphics_frame_event());
+    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
+    ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
+    const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
+    EXPECT_EQ(buffer_event2.duration_ns(), duration);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index f01e603..ffacbfe 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -20,8 +20,8 @@
 #include <TimeStats/TimeStats.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+
 #include <log/log.h>
-#include <perfetto/trace/trace.pb.h>
 #include <utils/String16.h>
 #include <utils/Vector.h>
 
@@ -109,15 +109,6 @@
         const ::testing::TestInfo* const test_info =
                 ::testing::UnitTest::GetInstance()->current_test_info();
         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-
-        // Need to initialize tracing in process for testing, and only once per test suite.
-        static bool wasInitialized = false;
-        if (!wasInitialized) {
-            perfetto::TracingInitArgs args;
-            args.backends = perfetto::kInProcessBackend;
-            perfetto::Tracing::Initialize(args);
-            wasInitialized = true;
-        }
     }
 
     ~TimeStatsTest() {
@@ -126,13 +117,6 @@
         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
     }
 
-    void SetUp() override {
-        mTimeStats = std::make_unique<impl::TimeStats>();
-        mTimeStats->registerTracingDataSource();
-    }
-
-    void TearDown() override { mTimeStats.reset(); }
-
     std::string inputCommand(InputCommand cmd, bool useProto);
 
     void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts);
@@ -147,22 +131,8 @@
         }
     }
 
-    // Each tracing session can be used for a single block of Start -> Stop.
-    static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
-        perfetto::TraceConfig cfg;
-        cfg.set_duration_ms(500);
-        cfg.add_buffers()->set_size_kb(1024);
-        auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-        ds_cfg->set_name(TimeStats::kTimeStatsDataSource);
-
-        auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
-        tracingSession->Setup(cfg);
-        return tracingSession;
-    }
-
     std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
-    std::unique_ptr<TimeStats> mTimeStats;
-    FenceToFenceTimeMap fenceFactory;
+    std::unique_ptr<TimeStats> mTimeStats = std::make_unique<impl::TimeStats>();
 };
 
 std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
@@ -239,330 +209,6 @@
     return distr(mRandomEngine);
 }
 
-TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) {
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    mTimeStats->traceNewLayer(layerID, layerName);
-
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
-    auto tracingSession = getTracingSessionForTest();
-    tracingSession->StartBlocking();
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-    mTimeStats->traceNewLayer(layerID, layerName);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
-    tracingSession->StopBlocking();
-}
-
-TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) {
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const int32_t secondLayerID = 6;
-
-    auto tracingSession = getTracingSessionForTest();
-    tracingSession->StartBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-    mTimeStats->traceNewLayer(secondLayerID, layerName);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n");
-    tracingSession->StopBlocking();
-
-    mTimeStats->onDestroy(layerID);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
-    mTimeStats->onDestroy(layerID);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
-    mTimeStats->onDestroy(secondLayerID);
-    EXPECT_EQ(mTimeStats->miniDump(),
-              "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
-              "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-}
-
-TEST_F(TimeStatsTest, canTraceAfterAddingLayer) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 1;
-    const uint32_t bufferID = 2;
-    const uint64_t frameNumber = 3;
-    const nsecs_t timestamp = 4;
-    const nsecs_t duration = 5;
-    const auto type = TimeStats::FrameEvent::POST;
-
-    {
-        auto tracingSession = getTracingSessionForTest();
-
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-
-        mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
-        // Create second trace packet to finalize the previous one.
-        mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        EXPECT_EQ(raw_trace.size(), 0);
-    }
-
-    {
-        auto tracingSession = getTracingSessionForTest();
-
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-
-        mTimeStats->traceNewLayer(layerID, layerName);
-        mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
-        // Create second trace packet to finalize the previous one.
-        mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        ASSERT_GT(raw_trace.size(), 0);
-
-        perfetto::protos::Trace trace;
-        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-        ASSERT_FALSE(trace.packet().empty());
-        EXPECT_EQ(trace.packet().size(), 1);
-
-        const auto& packet = trace.packet().Get(0);
-        ASSERT_TRUE(packet.has_timestamp());
-        EXPECT_EQ(packet.timestamp(), timestamp);
-        ASSERT_TRUE(packet.has_graphics_frame_event());
-        const auto& frame_event = packet.graphics_frame_event();
-        ASSERT_TRUE(frame_event.has_buffer_event());
-        const auto& buffer_event = frame_event.buffer_event();
-        ASSERT_TRUE(buffer_event.has_buffer_id());
-        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
-        ASSERT_TRUE(buffer_event.has_frame_number());
-        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
-        ASSERT_TRUE(buffer_event.has_type());
-        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
-        ASSERT_TRUE(buffer_event.has_duration_ns());
-        EXPECT_EQ(buffer_event.duration_ns(), duration);
-    }
-}
-
-TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-
-    {
-        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-        fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
-        auto tracingSession = getTracingSessionForTest();
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-        // Trace.
-        mTimeStats->traceNewLayer(layerID, layerName);
-        mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
-        // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
-        mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        EXPECT_EQ(raw_trace.size(), 0);
-    }
-
-    {
-        auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-        auto tracingSession = getTracingSessionForTest();
-        tracingSession->StartBlocking();
-        // Clean up irrelevant traces.
-        tracingSession->ReadTraceBlocking();
-        mTimeStats->traceNewLayer(layerID, layerName);
-        mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
-        const nsecs_t timestamp = systemTime();
-        fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
-        // Create extra trace packet to trigger and finalize fence trace packets.
-        mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-        tracingSession->StopBlocking();
-
-        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-        ASSERT_GT(raw_trace.size(), 0);
-
-        perfetto::protos::Trace trace;
-        ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-        ASSERT_FALSE(trace.packet().empty());
-        EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
-
-        const auto& packet = trace.packet().Get(1);
-        ASSERT_TRUE(packet.has_timestamp());
-        EXPECT_EQ(packet.timestamp(), timestamp);
-        ASSERT_TRUE(packet.has_graphics_frame_event());
-        const auto& frame_event = packet.graphics_frame_event();
-        ASSERT_TRUE(frame_event.has_buffer_event());
-        const auto& buffer_event = frame_event.buffer_event();
-        ASSERT_TRUE(buffer_event.has_buffer_id());
-        EXPECT_EQ(buffer_event.buffer_id(), bufferID);
-        ASSERT_TRUE(buffer_event.has_frame_number());
-        EXPECT_EQ(buffer_event.frame_number(), frameNumber);
-        ASSERT_TRUE(buffer_event.has_type());
-        EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
-        EXPECT_FALSE(buffer_event.has_duration_ns());
-    }
-}
-
-TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-
-    auto tracingSession = getTracingSessionForTest();
-
-    tracingSession->StartBlocking();
-    // Clean up irrelevant traces.
-    tracingSession->ReadTraceBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-
-    // traceFence called after fence signalled.
-    const nsecs_t signalTime1 = systemTime();
-    const nsecs_t startTime1 = signalTime1 + 100000;
-    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
-
-    // traceFence called before fence signalled.
-    const nsecs_t signalTime2 = systemTime();
-    const nsecs_t startTime2 = signalTime2 + 100000;
-    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
-
-    // Create extra trace packet to trigger and finalize fence trace packets.
-    mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-    tracingSession->StopBlocking();
-
-    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-    ASSERT_GT(raw_trace.size(), 0);
-
-    perfetto::protos::Trace trace;
-    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-    ASSERT_FALSE(trace.packet().empty());
-    EXPECT_EQ(trace.packet().size(), 2);
-
-    const auto& packet1 = trace.packet().Get(0);
-    ASSERT_TRUE(packet1.has_timestamp());
-    EXPECT_EQ(packet1.timestamp(), signalTime1);
-    ASSERT_TRUE(packet1.has_graphics_frame_event());
-    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
-    ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
-
-    const auto& packet2 = trace.packet().Get(1);
-    ASSERT_TRUE(packet2.has_timestamp());
-    EXPECT_EQ(packet2.timestamp(), signalTime2);
-    ASSERT_TRUE(packet2.has_graphics_frame_event());
-    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
-    ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
-}
-
-TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-    const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline;
-
-    auto tracingSession = getTracingSessionForTest();
-    auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-
-    tracingSession->StartBlocking();
-    // Clean up irrelevant traces.
-    tracingSession->ReadTraceBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
-    // Create extra trace packet to trigger and finalize any previous fence packets.
-    mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-    tracingSession->StopBlocking();
-
-    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-    EXPECT_EQ(raw_trace.size(), 0);
-}
-
-TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
-    const std::string layerName = "co.layername#0";
-    const int32_t layerID = 5;
-    const uint32_t bufferID = 4;
-    const uint64_t frameNumber = 3;
-    const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-    const nsecs_t duration = 1234;
-
-    auto tracingSession = getTracingSessionForTest();
-
-    tracingSession->StartBlocking();
-    // Clean up irrelevant traces.
-    tracingSession->ReadTraceBlocking();
-    mTimeStats->traceNewLayer(layerID, layerName);
-
-    // traceFence called after fence signalled.
-    const nsecs_t signalTime1 = systemTime();
-    const nsecs_t startTime1 = signalTime1 - duration;
-    auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
-
-    // traceFence called before fence signalled.
-    const nsecs_t signalTime2 = systemTime();
-    const nsecs_t startTime2 = signalTime2 - duration;
-    auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-    mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
-    fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
-
-    // Create extra trace packet to trigger and finalize fence trace packets.
-    mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
-    tracingSession->StopBlocking();
-
-    std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
-    ASSERT_GT(raw_trace.size(), 0);
-
-    perfetto::protos::Trace trace;
-    ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-    ASSERT_FALSE(trace.packet().empty());
-    EXPECT_EQ(trace.packet().size(), 2);
-
-    const auto& packet1 = trace.packet().Get(0);
-    ASSERT_TRUE(packet1.has_timestamp());
-    EXPECT_EQ(packet1.timestamp(), startTime1);
-    ASSERT_TRUE(packet1.has_graphics_frame_event());
-    ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
-    ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
-    const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
-    EXPECT_EQ(buffer_event1.duration_ns(), duration);
-
-    const auto& packet2 = trace.packet().Get(1);
-    ASSERT_TRUE(packet2.has_timestamp());
-    EXPECT_EQ(packet2.timestamp(), startTime2);
-    ASSERT_TRUE(packet2.has_graphics_frame_event());
-    ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
-    ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
-    const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
-    EXPECT_EQ(buffer_event2.duration_ns(), duration);
-}
-
 TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
     ASSERT_TRUE(mTimeStats->isEnabled());
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp
new file mode 100644
index 0000000..358dfdb
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mock/MockFrameTracer.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+FrameTracer::FrameTracer() = default;
+FrameTracer::~FrameTracer() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h
new file mode 100644
index 0000000..f768b81
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "FrameTracer/FrameTracer.h"
+
+namespace android {
+namespace mock {
+
+class FrameTracer : public android::FrameTracer {
+public:
+    FrameTracer();
+    ~FrameTracer();
+
+    MOCK_METHOD0(initialize, void());
+    MOCK_METHOD0(registerDataSource, void());
+    MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&));
+    MOCK_METHOD6(traceTimestamp,
+                 void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t));
+    MOCK_METHOD6(traceFence,
+                 void(int32_t, uint64_t, uint64_t, const std::shared_ptr<FenceTime>&,
+                      FrameEvent::BufferEventType, nsecs_t));
+    MOCK_METHOD0(miniDump, std::string());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 542c70a..b1634a8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -28,14 +28,6 @@
     TimeStats();
     ~TimeStats() override;
 
-    MOCK_METHOD0(initializeTracing, void());
-    MOCK_METHOD0(registerTracingDataSource, void());
-    MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&));
-    MOCK_METHOD6(traceTimestamp,
-                 void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t));
-    MOCK_METHOD6(traceFence,
-                 void(int32_t, uint64_t, uint64_t, const std::shared_ptr<FenceTime>&,
-                      FrameEvent::BufferEventType, nsecs_t));
     MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
     MOCK_METHOD0(isEnabled, bool());
     MOCK_METHOD0(miniDump, std::string());