Merge changes I6c75d89d,I265ec54a
* changes:
Clean up KawaseBlurFilter
Split BlurFilter into interface + implementation
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index e3c4ede..01c4723 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -265,6 +265,22 @@
chmod 0666 /sys/kernel/tracing/per_cpu/cpu14/trace
chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu15/trace
chmod 0666 /sys/kernel/tracing/per_cpu/cpu15/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu23/trace
+ chmod 0666 /sys/kernel/tracing/per_cpu/cpu23/trace
# Only create the tracing instance if persist.mm_events.enabled
# Attempting to remove the tracing instance after it has been created
@@ -337,6 +353,22 @@
chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu14/trace
chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu15/trace
chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu15/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu16/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu17/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu18/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu19/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu20/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu21/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu22/trace
+ chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu23/trace
+ chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu23/trace
on property:persist.debug.atrace.boottrace=1
start boottrace
diff --git a/cmds/rss_hwm_reset/rss_hwm_reset.rc b/cmds/rss_hwm_reset/rss_hwm_reset.rc
index fbbc820..271cbf8 100644
--- a/cmds/rss_hwm_reset/rss_hwm_reset.rc
+++ b/cmds/rss_hwm_reset/rss_hwm_reset.rc
@@ -18,7 +18,7 @@
oneshot
user nobody
group nobody readproc
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
capabilities DAC_OVERRIDE
on property:sys.rss_hwm_reset.on=1
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 0b00c2d..fdbe85b 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -77,6 +77,9 @@
bool wantsUsage = false;
int result = 0;
+ /* Strip path off the program name. */
+ char* prog_name = basename(argv[0]);
+
while (1) {
int ic = getopt(argc, argv, "h?");
if (ic < 0)
@@ -88,7 +91,7 @@
wantsUsage = true;
break;
default:
- aerr << "service: Unknown option -" << ic << endl;
+ aerr << prog_name << ": Unknown option -" << ic << endl;
wantsUsage = true;
result = 10;
break;
@@ -103,7 +106,7 @@
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
if (sm == nullptr) {
- aerr << "service: Unable to get default service manager!" << endl;
+ aerr << prog_name << ": Unable to get default service manager!" << endl;
return 20;
}
@@ -117,7 +120,7 @@
aout << "Service " << argv[optind] <<
(service == nullptr ? ": not found" : ": found") << endl;
} else {
- aerr << "service: No service specified for check" << endl;
+ aerr << prog_name << ": No service specified for check" << endl;
wantsUsage = true;
result = 10;
}
@@ -152,7 +155,7 @@
if (strcmp(argv[optind], "i32") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no integer supplied for 'i32'" << endl;
+ aerr << prog_name << ": no integer supplied for 'i32'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -161,7 +164,7 @@
} else if (strcmp(argv[optind], "i64") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no integer supplied for 'i64'" << endl;
+ aerr << prog_name << ": no integer supplied for 'i64'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -170,7 +173,7 @@
} else if (strcmp(argv[optind], "s16") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no string supplied for 's16'" << endl;
+ aerr << prog_name << ": no string supplied for 's16'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -179,7 +182,7 @@
} else if (strcmp(argv[optind], "f") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no number supplied for 'f'" << endl;
+ aerr << prog_name << ": no number supplied for 'f'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -188,7 +191,7 @@
} else if (strcmp(argv[optind], "d") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no number supplied for 'd'" << endl;
+ aerr << prog_name << ": no number supplied for 'd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -200,7 +203,7 @@
} else if (strcmp(argv[optind], "fd") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no path supplied for 'fd'" << endl;
+ aerr << prog_name << ": no path supplied for 'fd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -208,7 +211,7 @@
const char *path = argv[optind++];
int fd = open(path, O_RDONLY);
if (fd < 0) {
- aerr << "service: could not open '" << path << "'" << endl;
+ aerr << prog_name << ": could not open '" << path << "'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -217,7 +220,7 @@
} else if (strcmp(argv[optind], "afd") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no path supplied for 'afd'" << endl;
+ aerr << prog_name << ": no path supplied for 'afd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -226,7 +229,8 @@
int fd = open(path, O_RDONLY);
struct stat statbuf;
if (fd < 0 || fstat(fd, &statbuf) != 0) {
- aerr << "service: could not open or stat '" << path << "'" << endl;
+ aerr << prog_name << ": could not open or stat"
+ << " '" << path << "'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -240,7 +244,8 @@
} else if (strcmp(argv[optind], "nfd") == 0) {
optind++;
if (optind >= argc) {
- aerr << "service: no file descriptor supplied for 'nfd'" << endl;
+ aerr << prog_name << ": no file descriptor supplied for"
+ << " 'nfd'" << endl;
wantsUsage = true;
result = 10;
break;
@@ -327,7 +332,7 @@
// for now just set the extra field to be null.
data.writeInt32(-1);
} else {
- aerr << "service: unknown option " << argv[optind] << endl;
+ aerr << prog_name << ": unknown option " << argv[optind] << endl;
wantsUsage = true;
result = 10;
break;
@@ -337,44 +342,44 @@
service->transact(code, data, &reply);
aout << "Result: " << reply << endl;
} else {
- aerr << "service: Service " << argv[serviceArg]
+ aerr << prog_name << ": Service " << argv[serviceArg]
<< " does not exist" << endl;
result = 10;
}
} else {
if (optind < argc) {
- aerr << "service: No service specified for call" << endl;
+ aerr << prog_name << ": No service specified for call" << endl;
} else {
- aerr << "service: No code specified for call" << endl;
+ aerr << prog_name << ": No code specified for call" << endl;
}
wantsUsage = true;
result = 10;
}
} else {
- aerr << "service: Unknown command " << argv[optind] << endl;
+ aerr << prog_name << ": Unknown command " << argv[optind] << endl;
wantsUsage = true;
result = 10;
}
}
if (wantsUsage) {
- aout << "Usage: service [-h|-?]\n"
- " service list\n"
- " service check SERVICE\n"
- " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null"
- " | fd f | nfd n | afd f ] ...\n"
+ aout << "Usage: " << prog_name << " [-h|-?]\n"
+ " " << prog_name << " list\n"
+ " " << prog_name << " check SERVICE\n"
+ " " << prog_name << " call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR"
+ " | null | fd f | nfd n | afd f ] ...\n"
"Options:\n"
" i32: Write the 32-bit integer N into the send parcel.\n"
" i64: Write the 64-bit integer N into the send parcel.\n"
- " f: Write the 32-bit single-precision number N into the send parcel.\n"
- " d: Write the 64-bit double-precision number N into the send parcel.\n"
+ " f: Write the 32-bit single-precision number N into the send parcel.\n"
+ " d: Write the 64-bit double-precision number N into the send parcel.\n"
" s16: Write the UTF-16 string STR into the send parcel.\n"
" null: Write a null binder into the send parcel.\n"
- " fd: Write a file descriptor for the file f to the send parcel.\n"
- " nfd: Write file descriptor n to the send parcel.\n"
- " afd: Write an ashmem file descriptor for a region containing the data from"
- " file f to the send parcel.\n";
-// " intent: Write and Intent int the send parcel. ARGS can be\n"
+ " fd: Write a file descriptor for the file f into the send parcel.\n"
+ " nfd: Write the file descriptor n into the send parcel.\n"
+ " afd: Write an ashmem file descriptor for a region containing the data from\n"
+ " file f into the send parcel.\n";
+// " intent: Write an Intent into the send parcel. ARGS can be\n"
// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
return result;
}
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 6d5070f..0dd29e0 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -9,5 +9,5 @@
onrestart class_restart main
onrestart class_restart hal
onrestart class_restart early_hal
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
shutdown critical
diff --git a/cmds/servicemanager/vndservicemanager.rc b/cmds/servicemanager/vndservicemanager.rc
index 756f6c3..c9305a1 100644
--- a/cmds/servicemanager/vndservicemanager.rc
+++ b/cmds/servicemanager/vndservicemanager.rc
@@ -2,7 +2,7 @@
class core
user system
group system readproc
- writepid /dev/cpuset/system-background/tasks
+ task_profiles ServiceCapacityLow
onrestart class_restart main
onrestart class_restart hal
onrestart class_restart early_hal
diff --git a/include/input/Input.h b/include/input/Input.h
index 5015e68..54c7114 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -803,6 +803,9 @@
static vec2 calculateTransformedXY(uint32_t source, const ui::Transform&, const vec2& xy);
+ static float calculateTransformedAxisValue(int32_t axis, uint32_t source, const ui::Transform&,
+ const PointerCoords&);
+
protected:
int32_t mAction;
int32_t mActionButton;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2ecb895..56cf76f 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -331,6 +331,7 @@
"libbase",
"libbinder",
"libbinder_ndk",
+ "liblog",
"libutils",
],
export_include_dirs: ["include_rpc_unstable"],
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index d3eef4e..ec9d554 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -547,7 +547,6 @@
AutoMutex _l(e->mLock);
auto rpcServer = RpcServer::make();
LOG_ALWAYS_FATAL_IF(rpcServer == nullptr, "RpcServer::make returns null");
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
auto link = sp<RpcServerLink>::make(rpcServer, keepAliveBinder, weakThis);
if (auto status = keepAliveBinder->linkToDeath(link, nullptr, 0); status != OK) {
ALOGE("%s: keepAliveBinder->linkToDeath returns %s", __PRETTY_FUNCTION__,
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 4edc202..93ed50e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -58,10 +58,6 @@
return sp<RpcServer>::make(std::move(ctx));
}
-void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
- mAgreedExperimental = true;
-}
-
status_t RpcServer::setupUnixDomainServer(const char* path) {
return setupSocketServer(UnixSocketAddress(path));
}
@@ -163,14 +159,12 @@
}
void RpcServer::start() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
LOG_ALWAYS_FATAL_IF(mJoinThread.get(), "Already started!");
mJoinThread = std::make_unique<std::thread>(&joinRpcServer, sp<RpcServer>::fromExisting(this));
}
void RpcServer::join() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
{
std::lock_guard<std::mutex> _l(mLock);
@@ -274,9 +268,6 @@
void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
const sockaddr_storage addr, socklen_t addrLen) {
- // TODO(b/183988761): cannot trust this simple ID
- LOG_ALWAYS_FATAL_IF(!server->mAgreedExperimental, "no!");
-
// mShutdownTrigger can only be cleared once connection threads have joined.
// It must be set before this thread is started
LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr);
@@ -506,19 +497,16 @@
}
bool RpcServer::hasServer() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
return mServer.ok();
}
unique_fd RpcServer::releaseServer() {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
return std::move(mServer);
}
status_t RpcServer::setupExternalServer(base::unique_fd serverFd) {
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
std::lock_guard<std::mutex> _l(mLock);
if (mServer.ok()) {
ALOGE("Each RpcServer can only have one server.");
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 137411b..53c9b78 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -688,7 +688,8 @@
status_t status = OK;
if (init) {
- mRpcBinderState->sendConnectionInit(connection, sp<RpcSession>::fromExisting(this));
+ status =
+ mRpcBinderState->sendConnectionInit(connection, sp<RpcSession>::fromExisting(this));
}
{
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index 50de22b..dba0a43 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -60,20 +60,21 @@
RpcState();
~RpcState();
- status_t readNewSessionResponse(const sp<RpcSession::RpcConnection>& connection,
- const sp<RpcSession>& session, uint32_t* version);
- status_t sendConnectionInit(const sp<RpcSession::RpcConnection>& connection,
- const sp<RpcSession>& session);
- status_t readConnectionInit(const sp<RpcSession::RpcConnection>& connection,
- const sp<RpcSession>& session);
+ [[nodiscard]] status_t readNewSessionResponse(const sp<RpcSession::RpcConnection>& connection,
+ const sp<RpcSession>& session, uint32_t* version);
+ [[nodiscard]] status_t sendConnectionInit(const sp<RpcSession::RpcConnection>& connection,
+ const sp<RpcSession>& session);
+ [[nodiscard]] status_t readConnectionInit(const sp<RpcSession::RpcConnection>& connection,
+ const sp<RpcSession>& session);
// TODO(b/182940634): combine some special transactions into one "getServerInfo" call?
sp<IBinder> getRootObject(const sp<RpcSession::RpcConnection>& connection,
const sp<RpcSession>& session);
- status_t getMaxThreads(const sp<RpcSession::RpcConnection>& connection,
- const sp<RpcSession>& session, size_t* maxThreadsOut);
- status_t getSessionId(const sp<RpcSession::RpcConnection>& connection,
- const sp<RpcSession>& session, std::vector<uint8_t>* sessionIdOut);
+ [[nodiscard]] status_t getMaxThreads(const sp<RpcSession::RpcConnection>& connection,
+ const sp<RpcSession>& session, size_t* maxThreadsOut);
+ [[nodiscard]] status_t getSessionId(const sp<RpcSession::RpcConnection>& connection,
+ const sp<RpcSession>& session,
+ std::vector<uint8_t>* sessionIdOut);
[[nodiscard]] status_t transact(const sp<RpcSession::RpcConnection>& connection,
const sp<IBinder>& address, uint32_t code, const Parcel& data,
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 04c6b59..aaa812b 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -25,10 +25,6 @@
#include <mutex>
#include <thread>
-// WARNING: This is a feature which is still in development, and it is subject
-// to radical change. Any production use of this may subject your code to any
-// number of problems.
-
namespace android {
class FdTrigger;
@@ -99,8 +95,6 @@
*/
[[nodiscard]] status_t setupExternalServer(base::unique_fd serverFd);
- void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
-
/**
* This must be called before adding a client session.
*
@@ -185,10 +179,9 @@
static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
const sockaddr_storage addr, socklen_t addrLen);
- status_t setupSocketServer(const RpcSocketAddress& address);
+ [[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
const std::unique_ptr<RpcTransportCtx> mCtx;
- bool mAgreedExperimental = false;
size_t mMaxThreads = 1;
std::optional<uint32_t> mProtocolVersion;
base::unique_fd mServer; // socket we are accepting sessions on
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index f9b733d..1bc8464 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -26,10 +26,6 @@
#include <thread>
#include <vector>
-// WARNING: This is a feature which is still in development, and it is subject
-// to radical change. Any production use of this may subject your code to any
-// number of problems.
-
namespace android {
class Parcel;
@@ -140,7 +136,7 @@
* Query the other side of the session for the maximum number of threads
* it supports (maximum number of concurrent non-nested synchronous transactions)
*/
- status_t getRemoteMaxThreads(size_t* maxThreads);
+ [[nodiscard]] status_t getRemoteMaxThreads(size_t* maxThreads);
/**
* See RpcTransportCtx::getCertificate
@@ -220,7 +216,7 @@
bool allowNested = false;
};
- status_t readId();
+ [[nodiscard]] status_t readId();
// A thread joining a server must always call these functions in order, and
// cleanup is only programmed once into join. These are in separate
@@ -262,7 +258,7 @@
std::unique_ptr<RpcTransport> rpcTransport);
[[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection);
- status_t initShutdownTrigger();
+ [[nodiscard]] status_t initShutdownTrigger();
enum class ConnectionUse {
CLIENT,
@@ -273,8 +269,8 @@
// Object representing exclusive access to a connection.
class ExclusiveConnection {
public:
- static status_t find(const sp<RpcSession>& session, ConnectionUse use,
- ExclusiveConnection* connection);
+ [[nodiscard]] static status_t find(const sp<RpcSession>& session, ConnectionUse use,
+ ExclusiveConnection* connection);
~ExclusiveConnection();
const sp<RpcConnection>& get() { return mConnection; }
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index 08f5eed..34f1cbf 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -16,6 +16,8 @@
#pragma once
+#include <sys/socket.h>
+
extern "C" {
struct AIBinder;
@@ -30,6 +32,12 @@
bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
void* param);
+// Starts an RPC server on a given port and a given root IBinder object.
+// This function sets up the server, calls readyCallback with a given param, and
+// then joins before returning.
+bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
+ void* factoryContext, unsigned int port);
+
AIBinder* RpcClient(unsigned int cid, unsigned int port);
// Connect to an RPC server with preconnected file descriptors.
diff --git a/libs/binder/include_tls/binder/RpcAuth.h b/libs/binder/include_tls/binder/RpcAuth.h
index 4c2f296..ab64828 100644
--- a/libs/binder/include_tls/binder/RpcAuth.h
+++ b/libs/binder/include_tls/binder/RpcAuth.h
@@ -40,7 +40,7 @@
// - SSL_CTX_use_certificate
// - SSL_CTX_set*_chain
// - SSL_CTX_add0_chain_cert
- virtual status_t configure(SSL_CTX* ctx) = 0;
+ [[nodiscard]] virtual status_t configure(SSL_CTX* ctx) = 0;
};
} // namespace android
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index cad55fb..bf2b25b 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -19,6 +19,7 @@
#include <android/binder_libbinder.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
+#include <linux/vm_sockets.h>
using android::OK;
using android::RpcServer;
@@ -29,10 +30,31 @@
extern "C" {
+bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
+ void* factoryContext, unsigned int port) {
+ auto server = RpcServer::make();
+ if (status_t status = server->setupVsockServer(port); status != OK) {
+ LOG(ERROR) << "Failed to set up vsock server with port " << port
+ << " error: " << statusToString(status).c_str();
+ return false;
+ }
+ server->setPerSessionRootObject([=](const sockaddr* addr, socklen_t addrlen) {
+ LOG_ALWAYS_FATAL_IF(addr->sa_family != AF_VSOCK, "address is not a vsock");
+ LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
+ const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
+ return AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext));
+ });
+
+ server->join();
+
+ // Shutdown any open sessions since server failed.
+ (void)server->shutdown();
+ return true;
+}
+
bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
void* param) {
auto server = RpcServer::make();
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
if (status_t status = server->setupVsockServer(port); status != OK) {
LOG(ERROR) << "Failed to set up vsock server with port " << port
<< " error: " << statusToString(status).c_str();
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 854b1f9..cc5dd06 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -17,7 +17,7 @@
//! Trait definitions for binder objects
use crate::error::{status_t, Result, StatusCode};
-use crate::parcel::Parcel;
+use crate::parcel::{OwnedParcel, Parcel};
use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
use crate::sys;
@@ -177,25 +177,25 @@
fn get_extension(&mut self) -> Result<Option<SpIBinder>>;
/// Create a Parcel that can be used with `submit_transact`.
- fn prepare_transact(&self) -> Result<Parcel>;
+ fn prepare_transact(&self) -> Result<OwnedParcel>;
/// Perform a generic operation with the object.
///
- /// The provided [`Parcel`] must have been created by a call to
+ /// The provided [`OwnedParcel`] must have been created by a call to
/// `prepare_transact` on the same binder.
///
/// # Arguments
///
/// * `code` - Transaction code for the operation.
- /// * `data` - [`Parcel`] with input data.
+ /// * `data` - [`OwnedParcel`] with input data.
/// * `flags` - Transaction flags, e.g. marking the transaction as
/// asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)).
fn submit_transact(
&self,
code: TransactionCode,
- data: Parcel,
+ data: OwnedParcel,
flags: TransactionFlags,
- ) -> Result<Parcel>;
+ ) -> Result<OwnedParcel>;
/// Perform a generic operation with the object. This is a convenience
/// method that internally calls `prepare_transact` followed by
@@ -213,8 +213,8 @@
input_callback: F,
) -> Result<Parcel> {
let mut parcel = self.prepare_transact()?;
- input_callback(&mut parcel)?;
- self.submit_transact(code, parcel, flags)
+ input_callback(&mut parcel.borrowed())?;
+ self.submit_transact(code, parcel, flags).map(OwnedParcel::into_parcel)
}
}
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index d1d37d7..81b620e 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -113,7 +113,7 @@
};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder};
-pub use parcel::Parcel;
+pub use parcel::{OwnedParcel, Parcel};
pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service};
pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder};
pub use state::{ProcessState, ThreadState};
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 7391561..9dba950 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -23,6 +23,7 @@
use std::cell::RefCell;
use std::convert::TryInto;
+use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ptr;
use std::fmt;
@@ -52,6 +53,106 @@
Borrowed(*mut sys::AParcel),
}
+/// A variant of Parcel that is known to be owned.
+pub struct OwnedParcel {
+ ptr: *mut sys::AParcel,
+}
+
+/// # Safety
+///
+/// This type guarantees that it owns the AParcel and that all access to
+/// the AParcel happens through the OwnedParcel, so it is ok to send across
+/// threads.
+unsafe impl Send for OwnedParcel {}
+
+/// A variant of Parcel that is known to be borrowed.
+pub struct BorrowedParcel<'a> {
+ inner: Parcel,
+ _lifetime: PhantomData<&'a mut Parcel>,
+}
+
+impl OwnedParcel {
+ /// Create a new empty `OwnedParcel`.
+ pub fn new() -> OwnedParcel {
+ let ptr = unsafe {
+ // Safety: If `AParcel_create` succeeds, it always returns
+ // a valid pointer. If it fails, the process will crash.
+ sys::AParcel_create()
+ };
+ assert!(!ptr.is_null());
+ Self { ptr }
+ }
+
+ /// Create an owned reference to a parcel object from a raw pointer.
+ ///
+ /// # Safety
+ ///
+ /// This constructor is safe if the raw pointer parameter is either null
+ /// (resulting in `None`), or a valid pointer to an `AParcel` object. The
+ /// parcel object must be owned by the caller prior to this call, as this
+ /// constructor takes ownership of the parcel and will destroy it on drop.
+ ///
+ /// Additionally, the caller must guarantee that it is valid to take
+ /// ownership of the AParcel object. All future access to the AParcel
+ /// must happen through this `OwnedParcel`.
+ ///
+ /// Because `OwnedParcel` implements `Send`, the pointer must never point
+ /// to any thread-local data, e.g., a variable on the stack, either directly
+ /// or indirectly.
+ pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<OwnedParcel> {
+ ptr.as_mut().map(|ptr| Self { ptr })
+ }
+
+ /// Consume the parcel, transferring ownership to the caller.
+ pub(crate) fn into_raw(self) -> *mut sys::AParcel {
+ let ptr = self.ptr;
+ let _ = ManuallyDrop::new(self);
+ ptr
+ }
+
+ /// Convert this `OwnedParcel` into an owned `Parcel`.
+ pub fn into_parcel(self) -> Parcel {
+ Parcel::Owned(self.into_raw())
+ }
+
+ /// Get a borrowed view into the contents of this `Parcel`.
+ pub fn borrowed(&mut self) -> BorrowedParcel<'_> {
+ BorrowedParcel {
+ inner: Parcel::Borrowed(self.ptr),
+ _lifetime: PhantomData,
+ }
+ }
+}
+
+impl Default for OwnedParcel {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Clone for OwnedParcel {
+ fn clone(&self) -> Self {
+ let mut new_parcel = Self::new();
+ new_parcel
+ .borrowed()
+ .append_all_from(&Parcel::Borrowed(self.ptr))
+ .expect("Failed to append from Parcel");
+ new_parcel
+ }
+}
+
+impl<'a> std::ops::Deref for BorrowedParcel<'a> {
+ type Target = Parcel;
+ fn deref(&self) -> &Parcel {
+ &self.inner
+ }
+}
+impl<'a> std::ops::DerefMut for BorrowedParcel<'a> {
+ fn deref_mut(&mut self) -> &mut Parcel {
+ &mut self.inner
+ }
+}
+
/// # Safety
///
/// The `Parcel` constructors guarantee that a `Parcel` object will always
@@ -95,33 +196,6 @@
pub(crate) unsafe fn borrowed(ptr: *mut sys::AParcel) -> Option<Parcel> {
ptr.as_mut().map(|ptr| Self::Borrowed(ptr))
}
-
- /// Create an owned reference to a parcel object from a raw pointer.
- ///
- /// # Safety
- ///
- /// This constructor is safe if the raw pointer parameter is either null
- /// (resulting in `None`), or a valid pointer to an `AParcel` object. The
- /// parcel object must be owned by the caller prior to this call, as this
- /// constructor takes ownership of the parcel and will destroy it on drop.
- pub(crate) unsafe fn owned(ptr: *mut sys::AParcel) -> Option<Parcel> {
- ptr.as_mut().map(|ptr| Self::Owned(ptr))
- }
-
- /// Consume the parcel, transferring ownership to the caller if the parcel
- /// was owned.
- pub(crate) fn into_raw(mut self) -> *mut sys::AParcel {
- let ptr = self.as_native_mut();
- let _ = ManuallyDrop::new(self);
- ptr
- }
-
- pub(crate) fn is_owned(&self) -> bool {
- match *self {
- Self::Owned(_) => true,
- Self::Borrowed(_) => false,
- }
- }
}
impl Default for Parcel {
@@ -478,6 +552,18 @@
}
}
+impl Drop for OwnedParcel {
+ fn drop(&mut self) {
+ // Run the C++ Parcel complete object destructor
+ unsafe {
+ // Safety: `OwnedParcel` always contains a valid pointer to an
+ // `AParcel`. Since we own the parcel, we can safely delete it
+ // here.
+ sys::AParcel_delete(self.ptr)
+ }
+ }
+}
+
impl fmt::Debug for Parcel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Parcel")
@@ -485,6 +571,13 @@
}
}
+impl fmt::Debug for OwnedParcel {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OwnedParcel")
+ .finish()
+ }
+}
+
#[test]
fn test_read_write() {
let mut parcel = Parcel::new();
diff --git a/libs/binder/rust/src/parcel/parcelable_holder.rs b/libs/binder/rust/src/parcel/parcelable_holder.rs
index 3e75d1b..bccfd2d 100644
--- a/libs/binder/rust/src/parcel/parcelable_holder.rs
+++ b/libs/binder/rust/src/parcel/parcelable_holder.rs
@@ -16,13 +16,12 @@
use crate::binder::Stability;
use crate::error::{Result, StatusCode};
-use crate::parcel::{Parcel, Parcelable};
+use crate::parcel::{OwnedParcel, Parcel, Parcelable};
use crate::{impl_deserialize_for_parcelable, impl_serialize_for_parcelable};
-use downcast_rs::{impl_downcast, Downcast};
+use downcast_rs::{impl_downcast, DowncastSync};
use std::any::Any;
-use std::cell::RefCell;
-use std::rc::Rc;
+use std::sync::{Arc, Mutex};
/// Metadata that `ParcelableHolder` needs for all parcelables.
///
@@ -40,18 +39,18 @@
}
}
-trait AnyParcelable: Downcast + Parcelable + std::fmt::Debug {}
-impl_downcast!(AnyParcelable);
-impl<T> AnyParcelable for T where T: Downcast + Parcelable + std::fmt::Debug {}
+trait AnyParcelable: DowncastSync + Parcelable + std::fmt::Debug {}
+impl_downcast!(sync AnyParcelable);
+impl<T> AnyParcelable for T where T: DowncastSync + Parcelable + std::fmt::Debug {}
#[derive(Debug, Clone)]
enum ParcelableHolderData {
Empty,
Parcelable {
- parcelable: Rc<dyn AnyParcelable>,
+ parcelable: Arc<dyn AnyParcelable>,
name: String,
},
- Parcel(Parcel),
+ Parcel(OwnedParcel),
}
impl Default for ParcelableHolderData {
@@ -67,15 +66,15 @@
/// `ParcelableHolder` is currently not thread-safe (neither
/// `Send` nor `Sync`), mainly because it internally contains
/// a `Parcel` which in turn is not thread-safe.
-#[derive(Debug, Default, Clone)]
+#[derive(Debug, Default)]
pub struct ParcelableHolder {
- // This is a `RefCell` because of `get_parcelable`
+ // This is a `Mutex` because of `get_parcelable`
// which takes `&self` for consistency with C++.
// We could make `get_parcelable` take a `&mut self`
- // and get rid of the `RefCell` here for a performance
+ // and get rid of the `Mutex` here for a performance
// improvement, but then callers would require a mutable
// `ParcelableHolder` even for that getter method.
- data: RefCell<ParcelableHolderData>,
+ data: Mutex<ParcelableHolderData>,
stability: Stability,
}
@@ -83,7 +82,7 @@
/// Construct a new `ParcelableHolder` with the given stability.
pub fn new(stability: Stability) -> Self {
Self {
- data: RefCell::new(ParcelableHolderData::Empty),
+ data: Mutex::new(ParcelableHolderData::Empty),
stability,
}
}
@@ -93,20 +92,20 @@
/// Note that this method does not reset the stability,
/// only the contents.
pub fn reset(&mut self) {
- *self.data.get_mut() = ParcelableHolderData::Empty;
+ *self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
// We could also clear stability here, but C++ doesn't
}
/// Set the parcelable contained in this `ParcelableHolder`.
- pub fn set_parcelable<T>(&mut self, p: Rc<T>) -> Result<()>
+ pub fn set_parcelable<T>(&mut self, p: Arc<T>) -> Result<()>
where
- T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug,
+ T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,
{
if self.stability > p.get_stability() {
return Err(StatusCode::BAD_VALUE);
}
- *self.data.get_mut() = ParcelableHolderData::Parcelable {
+ *self.data.get_mut().unwrap() = ParcelableHolderData::Parcelable {
parcelable: p,
name: T::get_descriptor().into(),
};
@@ -127,12 +126,12 @@
/// * `Ok(None)` if the holder is empty or the descriptor does not match
/// * `Ok(Some(_))` if the object holds a parcelable of type `T`
/// with the correct descriptor
- pub fn get_parcelable<T>(&self) -> Result<Option<Rc<T>>>
+ pub fn get_parcelable<T>(&self) -> Result<Option<Arc<T>>>
where
- T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug,
+ T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,
{
let parcelable_desc = T::get_descriptor();
- let mut data = self.data.borrow_mut();
+ let mut data = self.data.lock().unwrap();
match *data {
ParcelableHolderData::Empty => Ok(None),
ParcelableHolderData::Parcelable {
@@ -143,12 +142,13 @@
return Err(StatusCode::BAD_VALUE);
}
- match Rc::clone(parcelable).downcast_rc::<T>() {
+ match Arc::clone(parcelable).downcast_arc::<T>() {
Err(_) => Err(StatusCode::BAD_VALUE),
Ok(x) => Ok(Some(x)),
}
}
- ParcelableHolderData::Parcel(ref parcel) => {
+ ParcelableHolderData::Parcel(ref mut parcel) => {
+ let parcel = parcel.borrowed();
unsafe {
// Safety: 0 should always be a valid position.
parcel.set_data_position(0)?;
@@ -160,10 +160,10 @@
}
let mut parcelable = T::default();
- parcelable.read_from_parcel(parcel)?;
+ parcelable.read_from_parcel(&parcel)?;
- let parcelable = Rc::new(parcelable);
- let result = Rc::clone(&parcelable);
+ let parcelable = Arc::new(parcelable);
+ let result = Arc::clone(&parcelable);
*data = ParcelableHolderData::Parcelable { parcelable, name };
Ok(Some(result))
@@ -184,7 +184,8 @@
fn write_to_parcel(&self, parcel: &mut Parcel) -> Result<()> {
parcel.write(&self.stability)?;
- match *self.data.borrow() {
+ let mut data = self.data.lock().unwrap();
+ match *data {
ParcelableHolderData::Empty => parcel.write(&0i32),
ParcelableHolderData::Parcelable {
ref parcelable,
@@ -212,9 +213,10 @@
Ok(())
}
- ParcelableHolderData::Parcel(ref p) => {
+ ParcelableHolderData::Parcel(ref mut p) => {
+ let p = p.borrowed();
parcel.write(&p.get_data_size())?;
- parcel.append_all_from(p)
+ parcel.append_all_from(&p)
}
}
}
@@ -229,7 +231,7 @@
return Err(StatusCode::BAD_VALUE);
}
if data_size == 0 {
- *self.data.get_mut() = ParcelableHolderData::Empty;
+ *self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
return Ok(());
}
@@ -240,9 +242,11 @@
.checked_add(data_size)
.ok_or(StatusCode::BAD_VALUE)?;
- let mut new_parcel = Parcel::new();
- new_parcel.append_from(parcel, data_start, data_size)?;
- *self.data.get_mut() = ParcelableHolderData::Parcel(new_parcel);
+ let mut new_parcel = OwnedParcel::new();
+ new_parcel
+ .borrowed()
+ .append_from(parcel, data_start, data_size)?;
+ *self.data.get_mut().unwrap() = ParcelableHolderData::Parcel(new_parcel);
unsafe {
// Safety: `append_from` checks if `data_size` overflows
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 2c5b0a8..a8d0c33 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -22,7 +22,7 @@
};
use crate::error::{status_result, Result, StatusCode};
use crate::parcel::{
- Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray,
+ Deserialize, DeserializeArray, DeserializeOption, OwnedParcel, Parcel, Serialize, SerializeArray,
SerializeOption,
};
use crate::sys;
@@ -235,7 +235,7 @@
}
impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
- fn prepare_transact(&self) -> Result<Parcel> {
+ fn prepare_transact(&self) -> Result<OwnedParcel> {
let mut input = ptr::null_mut();
let status = unsafe {
// Safety: `SpIBinder` guarantees that `self` always contains a
@@ -253,20 +253,19 @@
unsafe {
// Safety: At this point, `input` is either a valid, owned `AParcel`
- // pointer, or null. `Parcel::owned` safely handles both cases,
+ // pointer, or null. `OwnedParcel::from_raw` safely handles both cases,
// taking ownership of the parcel.
- Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL)
+ OwnedParcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL)
}
}
fn submit_transact(
&self,
code: TransactionCode,
- data: Parcel,
+ data: OwnedParcel,
flags: TransactionFlags,
- ) -> Result<Parcel> {
+ ) -> Result<OwnedParcel> {
let mut reply = ptr::null_mut();
- assert!(data.is_owned());
let status = unsafe {
// Safety: `SpIBinder` guarantees that `self` always contains a
// valid pointer to an `AIBinder`. Although `IBinder::transact` is
@@ -299,9 +298,8 @@
// after the call to `AIBinder_transact` above, so we can
// construct a `Parcel` out of it. `AIBinder_transact` passes
// ownership of the `reply` parcel to Rust, so we need to
- // construct an owned variant. `Parcel::owned` takes ownership
- // of the parcel pointer.
- Parcel::owned(reply).ok_or(StatusCode::UNEXPECTED_NULL)
+ // construct an owned variant.
+ OwnedParcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL)
}
}
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 23e34aa..777f3c9 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -90,7 +90,6 @@
LOG(ERROR) << "Cannot create RpcServer";
return EX_SOFTWARE;
}
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
if (status_t status = rpcServer->setupInetServer(kLocalInetAddress, 0, &port); status != OK) {
LOG(ERROR) << "setupInetServer failed: " << statusToString(status);
@@ -207,7 +206,6 @@
service = ServiceManagerProxyToNative::asBinder(interface);
auto rpcServer = RpcServer::make();
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
rpcServer->setRootObject(service);
unsigned int port;
if (status_t status = rpcServer->setupInetServer(kLocalInetAddress, 0, &port); status != OK) {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index c41f424..c893899 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -1194,7 +1194,6 @@
auto rpcServer = RpcServer::make();
EXPECT_NE(nullptr, rpcServer);
if (rpcServer == nullptr) return {};
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
if (status_t status = rpcServer->setupInetServer("127.0.0.1", 0, &port); status != OK) {
ADD_FAILURE() << "setupInetServer failed" << statusToString(status);
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index f8718aa..52ba9b0 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -206,7 +206,6 @@
if (0 == fork()) {
prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
server->setRootObject(sp<MyBinderRpcBenchmark>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(addr));
server->join();
exit(1);
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 62215bb..7bbe3d7 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -109,7 +109,6 @@
base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
int sinkFd = sink.get();
auto server = RpcServer::make(newFactory(GetParam()));
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
ASSERT_FALSE(server->hasServer());
ASSERT_EQ(OK, server->setupExternalServer(std::move(sink)));
ASSERT_TRUE(server->hasServer());
@@ -543,7 +542,6 @@
auto certVerifier = std::make_shared<RpcCertificateVerifierSimple>();
sp<RpcServer> server = RpcServer::make(newFactory(rpcSecurity, certVerifier));
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
server->setMaxThreads(options.numThreads);
unsigned int outPort = 0;
@@ -665,13 +663,15 @@
break;
case AF_INET:
CHECK_EQ(len, sizeof(sockaddr_in));
- service->port = reinterpret_cast<const sockaddr_in*>(addr)
- ->sin_port;
+ service->port =
+ ntohs(reinterpret_cast<const sockaddr_in*>(addr)
+ ->sin_port);
break;
case AF_INET6:
CHECK_EQ(len, sizeof(sockaddr_in));
- service->port = reinterpret_cast<const sockaddr_in6*>(addr)
- ->sin6_port;
+ service->port =
+ ntohs(reinterpret_cast<const sockaddr_in6*>(addr)
+ ->sin6_port);
break;
default:
LOG_ALWAYS_FATAL("Unrecognized address family %d",
@@ -1373,7 +1373,6 @@
// We don't need to enable TLS to know if vsock is supported.
unsigned int vsockPort = allocateVsockPort();
sp<RpcServer> server = RpcServer::make(RpcTransportCtxFactoryRaw::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
if (status_t status = server->setupVsockServer(vsockPort); status != OK) {
if (status == -EAFNOSUPPORT) {
return false;
@@ -1462,7 +1461,6 @@
TEST_P(BinderRpcSimple, Shutdown) {
auto addr = allocateSocketAddress();
auto server = RpcServer::make(newFactory(GetParam()));
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
auto joinEnds = std::make_shared<OneOffSignal>();
@@ -1502,7 +1500,6 @@
ASSERT_EQ(OK, binder->pingBinder());
auto rpcServer = RpcServer::make();
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
ASSERT_EQ(OK, rpcServer->setupInetServer(kLocalInetAddress, 0, &port));
auto socket = rpcServer->releaseServer();
@@ -1541,7 +1538,6 @@
std::unique_ptr<RpcAuth> auth = std::make_unique<RpcAuthSelfSigned>()) {
auto [socketType, rpcSecurity, certificateFormat] = param;
auto rpcServer = RpcServer::make(newFactory(rpcSecurity));
- rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
switch (socketType) {
case SocketType::PRECONNECTED: {
return AssertionFailure() << "Not supported by this test";
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index 83f2ebe..a8713a2 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -119,7 +119,6 @@
sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider));
server->setRootObject(sp<SomeBinder>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str()));
std::thread serverThread([=] { (void)server->join(); });
diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
index 20c5569..e77c55c 100644
--- a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
+++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
@@ -44,7 +44,6 @@
auto thread = std::thread([&]() {
prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
server->setRootObject(sp<BBinder>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
server->join();
});
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 8c359c7..19a29c1 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -208,7 +208,6 @@
],
shared_libs: [
- "android.frameworks.bufferhub@1.0",
"libbinder",
"libbufferhub",
"libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
@@ -234,7 +233,6 @@
"BufferHubProducer.cpp",
],
exclude_shared_libs: [
- "android.frameworks.bufferhub@1.0",
"libbufferhub",
"libbufferhubqueue",
"libpdx_default_transport",
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 6f1a7ae..c986b82 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -130,6 +130,19 @@
return 1; // keep the callback
}
+void DisplayEventDispatcher::populateFrameTimelines(const DisplayEventReceiver::Event& event,
+ VsyncEventData* outVsyncEventData) const {
+ for (size_t i = 0; i < DisplayEventReceiver::kFrameTimelinesLength; i++) {
+ DisplayEventReceiver::Event::VSync::FrameTimeline receiverTimeline =
+ event.vsync.frameTimelines[i];
+ outVsyncEventData->frameTimelines[i] = {.id = receiverTimeline.vsyncId,
+ .deadlineTimestamp =
+ receiverTimeline.deadlineTimestamp,
+ .expectedPresentTime =
+ receiverTimeline.expectedVSyncTimestamp};
+ }
+}
+
bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
PhysicalDisplayId* outDisplayId,
uint32_t* outCount,
@@ -154,6 +167,9 @@
outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
outVsyncEventData->frameInterval = ev.vsync.frameInterval;
outVsyncEventData->expectedPresentTime = ev.vsync.expectedVSyncTimestamp;
+ outVsyncEventData->preferredFrameTimelineIndex =
+ ev.vsync.preferredFrameTimelineIndex;
+ populateFrameTimelines(ev, outVsyncEventData);
break;
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index f3bd139..92c89b8 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -17,6 +17,7 @@
#include <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
#include <utils/Looper.h>
+#include <array>
namespace android {
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
@@ -36,6 +37,26 @@
// The anticipated Vsync present time.
int64_t expectedPresentTime = 0;
+
+ struct FrameTimeline {
+ // The Vsync Id corresponsing to this vsync event. This will be used to
+ // populate ISurfaceComposer::setFrameTimelineVsync and
+ // SurfaceComposerClient::setFrameTimelineVsync
+ int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
+
+ // The deadline in CLOCK_MONOTONIC that the app needs to complete its
+ // frame by (both on the CPU and the GPU)
+ int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();
+
+ // The anticipated Vsync present time.
+ int64_t expectedPresentTime = 0;
+ };
+
+ // Sorted possible frame timelines.
+ std::array<FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength> frameTimelines;
+
+ // Index into the frameTimelines that represents the platform's preferred frame timeline.
+ size_t preferredFrameTimelineIndex = std::numeric_limits<size_t>::max();
};
class DisplayEventDispatcher : public LooperCallback {
@@ -77,5 +98,8 @@
bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
uint32_t* outCount, VsyncEventData* outVsyncEventData);
+
+ void populateFrameTimelines(const DisplayEventReceiver::Event& event,
+ VsyncEventData* outVsyncEventData) const;
};
} // namespace android
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 0dffbde..ca36843 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -49,6 +49,9 @@
// ----------------------------------------------------------------------------
class DisplayEventReceiver {
public:
+ // Max amount of frame timelines is arbitrarily set to be reasonable.
+ static constexpr int64_t kFrameTimelinesLength = 7;
+
enum {
DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
@@ -77,6 +80,12 @@
nsecs_t deadlineTimestamp __attribute__((aligned(8)));
nsecs_t frameInterval __attribute__((aligned(8)));
int64_t vsyncId;
+ size_t preferredFrameTimelineIndex __attribute__((aligned(8)));
+ struct FrameTimeline {
+ nsecs_t expectedVSyncTimestamp __attribute__((aligned(8)));
+ nsecs_t deadlineTimestamp __attribute__((aligned(8)));
+ int64_t vsyncId;
+ } frameTimelines[kFrameTimelinesLength];
};
struct Hotplug {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index e540351..40d096e 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -429,11 +429,11 @@
uint32_t mReqHeight;
// mReqFormat is the buffer pixel format that will be requested at the next
- // deuque operation. It is initialized to PIXEL_FORMAT_RGBA_8888.
+ // dequeue operation. It is initialized to PIXEL_FORMAT_RGBA_8888.
PixelFormat mReqFormat;
// mReqUsage is the set of buffer usage flags that will be requested
- // at the next deuque operation. It is initialized to 0.
+ // at the next dequeue operation. It is initialized to 0.
uint64_t mReqUsage;
// mTimestamp is the timestamp that will be used for the next buffer queue
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 390ff96..d018800 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -56,13 +56,8 @@
transformedPoint.y -= origin.y;
// Derive the transformed vector's clockwise angle from vertical.
- float result = atan2f(transformedPoint.x, -transformedPoint.y);
- if (result < -M_PI_2) {
- result += M_PI;
- } else if (result > M_PI_2) {
- result -= M_PI;
- }
- return result;
+ // The return value of atan2f is in range [-pi, pi] which conforms to the orientation API.
+ return atan2f(transformedPoint.x, -transformedPoint.y);
}
vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) {
@@ -498,44 +493,14 @@
float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
size_t historicalIndex) const {
- const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex);
-
- if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
- const vec2 xy = calculateTransformedXY(mSource, mRawTransform, coords->getXYValue());
- static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
- return xy[axis];
- }
-
- if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
- const vec2 relativeXy =
- transformWithoutTranslation(mRawTransform,
- {coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
- coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)});
- return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
- }
-
- return coords->getAxisValue(axis);
+ const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex);
+ return calculateTransformedAxisValue(axis, mSource, mRawTransform, coords);
}
float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
size_t historicalIndex) const {
- const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex);
-
- if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
- const vec2 xy = calculateTransformedXY(mSource, mTransform, coords->getXYValue());
- static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
- return xy[axis];
- }
-
- if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
- const vec2 relativeXy =
- transformWithoutTranslation(mTransform,
- {coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
- coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)});
- return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
- }
-
- return coords->getAxisValue(axis);
+ const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex);
+ return calculateTransformedAxisValue(axis, mSource, mTransform, coords);
}
ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
@@ -574,15 +539,6 @@
ui::Transform newTransform;
newTransform.set(matrix);
mTransform = newTransform * mTransform;
-
- // We need to update the AXIS_ORIENTATION value here to maintain the old behavior where the
- // orientation angle is not affected by the initial transformation set in the MotionEvent.
- std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(),
- [&newTransform](PointerCoords& c) {
- float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
- c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
- transformAngle(newTransform, orientation));
- });
}
void MotionEvent::applyTransform(const std::array<float, 9>& matrix) {
@@ -814,6 +770,30 @@
: transform.transform(xy);
}
+float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source,
+ const ui::Transform& transform,
+ const PointerCoords& coords) {
+ if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
+ const vec2 xy = calculateTransformedXY(source, transform, coords.getXYValue());
+ static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
+ return xy[axis];
+ }
+
+ if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
+ const vec2 relativeXy =
+ transformWithoutTranslation(transform,
+ {coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)});
+ return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
+ }
+
+ if (axis == AMOTION_EVENT_AXIS_ORIENTATION) {
+ return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+ }
+
+ return coords.getAxisValue(axis);
+}
+
// --- FocusEvent ---
void FocusEvent::initialize(int32_t id, bool hasFocus, bool inTouchMode) {
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index caf3a61..1b594f1 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -444,12 +444,19 @@
ASSERT_EQ(217, event->getToolMinor(0));
ASSERT_EQ(227, event->getToolMinor(1));
- ASSERT_EQ(18, event->getHistoricalOrientation(0, 0));
- ASSERT_EQ(28, event->getHistoricalOrientation(1, 0));
- ASSERT_EQ(118, event->getHistoricalOrientation(0, 1));
- ASSERT_EQ(128, event->getHistoricalOrientation(1, 1));
- ASSERT_EQ(218, event->getOrientation(0));
- ASSERT_EQ(228, event->getOrientation(1));
+ // Calculate the orientation after scaling, keeping in mind that an orientation of 0 is "up",
+ // and the positive y direction is "down".
+ auto toScaledOrientation = [](float angle) {
+ const float x = sinf(angle) * X_SCALE;
+ const float y = -cosf(angle) * Y_SCALE;
+ return atan2f(x, -y);
+ };
+ ASSERT_EQ(toScaledOrientation(18), event->getHistoricalOrientation(0, 0));
+ ASSERT_EQ(toScaledOrientation(28), event->getHistoricalOrientation(1, 0));
+ ASSERT_EQ(toScaledOrientation(118), event->getHistoricalOrientation(0, 1));
+ ASSERT_EQ(toScaledOrientation(128), event->getHistoricalOrientation(1, 1));
+ ASSERT_EQ(toScaledOrientation(218), event->getOrientation(0));
+ ASSERT_EQ(toScaledOrientation(228), event->getOrientation(1));
}
TEST_F(MotionEventTest, Properties) {
@@ -518,6 +525,7 @@
TEST_F(MotionEventTest, Scale) {
MotionEvent event;
initializeEventWithHistory(&event);
+ const float unscaledOrientation = event.getOrientation(0);
event.scale(2.0f);
@@ -534,7 +542,7 @@
ASSERT_EQ(215 * 2, event.getTouchMinor(0));
ASSERT_EQ(216 * 2, event.getToolMajor(0));
ASSERT_EQ(217 * 2, event.getToolMinor(0));
- ASSERT_EQ(218, event.getOrientation(0));
+ ASSERT_EQ(unscaledOrientation, event.getOrientation(0));
}
TEST_F(MotionEventTest, Parcel) {
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index d09f2ac..973194c 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -259,7 +259,13 @@
EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), motionEvent->getTouchMinor(i));
EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), motionEvent->getToolMajor(i));
EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), motionEvent->getToolMinor(i));
- EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), motionEvent->getOrientation(i));
+
+ // Calculate the orientation after scaling, keeping in mind that an orientation of 0 is
+ // "up", and the positive y direction is "down".
+ const float unscaledOrientation = pc.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
+ const float x = sinf(unscaledOrientation) * xScale;
+ const float y = -cosf(unscaledOrientation) * yScale;
+ EXPECT_EQ(atan2f(x, -y), motionEvent->getOrientation(i));
}
status = mConsumer->sendFinishedSignal(seq, false);
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 79d9b93..fc9680b 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -100,17 +100,10 @@
* Implementation of AChoreographerFrameCallbackData.
*/
struct ChoreographerFrameCallbackDataImpl {
- struct FrameTimeline {
- int64_t vsyncId{0};
- int64_t expectedPresentTimeNanos{0};
- int64_t deadlineNanos{0};
- };
-
int64_t frameTimeNanos{0};
- size_t frameTimelinesLength;
-
- std::vector<FrameTimeline> frameTimelines;
+ std::array<VsyncEventData::FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength>
+ frameTimelines;
size_t preferredFrameTimelineIndex;
@@ -456,14 +449,9 @@
}
ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_t timestamp) const {
- std::vector<ChoreographerFrameCallbackDataImpl::FrameTimeline> frameTimelines;
- frameTimelines.push_back({.vsyncId = mLastVsyncEventData.id,
- .expectedPresentTimeNanos = mLastVsyncEventData.expectedPresentTime,
- .deadlineNanos = mLastVsyncEventData.deadlineTimestamp});
return {.frameTimeNanos = timestamp,
- .frameTimelinesLength = 1,
- .preferredFrameTimelineIndex = 0,
- .frameTimelines = frameTimelines,
+ .preferredFrameTimelineIndex = mLastVsyncEventData.preferredFrameTimelineIndex,
+ .frameTimelines = mLastVsyncEventData.frameTimelines,
.choreographer = this};
}
@@ -646,7 +634,7 @@
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
"Data is only valid in callback");
- return frameCallbackData->frameTimelinesLength;
+ return frameCallbackData->frameTimelines.size();
}
size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(
const AChoreographerFrameCallbackData* data) {
@@ -662,8 +650,8 @@
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
"Data is only valid in callback");
- LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds");
- return frameCallbackData->frameTimelines[index].vsyncId;
+ LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
+ return frameCallbackData->frameTimelines[index].id;
}
int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(
const AChoreographerFrameCallbackData* data, size_t index) {
@@ -671,8 +659,8 @@
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
"Data is only valid in callback");
- LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds");
- return frameCallbackData->frameTimelines[index].expectedPresentTimeNanos;
+ LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
+ return frameCallbackData->frameTimelines[index].expectedPresentTime;
}
int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline(
const AChoreographerFrameCallbackData* data, size_t index) {
@@ -680,8 +668,8 @@
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
"Data is only valid in callback");
- LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds");
- return frameCallbackData->frameTimelines[index].deadlineNanos;
+ LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
+ return frameCallbackData->frameTimelines[index].deadlineTimestamp;
}
AChoreographer* AChoreographer_create() {
diff --git a/services/inputflinger/dispatcher/EventLogTags.logtags b/services/inputflinger/dispatcher/EventLogTags.logtags
index 2836467..2c5fe21 100644
--- a/services/inputflinger/dispatcher/EventLogTags.logtags
+++ b/services/inputflinger/dispatcher/EventLogTags.logtags
@@ -37,6 +37,7 @@
62000 input_interaction (windows|4)
62001 input_focus (window|3),(reason|3)
+62003 input_cancel (window|3),(reason|3)
# NOTE - the range 1000000-2000000 is reserved for partners and others who
# want to define their own log tags without conflicting with the core platform.
\ No newline at end of file
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index ea5799a..176cf89 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -153,6 +153,7 @@
// Event log tags. See EventLogTags.logtags for reference
constexpr int LOGTAG_INPUT_INTERACTION = 62000;
constexpr int LOGTAG_INPUT_FOCUS = 62001;
+constexpr int LOGTAG_INPUT_CANCEL = 62003;
inline nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -2077,6 +2078,8 @@
// Handle the case where we did not find a window.
if (newTouchedWindowHandle == nullptr) {
+ ALOGD("No new touched window at (%" PRId32 ", %" PRId32 ") in display %" PRId32, x, y,
+ displayId);
// Try to assign the pointer to the first foreground window we find, if there is one.
newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle();
}
@@ -2870,6 +2873,11 @@
if (!splitMotionEntry) {
return; // split event was dropped
}
+ if (splitMotionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
+ std::string reason = std::string("reason=pointer cancel on split window");
+ android_log_event_list(LOGTAG_INPUT_CANCEL)
+ << connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;
+ }
if (DEBUG_FOCUS) {
ALOGD("channel '%s' ~ Split motion event.",
connection->getInputChannelName().c_str());
@@ -3575,6 +3583,10 @@
options.mode);
}
+ std::string reason = std::string("reason=").append(options.reason);
+ android_log_event_list(LOGTAG_INPUT_CANCEL)
+ << connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;
+
InputTarget target;
sp<WindowInfoHandle> windowHandle =
getWindowHandleLocked(connection->inputChannel->getConnectionToken());
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 1879cec..ba0ce95 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2841,6 +2841,17 @@
ASSERT_EQ(ui::Transform(), event->getTransform());
}
+TEST_F(InputDispatcherTest, GestureMonitor_NoWindow) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
+ true /*isGestureMonitor*/);
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+}
+
TEST_F(InputDispatcherTest, TestMoveEvent) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 969fd67..861d496 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -227,7 +227,7 @@
* of a camera where the buffer remains in native orientation,
* we want the pixels to always be upright.
*/
- auto p = mDrawingParent;
+ sp<Layer> p = mDrawingParent.promote();
if (p != nullptr) {
const auto parentTransform = p->getTransform();
tr = tr * inverseOrientation(parentTransform.getOrientation());
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index c213570..c0753f9 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -937,7 +937,7 @@
* how to go from screen space back to window space.
*/
ui::Transform BufferStateLayer::getInputTransform() const {
- auto parent = mDrawingParent;
+ sp<Layer> parent = mDrawingParent.promote();
if (parent == nullptr) {
return ui::Transform();
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 68ca2f0..388181c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -88,7 +88,7 @@
Layer::Layer(const LayerCreationArgs& args)
: mFlinger(args.flinger),
- mName(args.name),
+ mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
mClientRef(args.client),
mWindowType(
static_cast<WindowInfo::Type>(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) {
@@ -179,23 +179,9 @@
if (mDrawingState.sidebandStream != nullptr) {
mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
}
-
if (mHadClonedChild) {
mFlinger->mNumClones--;
}
-
- for (auto const& child : mCurrentChildren) {
- if (child->mCurrentParent == this) child->mCurrentParent = nullptr;
- if (child->mDrawingParent == this) {
- child->mDrawingParent = nullptr;
- }
- }
- for (auto const& child : mDrawingChildren) {
- if (child->mCurrentParent == this) child->mCurrentParent = nullptr;
- if (child->mDrawingParent == this) {
- child->mDrawingParent = nullptr;
- }
- }
}
LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
@@ -252,7 +238,7 @@
}
sp<Layer> Layer::getRootLayer() {
- auto parent = getParent();
+ sp<Layer> parent = getParent();
if (parent == nullptr) {
return this;
}
@@ -677,7 +663,7 @@
return true;
}
- const auto p = mDrawingParent;
+ const auto p = mDrawingParent.promote();
return (p != nullptr) ? p->isSecure() : false;
}
@@ -860,7 +846,7 @@
if (getDrawingState().isTrustedOverlay) {
return true;
}
- const auto p = mDrawingParent;
+ const auto& p = mDrawingParent.promote();
return (p != nullptr) && p->isTrustedOverlay();
}
@@ -1040,7 +1026,7 @@
return mDrawingState.frameRateSelectionPriority;
}
// If not, search whether its parents have it set.
- auto parent = getParent();
+ sp<Layer> parent = getParent();
if (parent != nullptr) {
return parent->getFrameRateSelectionPriority();
}
@@ -1053,11 +1039,10 @@
};
ui::LayerStack Layer::getLayerStack() const {
- auto p = mDrawingParent;
- if (p == nullptr) {
- return getDrawingState().layerStack;
+ if (const auto parent = mDrawingParent.promote()) {
+ return parent->getLayerStack();
}
- return mDrawingParent->getLayerStack();
+ return getDrawingState().layerStack;
}
bool Layer::setShadowRadius(float shadowRadius) {
@@ -1102,7 +1087,7 @@
return mDrawingState.stretchEffect;
}
- auto parent = mDrawingParent;
+ sp<Layer> parent = getParent();
if (parent != nullptr) {
auto effect = parent->getStretchEffect();
if (effect.hasEffect()) {
@@ -1317,7 +1302,7 @@
bool Layer::isHiddenByPolicy() const {
const State& s(mDrawingState);
- auto parent = mDrawingParent;
+ const auto& parent = mDrawingParent.promote();
if (parent != nullptr && parent->isHiddenByPolicy()) {
return true;
}
@@ -1364,7 +1349,7 @@
LayerDebugInfo info;
const State& ds = getDrawingState();
info.mName = getName();
- auto parent = mDrawingParent;
+ sp<Layer> parent = mDrawingParent.promote();
info.mParentName = parent ? parent->getName() : "none"s;
info.mType = getType();
info.mTransparentRegion = ds.activeTransparentRegion_legacy;
@@ -1596,7 +1581,7 @@
void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
for (const sp<Layer>& child : mDrawingChildren) {
- child->mDrawingParent = newParent.get();
+ child->mDrawingParent = newParent;
child->computeBounds(newParent->mBounds, newParent->mEffectiveTransform,
newParent->mEffectiveShadowRadius);
}
@@ -1616,7 +1601,7 @@
}
}
- auto parent = getParent();
+ sp<Layer> parent = getParent();
if (parent != nullptr) {
parent->removeChild(this);
}
@@ -1651,7 +1636,7 @@
mat4 Layer::getColorTransform() const {
mat4 colorTransform = mat4(getDrawingState().colorTransform);
- if (auto parent = mDrawingParent; parent != nullptr) {
+ if (sp<Layer> parent = mDrawingParent.promote(); parent != nullptr) {
colorTransform = parent->getColorTransform() * colorTransform;
}
return colorTransform;
@@ -1659,7 +1644,7 @@
bool Layer::hasColorTransform() const {
bool hasColorTransform = getDrawingState().hasColorTransform;
- if (auto parent = mDrawingParent; parent != nullptr) {
+ if (sp<Layer> parent = mDrawingParent.promote(); parent != nullptr) {
hasColorTransform = hasColorTransform || parent->hasColorTransform();
}
return hasColorTransform;
@@ -1673,7 +1658,7 @@
}
void Layer::setParent(const sp<Layer>& layer) {
- mCurrentParent = layer.get();
+ mCurrentParent = layer;
}
int32_t Layer::getZ(LayerVector::StateSet) const {
@@ -1877,7 +1862,7 @@
}
half Layer::getAlpha() const {
- auto p = mDrawingParent;
+ const auto& p = mDrawingParent.promote();
half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf;
return parentAlpha * getDrawingState().color.a;
@@ -1888,7 +1873,7 @@
if (fixedTransformHint != ui::Transform::ROT_INVALID) {
return fixedTransformHint;
}
- auto p = mCurrentParent;
+ const auto& p = mCurrentParent.promote();
if (!p) return fixedTransformHint;
return p->getFixedTransformHint();
}
@@ -1899,7 +1884,7 @@
}
int32_t Layer::getBackgroundBlurRadius() const {
- auto p = mDrawingParent;
+ const auto& p = mDrawingParent.promote();
half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf;
return parentAlpha * getDrawingState().backgroundBlurRadius;
@@ -1917,8 +1902,9 @@
Layer::RoundedCornerState Layer::getRoundedCornerState() const {
// Get parent settings
RoundedCornerState parentSettings;
- if (mDrawingParent != nullptr) {
- parentSettings = mDrawingParent->getRoundedCornerState();
+ const auto& parent = mDrawingParent.promote();
+ if (parent != nullptr) {
+ parentSettings = parent->getRoundedCornerState();
if (parentSettings.radius > 0) {
ui::Transform t = getActiveTransform(getDrawingState());
t = t.inverse();
@@ -2134,7 +2120,7 @@
LayerProtoHelper::writeToProtoDeprecated(requestedTransform,
layerInfo->mutable_requested_transform());
- auto parent = useDrawing ? mDrawingParent : mCurrentParent;
+ auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
if (parent != nullptr) {
layerInfo->set_parent(parent->sequence);
} else {
@@ -2281,9 +2267,9 @@
}
void Layer::fillTouchOcclusionMode(WindowInfo& info) {
- Layer* p = this;
+ sp<Layer> p = this;
while (p != nullptr && !p->hasInputInfo()) {
- p = p->mDrawingParent;
+ p = p->mDrawingParent.promote();
}
if (p != nullptr) {
info.touchOcclusionMode = p->mDrawingState.inputInfo.touchOcclusionMode;
@@ -2295,8 +2281,9 @@
if (mode == gui::DropInputMode::ALL) {
return mode;
}
- if (mDrawingParent) {
- gui::DropInputMode parentMode = mDrawingParent->getDropInputMode();
+ sp<Layer> parent = mDrawingParent.promote();
+ if (parent) {
+ gui::DropInputMode parentMode = parent->getDropInputMode();
if (parentMode != gui::DropInputMode::NONE) {
return parentMode;
}
@@ -2323,7 +2310,8 @@
}
// Check if the parent has set an alpha on the layer
- if (mDrawingParent && mDrawingParent->getAlpha() != 1.0_hf) {
+ sp<Layer> parent = mDrawingParent.promote();
+ if (parent && parent->getAlpha() != 1.0_hf) {
info.inputFeatures |= WindowInfo::Feature::DROP_INPUT;
ALOGV("Dropping input for %s as requested by policy because alpha=%f", getDebugName(),
static_cast<float>(getAlpha()));
@@ -2421,10 +2409,10 @@
if (mClonedChild != nullptr) {
return this;
}
- if (mDrawingParent == nullptr) {
+ if (mDrawingParent == nullptr || mDrawingParent.promote() == nullptr) {
return nullptr;
}
- return mDrawingParent->getClonedRoot();
+ return mDrawingParent.promote()->getClonedRoot();
}
bool Layer::hasInputInfo() const {
@@ -2611,7 +2599,8 @@
return true;
}
- return mDrawingParent && mDrawingParent->isInternalDisplayOverlay();
+ sp<Layer> parent = mDrawingParent.promote();
+ return parent && parent->isInternalDisplayOverlay();
}
void Layer::setClonedChild(const sp<Layer>& clonedChild) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 4569f9a..bf338c1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -796,12 +796,12 @@
// Returns index if removed, or negative value otherwise
// for symmetry with Vector::remove
ssize_t removeChild(const sp<Layer>& layer);
+ sp<Layer> getParent() const { return mCurrentParent.promote(); }
// Should be called with the surfaceflinger statelock held
bool isAtRoot() const { return mIsAtRoot; }
void setIsAtRoot(bool isAtRoot) { mIsAtRoot = isAtRoot; }
- Layer* getParent() const { return mCurrentParent; }
bool hasParent() const { return getParent() != nullptr; }
Rect getScreenBounds(bool reduceTransparentRegion = true) const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
@@ -1008,8 +1008,8 @@
LayerVector mCurrentChildren{LayerVector::StateSet::Current};
LayerVector mDrawingChildren{LayerVector::StateSet::Drawing};
- Layer* mCurrentParent = nullptr;
- Layer* mDrawingParent = nullptr;
+ wp<Layer> mCurrentParent;
+ wp<Layer> mDrawingParent;
// Window types from WindowManager.LayoutParams
const gui::WindowInfo::Type mWindowType;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 2bdcaf6..e07eae7 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -355,14 +355,7 @@
std::lock_guard<std::mutex> lock(mMutex);
LOG_FATAL_IF(!mVSyncState);
- const int64_t vsyncId = [&] {
- if (mTokenManager != nullptr) {
- return mTokenManager->generateTokenForPredictions(
- {timestamp, deadlineTimestamp, expectedVSyncTimestamp});
- }
- return FrameTimelineInfo::INVALID_VSYNC_ID;
- }();
-
+ const int64_t vsyncId = generateToken(timestamp, deadlineTimestamp, expectedVSyncTimestamp);
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
mCondition.notify_all();
@@ -567,12 +560,48 @@
}
}
+int64_t EventThread::generateToken(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
+ nsecs_t deadlineTimestamp) const {
+ if (mTokenManager != nullptr) {
+ return mTokenManager->generateTokenForPredictions(
+ {timestamp, deadlineTimestamp, expectedVSyncTimestamp});
+ }
+ return FrameTimelineInfo::INVALID_VSYNC_ID;
+}
+
+void EventThread::generateFrameTimeline(DisplayEventReceiver::Event& event) const {
+ // Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
+ for (int multiplier = -DisplayEventReceiver::kFrameTimelinesLength + 1, currentIndex = 0;
+ currentIndex < DisplayEventReceiver::kFrameTimelinesLength; multiplier++) {
+ nsecs_t deadline = event.vsync.deadlineTimestamp + multiplier * event.vsync.frameInterval;
+ // Valid possible frame timelines must have future values.
+ if (deadline > event.header.timestamp) {
+ if (multiplier == 0) {
+ event.vsync.preferredFrameTimelineIndex = currentIndex;
+ event.vsync.frameTimelines[currentIndex] =
+ {.vsyncId = event.vsync.vsyncId,
+ .deadlineTimestamp = event.vsync.deadlineTimestamp,
+ .expectedVSyncTimestamp = event.vsync.expectedVSyncTimestamp};
+ } else {
+ nsecs_t expectedVSync =
+ event.vsync.expectedVSyncTimestamp + multiplier * event.vsync.frameInterval;
+ event.vsync.frameTimelines[currentIndex] =
+ {.vsyncId = generateToken(event.header.timestamp, expectedVSync, deadline),
+ .deadlineTimestamp = deadline,
+ .expectedVSyncTimestamp = expectedVSync};
+ }
+ currentIndex++;
+ }
+ }
+}
+
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
for (const auto& consumer : consumers) {
DisplayEventReceiver::Event copy = event;
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
+ generateFrameTimeline(copy);
}
switch (consumer->postEvent(copy)) {
case NO_ERROR:
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 9265a25..73ae5dc 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -204,6 +204,10 @@
void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
nsecs_t deadlineTimestamp) override;
+ int64_t generateToken(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
+ nsecs_t deadlineTimestamp) const;
+ void generateFrameTimeline(DisplayEventReceiver::Event& event) const;
+
const std::unique_ptr<VSyncSource> mVSyncSource GUARDED_BY(mMutex);
frametimeline::TokenManager* const mTokenManager;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5f4acc9..8d7221c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3381,7 +3381,6 @@
states.add(composerState);
lbc->updateTransformHint(mActiveDisplayTransformHint);
-
if (outTransformHint) {
*outTransformHint = mActiveDisplayTransformHint;
}
@@ -3922,7 +3921,7 @@
}
if (what & layer_state_t::eLayerChanged) {
// NOTE: index needs to be calculated before we update the state
- auto p = layer->getParent();
+ const auto& p = layer->getParent();
if (p == nullptr) {
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
if (layer->setLayer(s.z) && idx >= 0) {
@@ -3940,7 +3939,7 @@
}
if (what & layer_state_t::eRelativeLayerChanged) {
// NOTE: index needs to be calculated before we update the state
- auto p = layer->getParent();
+ const auto& p = layer->getParent();
const auto& relativeHandle = s.relativeLayerSurfaceControl ?
s.relativeLayerSurfaceControl->getHandle() : nullptr;
if (p == nullptr) {
@@ -4209,7 +4208,7 @@
sp<Layer> mirrorLayer;
sp<Layer> mirrorFrom;
- std::string uniqueName = getUniqueLayerName("MirrorRoot");
+ std::string layerName = "MirrorRoot";
{
Mutex::Autolock _l(mStateLock);
@@ -4218,7 +4217,7 @@
return NAME_NOT_FOUND;
}
- status_t result = createContainerLayer(client, std::move(uniqueName), -1, -1, 0,
+ status_t result = createContainerLayer(client, std::move(layerName), -1, -1, 0,
LayerMetadata(), outHandle, &mirrorLayer);
if (result != NO_ERROR) {
return result;
@@ -4252,12 +4251,12 @@
sp<Layer> layer;
- std::string uniqueName = getUniqueLayerName(name.string());
+ std::string layerName{name.string()};
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceBufferQueue:
case ISurfaceComposerClient::eFXSurfaceBufferState: {
- result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
+ result = createBufferStateLayer(client, std::move(layerName), w, h, flags,
std::move(metadata), handle, &layer);
std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
if (pendingBufferCounter) {
@@ -4274,7 +4273,7 @@
return BAD_VALUE;
}
- result = createEffectLayer(client, std::move(uniqueName), w, h, flags,
+ result = createEffectLayer(client, std::move(layerName), w, h, flags,
std::move(metadata), handle, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceContainer:
@@ -4284,7 +4283,7 @@
int(w), int(h));
return BAD_VALUE;
}
- result = createContainerLayer(client, std::move(uniqueName), w, h, flags,
+ result = createContainerLayer(client, std::move(layerName), w, h, flags,
std::move(metadata), handle, &layer);
break;
default:
@@ -4302,38 +4301,12 @@
if (result != NO_ERROR) {
return result;
}
- mInterceptor->saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
*outLayerId = layer->sequence;
return result;
}
-std::string SurfaceFlinger::getUniqueLayerName(const char* name) {
- unsigned dupeCounter = 0;
-
- // Tack on our counter whether there is a hit or not, so everyone gets a tag
- std::string uniqueName = base::StringPrintf("%s#%u", name, dupeCounter);
-
- // Grab the state lock since we're accessing mCurrentState
- Mutex::Autolock lock(mStateLock);
-
- // Loop over layers until we're sure there is no matching name
- bool matchFound = true;
- while (matchFound) {
- matchFound = false;
- mCurrentState.traverse([&](Layer* layer) {
- if (layer->getName() == uniqueName) {
- matchFound = true;
- uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter);
- }
- });
- }
-
- ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name, uniqueName.c_str());
- return uniqueName;
-}
-
status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, PixelFormat& format,
@@ -6104,7 +6077,7 @@
return;
}
- auto p = layer;
+ sp<Layer> p = layer;
while (p != nullptr) {
if (excludeLayers.count(p) != 0) {
return;
@@ -6885,6 +6858,7 @@
}
}
+ mInterceptor->saveSurfaceCreation(layer);
return layer;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index feee5df..276c7f6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -786,8 +786,6 @@
status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
sp<IBinder>* outHandle, int32_t* outLayerId);
- std::string getUniqueLayerName(const char* name);
-
// called when all clients have released all their references to
// this layer meaning it is entirely safe to destroy all
// resources associated to this layer.
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index ee16f40..2082c42 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -19,6 +19,7 @@
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wextra"
+#include <android-base/stringprintf.h>
#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <gtest/gtest.h>
@@ -56,10 +57,7 @@
const String8 DISPLAY_NAME("SurfaceInterceptor Display Test");
constexpr auto TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface";
constexpr auto TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface";
-constexpr auto UNIQUE_TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface#0";
-constexpr auto UNIQUE_TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface#0";
constexpr auto LAYER_NAME = "Layer Create and Delete Test";
-constexpr auto UNIQUE_LAYER_NAME = "Layer Create and Delete Test#0";
constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/transaction_trace.winscope";
@@ -105,11 +103,15 @@
system("service call SurfaceFlinger 1020 i32 0 > /dev/null");
}
+std::string getUniqueName(const std::string& name, const Increment& increment) {
+ return base::StringPrintf("%s#%d", name.c_str(), increment.surface_creation().id());
+}
+
int32_t getSurfaceId(const Trace& capturedTrace, const std::string& surfaceName) {
int32_t layerId = 0;
for (const auto& increment : capturedTrace.increment()) {
if (increment.increment_case() == increment.kSurfaceCreation) {
- if (increment.surface_creation().name() == surfaceName) {
+ if (increment.surface_creation().name() == getUniqueName(surfaceName, increment)) {
layerId = increment.surface_creation().id();
}
}
@@ -293,8 +295,8 @@
}
void SurfaceInterceptorTest::preProcessTrace(const Trace& trace) {
- mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_BG_SURFACE_NAME);
- mFGLayerId = getSurfaceId(trace, UNIQUE_TEST_FG_SURFACE_NAME);
+ mBGLayerId = getSurfaceId(trace, TEST_BG_SURFACE_NAME);
+ mFGLayerId = getSurfaceId(trace, TEST_FG_SURFACE_NAME);
}
void SurfaceInterceptorTest::captureTest(TestTransactionAction action,
@@ -752,9 +754,9 @@
}
bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
- bool isMatch(increment.surface_creation().name() == UNIQUE_LAYER_NAME &&
- increment.surface_creation().w() == SIZE_UPDATE &&
- increment.surface_creation().h() == SIZE_UPDATE);
+ bool isMatch(increment.surface_creation().name() == getUniqueName(LAYER_NAME, increment) &&
+ increment.surface_creation().w() == SIZE_UPDATE &&
+ increment.surface_creation().h() == SIZE_UPDATE);
if (isMatch && !foundSurface) {
foundSurface = true;
} else if (isMatch && foundSurface) {
@@ -808,7 +810,7 @@
break;
case Increment::IncrementCase::kSurfaceDeletion:
// Find the id of created surface.
- targetId = getSurfaceId(trace, UNIQUE_LAYER_NAME);
+ targetId = getSurfaceId(trace, LAYER_NAME);
foundIncrement = surfaceDeletionFound(increment, targetId, foundIncrement);
break;
case Increment::IncrementCase::kDisplayCreation:
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 28d0222..cb690aa 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -28,6 +28,7 @@
#include "AsyncCallRecorder.h"
#include "DisplayHardware/DisplayMode.h"
+#include "FrameTimeline.h"
#include "Scheduler/EventThread.h"
using namespace std::chrono_literals;
@@ -96,6 +97,8 @@
ConnectionEventRecorder& connectionEventRecorder,
nsecs_t expectedTimestamp, unsigned expectedCount);
void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
+ void expectVsyncEventFrameTimelinesCorrect(nsecs_t expectedTimestamp,
+ nsecs_t preferredDeadline);
void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
bool expectedConnected);
void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
@@ -120,6 +123,7 @@
std::unique_ptr<impl::EventThread> mThread;
sp<MockEventThreadConnection> mConnection;
sp<MockEventThreadConnection> mThrottledConnection;
+ std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager;
static constexpr uid_t mConnectionUid = 443;
static constexpr uid_t mThrottledConnectionUid = 177;
@@ -173,8 +177,8 @@
return VSYNC_PERIOD.count();
};
- mThread = std::make_unique<impl::EventThread>(std::move(source),
- /*tokenManager=*/nullptr,
+ mTokenManager = std::make_unique<frametimeline::impl::TokenManager>();
+ mThread = std::make_unique<impl::EventThread>(std::move(source), mTokenManager.get(),
mInterceptVSyncCallRecorder.getInvocable(),
throttleVsync, getVsyncPeriod);
@@ -247,6 +251,36 @@
expectedCount);
}
+void EventThreadTest::expectVsyncEventFrameTimelinesCorrect(nsecs_t expectedTimestamp,
+ nsecs_t preferredDeadline) {
+ auto args = mConnectionEventCallRecorder.waitForCall();
+ ASSERT_TRUE(args.has_value()) << " did not receive an event for timestamp "
+ << expectedTimestamp;
+ const auto& event = std::get<0>(args.value());
+ for (int i = 0; i < DisplayEventReceiver::kFrameTimelinesLength; i++) {
+ if (i > 0) {
+ EXPECT_GT(event.vsync.frameTimelines[i].deadlineTimestamp,
+ event.vsync.frameTimelines[i - 1].deadlineTimestamp)
+ << "Deadline timestamp out of order for frame timeline " << i;
+ EXPECT_GT(event.vsync.frameTimelines[i].expectedVSyncTimestamp,
+ event.vsync.frameTimelines[i - 1].expectedVSyncTimestamp)
+ << "Expected vsync timestamp out of order for frame timeline " << i;
+ }
+ if (event.vsync.frameTimelines[i].deadlineTimestamp == preferredDeadline) {
+ EXPECT_EQ(i, event.vsync.preferredFrameTimelineIndex)
+ << "Preferred frame timeline index should be " << i;
+ // For the platform-preferred frame timeline, the vsync ID is 0 because the first frame
+ // timeline is made before the rest.
+ EXPECT_EQ(0, event.vsync.frameTimelines[i].vsyncId)
+ << "Vsync ID incorrect for frame timeline " << i;
+ } else {
+ // Vsync ID 0 is used for the preferred frame timeline.
+ EXPECT_EQ(i + 1, event.vsync.frameTimelines[i].vsyncId)
+ << "Vsync ID incorrect for frame timeline " << i;
+ }
+ }
+}
+
void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
bool expectedConnected) {
auto args = mConnectionEventCallRecorder.waitForCall();
@@ -344,6 +378,19 @@
expectVSyncSetEnabledCallReceived(false);
}
+TEST_F(EventThreadTest, requestNextVsyncEventFrameTimelinesCorrect) {
+ // Signal that we want the next vsync event to be posted to the connection
+ mThread->requestNextVsync(mConnection);
+
+ expectVSyncSetEnabledCallReceived(true);
+
+ // Use the received callback to signal a vsync event.
+ // The interceptor should receive the event, as well as the connection.
+ mCallback->onVSyncEvent(123, 456, 789);
+ expectInterceptCallReceived(123);
+ expectVsyncEventFrameTimelinesCorrect(123, 789);
+}
+
TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
// Create a first connection, register it, and request a vsync rate of zero.
ConnectionEventRecorder firstConnectionEventRecorder{0};
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index dd20d0d..c23fcc7 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -289,7 +289,7 @@
}
static void setLayerDrawingParent(const sp<Layer>& layer, const sp<Layer>& drawingParent) {
- layer->mDrawingParent = drawingParent.get();
+ layer->mDrawingParent = drawingParent;
}
/* ------------------------------------------------------------------------
diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc
index 0de0f9e..1612743 100644
--- a/services/vr/virtual_touchpad/virtual_touchpad.rc
+++ b/services/vr/virtual_touchpad/virtual_touchpad.rc
@@ -2,4 +2,4 @@
class core
user system
group system input uhid
- writepid /dev/cpuset/system/tasks
+ task_profiles VrServiceCapacityNormal