Merge "SF: Move layer visibility state 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/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 528bfb1..3a7cb44 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -166,7 +166,9 @@
mCore->mFreeBuffers.push_back(front->mSlot);
}
- listener = mCore->mConnectedProducerListener;
+ if (mCore->mBufferReleasedCbEnabled) {
+ listener = mCore->mConnectedProducerListener;
+ }
++numDroppedBuffers;
}
@@ -457,7 +459,9 @@
mCore->mFreeBuffers.push_back(slot);
}
- listener = mCore->mConnectedProducerListener;
+ if (mCore->mBufferReleasedCbEnabled) {
+ listener = mCore->mConnectedProducerListener;
+ }
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
mCore->mDequeueCondition.notify_all();
@@ -668,7 +672,7 @@
BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
VALIDATE_CONSISTENCY();
- if (delta < 0) {
+ if (delta < 0 && mCore->mBufferReleasedCbEnabled) {
listener = mCore->mConsumerListener;
}
}
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index b429d38..d6009d6 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -65,6 +65,7 @@
mConnectedApi(NO_CONNECTED_API),
mLinkedToDeath(),
mConnectedProducerListener(),
+ mBufferReleasedCbEnabled(false),
mSlots(),
mQueue(),
mFreeSlots(),
@@ -264,6 +265,12 @@
}
void BufferQueueCore::discardFreeBuffersLocked() {
+ // Notify producer about the discarded buffers.
+ if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) {
+ std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end());
+ mConnectedProducerListener->onBuffersDiscarded(freeBuffers);
+ }
+
for (int s : mFreeBuffers) {
mFreeSlots.insert(s);
clearBufferSlotLocked(s);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index d149674..5674674 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1223,9 +1223,8 @@
}
mCore->mLinkedToDeath = listener;
}
- if (listener->needsReleaseNotify()) {
- mCore->mConnectedProducerListener = listener;
- }
+ mCore->mConnectedProducerListener = listener;
+ mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
}
break;
default:
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 936063a..808e336 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -24,6 +24,7 @@
enum {
ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
NEEDS_RELEASE_NOTIFY,
+ ON_BUFFERS_DISCARDED,
};
class BpProducerListener : public BpInterface<IProducerListener>
@@ -56,6 +57,13 @@
}
return result;
}
+
+ virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
+ data.writeInt32Vector(discardedSlots);
+ remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -76,6 +84,10 @@
virtual bool needsReleaseNotify() override {
return mBase->needsReleaseNotify();
}
+
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override {
+ return mBase->onBuffersDiscarded(discardedSlots);
+ }
};
IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener,
@@ -92,6 +104,17 @@
CHECK_INTERFACE(IProducerListener, data, reply);
reply->writeBool(needsReleaseNotify());
return NO_ERROR;
+ case ON_BUFFERS_DISCARDED: {
+ CHECK_INTERFACE(IProducerListener, data, reply);
+ std::vector<int32_t> discardedSlots;
+ status_t result = data.readInt32Vector(&discardedSlots);
+ if (result != NO_ERROR) {
+ ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result);
+ return result;
+ }
+ onBuffersDiscarded(discardedSlots);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
@@ -104,4 +127,7 @@
return true;
}
+void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) {
+}
+
} // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index eb2e3f0..7e356e4 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -35,6 +35,7 @@
#include <ui/DisplayStatInfo.h>
#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
@@ -1300,6 +1301,14 @@
}
int Surface::connect(
+ int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) {
+ if (sListener != nullptr) {
+ mListenerProxy = new ProducerListenerProxy(this, sListener);
+ }
+ return connect(api, mListenerProxy, reportBufferRemoval);
+}
+
+int Surface::connect(
int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
ATRACE_CALL();
ALOGV("Surface::connect");
@@ -1700,6 +1709,28 @@
}
}
+status_t Surface::getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
+ std::vector<sp<GraphicBuffer>>* outBuffers) {
+ ALOGV("Surface::getAndFlushBuffersFromSlots");
+ for (int32_t i : slots) {
+ if (i < 0 || i >= NUM_BUFFER_SLOTS) {
+ ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i);
+ return BAD_VALUE;
+ }
+ }
+
+ Mutex::Autolock lock(mMutex);
+ for (int32_t i : slots) {
+ if (mSlots[i].buffer == nullptr) {
+ ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i);
+ continue;
+ }
+ outBuffers->push_back(mSlots[i].buffer);
+ mSlots[i].buffer = nullptr;
+ }
+ return OK;
+}
+
void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
ATRACE_CALL();
ALOGV("Surface::setSurfaceDamage");
@@ -1985,4 +2016,22 @@
return err;
}
+void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_t>& slots) {
+ ATRACE_CALL();
+ sp<Surface> parent = mParent.promote();
+ if (parent == nullptr) {
+ return;
+ }
+
+ std::vector<sp<GraphicBuffer>> discardedBufs;
+ status_t res = parent->getAndFlushBuffersFromSlots(slots, &discardedBufs);
+ if (res != OK) {
+ ALOGE("%s: Failed to get buffers from slots: %s(%d)", __FUNCTION__,
+ strerror(-res), res);
+ return;
+ }
+
+ mSurfaceListener->onBuffersDiscarded(discardedBufs);
+}
+
}; // namespace android
diff --git a/libs/gui/TEST_MAPPING b/libs/gui/TEST_MAPPING
new file mode 100644
index 0000000..1c43530
--- /dev/null
+++ b/libs/gui/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/native/libs/nativewindow"
+ }
+ ]
+}
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 205e79c..3c96089 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -189,8 +189,12 @@
sp<IProducerListener> mLinkedToDeath;
// mConnectedProducerListener is used to handle the onBufferReleased
- // notification.
+ // and onBuffersDiscarded notification.
sp<IProducerListener> mConnectedProducerListener;
+ // mBufferReleasedCbEnabled is used to indicate whether onBufferReleased()
+ // callback is registered by the listener. When set to false,
+ // mConnectedProducerListener will not trigger onBufferReleased() callback.
+ bool mBufferReleasedCbEnabled;
// mSlots is an array of buffer slots that must be mirrored on the producer
// side. This allows buffer ownership to be transferred between the producer
diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
index a13d8e4..32a3690 100644
--- a/libs/gui/include/gui/IProducerListener.h
+++ b/libs/gui/include/gui/IProducerListener.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GUI_IPRODUCERLISTENER_H
#define ANDROID_GUI_IPRODUCERLISTENER_H
+#include <vector>
+
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
#include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
#include <binder/IInterface.h>
@@ -44,6 +46,9 @@
// multiple threads.
virtual void onBufferReleased() = 0; // Asynchronous
virtual bool needsReleaseNotify() = 0;
+ // onBuffersFreed is called from IGraphicBufferConsumer::discardFreeBuffers
+ // to notify the producer that certain free buffers are discarded by the consumer.
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) = 0; // Asynchronous
};
class IProducerListener : public ProducerListener, public IInterface
@@ -65,6 +70,7 @@
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
virtual bool needsReleaseNotify();
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
};
class DummyProducerListener : public BnProducerListener
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index fe528b3..28f5a26 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -20,6 +20,7 @@
#include <gui/BufferQueueDefs.h>
#include <gui/HdrMetadata.h>
#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
#include <ui/ANativeObjectBase.h>
#include <ui/GraphicTypes.h>
@@ -35,6 +36,21 @@
class ISurfaceComposer;
+/* This is the same as ProducerListener except that onBuffersDiscarded is
+ * called with a vector of graphic buffers instead of buffer slots.
+ */
+class SurfaceListener : public virtual RefBase
+{
+public:
+ SurfaceListener() = default;
+ virtual ~SurfaceListener() = default;
+
+ virtual void onBufferReleased() = 0;
+ virtual bool needsReleaseNotify() = 0;
+
+ virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) = 0;
+};
+
/*
* An implementation of ANativeWindow that feeds graphics buffers into a
* BufferQueue.
@@ -285,6 +301,10 @@
sp<Fence>* outFence);
virtual int attachBuffer(ANativeWindowBuffer*);
+ virtual int connect(
+ int api, bool reportBufferRemoval,
+ const sp<SurfaceListener>& sListener);
+
// When client connects to Surface with reportBufferRemoval set to true, any buffers removed
// from this Surface will be collected and returned here. Once this method returns, these
// buffers will no longer be referenced by this Surface unless they are attached to this
@@ -301,6 +321,26 @@
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
+ class ProducerListenerProxy : public BnProducerListener {
+ public:
+ ProducerListenerProxy(wp<Surface> parent, sp<SurfaceListener> listener)
+ : mParent(parent), mSurfaceListener(listener) {}
+ virtual ~ProducerListenerProxy() {}
+
+ virtual void onBufferReleased() {
+ mSurfaceListener->onBufferReleased();
+ }
+
+ virtual bool needsReleaseNotify() {
+ return mSurfaceListener->needsReleaseNotify();
+ }
+
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots);
+ private:
+ wp<Surface> mParent;
+ sp<SurfaceListener> mSurfaceListener;
+ };
+
void querySupportedTimestampsLocked() const;
void freeAllBuffers();
@@ -470,6 +510,10 @@
bool mReportRemovedBuffers = false;
std::vector<sp<GraphicBuffer>> mRemovedBuffers;
int mMaxBufferCount;
+
+ sp<IProducerListener> mListenerProxy;
+ status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
+ std::vector<sp<GraphicBuffer>>* outBuffers);
};
} // namespace android
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 98dc1e6..6d7b6bb 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -1010,12 +1010,31 @@
ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
}
+struct BufferDiscardedListener : public BnProducerListener {
+public:
+ BufferDiscardedListener() = default;
+ virtual ~BufferDiscardedListener() = default;
+
+ virtual void onBufferReleased() {}
+ virtual bool needsReleaseNotify() { return false; }
+ virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
+ mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
+ }
+
+ const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
+private:
+ // No need to use lock given the test triggers the listener in the same
+ // thread context.
+ std::vector<int32_t> mDiscardedSlots;
+};
+
TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
+ ASSERT_EQ(OK, mProducer->connect(pl,
NATIVE_WINDOW_API_CPU, false, &output));
int slot = BufferQueue::INVALID_BUFFER_SLOT;
@@ -1056,12 +1075,19 @@
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ int releasedSlot = item.mSlot;
+
// Acquire 1 buffer, leaving 1 filled buffer in queue
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
// Now discard the free buffers
ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
+ // Check onBuffersDiscarded is called with correct slots
+ auto buffersDiscarded = pl->getDiscardedSlots();
+ ASSERT_EQ(buffersDiscarded.size(), 1);
+ ASSERT_EQ(buffersDiscarded[0], releasedSlot);
+
// Check no free buffers in dump
String8 dumpString;
mConsumer->dumpState(String8{}, &dumpString);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 7718bc1..5a121d7 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -57,6 +57,37 @@
static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max();
+class DummySurfaceListener : public SurfaceListener {
+public:
+ DummySurfaceListener(bool enableReleasedCb = false) :
+ mEnableReleaseCb(enableReleasedCb),
+ mBuffersReleased(0) {}
+ virtual ~DummySurfaceListener() = default;
+
+ virtual void onBufferReleased() {
+ mBuffersReleased++;
+ }
+ virtual bool needsReleaseNotify() {
+ return mEnableReleaseCb;
+ }
+ virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) {
+ mDiscardedBuffers.insert(mDiscardedBuffers.end(), buffers.begin(), buffers.end());
+ }
+
+ int getReleaseNotifyCount() const {
+ return mBuffersReleased;
+ }
+ const std::vector<sp<GraphicBuffer>>& getDiscardedBuffers() const {
+ return mDiscardedBuffers;
+ }
+private:
+ // No need to use lock given the test triggers the listener in the same
+ // thread context.
+ bool mEnableReleaseCb;
+ int32_t mBuffersReleased;
+ std::vector<sp<GraphicBuffer>> mDiscardedBuffers;
+};
+
class SurfaceTest : public ::testing::Test {
protected:
SurfaceTest() {
@@ -88,6 +119,86 @@
mComposerClient->dispose();
}
+ void testSurfaceListener(bool hasSurfaceListener, bool enableReleasedCb,
+ int32_t extraDiscardedBuffers) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+ sp<DummySurfaceListener> listener;
+ if (hasSurfaceListener) {
+ listener = new DummySurfaceListener(enableReleasedCb);
+ }
+ ASSERT_EQ(OK, surface->connect(
+ NATIVE_WINDOW_API_CPU,
+ /*reportBufferRemoval*/true,
+ /*listener*/listener));
+ const int BUFFER_COUNT = 4 + extraDiscardedBuffers;
+ ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT));
+
+ ANativeWindowBuffer* buffers[BUFFER_COUNT];
+ // Dequeue first to allocate a number of buffers
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffers[i]));
+ }
+ for (int i = 0; i < BUFFER_COUNT; i++) {
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], -1));
+ }
+
+ ANativeWindowBuffer* buffer;
+ // Fill BUFFER_COUNT-1 buffers
+ for (int i = 0; i < BUFFER_COUNT-1; i++) {
+ ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer));
+ ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, -1));
+ }
+
+ // Dequeue 1 buffer
+ ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer));
+
+ // Acquire and free 1+extraDiscardedBuffers buffer, check onBufferReleased is called.
+ std::vector<BufferItem> releasedItems;
+ releasedItems.resize(1+extraDiscardedBuffers);
+ for (int i = 0; i < releasedItems.size(); i++) {
+ ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&releasedItems[i], 0));
+ ASSERT_EQ(NO_ERROR, consumer->releaseBuffer(releasedItems[i].mSlot,
+ releasedItems[i].mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
+ Fence::NO_FENCE));
+ }
+ int32_t expectedReleaseCb = (enableReleasedCb ? releasedItems.size() : 0);
+ if (hasSurfaceListener) {
+ ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+ }
+
+ // Acquire 1 buffer, leaving 1+extraDiscardedBuffers filled buffer in queue
+ BufferItem item;
+ ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&item, 0));
+
+ // Discard free buffers
+ ASSERT_EQ(NO_ERROR, consumer->discardFreeBuffers());
+
+ if (hasSurfaceListener) {
+ ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+
+ // Check onBufferDiscarded is called with correct buffer
+ auto discardedBuffers = listener->getDiscardedBuffers();
+ ASSERT_EQ(discardedBuffers.size(), releasedItems.size());
+ for (int i = 0; i < releasedItems.size(); i++) {
+ ASSERT_EQ(discardedBuffers[i], releasedItems[i].mGraphicBuffer);
+ }
+
+ ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount());
+ }
+
+ // Disconnect the surface
+ ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU));
+ }
+
sp<Surface> mSurface;
sp<SurfaceComposerClient> mComposerClient;
sp<SurfaceControl> mSurfaceControl;
@@ -480,6 +591,21 @@
ASSERT_LE(removedBuffers.size(), 1u);
}
+TEST_F(SurfaceTest, SurfaceListenerTest) {
+ // Test discarding 1 free buffers with no listener
+ testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/0);
+ // Test discarding 2 free buffers with no listener
+ testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/1);
+ // Test discarding 1 free buffers with a listener, disabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/0);
+ // Test discarding 2 free buffers with a listener, disabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/1);
+ // Test discarding 1 free buffers with a listener, enabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/0);
+ // Test discarding 3 free buffers with a listener, enabling onBufferReleased
+ testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/2);
+}
+
TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
sp<ANativeWindow> anw(mSurface);
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 1751443..4c59e6c 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -266,3 +266,11 @@
int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation) {
return native_window_set_auto_prerotation(window, autoPrerotation);
}
+
+/**************************************************************************************************
+ * apex-stable
+ **************************************************************************************************/
+
+int ANativeWindow_getLastDequeueDuration(ANativeWindow* window) {
+ return query(window, NATIVE_WINDOW_LAST_DEQUEUE_DURATION);
+}
diff --git a/libs/nativewindow/TEST_MAPPING b/libs/nativewindow/TEST_MAPPING
new file mode 100644
index 0000000..3d7f3c2
--- /dev/null
+++ b/libs/nativewindow/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libnativewindow_test"
+ }
+ ]
+}
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
new file mode 100644
index 0000000..0260cbc
--- /dev/null
+++ b/libs/nativewindow/include/apex/window.h
@@ -0,0 +1,34 @@
+/*
+ * 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 <nativebase/nativebase.h>
+
+// apex is a superset of the NDK
+#include <android/native_window.h>
+
+__BEGIN_DECLS
+
+/**
+ * Retrieves how long it took for the last time a buffer was dequeued.
+ *
+ * \return a negative value on error, otherwise returns the duration in
+ * microseconds.
+ */
+int ANativeWindow_getLastDequeueDuration(ANativeWindow* window);
+
+__END_DECLS
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 8cbf0a4..78354bb 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -41,7 +41,8 @@
#include <unistd.h>
#include <stdbool.h>
-// system/window.h is a superset of the vndk
+// system/window.h is a superset of the vndk and apex apis
+#include <apex/window.h>
#include <vndk/window.h>
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 119a07d..7fe4df0 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -22,6 +22,7 @@
ANativeWindow_getBuffersDataSpace; # introduced=28
ANativeWindow_getFormat;
ANativeWindow_getHeight;
+ ANativeWindow_getLastDequeueDuration; # apex # introduced=30
ANativeWindow_getWidth;
ANativeWindow_lock;
ANativeWindow_query; # vndk
diff --git a/libs/nativewindow/tests/ANativeWindowTest.cpp b/libs/nativewindow/tests/ANativeWindowTest.cpp
new file mode 100644
index 0000000..5247e04
--- /dev/null
+++ b/libs/nativewindow/tests/ANativeWindowTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ANativeWindow_test"
+//#define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/BufferQueue.h>
+#include <gui/Surface.h>
+#include <log/log.h>
+#include <sync/sync.h>
+// We need to use the private system apis since not everything is visible to
+// apexes yet.
+#include <system/window.h>
+
+using namespace android;
+
+class TestableSurface final : public Surface {
+public:
+ explicit TestableSurface(const sp<IGraphicBufferProducer>& bufferProducer)
+ : Surface(bufferProducer) {}
+
+ // Exposes the internal last dequeue duration that's stored on the Surface.
+ nsecs_t getLastDequeueDuration() const { return mLastDequeueDuration; }
+};
+
+class ANativeWindowTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGV("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mItemConsumer = new BufferItemConsumer(mConsumer, GRALLOC_USAGE_SW_READ_OFTEN);
+ mWindow = new TestableSurface(mProducer);
+ const int success = native_window_api_connect(mWindow.get(), NATIVE_WINDOW_API_CPU);
+ EXPECT_EQ(0, success);
+ }
+
+ void TearDown() override {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGV("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+ const int success = native_window_api_disconnect(mWindow.get(), NATIVE_WINDOW_API_CPU);
+ EXPECT_EQ(0, success);
+ }
+ sp<IGraphicBufferProducer> mProducer;
+ sp<IGraphicBufferConsumer> mConsumer;
+ sp<BufferItemConsumer> mItemConsumer;
+
+ sp<TestableSurface> mWindow;
+};
+
+TEST_F(ANativeWindowTest, getLastDequeueDuration_noDequeue_returnsZero) {
+ int result = ANativeWindow_getLastDequeueDuration(mWindow.get());
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(0, mWindow->getLastDequeueDuration() / 1000);
+}
+
+TEST_F(ANativeWindowTest, getLastDequeueDuration_withDequeue_returnsTime) {
+ ANativeWindowBuffer* buffer;
+ int fd;
+ int result = ANativeWindow_dequeueBuffer(mWindow.get(), &buffer, &fd);
+ close(fd);
+ EXPECT_EQ(0, result);
+
+ result = ANativeWindow_getLastDequeueDuration(mWindow.get());
+ EXPECT_GT(result, 0);
+ EXPECT_EQ(result, mWindow->getLastDequeueDuration() / 1000);
+}
diff --git a/libs/nativewindow/tests/Android.bp b/libs/nativewindow/tests/Android.bp
index 20071be..cdb3d20 100644
--- a/libs/nativewindow/tests/Android.bp
+++ b/libs/nativewindow/tests/Android.bp
@@ -15,13 +15,22 @@
//
cc_test {
- name: "AHardwareBufferTest",
+ name: "libnativewindow_test",
+ test_suites: [
+ "device-tests",
+ ],
shared_libs: [
+ "libgui",
+ "liblog",
"libnativewindow",
+ "libsync",
+ "libutils",
"android.hardware.graphics.common@1.0",
],
srcs: [
"AHardwareBufferTest.cpp",
- "c_compatibility.c"],
+ "ANativeWindowTest.cpp",
+ "c_compatibility.c",
+ ],
cflags: ["-Wall", "-Werror"],
}
diff --git a/libs/nativewindow/tests/c_compatibility.c b/libs/nativewindow/tests/c_compatibility.c
index befd88f..aa9b4f7 100644
--- a/libs/nativewindow/tests/c_compatibility.c
+++ b/libs/nativewindow/tests/c_compatibility.c
@@ -16,6 +16,7 @@
#include <android/hardware_buffer.h>
#include <android/native_window.h>
+#include <apex/window.h>
#include <vndk/hardware_buffer.h>
#include <vndk/window.h>
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index f67e258..62856df 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -178,6 +178,10 @@
return status;
}
+Status<uint8_t> DisplayClient::GetDisplayIdentificationPort() {
+ return InvokeRemoteMethod<DisplayProtocol::GetDisplayIdentificationPort>();
+}
+
Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
const SurfaceAttributes& attributes) {
int error;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index f8f5b3d..81546ac 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -72,6 +72,7 @@
public:
pdx::Status<Metrics> GetDisplayMetrics();
pdx::Status<std::string> GetConfigurationData(ConfigFileType config_type);
+ pdx::Status<uint8_t> GetDisplayIdentificationPort();
pdx::Status<std::unique_ptr<IonBuffer>> SetupGlobalBuffer(
DvrGlobalBufferKey key, size_t size, uint64_t usage);
pdx::Status<void> DeleteGlobalBuffer(DvrGlobalBufferKey key);
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index 861dc6c..9f4cc4a 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -211,6 +211,7 @@
kOpGetSurfaceInfo,
kOpCreateQueue,
kOpSetAttributes,
+ kOpGetDisplayIdentificationPort,
};
// Aliases.
@@ -221,6 +222,8 @@
PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, Metrics(Void));
PDX_REMOTE_METHOD(GetConfigurationData, kOpGetConfigurationData,
std::string(ConfigFileType config_type));
+ PDX_REMOTE_METHOD(GetDisplayIdentificationPort,
+ kOpGetDisplayIdentificationPort, uint8_t(Void));
PDX_REMOTE_METHOD(SetupGlobalBuffer, kOpSetupGlobalBuffer,
LocalNativeBufferHandle(DvrGlobalBufferKey key, size_t size,
uint64_t usage));
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 2829353..4441672 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -35,7 +35,7 @@
]
sharedLibraries = [
- "android.frameworks.vr.composer@1.0",
+ "android.frameworks.vr.composer@2.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 8980a92..5a9360c 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -47,7 +47,8 @@
uint8_t port;
const auto error = hidl->getDisplayIdentificationData(
- primary_display_id, &port, &display_identification_data_);
+ primary_display_id, &display_identification_port_,
+ &display_identification_data_);
if (error != android::hardware::graphics::composer::V2_1::Error::NONE) {
if (error !=
android::hardware::graphics::composer::V2_1::Error::UNSUPPORTED) {
@@ -151,6 +152,11 @@
*this, &DisplayService::OnGetConfigurationData, message);
return {};
+ case DisplayProtocol::GetDisplayIdentificationPort::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::GetDisplayIdentificationPort>(
+ *this, &DisplayService::OnGetDisplayIdentificationPort, message);
+ return {};
+
case DisplayProtocol::CreateSurface::Opcode:
DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
*this, &DisplayService::OnCreateSurface, message);
@@ -238,6 +244,11 @@
return std::move(data);
}
+pdx::Status<uint8_t> DisplayService::OnGetDisplayIdentificationPort(
+ pdx::Message& /*message*/) {
+ return display_identification_port_;
+}
+
// Creates a new DisplaySurface and associates it with this channel. This may
// only be done once per channel.
Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index d45a61f..06ba566 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -82,6 +82,7 @@
pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
pdx::Status<std::string> OnGetConfigurationData(
pdx::Message& message, display::ConfigFileType config_type);
+ pdx::Status<uint8_t> OnGetDisplayIdentificationPort(pdx::Message& message);
pdx::Status<display::SurfaceInfo> OnCreateSurface(
pdx::Message& message, const display::SurfaceAttributes& attributes);
pdx::Status<BorrowedNativeBufferHandle> OnSetupGlobalBuffer(
@@ -121,6 +122,7 @@
void operator=(const DisplayService&) = delete;
DisplayIdentificationData display_identification_data_;
+ uint8_t display_identification_port_;
};
} // namespace dvr
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index e996be6..d1b4a4e 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -1379,6 +1379,9 @@
if (!_s.get())
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ if (n_rects < 0 || (n_rects > 0 && rects == NULL))
+ return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
+
egl_surface_t* const s = get_surface(draw);
if (CC_UNLIKELY(dp->traceGpuCompletion)) {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 438f8f3..93c738d 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -19,7 +19,7 @@
"-DEGL_EGLEXT_PROTOTYPES",
],
shared_libs: [
- "android.frameworks.vr.composer@1.0",
+ "android.frameworks.vr.composer@2.0",
"android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
@@ -58,6 +58,14 @@
"libutils",
"libSurfaceFlingerProp",
],
+ // VrComposer is not used when building surfaceflinger for vendors
+ target: {
+ vendor: {
+ exclude_shared_libs: [
+ "android.frameworks.vr.composer@2.0",
+ ],
+ },
+ },
static_libs: [
"libcompositionengine",
"libperfetto_client_experimental",
@@ -139,6 +147,7 @@
"DisplayHardware/VirtualDisplaySurface.cpp",
"Effects/Daltonizer.cpp",
"EventLog/EventLog.cpp",
+ "FrameTracer/FrameTracer.cpp",
"FrameTracker.cpp",
"Layer.cpp",
"LayerProtoHelper.cpp",
@@ -181,6 +190,17 @@
// can be easily replaced.
"SurfaceFlingerFactory.cpp",
],
+ cflags: [
+ "-DUSE_VR_COMPOSER=1",
+ ],
+ // VrComposer is not used when building surfaceflinger for vendors
+ target: {
+ vendor: {
+ cflags: [
+ "-DUSE_VR_COMPOSER=0",
+ ],
+ },
+ },
logtags: ["EventLog/EventLogTags.logtags"],
}
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a7970db..26abe1c 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() {
@@ -315,17 +318,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/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 580bde8..e49b65f 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -5,7 +5,7 @@
"-DLOG_TAG=\"CompositionEngine\"",
],
shared_libs: [
- "android.frameworks.vr.composer@1.0",
+ "android.frameworks.vr.composer@2.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 7f47a2e..e53d099 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -110,6 +110,7 @@
namespace impl {
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize)
: CommandWriterBase(initialMaxSize) {}
@@ -160,6 +161,7 @@
writeSigned(static_cast<int32_t>(metadata.format));
write64(metadata.usage);
}
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
Composer::Composer(const std::string& serviceName)
: mWriter(kWriterInitialSize),
@@ -198,12 +200,14 @@
LOG_ALWAYS_FATAL("failed to create composer client");
}
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
if (mIsUsingVrComposer) {
sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient);
if (vrClient == nullptr) {
LOG_ALWAYS_FATAL("failed to create vr composer client");
}
}
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
}
Composer::~Composer() = default;
@@ -565,17 +569,20 @@
const std::vector<IComposerClient::Rect>& damage)
{
mWriter.selectDisplay(display);
+
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
if (mIsUsingVrComposer && target.get()) {
IVrComposerClient::BufferMetadata metadata = {
- .width = target->getWidth(),
- .height = target->getHeight(),
- .stride = target->getStride(),
- .layerCount = target->getLayerCount(),
- .format = static_cast<types::V1_0::PixelFormat>(target->getPixelFormat()),
- .usage = target->getUsage(),
+ .width = target->getWidth(),
+ .height = target->getHeight(),
+ .stride = target->getStride(),
+ .layerCount = target->getLayerCount(),
+ .format = static_cast<types::V1_2::PixelFormat>(target->getPixelFormat()),
+ .usage = target->getUsage(),
};
mWriter.setClientTargetMetadata(metadata);
}
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
const native_handle_t* handle = nullptr;
if (target.get()) {
@@ -695,17 +702,20 @@
{
mWriter.selectDisplay(display);
mWriter.selectLayer(layer);
+
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
if (mIsUsingVrComposer && buffer.get()) {
IVrComposerClient::BufferMetadata metadata = {
- .width = buffer->getWidth(),
- .height = buffer->getHeight(),
- .stride = buffer->getStride(),
- .layerCount = buffer->getLayerCount(),
- .format = static_cast<types::V1_0::PixelFormat>(buffer->getPixelFormat()),
- .usage = buffer->getUsage(),
+ .width = buffer->getWidth(),
+ .height = buffer->getHeight(),
+ .stride = buffer->getStride(),
+ .layerCount = buffer->getLayerCount(),
+ .format = static_cast<types::V1_2::PixelFormat>(buffer->getPixelFormat()),
+ .usage = buffer->getUsage(),
};
mWriter.setLayerBufferMetadata(metadata);
}
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
const native_handle_t* handle = nullptr;
if (buffer.get()) {
@@ -823,6 +833,7 @@
return Error::NONE;
}
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
Error Composer::setLayerInfo(Display display, Layer layer, uint32_t type,
uint32_t appId)
{
@@ -833,6 +844,15 @@
}
return Error::NONE;
}
+#else
+Error Composer::setLayerInfo(Display display, Layer layer, uint32_t, uint32_t) {
+ if (mIsUsingVrComposer) {
+ mWriter.selectDisplay(display);
+ mWriter.selectLayer(layer);
+ }
+ return Error::NONE;
+}
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
Error Composer::execute()
{
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index c4e952b..9f6cac2 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -23,7 +23,9 @@
#include <utility>
#include <vector>
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
+#include <android/frameworks/vr/composer/2.0/IVrComposerClient.h>
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
#include <android/hardware/graphics/common/1.1/types.h>
#include <android/hardware/graphics/composer/2.3/IComposer.h>
#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
@@ -38,7 +40,9 @@
namespace Hwc2 {
-using frameworks::vr::composer::V1_0::IVrComposerClient;
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
+using frameworks::vr::composer::V2_0::IVrComposerClient;
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
namespace types = hardware::graphics::common;
@@ -418,6 +422,7 @@
Error setDisplayBrightness(Display display, float brightness) override;
private:
+#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
class CommandWriter : public CommandWriterBase {
public:
explicit CommandWriter(uint32_t initialMaxSize);
@@ -433,6 +438,13 @@
void writeBufferMetadata(
const IVrComposerClient::BufferMetadata& metadata);
};
+#else
+ class CommandWriter : public CommandWriterBase {
+ public:
+ explicit CommandWriter(uint32_t initialMaxSize) : CommandWriterBase(initialMaxSize) {}
+ ~CommandWriter() override {}
+ };
+#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
// Many public functions above simply write a command into the command
// queue to batch the calls. validateDisplay and presentDisplay will call
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
new file mode 100644
index 0000000..006dbfe
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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>
+#include <mutex>
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
+
+namespace android {
+
+void FrameTracer::initialize() {
+ std::call_once(mInitializationFlag, [this]() {
+ 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..d4dfab9
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.h
@@ -0,0 +1,106 @@
+/*
+ * 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;
+ std::once_flag mInitializationFlag;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b669421..5e5302d 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
// ---------------------------------------------------------------------------
@@ -1299,10 +1317,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,
@@ -1905,7 +1930,7 @@
InputWindowInfo info = mDrawingState.inputInfo;
if (info.displayId == ADISPLAY_ID_NONE) {
- info.displayId = mDrawingState.layerStack;
+ info.displayId = getLayerStack();
}
ui::Transform t = getTransform();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 02a7d36..1486efe 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 compositionengine::LayerFE {
@@ -580,6 +580,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;
@@ -906,6 +907,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/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8d9357a..eb52d3f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -512,6 +512,7 @@
}
// Content detection is on, find the appropriate refresh rate with minimal error
+ // TODO(b/139751853): Scan allowed refresh rates only (SurfaceFlinger::mAllowedDisplayConfigs)
const float rate = static_cast<float>(mFeatures.contentRefreshRate);
auto iter = min_element(mRefreshRateConfigs.getRefreshRates().cbegin(),
mRefreshRateConfigs.getRefreshRates().cend(),
@@ -541,6 +542,11 @@
return currRefreshRateType;
}
+Scheduler::RefreshRateType Scheduler::getPreferredRefreshRateType() {
+ std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ return mFeatures.refreshRateType;
+}
+
void Scheduler::changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent) {
std::lock_guard<std::mutex> lock(mCallbackLock);
if (mChangeRefreshRateCallback) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index c15f793..34e527c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -127,6 +127,9 @@
void dump(std::string&) const;
void dump(ConnectionHandle, std::string&) const;
+ // Get the appropriate refresh type for current conditions.
+ RefreshRateType getPreferredRefreshRateType();
+
private:
friend class TestableScheduler;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 11e9702..3498419 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");
@@ -2655,32 +2657,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;
@@ -4080,9 +4081,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);
}
}
}
@@ -4340,12 +4343,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);
@@ -5555,25 +5600,47 @@
}
}
+void SurfaceFlinger::setPreferredDisplayConfig() {
+ const auto& type = mScheduler->getPreferredRefreshRateType();
+ const auto& config = mRefreshRateConfigs.getRefreshRate(type);
+ if (config && isDisplayConfigAllowed(config->configId)) {
+ ALOGV("switching to Scheduler preferred config %d", config->configId);
+ setDesiredActiveConfig({type, config->configId, Scheduler::ConfigEvent::Changed});
+ } else {
+ // Set the highest allowed config by iterating backwards on available refresh rates
+ const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
+ for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
+ if (iter->second && isDisplayConfigAllowed(iter->second->configId)) {
+ ALOGV("switching to allowed config %d", iter->second->configId);
+ setDesiredActiveConfig({iter->first, iter->second->configId,
+ Scheduler::ConfigEvent::Changed});
+ }
+ }
+ }
+}
+
void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
const std::vector<int32_t>& allowedConfigs) {
if (!display->isPrimary()) {
return;
}
- ALOGV("Updating allowed configs");
- mAllowedDisplayConfigs = DisplayConfigs(allowedConfigs.begin(), allowedConfigs.end());
-
- // Set the highest allowed config by iterating backwards on available refresh rates
- const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
- for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
- if (iter->second && isDisplayConfigAllowed(iter->second->configId)) {
- ALOGV("switching to config %d", iter->second->configId);
- setDesiredActiveConfig(
- {iter->first, iter->second->configId, Scheduler::ConfigEvent::Changed});
- break;
- }
+ const auto allowedDisplayConfigs = DisplayConfigs(allowedConfigs.begin(),
+ allowedConfigs.end());
+ if (allowedDisplayConfigs == mAllowedDisplayConfigs) {
+ return;
}
+
+ ALOGV("Updating allowed configs");
+ mAllowedDisplayConfigs = std::move(allowedDisplayConfigs);
+
+ // TODO(b/140204874): This hack triggers a notification that something has changed, so
+ // that listeners that care about a change in allowed configs can get the notification.
+ // Giving current ActiveConfig so that most other listeners would just drop the event
+ mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
+ display->getActiveConfig());
+
+ setPreferredDisplayConfig();
}
status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToken,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 07efba9..f220c26 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;
@@ -528,6 +529,9 @@
// called on the main thread in response to setPowerMode()
void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
+ // Query the Scheduler or allowed display configs list for a matching config, and set it
+ void setPreferredDisplayConfig() REQUIRES(mStateLock);
+
// called on the main thread in response to setAllowedDisplayConfigs()
void setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
const std::vector<int32_t>& allowedConfigs)
@@ -863,8 +867,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 +990,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());
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 0e5faf4..4e461f9 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -12,8 +12,10 @@
],
shared_libs: [
- "android.frameworks.vr.composer@1.0",
+ "android.frameworks.vr.composer@2.0",
"android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.1-resources",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@3.0",
@@ -35,11 +37,11 @@
header_libs: [
"android.hardware.graphics.composer@2.1-command-buffer",
- "android.hardware.graphics.composer@2.1-hal",
+ "android.hardware.graphics.composer@2.3-hal",
],
export_header_lib_headers: [
- "android.hardware.graphics.composer@2.1-hal",
+ "android.hardware.graphics.composer@2.3-hal",
],
export_static_lib_headers: [
@@ -47,8 +49,10 @@
],
export_shared_lib_headers: [
- "android.frameworks.vr.composer@1.0",
+ "android.frameworks.vr.composer@2.0",
"android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
],
export_include_dirs: ["."],
@@ -105,8 +109,8 @@
"libvr_hwc-binder",
],
shared_libs: [
- "android.frameworks.vr.composer@1.0",
- "android.hardware.graphics.composer@2.1",
+ "android.frameworks.vr.composer@2.0",
+ "android.hardware.graphics.composer@2.3",
"libbase",
"libbinder",
"liblog",
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.cpp b/services/vr/hardware_composer/impl/vr_composer_client.cpp
index 786d5fa..36f6b32 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.cpp
+++ b/services/vr/hardware_composer/impl/vr_composer_client.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
+#include <android/frameworks/vr/composer/2.0/IVrComposerClient.h>
#include <hardware/gralloc.h>
#include <hardware/gralloc1.h>
#include <log/log.h>
@@ -27,8 +27,7 @@
namespace android {
namespace dvr {
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::frameworks::vr::composer::V1_0::IVrComposerClient;
+using android::frameworks::vr::composer::V2_0::IVrComposerClient;
VrComposerClient::VrComposerClient(dvr::VrHwc& hal)
: ComposerClient(&hal), mVrHal(hal) {
@@ -51,7 +50,8 @@
VrComposerClient::VrCommandEngine::~VrCommandEngine() {}
bool VrComposerClient::VrCommandEngine::executeCommand(
- IComposerClient::Command command, uint16_t length) {
+ hardware::graphics::composer::V2_1::IComposerClient::Command command,
+ uint16_t length) {
IVrComposerClient::VrCommand vrCommand =
static_cast<IVrComposerClient::VrCommand>(command);
switch (vrCommand) {
@@ -107,12 +107,14 @@
IVrComposerClient::BufferMetadata
VrComposerClient::VrCommandEngine::readBufferMetadata() {
IVrComposerClient::BufferMetadata metadata = {
- .width = read(),
- .height = read(),
- .stride = read(),
- .layerCount = read(),
- .format = static_cast<PixelFormat>(readSigned()),
- .usage = read64(),
+ .width = read(),
+ .height = read(),
+ .stride = read(),
+ .layerCount = read(),
+ .format =
+ static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(
+ readSigned()),
+ .usage = read64(),
};
return metadata;
}
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
index 0b7ce5e..1b2b5f4 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -17,10 +17,12 @@
#ifndef ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
#define ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <android/frameworks/vr/composer/2.0/IVrComposerClient.h>
+#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
#include <composer-hal/2.1/ComposerClient.h>
#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerClient.h>
+#include <composer-hal/2.3/ComposerClient.h>
namespace android {
namespace dvr {
@@ -28,8 +30,8 @@
class VrHwc;
using hardware::graphics::composer::V2_1::hal::ComposerCommandEngine;
-using hardware::graphics::composer::V2_1::hal::ComposerHal;
-using hardware::graphics::composer::V2_1::hal::detail::ComposerClientImpl;
+using hardware::graphics::composer::V2_3::hal::ComposerHal;
+using hardware::graphics::composer::V2_3::hal::detail::ComposerClientImpl;
using ComposerClient = ComposerClientImpl<IVrComposerClient, ComposerHal>;
@@ -44,8 +46,9 @@
explicit VrCommandEngine(VrComposerClient& client);
~VrCommandEngine() override;
- bool executeCommand(IComposerClient::Command command,
- uint16_t length) override;
+ bool executeCommand(
+ hardware::graphics::composer::V2_1::IComposerClient::Command command,
+ uint16_t length) override;
private:
bool executeSetLayerInfo(uint16_t length);
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index 7323277..e530b16 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -27,7 +27,7 @@
#include "vr_composer_client.h"
using namespace android::hardware::graphics::common::V1_0;
-using namespace android::hardware::graphics::composer::V2_1;
+using namespace android::hardware::graphics::composer::V2_3;
using android::base::StringPrintf;
using android::hardware::hidl_handle;
@@ -36,12 +36,12 @@
using android::hardware::Return;
using android::hardware::Void;
+namespace types = android::hardware::graphics::common;
+
namespace android {
namespace dvr {
namespace {
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
const Display kDefaultDisplayId = 1;
const Config kDefaultConfigId = 1;
@@ -269,7 +269,8 @@
// onHotplug() call, so it's important to release mutex_ here.
lock.unlock();
event_callback_->onHotplug(kDefaultDisplayId,
- IComposerCallback::Connection::CONNECTED);
+ hardware::graphics::composer::V2_1::
+ IComposerCallback::Connection::CONNECTED);
lock.lock();
UpdateVsyncCallbackEnabledLocked();
}
@@ -282,15 +283,6 @@
uint32_t VrHwc::getMaxVirtualDisplayCount() { return 1; }
-Error VrHwc::createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat* format, Display* outDisplay) {
- *format = PixelFormat::RGBA_8888;
- *outDisplay = display_count_;
- displays_[display_count_].reset(new HwcDisplay(width, height));
- display_count_++;
- return Error::NONE;
-}
-
Error VrHwc::destroyVirtualDisplay(Display display) {
std::lock_guard<std::mutex> guard(mutex_);
if (display == kDefaultDisplayId || displays_.erase(display) == 0)
@@ -332,24 +324,6 @@
return Error::NONE;
}
-Error VrHwc::getClientTargetSupport(Display display, uint32_t /* width */,
- uint32_t /* height */,
- PixelFormat /* format */,
- Dataspace /* dataspace */) {
- std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
- return Error::BAD_DISPLAY;
-
- return Error::NONE;
-}
-
-Error VrHwc::getColorModes(Display /* display */,
- hidl_vec<ColorMode>* outModes) {
- std::vector<ColorMode> color_modes(1, ColorMode::NATIVE);
- *outModes = hidl_vec<ColorMode>(color_modes);
- return Error::NONE;
-}
-
Error VrHwc::getDisplayAttribute(Display display, Config config,
IComposerClient::Attribute attribute,
int32_t* outValue) {
@@ -441,17 +415,6 @@
return Error::NONE;
}
-Error VrHwc::getHdrCapabilities(Display /* display */,
- hidl_vec<Hdr>* /* outTypes */,
- float* outMaxLuminance,
- float* outMaxAverageLuminance,
- float* outMinLuminance) {
- *outMaxLuminance = 0;
- *outMaxAverageLuminance = 0;
- *outMinLuminance = 0;
- return Error::NONE;
-}
-
Error VrHwc::setActiveConfig(Display display, Config config) {
std::lock_guard<std::mutex> guard(mutex_);
auto display_ptr = FindDisplay(display);
@@ -464,47 +427,6 @@
return Error::NONE;
}
-Error VrHwc::setColorMode(Display display, ColorMode mode) {
- std::lock_guard<std::mutex> guard(mutex_);
- auto display_ptr = FindDisplay(display);
- if (!display_ptr)
- return Error::BAD_DISPLAY;
-
- if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3)
- return Error::BAD_PARAMETER;
-
- display_ptr->set_color_mode(mode);
- return Error::NONE;
-}
-
-Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) {
- bool dozeSupported = false;
-
- Error dozeSupportError = getDozeSupport(display, &dozeSupported);
-
- if (dozeSupportError != Error::NONE)
- return dozeSupportError;
-
- std::lock_guard<std::mutex> guard(mutex_);
- auto display_ptr = FindDisplay(display);
- if (!display_ptr)
- return Error::BAD_DISPLAY;
-
- if (mode < IComposerClient::PowerMode::OFF ||
- mode > IComposerClient::PowerMode::DOZE_SUSPEND) {
- return Error::BAD_PARAMETER;
- }
-
- if (!dozeSupported &&
- (mode == IComposerClient::PowerMode::DOZE ||
- mode == IComposerClient::PowerMode::DOZE_SUSPEND)) {
- return Error::UNSUPPORTED;
- }
-
- display_ptr->set_power_mode(mode);
- return Error::NONE;
-}
-
Error VrHwc::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) {
std::lock_guard<std::mutex> guard(mutex_);
auto display_ptr = FindDisplay(display);
@@ -956,6 +878,23 @@
return Void();
}
+Return<void> VrHwc::createClient_2_3(IComposer::createClient_2_3_cb hidl_cb) {
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ Error status = Error::NONE;
+ sp<VrComposerClient> client;
+ if (!client_.promote().get()) {
+ client = new VrComposerClient(*this);
+ } else {
+ ALOGE("Already have a client");
+ status = Error::NO_RESOURCES;
+ }
+
+ client_ = client;
+ hidl_cb(status, client);
+ return Void();
+}
+
void VrHwc::ForceDisplaysRefresh() {
std::lock_guard<std::mutex> guard(mutex_);
if (event_callback_ != nullptr) {
@@ -1044,5 +983,196 @@
callback_ = callback;
}
+// composer::V2_2::ComposerHal
+Error VrHwc::setReadbackBuffer(Display display,
+ const native_handle_t* bufferHandle,
+ android::base::unique_fd fenceFd) {
+ return Error::NONE;
+}
+
+Error VrHwc::getReadbackBufferFence(Display display,
+ android::base::unique_fd* outFenceFd) {
+ return Error::NONE;
+}
+
+Error VrHwc::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+ types::V1_1::PixelFormat* format,
+ Display* outDisplay) {
+ *format = types::V1_1::PixelFormat::RGBA_8888;
+ *outDisplay = display_count_;
+ displays_[display_count_].reset(new HwcDisplay(width, height));
+ display_count_++;
+ return Error::NONE;
+}
+
+Error VrHwc::setPowerMode_2_2(Display display,
+ IComposerClient::PowerMode mode) {
+ bool dozeSupported = false;
+
+ Error dozeSupportError = getDozeSupport(display, &dozeSupported);
+
+ if (dozeSupportError != Error::NONE)
+ return dozeSupportError;
+
+ std::lock_guard<std::mutex> guard(mutex_);
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
+ return Error::BAD_DISPLAY;
+
+ if (mode < IComposerClient::PowerMode::OFF ||
+ mode > IComposerClient::PowerMode::DOZE_SUSPEND) {
+ return Error::BAD_PARAMETER;
+ }
+
+ if (!dozeSupported && (mode == IComposerClient::PowerMode::DOZE ||
+ mode == IComposerClient::PowerMode::DOZE_SUSPEND)) {
+ return Error::UNSUPPORTED;
+ }
+
+ display_ptr->set_power_mode(mode);
+ return Error::NONE;
+}
+
+Error VrHwc::setLayerFloatColor(Display display, Layer layer,
+ IComposerClient::FloatColor color) {
+ return Error::NONE;
+}
+
+Error VrHwc::getRenderIntents(Display display, types::V1_1::ColorMode mode,
+ std::vector<RenderIntent>* outIntents) {
+ return Error::NONE;
+}
+
+std::array<float, 16> VrHwc::getDataspaceSaturationMatrix(
+ types::V1_1::Dataspace dataspace) {
+ return {};
+}
+
+// composer::V2_3::ComposerHal
+Error VrHwc::getHdrCapabilities_2_3(Display /*display*/,
+ hidl_vec<Hdr>* /*outTypes*/,
+ float* outMaxLuminance,
+ float* outMaxAverageLuminance,
+ float* outMinLuminance) {
+ *outMaxLuminance = 0;
+ *outMaxAverageLuminance = 0;
+ *outMinLuminance = 0;
+ return Error::NONE;
+}
+
+Error VrHwc::setLayerPerFrameMetadata_2_3(
+ Display display, Layer layer,
+ const std::vector<IComposerClient::PerFrameMetadata>& metadata) {
+ return Error::NONE;
+}
+
+Error VrHwc::getPerFrameMetadataKeys_2_3(
+ Display display,
+ std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) {
+ return Error::NONE;
+}
+
+Error VrHwc::setColorMode_2_3(Display display, ColorMode mode,
+ RenderIntent intent) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
+ return Error::BAD_DISPLAY;
+
+ if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3)
+ return Error::BAD_PARAMETER;
+
+ display_ptr->set_color_mode(mode);
+ return Error::NONE;
+}
+
+Error VrHwc::getRenderIntents_2_3(Display display, ColorMode mode,
+ std::vector<RenderIntent>* outIntents) {
+ return Error::NONE;
+}
+
+Error VrHwc::getColorModes_2_3(Display display, hidl_vec<ColorMode>* outModes) {
+ return Error::NONE;
+}
+
+Error VrHwc::getClientTargetSupport_2_3(Display display, uint32_t width,
+ uint32_t height, PixelFormat format,
+ Dataspace dataspace) {
+ return Error::NONE;
+}
+
+Error VrHwc::getReadbackBufferAttributes_2_3(Display display,
+ PixelFormat* outFormat,
+ Dataspace* outDataspace) {
+ return Error::NONE;
+}
+
+Error VrHwc::getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) {
+ int error = 0;
+ auto display_client = display::DisplayClient::Create(&error);
+ if (!display_client) {
+ ALOGE("Could not connect to display service : %s(%d)", strerror(error),
+ error);
+ return Error::BAD_CONFIG;
+ }
+ auto edid_data = display_client->GetConfigurationData(
+ display::ConfigFileType::kDeviceEdid);
+ auto display_identification_port =
+ display_client->GetDisplayIdentificationPort();
+ *outPort = display_identification_port.get();
+
+ std::copy(edid_data.get().begin(), edid_data.get().end(),
+ std::back_inserter(*outData));
+ return Error::NONE;
+}
+
+Error VrHwc::setLayerColorTransform(Display display, Layer layer,
+ const float* matrix) {
+ return Error::NONE;
+}
+
+Error VrHwc::getDisplayedContentSamplingAttributes(
+ Display display, PixelFormat& format, Dataspace& dataspace,
+ hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask) {
+ return Error::NONE;
+}
+
+Error VrHwc::setDisplayedContentSamplingEnabled(
+ Display display, IComposerClient::DisplayedContentSampling enable,
+ hidl_bitfield<IComposerClient::FormatColorComponent> componentMask,
+ uint64_t maxFrames) {
+ return Error::NONE;
+}
+
+Error VrHwc::getDisplayedContentSample(Display display, uint64_t maxFrames,
+ uint64_t timestamp, uint64_t& frameCount,
+ hidl_vec<uint64_t>& sampleComponent0,
+ hidl_vec<uint64_t>& sampleComponent1,
+ hidl_vec<uint64_t>& sampleComponent2,
+ hidl_vec<uint64_t>& sampleComponent3) {
+ return Error::NONE;
+}
+
+Error VrHwc::getDisplayCapabilities(
+ Display display,
+ std::vector<IComposerClient::DisplayCapability>* outCapabilities) {
+ return Error::NONE;
+}
+
+Error VrHwc::setLayerPerFrameMetadataBlobs(
+ Display display, Layer layer,
+ std::vector<IComposerClient::PerFrameMetadataBlob>& blobs) {
+ return Error::NONE;
+}
+
+Error VrHwc::getDisplayBrightnessSupport(Display display, bool* outSupport) {
+ return Error::NONE;
+}
+
+Error VrHwc::setDisplayBrightness(Display display, float brightness) {
+ return Error::NONE;
+}
+
} // namespace dvr
} // namespace android
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index 15358c5..3e3a630 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -17,9 +17,9 @@
#define ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_HWC_H
#include <android-base/unique_fd.h>
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-hal/2.1/ComposerHal.h>
+#include <android/frameworks/vr/composer/2.0/IVrComposerClient.h>
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <composer-hal/2.3/ComposerHal.h>
#include <private/dvr/vsync_service.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
@@ -28,15 +28,21 @@
#include <mutex>
#include <unordered_map>
-using namespace android::frameworks::vr::composer::V1_0;
+using namespace android::frameworks::vr::composer::V2_0;
using namespace android::hardware::graphics::common::V1_0;
-using namespace android::hardware::graphics::composer::V2_1;
+using namespace android::hardware::graphics::composer::V2_3;
+using android::hardware::hidl_bitfield;
using android::hardware::hidl_handle;
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using android::hardware::Return;
using android::hardware::Void;
+using android::hardware::graphics::composer::V2_1::Config;
+using android::hardware::graphics::composer::V2_1::Display;
+using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_1::Layer;
+using android::hardware::graphics::composer::V2_3::IComposerClient;
namespace android {
@@ -46,16 +52,23 @@
class VrComposerClient;
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::composer::V2_1::hal::ComposerHal;
+using android::hardware::graphics::composer::V2_3::hal::ComposerHal;
+
+namespace types = android::hardware::graphics::common;
+
+using types::V1_1::RenderIntent;
+using types::V1_2::ColorMode;
+using types::V1_2::Dataspace;
+using types::V1_2::Hdr;
+using types::V1_2::PixelFormat;
class ComposerView {
public:
struct ComposerLayer {
- using Recti = hardware::graphics::composer::V2_1::IComposerClient::Rect;
- using Rectf = hardware::graphics::composer::V2_1::IComposerClient::FRect;
+ using Recti = hardware::graphics::composer::V2_3::IComposerClient::Rect;
+ using Rectf = hardware::graphics::composer::V2_3::IComposerClient::FRect;
using BlendMode =
- hardware::graphics::composer::V2_1::IComposerClient::BlendMode;
+ hardware::graphics::composer::V2_3::IComposerClient::BlendMode;
Layer id;
sp<GraphicBuffer> buffer;
@@ -111,7 +124,7 @@
struct HwcLayer {
using Composition =
- hardware::graphics::composer::V2_1::IComposerClient::Composition;
+ hardware::graphics::composer::V2_3::IComposerClient::Composition;
explicit HwcLayer(Layer new_id) { info.id = new_id; }
@@ -205,90 +218,148 @@
Display display, Layer layer,
const IVrComposerClient::BufferMetadata& metadata);
- // ComposerHal
+ // composer::V2_1::ComposerHal
bool hasCapability(hwc2_capability_t capability) override;
std::string dumpDebugInfo() override { return {}; }
- void registerEventCallback(EventCallback* callback) override;
+
+ void registerEventCallback(ComposerHal::EventCallback* callback) override;
void unregisterEventCallback() override;
uint32_t getMaxVirtualDisplayCount() override;
- Error createVirtualDisplay(uint32_t width, uint32_t height,
- PixelFormat* format, Display* outDisplay) override;
Error destroyVirtualDisplay(Display display) override;
Error createLayer(Display display, Layer* outLayer) override;
Error destroyLayer(Display display, Layer layer) override;
Error getActiveConfig(Display display, Config* outConfig) override;
- Error getClientTargetSupport(Display display,
- uint32_t width, uint32_t height,
- PixelFormat format, Dataspace dataspace) override;
- Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) override;
Error getDisplayAttribute(Display display, Config config,
- IComposerClient::Attribute attribute, int32_t* outValue) override;
+ IComposerClient::Attribute attribute,
+ int32_t* outValue) override;
Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) override;
Error getDisplayName(Display display, hidl_string* outName) override;
Error getDisplayType(Display display,
- IComposerClient::DisplayType* outType) override;
+ IComposerClient::DisplayType* outType) override;
Error getDozeSupport(Display display, bool* outSupport) override;
- Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
- float* outMaxLuminance, float* outMaxAverageLuminance,
- float* outMinLuminance) override;
Error setActiveConfig(Display display, Config config) override;
- Error setColorMode(Display display, ColorMode mode) override;
- Error setPowerMode(Display display, IComposerClient::PowerMode mode) override;
Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override;
Error setColorTransform(Display display, const float* matrix,
- int32_t hint) override;
+ int32_t hint) override;
Error setClientTarget(Display display, buffer_handle_t target,
- int32_t acquireFence, int32_t dataspace,
- const std::vector<hwc_rect_t>& damage) override;
+ int32_t acquireFence, int32_t dataspace,
+ const std::vector<hwc_rect_t>& damage) override;
Error setOutputBuffer(Display display, buffer_handle_t buffer,
- int32_t releaseFence) override;
- Error validateDisplay(Display display,
- std::vector<Layer>* outChangedLayers,
- std::vector<IComposerClient::Composition>* outCompositionTypes,
- uint32_t* outDisplayRequestMask,
- std::vector<Layer>* outRequestedLayers,
- std::vector<uint32_t>* outRequestMasks) override;
+ int32_t releaseFence) override;
+ Error validateDisplay(
+ Display display, std::vector<Layer>* outChangedLayers,
+ std::vector<IComposerClient::Composition>* outCompositionTypes,
+ uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
+ std::vector<uint32_t>* outRequestMasks) override;
Error acceptDisplayChanges(Display display) override;
Error presentDisplay(Display display, int32_t* outPresentFence,
- std::vector<Layer>* outLayers,
- std::vector<int32_t>* outReleaseFences) override;
+ std::vector<Layer>* outLayers,
+ std::vector<int32_t>* outReleaseFences) override;
- Error setLayerCursorPosition(Display display, Layer layer,
- int32_t x, int32_t y) override;
- Error setLayerBuffer(Display display, Layer layer,
- buffer_handle_t buffer, int32_t acquireFence) override;
+ Error setLayerCursorPosition(Display display, Layer layer, int32_t x,
+ int32_t y) override;
+ Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+ int32_t acquireFence) override;
Error setLayerSurfaceDamage(Display display, Layer layer,
- const std::vector<hwc_rect_t>& damage) override;
+ const std::vector<hwc_rect_t>& damage) override;
Error setLayerBlendMode(Display display, Layer layer, int32_t mode) override;
Error setLayerColor(Display display, Layer layer,
- IComposerClient::Color color) override;
+ IComposerClient::Color color) override;
Error setLayerCompositionType(Display display, Layer layer,
- int32_t type) override;
+ int32_t type) override;
Error setLayerDataspace(Display display, Layer layer,
- int32_t dataspace) override;
+ int32_t dataspace) override;
Error setLayerDisplayFrame(Display display, Layer layer,
- const hwc_rect_t& frame) override;
+ const hwc_rect_t& frame) override;
Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override;
Error setLayerSidebandStream(Display display, Layer layer,
- buffer_handle_t stream) override;
+ buffer_handle_t stream) override;
Error setLayerSourceCrop(Display display, Layer layer,
- const hwc_frect_t& crop) override;
+ const hwc_frect_t& crop) override;
Error setLayerTransform(Display display, Layer layer,
- int32_t transform) override;
+ int32_t transform) override;
Error setLayerVisibleRegion(Display display, Layer layer,
- const std::vector<hwc_rect_t>& visible) override;
+ const std::vector<hwc_rect_t>& visible) override;
Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
+ // composer::V2_2::ComposerHal
+ Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+ android::base::unique_fd fenceFd) override;
+ Error getReadbackBufferFence(Display display,
+ android::base::unique_fd* outFenceFd) override;
+ Error createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+ types::V1_1::PixelFormat* format,
+ Display* outDisplay) override;
+ Error setPowerMode_2_2(Display display,
+ IComposerClient::PowerMode mode) override;
+ Error setLayerFloatColor(Display display, Layer layer,
+ IComposerClient::FloatColor color) override;
+ Error getRenderIntents(Display display, types::V1_1::ColorMode mode,
+ std::vector<RenderIntent>* outIntents) override;
+ std::array<float, 16> getDataspaceSaturationMatrix(
+ types::V1_1::Dataspace dataspace) override;
+
+ // composer::V2_3::ComposerHal
+ Error getHdrCapabilities_2_3(Display display, hidl_vec<Hdr>* outTypes,
+ float* outMaxLuminance,
+ float* outMaxAverageLuminance,
+ float* outMinLuminance) override;
+ Error setLayerPerFrameMetadata_2_3(
+ Display display, Layer layer,
+ const std::vector<IComposerClient::PerFrameMetadata>& metadata) override;
+ Error getPerFrameMetadataKeys_2_3(
+ Display display,
+ std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override;
+ Error setColorMode_2_3(Display display, ColorMode mode,
+ RenderIntent intent) override;
+ Error getRenderIntents_2_3(Display display, ColorMode mode,
+ std::vector<RenderIntent>* outIntents) override;
+ Error getColorModes_2_3(Display display,
+ hidl_vec<ColorMode>* outModes) override;
+ Error getClientTargetSupport_2_3(Display display, uint32_t width,
+ uint32_t height, PixelFormat format,
+ Dataspace dataspace) override;
+ Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat,
+ Dataspace* outDataspace) override;
+ Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) override;
+ Error setLayerColorTransform(Display display, Layer layer,
+ const float* matrix) override;
+ Error getDisplayedContentSamplingAttributes(
+ Display display, PixelFormat& format, Dataspace& dataspace,
+ hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask)
+ override;
+ Error setDisplayedContentSamplingEnabled(
+ Display display, IComposerClient::DisplayedContentSampling enable,
+ hidl_bitfield<IComposerClient::FormatColorComponent> componentMask,
+ uint64_t maxFrames) override;
+ Error getDisplayedContentSample(
+ Display display, uint64_t maxFrames, uint64_t timestamp,
+ uint64_t& frameCount, hidl_vec<uint64_t>& sampleComponent0,
+ hidl_vec<uint64_t>& sampleComponent1,
+ hidl_vec<uint64_t>& sampleComponent2,
+ hidl_vec<uint64_t>& sampleComponent3) override;
+ Error getDisplayCapabilities(Display display,
+ std::vector<IComposerClient::DisplayCapability>*
+ outCapabilities) override;
+ Error setLayerPerFrameMetadataBlobs(
+ Display display, Layer layer,
+ std::vector<IComposerClient::PerFrameMetadataBlob>& blobs) override;
+ Error getDisplayBrightnessSupport(Display display, bool* outSupport) override;
+ Error setDisplayBrightness(Display display, float brightness) override;
+
// IComposer:
Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
Return<void> createClient(createClient_cb hidl_cb) override;
+ Return<void> createClient_2_3(
+ IComposer::createClient_2_3_cb hidl_cb) override;
// ComposerView:
void ForceDisplaysRefresh() override;