Merge "Cache shaders for rounded corners and window transition."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 738c20f..1fbd2b3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1583,6 +1583,9 @@
RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index b60bbc0..d66066e 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -146,9 +146,11 @@
],
shared_libs: [
"libbase",
+ "libbinder",
"liblog",
"libprotobuf-cpp-full",
"libselinux",
+ "libutils",
"libziparchive",
],
static_libs: [
@@ -157,6 +159,7 @@
"lib_apex_manifest_proto",
"libavb",
"libdm",
+ "libvold_binder",
],
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 2efcf11..92fac66 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1648,7 +1648,8 @@
ATRACE_BEGIN("obb");
for (const auto& packageName : packageNames) {
- auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str());
+ auto obbCodePath = create_data_media_package_path(uuid_, userId,
+ "obb", packageName.c_str());
calculate_tree_size(obbCodePath, &extStats.codeSize);
}
ATRACE_END();
@@ -1982,7 +1983,8 @@
ATRACE_END();
ATRACE_BEGIN("obb");
- auto obbPath = create_data_media_obb_path(uuid_, "");
+ auto obbPath = StringPrintf("%s/Android/obb",
+ create_data_media_path(uuid_, userId).c_str());
calculate_tree_size(obbPath, &obbSize);
ATRACE_END();
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 72571cf..20142aa 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -58,6 +58,7 @@
using android::base::EndsWith;
using android::base::GetBoolProperty;
using android::base::GetProperty;
+using android::base::ReadFdToString;
using android::base::ReadFully;
using android::base::StringPrintf;
using android::base::WriteFully;
@@ -319,6 +320,7 @@
bool background_job_compile,
int profile_fd,
const char* class_loader_context,
+ const std::string& class_loader_context_fds,
int target_sdk_version,
bool enable_hidden_api_checks,
bool generate_compact_dex,
@@ -423,9 +425,14 @@
target_sdk_version_arg = StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
}
std::string class_loader_context_arg;
+ std::string class_loader_context_fds_arg;
if (class_loader_context != nullptr) {
class_loader_context_arg = StringPrintf("--class-loader-context=%s",
class_loader_context);
+ if (!class_loader_context_fds.empty()) {
+ class_loader_context_fds_arg = StringPrintf("--class-loader-context-fds=%s",
+ class_loader_context_fds.c_str());
+ }
}
if (swap_fd >= 0) {
@@ -518,6 +525,7 @@
AddArg(profile_arg);
AddArg(base_dir);
AddArg(class_loader_context_arg);
+ AddArg(class_loader_context_fds_arg);
if (generate_minidebug_info) {
AddArg(kMinidebugDex2oatFlag);
}
@@ -1514,14 +1522,15 @@
class RunDexoptAnalyzer : public ExecVHelper {
public:
RunDexoptAnalyzer(const std::string& dex_file,
- int vdex_fd,
- int oat_fd,
- int zip_fd,
- const std::string& instruction_set,
- const std::string& compiler_filter,
- bool profile_was_updated,
- bool downgrade,
- const char* class_loader_context) {
+ int vdex_fd,
+ int oat_fd,
+ int zip_fd,
+ const std::string& instruction_set,
+ const std::string& compiler_filter,
+ bool profile_was_updated,
+ bool downgrade,
+ const char* class_loader_context,
+ const std::string& class_loader_context_fds) {
CHECK_GE(zip_fd, 0);
// We always run the analyzer in the background job.
@@ -1540,6 +1549,10 @@
if (class_loader_context != nullptr) {
class_loader_context_arg += class_loader_context;
}
+ std::string class_loader_context_fds_arg = "--class-loader-context-fds=";
+ if (!class_loader_context_fds.empty()) {
+ class_loader_context_fds_arg += class_loader_context_fds;
+ }
// program name, dex file, isa, filter
AddArg(dex_file_arg);
@@ -1560,10 +1573,27 @@
}
if (class_loader_context != nullptr) {
AddArg(class_loader_context_arg.c_str());
+ if (!class_loader_context_fds.empty()) {
+ AddArg(class_loader_context_fds_arg.c_str());
+ }
}
PrepareArgs(dexoptanalyzer_bin);
}
+
+ // Dexoptanalyzer mode which flattens the given class loader context and
+ // prints a list of its dex files in that flattened order.
+ RunDexoptAnalyzer(const char* class_loader_context) {
+ CHECK(class_loader_context != nullptr);
+
+ // We always run the analyzer in the background job.
+ const char* dexoptanalyzer_bin = select_execution_binary(
+ kDexoptanalyzerPath, kDexoptanalyzerDebugPath, /*background_job_compile=*/ true);
+
+ AddArg("--flatten-class-loader-context");
+ AddArg(std::string("--class-loader-context=") + class_loader_context);
+ PrepareArgs(dexoptanalyzer_bin);
+ }
};
// Prepares the oat dir for the secondary dex files.
@@ -1743,6 +1773,95 @@
return true;
}
+static bool get_class_loader_context_dex_paths(const char* class_loader_context, int uid,
+ /* out */ std::vector<std::string>* context_dex_paths) {
+ if (class_loader_context == nullptr) {
+ return true;
+ }
+
+ LOG(DEBUG) << "Getting dex paths for context " << class_loader_context;
+
+ // Pipe to get the hash result back from our child process.
+ unique_fd pipe_read, pipe_write;
+ if (!Pipe(&pipe_read, &pipe_write)) {
+ PLOG(ERROR) << "Failed to create pipe";
+ return false;
+ }
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ // child -- drop privileges before continuing.
+ drop_capabilities(uid);
+
+ // Route stdout to `pipe_write`
+ while ((dup2(pipe_write, STDOUT_FILENO) == -1) && (errno == EINTR)) {}
+ pipe_write.reset();
+ pipe_read.reset();
+
+ RunDexoptAnalyzer run_dexopt_analyzer(class_loader_context);
+ run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
+ }
+
+ /* parent */
+ pipe_write.reset();
+
+ std::string str_dex_paths;
+ if (!ReadFdToString(pipe_read, &str_dex_paths)) {
+ PLOG(ERROR) << "Failed to read from pipe";
+ return false;
+ }
+ pipe_read.reset();
+
+ int return_code = wait_child(pid);
+ if (!WIFEXITED(return_code)) {
+ PLOG(ERROR) << "Error waiting for child dexoptanalyzer process";
+ return false;
+ }
+
+ constexpr int kFlattenClassLoaderContextSuccess = 50;
+ return_code = WEXITSTATUS(return_code);
+ if (return_code != kFlattenClassLoaderContextSuccess) {
+ LOG(ERROR) << "Dexoptanalyzer could not flatten class loader context, code=" << return_code;
+ return false;
+ }
+
+ if (!str_dex_paths.empty()) {
+ *context_dex_paths = android::base::Split(str_dex_paths, ":");
+ }
+ return true;
+}
+
+static int open_dex_paths(const std::vector<std::string>& dex_paths,
+ /* out */ std::vector<unique_fd>* zip_fds, /* out */ std::string* error_msg) {
+ for (const std::string& dex_path : dex_paths) {
+ zip_fds->emplace_back(open(dex_path.c_str(), O_RDONLY));
+ if (zip_fds->back().get() < 0) {
+ *error_msg = StringPrintf(
+ "installd cannot open '%s' for input during dexopt", dex_path.c_str());
+ if (errno == ENOENT) {
+ return kSecondaryDexDexoptAnalyzerSkippedNoFile;
+ } else {
+ return kSecondaryDexDexoptAnalyzerSkippedOpenZip;
+ }
+ }
+ }
+ return 0;
+}
+
+static std::string join_fds(const std::vector<unique_fd>& fds) {
+ std::stringstream ss;
+ bool is_first = true;
+ for (const unique_fd& fd : fds) {
+ if (is_first) {
+ is_first = false;
+ } else {
+ ss << ":";
+ }
+ ss << fd.get();
+ }
+ return ss.str();
+}
+
// Processes the dex_path as a secondary dex files and return true if the path dex file should
// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
// successfully.
@@ -1754,7 +1873,7 @@
int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
std::string* oat_dir_out, bool downgrade, const char* class_loader_context,
- /* out */ std::string* error_msg) {
+ const std::vector<std::string>& context_dex_paths, /* out */ std::string* error_msg) {
LOG(DEBUG) << "Processing secondary dex path " << dex_path;
int storage_flag;
if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag, error_msg)) {
@@ -1794,6 +1913,13 @@
}
}
+ // Open class loader context dex files.
+ std::vector<unique_fd> context_zip_fds;
+ int open_dex_paths_rc = open_dex_paths(context_dex_paths, &context_zip_fds, error_msg);
+ if (open_dex_paths_rc != 0) {
+ _exit(open_dex_paths_rc);
+ }
+
// Prepare the oat directories.
if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set)) {
_exit(kSecondaryDexDexoptAnalyzerSkippedPrepareDir);
@@ -1825,7 +1951,8 @@
instruction_set,
compiler_filter, profile_was_updated,
downgrade,
- class_loader_context);
+ class_loader_context,
+ join_fds(context_zip_fds));
run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
}
@@ -1913,10 +2040,16 @@
// Check if we're dealing with a secondary dex file and if we need to compile it.
std::string oat_dir_str;
+ std::vector<std::string> context_dex_paths;
if (is_secondary_dex) {
+ if (!get_class_loader_context_dex_paths(class_loader_context, uid, &context_dex_paths)) {
+ *error_msg = "Failed acquiring context dex paths";
+ return -1; // We had an error, logged in the process method.
+ }
+
if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
- downgrade, class_loader_context, error_msg)) {
+ downgrade, class_loader_context, context_dex_paths, error_msg)) {
oat_dir = oat_dir_str.c_str();
if (dexopt_needed == NO_DEXOPT_NEEDED) {
return 0; // Nothing to do, report success.
@@ -1928,7 +2061,7 @@
return -1; // We had an error, logged in the process method.
}
} else {
- // Currently these flags are only use for secondary dex files.
+ // Currently these flags are only used for secondary dex files.
// Verify that they are not set for primary apks.
CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
@@ -1942,6 +2075,13 @@
return -1;
}
+ // Open class loader context dex files.
+ std::vector<unique_fd> context_input_fds;
+ if (open_dex_paths(context_dex_paths, &context_input_fds, error_msg) != 0) {
+ LOG(ERROR) << *error_msg;
+ return -1;
+ }
+
// Create the output OAT file.
char out_oat_path[PKG_PATH_MAX];
Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
@@ -2010,6 +2150,7 @@
background_job_compile,
reference_profile_fd.get(),
class_loader_context,
+ join_fds(context_input_fds),
target_sdk_version,
enable_hidden_api_checks,
generate_compact_dex,
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 0fdc9d6..2e2cc18 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -25,6 +25,7 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
+#include <libdm/dm.h>
#include <selinux/android.h>
#include <apexd.h>
@@ -77,6 +78,37 @@
}
}
+static void TryExtraMount(const char* name, const char* slot, const char* target) {
+ std::string partition_name = StringPrintf("%s%s", name, slot);
+
+ // See whether update_engine mounted a logical partition.
+ {
+ auto& dm = dm::DeviceMapper::Instance();
+ if (dm.GetState(partition_name) != dm::DmDeviceState::INVALID) {
+ std::string path;
+ if (dm.GetDmDevicePathByName(partition_name, &path)) {
+ int mount_result = mount(path.c_str(),
+ target,
+ "ext4",
+ MS_RDONLY,
+ /* data */ nullptr);
+ if (mount_result == 0) {
+ return;
+ }
+ }
+ }
+ }
+
+ // Fall back and attempt a direct mount.
+ std::string block_device = StringPrintf("/dev/block/by-name/%s", partition_name.c_str());
+ int mount_result = mount(block_device.c_str(),
+ target,
+ "ext4",
+ MS_RDONLY,
+ /* data */ nullptr);
+ UNUSED(mount_result);
+}
+
// Entry for otapreopt_chroot. Expected parameters are:
// [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params]
// The file descriptor denoted by status-fd will be closed. The rest of the parameters will
@@ -137,29 +169,11 @@
LOG(ERROR) << "Target slot suffix not legal: " << arg[2];
exit(207);
}
- {
- std::string vendor_partition = StringPrintf("/dev/block/by-name/vendor%s",
- arg[2]);
- int vendor_result = mount(vendor_partition.c_str(),
- "/postinstall/vendor",
- "ext4",
- MS_RDONLY,
- /* data */ nullptr);
- UNUSED(vendor_result);
- }
+ TryExtraMount("vendor", arg[2], "/postinstall/vendor");
// Try to mount the product partition. update_engine doesn't do this for us, but we
// want it for product APKs. Same notes as vendor above.
- {
- std::string product_partition = StringPrintf("/dev/block/by-name/product%s",
- arg[2]);
- int product_result = mount(product_partition.c_str(),
- "/postinstall/product",
- "ext4",
- MS_RDONLY,
- /* data */ nullptr);
- UNUSED(product_result);
- }
+ TryExtraMount("product", arg[2], "/postinstall/product");
// Setup APEX mount point and its security context.
static constexpr const char* kPostinstallApexDir = "/postinstall/apex";
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 71b710b..36d5a60 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -327,16 +327,21 @@
void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
bool should_binder_call_succeed, bool should_dex_be_compiled = true,
- /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1) {
+ /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1,
+ const char* class_loader_context = nullptr) {
if (uid == -1) {
uid = kTestAppUid;
}
+ if (class_loader_context == nullptr) {
+ class_loader_context = "&";
+ }
std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
int32_t dexopt_needed = 0; // does not matter;
std::unique_ptr<std::string> out_path = nullptr; // does not matter
int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag;
std::string compiler_filter = "speed-profile";
- std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
+ std::unique_ptr<std::string> class_loader_context_ptr(
+ new std::string(class_loader_context));
std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
bool downgrade = false;
int32_t target_sdk_version = 0; // default
@@ -555,12 +560,26 @@
/*binder_ok*/ true, /*compile_ok*/ true);
}
+TEST_F(DexoptTest, DexoptSecondaryCeWithContext) {
+ LOG(INFO) << "DexoptSecondaryCeWithContext";
+ std::string class_loader_context = "PCL[" + secondary_dex_ce_ + "]";
+ CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
+ /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str());
+}
+
TEST_F(DexoptTest, DexoptSecondaryDe) {
LOG(INFO) << "DexoptSecondaryDe";
CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
/*binder_ok*/ true, /*compile_ok*/ true);
}
+TEST_F(DexoptTest, DexoptSecondaryDeWithContext) {
+ LOG(INFO) << "DexoptSecondaryDeWithContext";
+ std::string class_loader_context = "PCL[" + secondary_dex_de_ + "]";
+ CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
+ /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str());
+}
+
TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
LOG(INFO) << "DexoptSecondaryDoesNotExist";
// If the file validates but does not exist we do not treat it as an error.
@@ -576,7 +595,7 @@
CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
/*binder_ok*/ false, /*compile_ok*/ false, &status);
EXPECT_STREQ(status.toString8().c_str(),
- "Status(-8): '-1: Dexoptanalyzer path validation failed'");
+ "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'");
}
TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
@@ -585,7 +604,7 @@
CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
/*binder_ok*/ false, /*compile_ok*/ false, &status);
EXPECT_STREQ(status.toString8().c_str(),
- "Status(-8): '-1: Dexoptanalyzer path validation failed'");
+ "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'");
}
TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
@@ -593,7 +612,8 @@
binder::Status status;
CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
/*binder_ok*/ false, /*compile_ok*/ false, &status, kSystemUid);
- EXPECT_STREQ(status.toString8().c_str(), "Status(-8): '-1: Dexoptanalyzer open zip failed'");
+ EXPECT_STREQ(status.toString8().c_str(),
+ "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer open zip failed'");
}
TEST_F(DexoptTest, DexoptPrimaryPublic) {
@@ -615,7 +635,7 @@
DEX2OAT_FROM_SCRATCH,
&status);
EXPECT_STREQ(status.toString8().c_str(),
- "Status(-8): \'256: Dex2oat invocation for "
+ "Status(-8, EX_SERVICE_SPECIFIC): \'256: Dex2oat invocation for "
"/data/app/com.installd.test.dexopt/base.jar failed: unspecified dex2oat error'");
}
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index da097db..4eb1df0 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -244,10 +244,6 @@
return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
}
-std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name) {
- return StringPrintf("%s/media/obb/%s", create_data_path(volume_uuid).c_str(), package_name);
-}
-
std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
const char* data_type, const char* package_name) {
return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 955d524..6a42026 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -75,7 +75,6 @@
userid_t user, int32_t snapshot_id, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
-std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
const char* data_type, const char* package_name);
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index 5c1cab6..ad7791e 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -46,12 +46,6 @@
<feature name="android.software.cant_save_state" />
<feature name="android.software.secure_lock_screen" />
- <!-- Feature to specify if the device supports adding device admins. -->
- <feature name="android.software.device_admin" />
-
- <!-- Feature to specify if the device support managed users. -->
- <feature name="android.software.managed_users" />
-
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 247dc8d..bc63d31 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -68,7 +68,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& commands,
- int64_t desiredPresentTime) {
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -86,6 +87,8 @@
data.writeStrongBinder(applyToken);
commands.write(data);
data.writeInt64(desiredPresentTime);
+ data.writeStrongBinder(uncacheBuffer.token);
+ data.writeUint64(uncacheBuffer.cacheId);
remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
@@ -970,8 +973,13 @@
inputWindowCommands.read(data);
int64_t desiredPresentTime = data.readInt64();
+
+ cached_buffer_t uncachedBuffer;
+ uncachedBuffer.token = data.readStrongBinder();
+ uncachedBuffer.cacheId = data.readUint64();
+
setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands,
- desiredPresentTime);
+ desiredPresentTime, uncachedBuffer);
return NO_ERROR;
}
case BOOT_FINISHED: {
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 84ba644..f6ca9e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -95,7 +95,7 @@
}
output.writeStrongBinder(cachedBuffer.token);
- output.writeInt32(cachedBuffer.bufferId);
+ output.writeUint64(cachedBuffer.cacheId);
output.writeParcelable(metadata);
output.writeFloat(bgColorAlpha);
@@ -173,7 +173,7 @@
}
cachedBuffer.token = input.readStrongBinder();
- cachedBuffer.bufferId = input.readInt32();
+ cachedBuffer.cacheId = input.readUint64();
input.readParcelable(&metadata);
bgColorAlpha = input.readFloat();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index b0e8275..39cd62f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -233,6 +233,8 @@
// ---------------------------------------------------------------------------
+void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId);
+
class BufferCache : public Singleton<BufferCache> {
public:
BufferCache() : token(new BBinder()) {}
@@ -241,77 +243,57 @@
return IInterface::asBinder(TransactionCompletedListener::getIInstance());
}
- int32_t getId(const sp<GraphicBuffer>& buffer) {
+ status_t getCacheId(const sp<GraphicBuffer>& buffer, uint64_t* cacheId) {
std::lock_guard<std::mutex> lock(mMutex);
- auto itr = mBuffers.find(buffer);
+ auto itr = mBuffers.find(buffer->getId());
if (itr == mBuffers.end()) {
- return -1;
+ return BAD_VALUE;
}
- itr->second.counter = getCounter();
- return itr->second.id;
+ itr->second = getCounter();
+ *cacheId = buffer->getId();
+ return NO_ERROR;
}
- int32_t cache(const sp<GraphicBuffer>& buffer) {
+ uint64_t cache(const sp<GraphicBuffer>& buffer) {
std::lock_guard<std::mutex> lock(mMutex);
- int32_t bufferId = getNextAvailableId();
+ if (mBuffers.size() >= BUFFER_CACHE_MAX_SIZE) {
+ evictLeastRecentlyUsedBuffer();
+ }
- mBuffers[buffer].id = bufferId;
- mBuffers[buffer].counter = getCounter();
- return bufferId;
+ buffer->addDeathCallback(bufferCacheCallback, nullptr);
+
+ mBuffers[buffer->getId()] = getCounter();
+ return buffer->getId();
+ }
+
+ void uncache(uint64_t cacheId) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ uncacheLocked(cacheId);
+ }
+
+ void uncacheLocked(uint64_t cacheId) REQUIRES(mMutex) {
+ mBuffers.erase(cacheId);
+ SurfaceComposerClient::doUncacheBufferTransaction(cacheId);
}
private:
- int32_t evictDestroyedBuffer() REQUIRES(mMutex) {
+ void evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
auto itr = mBuffers.begin();
- while (itr != mBuffers.end()) {
- auto& buffer = itr->first;
- if (buffer == nullptr || buffer.promote() == nullptr) {
- int32_t bufferId = itr->second.id;
- mBuffers.erase(itr);
- return bufferId;
- }
- itr++;
- }
- return -1;
- }
-
- int32_t evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
- if (mBuffers.size() < 0) {
- return -1;
- }
- auto itr = mBuffers.begin();
- uint64_t minCounter = itr->second.counter;
+ uint64_t minCounter = itr->second;
auto minBuffer = itr;
itr++;
while (itr != mBuffers.end()) {
- uint64_t counter = itr->second.counter;
+ uint64_t counter = itr->second;
if (counter < minCounter) {
minCounter = counter;
minBuffer = itr;
}
itr++;
}
- int32_t minBufferId = minBuffer->second.id;
- mBuffers.erase(minBuffer);
- return minBufferId;
- }
-
- int32_t getNextAvailableId() REQUIRES(mMutex) {
- static int32_t id = 0;
- if (id + 1 < BUFFER_CACHE_MAX_SIZE) {
- return id++;
- }
-
- // There are no more valid cache ids. To set additional buffers, evict existing buffers
- // and reuse their cache ids.
- int32_t bufferId = evictDestroyedBuffer();
- if (bufferId > 0) {
- return bufferId;
- }
- return evictLeastRecentlyUsedBuffer();
+ uncacheLocked(minBuffer->first);
}
uint64_t getCounter() REQUIRES(mMutex) {
@@ -319,18 +301,8 @@
return counter++;
}
- struct Metadata {
- // The cache id of a buffer that can be set to ISurfaceComposer. When ISurfaceComposer
- // recieves this id, it can retrieve the buffer from its cache. Caching GraphicBuffers
- // is important because sending them across processes is expensive.
- int32_t id = 0;
- // When a buffer is set, a counter is incremented and stored in the cache's metadata.
- // When an buffer must be evicted, the entry with the lowest counter value is chosen.
- uint64_t counter = 0;
- };
-
std::mutex mMutex;
- std::map<wp<GraphicBuffer>, Metadata> mBuffers GUARDED_BY(mMutex);
+ std::map<uint64_t /*Cache id*/, uint64_t /*counter*/> mBuffers GUARDED_BY(mMutex);
// Used by ISurfaceComposer to identify which process is sending the cached buffer.
sp<IBinder> token;
@@ -338,6 +310,11 @@
ANDROID_SINGLETON_STATIC_INSTANCE(BufferCache);
+void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId) {
+ // GraphicBuffer id's are used as the cache ids.
+ BufferCache::getInstance().uncache(graphicBufferId);
+}
+
// ---------------------------------------------------------------------------
SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
@@ -385,6 +362,9 @@
mInputWindowCommands.merge(other.mInputWindowCommands);
other.mInputWindowCommands.clear();
+ mContainsBuffer = other.mContainsBuffer;
+ other.mContainsBuffer = false;
+
return *this;
}
@@ -401,7 +381,50 @@
s.state.parentHandleForChild = nullptr;
composerStates.add(s);
- sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1);
+ sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {});
+}
+
+void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+ cached_buffer_t uncacheBuffer;
+ uncacheBuffer.token = BufferCache::getInstance().getToken();
+ uncacheBuffer.cacheId = cacheId;
+
+ sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer);
+}
+
+void SurfaceComposerClient::Transaction::cacheBuffers() {
+ if (!mContainsBuffer) {
+ return;
+ }
+
+ size_t count = 0;
+ for (auto& [sc, cs] : mComposerStates) {
+ layer_state_t* s = getLayerState(sc);
+ if (!(s->what & layer_state_t::eBufferChanged)) {
+ continue;
+ }
+
+ uint64_t cacheId = 0;
+ status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId);
+ if (ret == NO_ERROR) {
+ s->what &= ~static_cast<uint32_t>(layer_state_t::eBufferChanged);
+ s->buffer = nullptr;
+ } else {
+ cacheId = BufferCache::getInstance().cache(s->buffer);
+ }
+ s->what |= layer_state_t::eCachedBufferChanged;
+ s->cachedBuffer.token = BufferCache::getInstance().getToken();
+ s->cachedBuffer.cacheId = cacheId;
+
+ // If we have more buffers than the size of the cache, we should stop caching so we don't
+ // evict other buffers in this transaction
+ count++;
+ if (count >= BUFFER_CACHE_MAX_SIZE) {
+ break;
+ }
+ }
}
status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
@@ -437,6 +460,8 @@
}
mListenerCallbacks.clear();
+ cacheBuffers();
+
Vector<ComposerState> composerStates;
Vector<DisplayState> displayStates;
uint32_t flags = 0;
@@ -468,7 +493,8 @@
sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands,
- mDesiredPresentTime);
+ mDesiredPresentTime,
+ {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/);
mInputWindowCommands.clear();
mStatus = NO_ERROR;
return NO_ERROR;
@@ -882,20 +908,12 @@
mStatus = BAD_INDEX;
return *this;
}
-
- int32_t bufferId = BufferCache::getInstance().getId(buffer);
- if (bufferId < 0) {
- bufferId = BufferCache::getInstance().cache(buffer);
-
- s->what |= layer_state_t::eBufferChanged;
- s->buffer = buffer;
- }
-
- s->what |= layer_state_t::eCachedBufferChanged;
- s->cachedBuffer.token = BufferCache::getInstance().getToken();
- s->cachedBuffer.bufferId = bufferId;
+ s->what |= layer_state_t::eBufferChanged;
+ s->buffer = buffer;
registerSurfaceControlForCallback(sc);
+
+ mContainsBuffer = true;
return *this;
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3dffa8f..0ef5b39 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -40,6 +40,7 @@
namespace android {
// ----------------------------------------------------------------------------
+struct cached_buffer_t;
struct ComposerState;
struct DisplayState;
struct DisplayInfo;
@@ -131,7 +132,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime) = 0;
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) = 0;
/* signal that we're done booting.
* Requires ACCESS_SURFACE_FLINGER permission
@@ -194,8 +196,7 @@
* of the buffer. The caller should pick the data space and pixel format
* that it can consume.
*
- * At the moment, sourceCrop is ignored and is always set to the visible
- * region (projected display viewport) of the screen.
+ * sourceCrop is the crop on the logical display.
*
* reqWidth and reqHeight specifies the size of the buffer. When either
* of them is 0, they are set to the size of the logical display viewport.
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 35e795c..77bf8f1 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -41,6 +41,11 @@
class Parcel;
class ISurfaceComposerClient;
+struct cached_buffer_t {
+ sp<IBinder> token = nullptr;
+ uint64_t cacheId;
+};
+
/*
* Used to communicate layer information between SurfaceFlinger and its clients.
*/
@@ -133,10 +138,6 @@
float dtdy{0};
float dsdy{0};
};
- struct cached_buffer_t {
- sp<IBinder> token = nullptr;
- int32_t bufferId = -1;
- };
sp<IBinder> surface;
uint64_t what;
float x;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 39d6d13..593a5e7 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -165,6 +165,12 @@
static void doDropReferenceTransaction(const sp<IBinder>& handle,
const sp<ISurfaceComposerClient>& client);
+ /**
+ * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is
+ * in order with other transactions that use buffers.
+ */
+ static void doUncacheBufferTransaction(uint64_t cacheId);
+
// Queries whether a given display is wide color display.
static status_t isWideColorDisplay(const sp<IBinder>& display, bool* outIsWideColorDisplay);
@@ -279,6 +285,9 @@
bool mAnimation = false;
bool mEarlyWakeup = false;
+ // Indicates that the Transaction contains a buffer that should be cached
+ bool mContainsBuffer = false;
+
// mDesiredPresentTime is the time in nanoseconds that the client would like the transaction
// to be presented. When it is not possible to present at exactly that time, it will be
// presented after the time has passed.
@@ -297,6 +306,7 @@
layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
DisplayState& getDisplayState(const sp<IBinder>& token);
+ void cacheBuffers();
void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc);
public:
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 06fe86c..94b669d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -560,7 +560,8 @@
const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/,
const InputWindowCommands& /*inputWindowCommands*/,
- int64_t /*desiredPresentTime*/) override {}
+ int64_t /*desiredPresentTime*/,
+ const cached_buffer_t& /*cachedBuffer*/) override {}
void bootFinished() override {}
bool authenticateSurfaceTexture(
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 165b75a..da959e3 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -422,18 +422,6 @@
int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26);
/**
- * Lock an AHardwareBuffer for direct CPU access.
- *
- * This function is the same as the above lock function, but passes back
- * additional information about the bytes per pixel and the bytes per stride
- * of the locked buffer. If the bytes per pixel or bytes per stride are unknown
- * or variable, or if the underlying mapper implementation does not support returning
- * additional information, then this call will fail with INVALID_OPERATION
- */
-int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
- int32_t fence, const ARect* rect, void** outVirtualAddress,
- int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
-/**
* Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
*
* This function is similar to AHardwareBuffer_lock, but can lock multi-planar
@@ -518,6 +506,18 @@
*/
int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_IN(29);
+/**
+ * Lock an AHardwareBuffer for direct CPU access.
+ *
+ * This function is the same as the above lock function, but passes back
+ * additional information about the bytes per pixel and the bytes per stride
+ * of the locked buffer. If the bytes per pixel or bytes per stride are unknown
+ * or variable, or if the underlying mapper implementation does not support returning
+ * additional information, then this call will fail with INVALID_OPERATION
+ */
+int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
+ int32_t fence, const ARect* rect, void** outVirtualAddress,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
#endif // __ANDROID_API__ >= 29
__END_DECLS
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index e521b61..755418e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -167,6 +167,12 @@
override_export_include_dirs: ["include_vndk"],
},
},
+ header_libs: [
+ "libnativewindow_headers",
+ ],
+ export_header_lib_headers: [
+ "libnativewindow_headers",
+ ],
}
subdirs = [
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index ed7ccb0b..4ce891e 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -110,7 +110,7 @@
}
struct sync_file_info* finfo = sync_file_info(mFenceFd);
- if (finfo == NULL) {
+ if (finfo == nullptr) {
ALOGE("sync_file_info returned NULL for fd %d", mFenceFd.get());
return SIGNAL_TIME_INVALID;
}
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index f800627..40df260 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -76,7 +76,7 @@
usage_deprecated = 0;
usage = 0;
layerCount = 0;
- handle = NULL;
+ handle = nullptr;
}
// deprecated
@@ -133,6 +133,9 @@
if (handle) {
free_handle();
}
+ for (auto& [callback, context] : mDeathCallbacks) {
+ callback(context, mId);
+ }
}
void GraphicBuffer::free_handle()
@@ -143,7 +146,7 @@
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
}
- handle = NULL;
+ handle = nullptr;
}
status_t GraphicBuffer::initCheck() const {
@@ -178,7 +181,7 @@
if (handle) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
- handle = 0;
+ handle = nullptr;
}
return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
}
@@ -371,14 +374,29 @@
}
size_t GraphicBuffer::getFlattenedSize() const {
+#ifndef LIBUI_IN_VNDK
+ if (mBufferHubBuffer != nullptr) {
+ return 48;
+ }
+#endif
return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
}
size_t GraphicBuffer::getFdCount() const {
+#ifndef LIBUI_IN_VNDK
+ if (mBufferHubBuffer != nullptr) {
+ return 0;
+ }
+#endif
return static_cast<size_t>(handle ? mTransportNumFds : 0);
}
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
+#ifndef LIBUI_IN_VNDK
+ if (mBufferHubBuffer != nullptr) {
+ return flattenBufferHubBuffer(buffer, size, fds, count);
+ }
+#endif
size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
if (size < sizeNeeded) return NO_MEMORY;
@@ -405,7 +423,7 @@
buf[11] = int32_t(mTransportNumInts);
memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
memcpy(buf + 13, handle->data + handle->numFds,
- static_cast<size_t>(mTransportNumInts) * sizeof(int));
+ static_cast<size_t>(mTransportNumInts) * sizeof(int));
}
buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
@@ -414,17 +432,11 @@
fds += mTransportNumFds;
count -= static_cast<size_t>(mTransportNumFds);
}
-
return NO_ERROR;
}
-status_t GraphicBuffer::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count) {
- if (size < 12 * sizeof(int)) {
- android_errorWriteLog(0x534e4554, "114223584");
- return NO_MEMORY;
- }
-
+status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds,
+ size_t& count) {
int const* buf = static_cast<int const*>(buffer);
// NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
@@ -436,10 +448,21 @@
} else if (buf[0] == 'GBFR') {
// old version, when usage bits were 32-bits
flattenWordCount = 12;
+ } else if (buf[0] == 'BHBB') { // BufferHub backed buffer.
+#ifndef LIBUI_IN_VNDK
+ return unflattenBufferHubBuffer(buffer, size, fds, count);
+#else
+ return BAD_TYPE;
+#endif
} else {
return BAD_TYPE;
}
+ if (size < 12 * sizeof(int)) {
+ android_errorWriteLog(0x534e4554, "114223584");
+ return NO_MEMORY;
+ }
+
const size_t numFds = static_cast<size_t>(buf[10]);
const size_t numInts = static_cast<size_t>(buf[11]);
@@ -452,7 +475,7 @@
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
return BAD_VALUE;
}
@@ -480,13 +503,13 @@
} else {
usage = uint64_t(usage_deprecated);
}
- native_handle* h = native_handle_create(
- static_cast<int>(numFds), static_cast<int>(numInts));
+ native_handle* h =
+ native_handle_create(static_cast<int>(numFds), static_cast<int>(numInts));
if (!h) {
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
ALOGE("unflatten: native_handle_create failed");
return NO_MEMORY;
}
@@ -497,7 +520,7 @@
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
}
mId = static_cast<uint64_t>(buf[7]) << 32;
@@ -507,7 +530,7 @@
mOwner = ownHandle;
- if (handle != 0) {
+ if (handle != nullptr) {
buffer_handle_t importedHandle;
status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
@@ -515,7 +538,7 @@
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
- handle = NULL;
+ handle = nullptr;
ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
return err;
}
@@ -530,11 +553,87 @@
size -= sizeNeeded;
fds += numFds;
count -= numFds;
-
return NO_ERROR;
}
+void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) {
+ mDeathCallbacks.emplace_back(deathCallback, context);
+}
+
#ifndef LIBUI_IN_VNDK
+status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds,
+ size_t& count) const {
+ sp<NativeHandle> tokenHandle = mBufferHubBuffer->duplicate();
+ if (tokenHandle == nullptr || tokenHandle->handle() == nullptr ||
+ tokenHandle->handle()->numFds != 0) {
+ return BAD_VALUE;
+ }
+
+ // Size needed for one label, one number of ints inside the token, one generation number and
+ // the token itself.
+ int numIntsInToken = tokenHandle->handle()->numInts;
+ const size_t sizeNeeded = static_cast<size_t>(3 + numIntsInToken) * sizeof(int);
+ if (size < sizeNeeded) {
+ ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__,
+ static_cast<int>(sizeNeeded), static_cast<int>(size));
+ return NO_MEMORY;
+ }
+ size -= sizeNeeded;
+
+ int* buf = static_cast<int*>(buffer);
+ buf[0] = 'BHBB';
+ buf[1] = numIntsInToken;
+ memcpy(buf + 2, tokenHandle->handle()->data, static_cast<size_t>(numIntsInToken) * sizeof(int));
+ buf[2 + numIntsInToken] = static_cast<int32_t>(mGenerationNumber);
+
+ // Do not pass fds if it is BufferHubBuffer backed GraphicBuffer. Not modifying fds or count.
+ fds += 0;
+ count -= 0;
+ return NO_ERROR;
+}
+
+status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& size, int const*& fds,
+ size_t& count) {
+ const int* buf = static_cast<const int*>(buffer);
+ int numIntsInToken = buf[1];
+ // Size needed for one label, one number of ints inside the token, one generation number and
+ // the token itself.
+ const size_t sizeNeeded = static_cast<size_t>(3 + numIntsInToken) * sizeof(int);
+ if (size < sizeNeeded) {
+ ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__,
+ static_cast<int>(sizeNeeded), static_cast<int>(size));
+ return NO_MEMORY;
+ }
+ size -= sizeNeeded;
+ native_handle_t* importToken = native_handle_create(/*numFds=*/0, /*numInts=*/numIntsInToken);
+ memcpy(importToken->data, buf + 2, static_cast<size_t>(buf[1]) * sizeof(int));
+ sp<NativeHandle> importTokenHandle = NativeHandle::create(importToken, /*ownHandle=*/true);
+ std::unique_ptr<BufferHubBuffer> bufferHubBuffer = BufferHubBuffer::import(importTokenHandle);
+ if (bufferHubBuffer == nullptr || bufferHubBuffer.get() == nullptr) {
+ return BAD_VALUE;
+ }
+ // Reconstruct this GraphicBuffer object using the new BufferHubBuffer object.
+ if (handle) {
+ free_handle();
+ }
+ mId = 0;
+ mGenerationNumber = static_cast<uint32_t>(buf[2 + numIntsInToken]);
+ mInitCheck =
+ initWithHandle(bufferHubBuffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
+ bufferHubBuffer->desc().width, bufferHubBuffer->desc().height,
+ static_cast<PixelFormat>(bufferHubBuffer->desc().format),
+ bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage,
+ bufferHubBuffer->desc().stride);
+ mBufferId = bufferHubBuffer->id();
+ mBufferHubBuffer.reset(std::move(bufferHubBuffer.get()));
+
+ // BufferHubBuffer backed GraphicBuffer does not have flattened handle. Not modifying fds or
+ // count.
+ fds += 0;
+ count -= 0;
+ return NO_ERROR;
+}
+
bool GraphicBuffer::isBufferHubBuffer() const {
return mBufferHubBuffer != nullptr;
}
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 3bd3748..224dc2c 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -820,7 +820,7 @@
}
if (numRects > (UINT32_MAX / sizeof(Rect))) {
- android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, NULL, 0);
+ android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, nullptr, 0);
return NO_MEMORY;
}
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 1c88777..c137860 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -21,6 +21,8 @@
#include <sys/types.h>
#include <string>
+#include <utility>
+#include <vector>
#include <android/hardware_buffer.h>
#include <ui/ANativeObjectBase.h>
@@ -42,6 +44,8 @@
class GraphicBufferMapper;
+using GraphicBufferDeathCallback = std::function<void(void* /*context*/, uint64_t bufferId)>;
+
// ===========================================================================
// GraphicBuffer
// ===========================================================================
@@ -219,6 +223,8 @@
return mBufferMapper.getMapperVersion();
}
+ void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context);
+
#ifndef LIBUI_IN_VNDK
// Returns whether this GraphicBuffer is backed by BufferHubBuffer.
bool isBufferHubBuffer() const;
@@ -280,7 +286,33 @@
// IGBP::setGenerationNumber), attempts to attach the buffer will fail.
uint32_t mGenerationNumber;
+ // Send a callback when a GraphicBuffer dies.
+ //
+ // This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When
+ // A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes
+ // problems when trying to implicitcly cache across process boundaries. Ideally, both sides
+ // of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer
+ // would be destroyed. Unfortunately, when SurfaceFlinger has only a wp<> reference to the
+ // GraphicBuffer, it immediately goes out of scope in the SurfaceFlinger process. SurfaceFlinger
+ // must hold onto a sp<> to the buffer. When the GraphicBuffer goes out of scope in the app's
+ // process, the client side cache will get this callback. It erases the buffer from its cache
+ // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer.
+ std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>>
+ mDeathCallbacks;
+
#ifndef LIBUI_IN_VNDK
+ // Flatten this GraphicBuffer object if backed by BufferHubBuffer.
+ status_t flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, size_t& count) const;
+
+ // Unflatten into BufferHubBuffer backed GraphicBuffer.
+ // Unflatten will fail if the original GraphicBuffer object is destructed. For instance, a
+ // GraphicBuffer backed by BufferHubBuffer_1 flatten in process/thread A, transport the token
+ // to process/thread B through a socket, BufferHubBuffer_1 dies and bufferhub invalidated the
+ // token. Race condition occurs between the invalidation of the token in bufferhub process and
+ // process/thread B trying to unflatten and import the buffer with that token.
+ status_t unflattenBufferHubBuffer(void const*& buffer, size_t& size, int const*& fds,
+ size_t& count);
+
// Stores a BufferHubBuffer that handles buffer signaling, identification.
std::unique_ptr<BufferHubBuffer> mBufferHubBuffer;
#endif // LIBUI_IN_VNDK
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index c767ce0..a7c248c 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -74,4 +74,49 @@
EXPECT_EQ(gb->getBufferId(), b1_id);
}
+TEST_F(GraphicBufferTest, flattenAndUnflatten) {
+ std::unique_ptr<BufferHubBuffer> b1 =
+ BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+ kTestUsage, /*userMetadataSize=*/0);
+ ASSERT_NE(b1, nullptr);
+ sp<GraphicBuffer> gb1(new GraphicBuffer(std::move(b1)));
+ gb1->setGenerationNumber(42);
+
+ size_t flattenedSize = gb1->getFlattenedSize();
+ EXPECT_EQ(flattenedSize, 48);
+ size_t fdCount = gb1->getFdCount();
+ EXPECT_EQ(fdCount, 0);
+
+ int data[flattenedSize];
+ int fds[0];
+
+ // Make copies of needed items since flatten modifies them.
+ size_t flattenedSizeCopy = flattenedSize;
+ size_t fdCountCopy = fdCount;
+ void* dataStart = data;
+ int* fdsStart = fds;
+ status_t err = gb1->flatten(dataStart, flattenedSizeCopy, fdsStart, fdCountCopy);
+ ASSERT_EQ(err, NO_ERROR);
+ EXPECT_EQ(flattenedSizeCopy, 0);
+ EXPECT_EQ(fdCountCopy, 0);
+
+ size_t unflattenSize = flattenedSize;
+ size_t unflattenFdCount = fdCount;
+ const void* unflattenData = static_cast<const void*>(dataStart);
+ const int* unflattenFdData = static_cast<const int*>(fdsStart);
+
+ GraphicBuffer* gb2 = new GraphicBuffer();
+ err = gb2->unflatten(unflattenData, unflattenSize, unflattenFdData, unflattenFdCount);
+ ASSERT_EQ(err, NO_ERROR);
+ EXPECT_TRUE(gb2->isBufferHubBuffer());
+
+ EXPECT_EQ(gb2->getWidth(), kTestWidth);
+ EXPECT_EQ(gb2->getHeight(), kTestHeight);
+ EXPECT_EQ(static_cast<uint32_t>(gb2->getPixelFormat()), kTestFormat);
+ EXPECT_EQ(gb2->getUsage(), kTestUsage);
+ EXPECT_EQ(gb2->getLayerCount(), kTestLayerCount);
+ EXPECT_EQ(gb1->getBufferId(), gb2->getBufferId());
+ EXPECT_EQ(gb2->getGenerationNumber(), 42);
+}
+
} // namespace android
diff --git a/libs/ui/tools/lutgen.cpp b/libs/ui/tools/lutgen.cpp
index 97b0822..85a1ceb 100644
--- a/libs/ui/tools/lutgen.cpp
+++ b/libs/ui/tools/lutgen.cpp
@@ -85,11 +85,11 @@
static int handleCommandLineArgments(int argc, char* argv[]) {
static constexpr const char* OPTSTR = "h:d:s:t:";
static const struct option OPTIONS[] = {
- { "help", no_argument, 0, 'h' },
- { "dimension", required_argument, 0, 'd' },
- { "source", required_argument, 0, 's' },
- { "target", required_argument, 0, 't' },
- { 0, 0, 0, 0 } // termination of the option list
+ { "help", no_argument, nullptr, 'h' },
+ { "dimension", required_argument, nullptr, 'd' },
+ { "source", required_argument, nullptr, 's' },
+ { "target", required_argument, nullptr, 't' },
+ { nullptr, 0, nullptr, 0 } // termination of the option list
};
int opt;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index c100db7..54fa89f 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -314,6 +314,24 @@
}
}
+ if (cnx->minor == 5) {
+ // full list in egl_entries.in
+ if (!cnx->egl.eglCreateImage ||
+ !cnx->egl.eglDestroyImage ||
+ !cnx->egl.eglGetPlatformDisplay ||
+ !cnx->egl.eglCreatePlatformWindowSurface ||
+ !cnx->egl.eglCreatePlatformPixmapSurface ||
+ !cnx->egl.eglCreateSync ||
+ !cnx->egl.eglDestroySync ||
+ !cnx->egl.eglClientWaitSync ||
+ !cnx->egl.eglGetSyncAttrib ||
+ !cnx->egl.eglWaitSync) {
+ ALOGE("Driver indicates EGL 1.5 support, but does not have "
+ "a critical API");
+ cnx->minor = 4;
+ }
+ }
+
// the query strings are per-display
mVendorString = sVendorString;
mVersionString.clear();
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 0cc37a0..a45b8a5 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -4314,7 +4314,8 @@
nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime;
if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) {
android::util::stats_write(android::util::TOUCH_EVENT_REPORTED,
- mStatistics.min, mStatistics.max, mStatistics.mean(), mStatistics.stdev());
+ mStatistics.min, mStatistics.max,
+ mStatistics.mean(), mStatistics.stdev(), mStatistics.count);
mStatistics.reset(now);
}
}
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index cc78ece..f2d4c51 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -323,7 +323,8 @@
mCurrentTextureBuffer == nullptr
? nullptr
: mCurrentTextureBuffer->graphicBuffer(),
- mCurrentCrop, mCurrentTransform, mFilteringEnabled);
+ getCurrentCropLocked(), mCurrentTransform,
+ mFilteringEnabled);
}
nsecs_t BufferLayerConsumer::getTimestamp() {
@@ -380,6 +381,10 @@
Rect BufferLayerConsumer::getCurrentCrop() const {
Mutex::Autolock lock(mMutex);
+ return getCurrentCropLocked();
+}
+
+Rect BufferLayerConsumer::getCurrentCropLocked() const {
return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
? GLConsumer::scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
: mCurrentCrop;
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 32ccfbb..f4ca846 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -253,6 +253,9 @@
// access the current texture buffer.
status_t doFenceWaitLocked() const;
+ // getCurrentCropLocked returns the cropping rectangle of the current buffer.
+ Rect getCurrentCropLocked() const;
+
// The default consumer usage flags that BufferLayerConsumer always sets on its
// BufferQueue instance; these will be OR:d with any additional flags passed
// from the BufferLayerConsumer user. In particular, BufferLayerConsumer will always
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 1ca0b02..5efa4e0 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -139,7 +139,6 @@
bool BufferStateLayer::setTransform(uint32_t transform) {
if (mCurrentState.transform == transform) return false;
- mCurrentState.sequence++;
mCurrentState.transform = transform;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -170,7 +169,6 @@
}
if (mCurrentState.crop == c) return false;
- mCurrentState.sequence++;
mCurrentState.crop = c;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -242,7 +240,6 @@
bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
if (mCurrentState.hdrMetadata == hdrMetadata) return false;
- mCurrentState.sequence++;
mCurrentState.hdrMetadata = hdrMetadata;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -250,7 +247,6 @@
}
bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
- mCurrentState.sequence++;
mCurrentState.surfaceDamageRegion = surfaceDamage;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -259,7 +255,6 @@
bool BufferStateLayer::setApi(int32_t api) {
if (mCurrentState.api == api) return false;
- mCurrentState.sequence++;
mCurrentState.api = api;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -268,7 +263,6 @@
bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
if (mCurrentState.sidebandStream == sidebandStream) return false;
- mCurrentState.sequence++;
mCurrentState.sidebandStream = sidebandStream;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -551,6 +545,8 @@
mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
+ mCurrentStateModified = false;
+
return NO_ERROR;
}
@@ -600,7 +596,6 @@
s.buffer->handle, to_string(error).c_str(), static_cast<int32_t>(error));
}
- mCurrentStateModified = false;
mFrameNumber++;
}
diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp
index cb02d16..51ca45c 100644
--- a/services/surfaceflinger/BufferStateLayerCache.cpp
+++ b/services/surfaceflinger/BufferStateLayerCache.cpp
@@ -23,21 +23,14 @@
#include "BufferStateLayerCache.h"
-#define VALID_CACHE_ID(id) ((id) >= 0 || (id) < (BUFFER_CACHE_MAX_SIZE))
-
namespace android {
ANDROID_SINGLETON_STATIC_INSTANCE(BufferStateLayerCache);
BufferStateLayerCache::BufferStateLayerCache() : mDeathRecipient(new CacheDeathRecipient) {}
-void BufferStateLayerCache::add(sp<IBinder> processToken, int32_t id,
+void BufferStateLayerCache::add(const sp<IBinder>& processToken, uint64_t id,
const sp<GraphicBuffer>& buffer) {
- if (!VALID_CACHE_ID(id)) {
- ALOGE("failed to cache buffer: invalid buffer id");
- return;
- }
-
if (!processToken) {
ALOGE("failed to cache buffer: invalid process token");
return;
@@ -61,15 +54,33 @@
}
auto& processBuffers = mBuffers[processToken];
+
+ if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
+ ALOGE("failed to cache buffer: cache is full");
+ return;
+ }
+
processBuffers[id] = buffer;
}
-sp<GraphicBuffer> BufferStateLayerCache::get(sp<IBinder> processToken, int32_t id) {
- if (!VALID_CACHE_ID(id)) {
- ALOGE("failed to get buffer: invalid buffer id");
- return nullptr;
+void BufferStateLayerCache::erase(const sp<IBinder>& processToken, uint64_t id) {
+ if (!processToken) {
+ ALOGE("failed to uncache buffer: invalid process token");
+ return;
}
+ std::lock_guard lock(mMutex);
+
+ if (mBuffers.find(processToken) == mBuffers.end()) {
+ ALOGE("failed to uncache buffer: process token not found");
+ return;
+ }
+
+ auto& processBuffers = mBuffers[processToken];
+ processBuffers.erase(id);
+}
+
+sp<GraphicBuffer> BufferStateLayerCache::get(const sp<IBinder>& processToken, uint64_t id) {
if (!processToken) {
ALOGE("failed to cache buffer: invalid process token");
return nullptr;
@@ -82,8 +93,8 @@
return nullptr;
}
- if (id >= itr->second.size()) {
- ALOGE("failed to get buffer: id outside the bounds of the cache");
+ if (itr->second.find(id) == itr->second.end()) {
+ ALOGE("failed to get buffer: buffer not found");
return nullptr;
}
diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h
index ede3feb..415c09c 100644
--- a/services/surfaceflinger/BufferStateLayerCache.h
+++ b/services/surfaceflinger/BufferStateLayerCache.h
@@ -34,14 +34,16 @@
public:
BufferStateLayerCache();
- void add(sp<IBinder> processToken, int32_t id, const sp<GraphicBuffer>& buffer);
- sp<GraphicBuffer> get(sp<IBinder> processToken, int32_t id);
+ void add(const sp<IBinder>& processToken, uint64_t id, const sp<GraphicBuffer>& buffer);
+ void erase(const sp<IBinder>& processToken, uint64_t id);
+
+ sp<GraphicBuffer> get(const sp<IBinder>& processToken, uint64_t id);
void removeProcess(const wp<IBinder>& processToken);
private:
std::mutex mMutex;
- std::map<wp<IBinder> /*caching process*/, std::array<sp<GraphicBuffer>, BUFFER_CACHE_MAX_SIZE>>
+ std::map<wp<IBinder> /*caching process*/, std::map<uint64_t /*Cache id*/, sp<GraphicBuffer>>>
mBuffers GUARDED_BY(mMutex);
class CacheDeathRecipient : public IBinder::DeathRecipient {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 07fe03e..898d37e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1845,7 +1845,8 @@
setTransactionFlags(eTransactionNeeded);
}
-void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
+void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+ uint32_t traceFlags) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mCurrentState;
@@ -1853,114 +1854,129 @@
ui::Transform requestedTransform = state.active_legacy.transform;
ui::Transform transform = getTransform();
- layerInfo->set_id(sequence);
- layerInfo->set_name(getName().c_str());
- layerInfo->set_type(String8(getTypeId()));
+ if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
+ layerInfo->set_id(sequence);
+ layerInfo->set_name(getName().c_str());
+ layerInfo->set_type(String8(getTypeId()));
- for (const auto& child : children) {
- layerInfo->add_children(child->sequence);
- }
-
- for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
- sp<Layer> strongRelative = weakRelative.promote();
- if (strongRelative != nullptr) {
- layerInfo->add_relatives(strongRelative->sequence);
+ for (const auto& child : children) {
+ layerInfo->add_children(child->sequence);
}
- }
- LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
- [&]() { return layerInfo->mutable_transparent_region(); });
- LayerProtoHelper::writeToProto(visibleRegion,
- [&]() { return layerInfo->mutable_visible_region(); });
- LayerProtoHelper::writeToProto(surfaceDamageRegion,
- [&]() { return layerInfo->mutable_damage_region(); });
-
- layerInfo->set_layer_stack(getLayerStack());
- layerInfo->set_z(state.z);
-
- LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
- [&]() { return layerInfo->mutable_position(); });
-
- LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(), [&]() {
- return layerInfo->mutable_requested_position();
- });
-
- LayerProtoHelper::writeSizeToProto(state.active_legacy.w, state.active_legacy.h,
- [&]() { return layerInfo->mutable_size(); });
-
- LayerProtoHelper::writeToProto(state.crop_legacy, [&]() { return layerInfo->mutable_crop(); });
- layerInfo->set_corner_radius(getRoundedCornerState().radius);
-
- layerInfo->set_is_opaque(isOpaque(state));
- layerInfo->set_invalidate(contentDirty);
-
- // XXX (b/79210409) mCurrentDataSpace is not protected
- layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
-
- layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
- LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
- LayerProtoHelper::writeToProto(state.color,
- [&]() { return layerInfo->mutable_requested_color(); });
- layerInfo->set_flags(state.flags);
-
- LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
- LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform());
-
- auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
- if (parent != nullptr) {
- layerInfo->set_parent(parent->sequence);
- } else {
- layerInfo->set_parent(-1);
- }
-
- auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
- if (zOrderRelativeOf != nullptr) {
- layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
- } else {
- layerInfo->set_z_order_relative_of(-1);
- }
-
- auto buffer = mActiveBuffer;
- if (buffer != nullptr) {
- LayerProtoHelper::writeToProto(buffer,
- [&]() { return layerInfo->mutable_active_buffer(); });
- LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
- layerInfo->mutable_buffer_transform());
- }
-
- layerInfo->set_queued_frames(getQueuedFrameCount());
- layerInfo->set_refresh_pending(isBufferLatched());
- layerInfo->set_curr_frame(mCurrentFrameNumber);
- layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
-
- for (const auto& pendingState : mPendingStates) {
- auto barrierLayer = pendingState.barrierLayer_legacy.promote();
- if (barrierLayer != nullptr) {
- BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
- barrierLayerProto->set_id(barrierLayer->sequence);
- barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
+ for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
+ sp<Layer> strongRelative = weakRelative.promote();
+ if (strongRelative != nullptr) {
+ layerInfo->add_relatives(strongRelative->sequence);
+ }
}
+
+ LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
+ [&]() { return layerInfo->mutable_transparent_region(); });
+ LayerProtoHelper::writeToProto(visibleRegion,
+ [&]() { return layerInfo->mutable_visible_region(); });
+ LayerProtoHelper::writeToProto(surfaceDamageRegion,
+ [&]() { return layerInfo->mutable_damage_region(); });
+
+ layerInfo->set_layer_stack(getLayerStack());
+ layerInfo->set_z(state.z);
+
+ LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+ [&]() { return layerInfo->mutable_position(); });
+
+ LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
+ [&]() {
+ return layerInfo->mutable_requested_position();
+ });
+
+ LayerProtoHelper::writeSizeToProto(state.active_legacy.w, state.active_legacy.h,
+ [&]() { return layerInfo->mutable_size(); });
+
+ LayerProtoHelper::writeToProto(state.crop_legacy,
+ [&]() { return layerInfo->mutable_crop(); });
+ layerInfo->set_corner_radius(getRoundedCornerState().radius);
+
+ layerInfo->set_is_opaque(isOpaque(state));
+ layerInfo->set_invalidate(contentDirty);
+
+ // XXX (b/79210409) mCurrentDataSpace is not protected
+ layerInfo->set_dataspace(
+ dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
+
+ layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
+ LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
+ LayerProtoHelper::writeToProto(state.color,
+ [&]() { return layerInfo->mutable_requested_color(); });
+ layerInfo->set_flags(state.flags);
+
+ LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
+ LayerProtoHelper::writeToProto(requestedTransform,
+ layerInfo->mutable_requested_transform());
+
+ auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
+ if (parent != nullptr) {
+ layerInfo->set_parent(parent->sequence);
+ } else {
+ layerInfo->set_parent(-1);
+ }
+
+ auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
+ if (zOrderRelativeOf != nullptr) {
+ layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
+ } else {
+ layerInfo->set_z_order_relative_of(-1);
+ }
+
+ auto buffer = mActiveBuffer;
+ if (buffer != nullptr) {
+ LayerProtoHelper::writeToProto(buffer,
+ [&]() { return layerInfo->mutable_active_buffer(); });
+ LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
+ layerInfo->mutable_buffer_transform());
+ }
+
+ layerInfo->set_queued_frames(getQueuedFrameCount());
+ layerInfo->set_refresh_pending(isBufferLatched());
+ layerInfo->set_curr_frame(mCurrentFrameNumber);
+ layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
+
+ for (const auto& pendingState : mPendingStates) {
+ auto barrierLayer = pendingState.barrierLayer_legacy.promote();
+ if (barrierLayer != nullptr) {
+ BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+ barrierLayerProto->set_id(barrierLayer->sequence);
+ barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
+ }
+ }
+ LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
}
- auto protoMap = layerInfo->mutable_metadata();
- for (const auto& entry : state.metadata.mMap) {
- (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
+ if (traceFlags & SurfaceTracing::TRACE_INPUT) {
+ LayerProtoHelper::writeToProto(state.inputInfo, state.touchableRegionCrop,
+ [&]() { return layerInfo->mutable_input_window_info(); });
}
- LayerProtoHelper::writeToProto(mEffectiveTransform, layerInfo->mutable_effective_transform());
- LayerProtoHelper::writeToProto(mSourceBounds,
- [&]() { return layerInfo->mutable_source_bounds(); });
- LayerProtoHelper::writeToProto(mScreenBounds,
- [&]() { return layerInfo->mutable_screen_bounds(); });
- LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
+
+ if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
+ auto protoMap = layerInfo->mutable_metadata();
+ for (const auto& entry : state.metadata.mMap) {
+ (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
+ }
+ LayerProtoHelper::writeToProto(mEffectiveTransform,
+ layerInfo->mutable_effective_transform());
+ LayerProtoHelper::writeToProto(mSourceBounds,
+ [&]() { return layerInfo->mutable_source_bounds(); });
+ LayerProtoHelper::writeToProto(mScreenBounds,
+ [&]() { return layerInfo->mutable_screen_bounds(); });
+ }
}
-void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice) {
+void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+ uint32_t traceFlags) {
auto outputLayer = findOutputLayerForDisplay(displayDevice);
if (!outputLayer) {
return;
}
- writeToProto(layerInfo, LayerVector::StateSet::Drawing);
+ writeToProto(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
const auto& compositionState = outputLayer->getState();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index b7cfc16..83ff3b6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -433,10 +433,11 @@
bool isRemovedFromCurrentState() const;
- void writeToProto(LayerProto* layerInfo,
- LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
+ void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
- void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice);
+ void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index c25c418..c94e439 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -119,5 +119,41 @@
}
}
+void LayerProtoHelper::writeToProto(
+ const InputWindowInfo& inputInfo, const wp<Layer>& touchableRegionBounds,
+ std::function<InputWindowInfoProto*()> getInputWindowInfoProto) {
+ if (inputInfo.token == nullptr) {
+ return;
+ }
+
+ InputWindowInfoProto* proto = getInputWindowInfoProto();
+ proto->set_layout_params_flags(inputInfo.layoutParamsFlags);
+ proto->set_layout_params_type(inputInfo.layoutParamsType);
+
+ LayerProtoHelper::writeToProto({inputInfo.frameLeft, inputInfo.frameTop, inputInfo.frameRight,
+ inputInfo.frameBottom},
+ [&]() { return proto->mutable_frame(); });
+ LayerProtoHelper::writeToProto(inputInfo.touchableRegion,
+ [&]() { return proto->mutable_touchable_region(); });
+
+ proto->set_surface_inset(inputInfo.surfaceInset);
+ proto->set_visible(inputInfo.visible);
+ proto->set_can_receive_keys(inputInfo.canReceiveKeys);
+ proto->set_has_focus(inputInfo.hasFocus);
+ proto->set_has_wallpaper(inputInfo.hasWallpaper);
+
+ proto->set_global_scale_factor(inputInfo.globalScaleFactor);
+ proto->set_window_x_scale(inputInfo.windowXScale);
+ proto->set_window_y_scale(inputInfo.windowYScale);
+ proto->set_replace_touchable_region_with_crop(inputInfo.replaceTouchableRegionWithCrop);
+ auto cropLayer = touchableRegionBounds.promote();
+ if (cropLayer != nullptr) {
+ proto->set_crop_layer_id(cropLayer->sequence);
+ LayerProtoHelper::writeToProto(cropLayer->getScreenBounds(
+ false /* reduceTransparentRegion */),
+ [&]() { return proto->mutable_touchable_region_crop(); });
+ }
+}
+
} // namespace surfaceflinger
} // namespace android
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
index dca9a5e..1754a3f 100644
--- a/services/surfaceflinger/LayerProtoHelper.h
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -16,6 +16,8 @@
#include <layerproto/LayerProtoHeader.h>
+#include <Layer.h>
+#include <input/InputWindow.h>
#include <math/vec4.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
@@ -38,6 +40,9 @@
static void writeToProto(const ui::Transform& transform, TransformProto* transformProto);
static void writeToProto(const sp<GraphicBuffer>& buffer,
std::function<ActiveBufferProto*()> getActiveBufferProto);
+ static void writeToProto(const InputWindowInfo& inputInfo,
+ const wp<Layer>& touchableRegionBounds,
+ std::function<InputWindowInfoProto*()> getInputWindowInfoProto);
};
} // namespace surfaceflinger
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 77c8d10..ad4a769 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3508,13 +3508,15 @@
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
- const auto& [states, displays, flags, desiredPresentTime, postTime, privileged] =
- transactionQueue.front();
+ const auto&
+ [states, displays, flags, desiredPresentTime, uncacheBuffer, postTime,
+ privileged] = transactionQueue.front();
if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
break;
}
applyTransactionState(states, displays, flags, mPendingInputWindowCommands,
- desiredPresentTime, postTime, privileged);
+ desiredPresentTime, uncacheBuffer, postTime, privileged,
+ /*isMainThread*/ true);
transactionQueue.pop();
}
@@ -3571,7 +3573,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime) {
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) {
ATRACE_CALL();
const int64_t postTime = systemTime();
@@ -3588,20 +3591,22 @@
if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
- postTime, privileged);
+ uncacheBuffer, postTime, privileged);
setTransactionFlags(eTransactionNeeded);
return;
}
applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime,
- postTime, privileged);
+ uncacheBuffer, postTime, privileged);
}
void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
- const int64_t desiredPresentTime, const int64_t postTime,
- bool privileged) {
+ const int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer,
+ const int64_t postTime, bool privileged,
+ bool isMainThread) {
uint32_t transactionFlags = 0;
if (flags & eAnimation) {
@@ -3636,6 +3641,10 @@
transactionFlags |= addInputWindowCommands(inputWindowCommands);
+ if (uncacheBuffer.token) {
+ BufferStateLayerCache::getInstance().erase(uncacheBuffer.token, uncacheBuffer.cacheId);
+ }
+
// If a synchronous transaction is explicitly requested without any changes, force a transaction
// anyway. This can be used as a flush mechanism for previous async transactions.
// Empty animation transaction can be used to simulate back-pressure, so also force a
@@ -3665,7 +3674,12 @@
}
mPendingSyncInputWindows = mPendingInputWindowCommands.syncInputWindows;
- while (mTransactionPending || mPendingSyncInputWindows) {
+
+ // applyTransactionState can be called by either the main SF thread or by
+ // another process through setTransactionState. While a given process may wish
+ // to wait on synchronous transactions, the main SF thread should never
+ // be blocked. Therefore, we only wait if isMainThread is false.
+ while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
@@ -3972,16 +3986,20 @@
callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
}
}
-
- if (what & layer_state_t::eBufferChanged) {
- // Add the new buffer to the cache. This should always come before eCachedBufferChanged.
- BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.bufferId,
+ bool bufferChanged = what & layer_state_t::eBufferChanged;
+ bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
+ sp<GraphicBuffer> buffer;
+ if (bufferChanged && cacheIdChanged) {
+ BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.cacheId,
s.buffer);
+ buffer = s.buffer;
+ } else if (cacheIdChanged) {
+ buffer = BufferStateLayerCache::getInstance().get(s.cachedBuffer.token,
+ s.cachedBuffer.cacheId);
+ } else if (bufferChanged) {
+ buffer = s.buffer;
}
- if (what & layer_state_t::eCachedBufferChanged) {
- sp<GraphicBuffer> buffer =
- BufferStateLayerCache::getInstance().get(s.cachedBuffer.token,
- s.cachedBuffer.bufferId);
+ if (buffer) {
if (layer->setBuffer(buffer)) {
flags |= eTraversalNeeded;
layer->setPostTime(postTime);
@@ -4225,7 +4243,7 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1);
+ setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {});
setPowerModeInternal(display, HWC_POWER_MODE_NORMAL);
@@ -4639,13 +4657,14 @@
result.append("\n");
}
-LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const {
+LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet,
+ uint32_t traceFlags) const {
LayersProto layersProto;
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const State& state = useDrawing ? mDrawingState : mCurrentState;
state.traverseInZOrder([&](Layer* layer) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProto(layerProto, stateSet);
+ layer->writeToProto(layerProto, stateSet, traceFlags);
});
return layersProto;
@@ -4988,9 +5007,9 @@
code == IBinder::SYSPROPS_TRANSACTION) {
return OK;
}
- // Numbers from 1000 to 1032 are currently use for backdoors. The code
+ // Numbers from 1000 to 1033 are currently used for backdoors. The code
// in onTransact verifies that the user is root, and has access to use SF.
- if (code >= 1000 && code <= 1032) {
+ if (code >= 1000 && code <= 1033) {
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
return OK;
}
@@ -5298,6 +5317,14 @@
mDebugEnableProtectedContent = n;
return NO_ERROR;
}
+ // Set trace flags
+ case 1033: {
+ n = data.readUint32();
+ ALOGD("Updating trace flags to 0x%x", n);
+ mTracing.setTraceFlags(n);
+ reply->writeInt32(NO_ERROR);
+ return NO_ERROR;
+ }
}
}
return err;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0d39cb5..26d0cd1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -431,7 +431,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime) override;
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) override;
void bootFinished() override;
bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const override;
@@ -577,8 +578,9 @@
void applyTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
- const int64_t desiredPresentTime, const int64_t postTime,
- bool privileged) REQUIRES(mStateLock);
+ const int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer, const int64_t postTime,
+ bool privileged, bool isMainThread = false) REQUIRES(mStateLock);
bool flushTransactionQueues();
uint32_t getTransactionFlags(uint32_t flags);
uint32_t peekTransactionFlags();
@@ -895,7 +897,8 @@
void dumpBufferingStats(std::string& result) const;
void dumpDisplayIdentificationData(std::string& result) const;
void dumpWideColorInfo(std::string& result) const;
- LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
+ LayersProto dumpProtoInfo(LayerVector::StateSet stateSet,
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
@@ -1058,11 +1061,13 @@
struct TransactionState {
TransactionState(const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- int64_t desiredPresentTime, int64_t postTime, bool privileged)
+ int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer,
+ int64_t postTime, bool privileged)
: states(composerStates),
displays(displayStates),
flags(transactionFlags),
desiredPresentTime(desiredPresentTime),
+ buffer(uncacheBuffer),
postTime(postTime),
privileged(privileged) {}
@@ -1070,6 +1075,7 @@
Vector<DisplayState> displays;
uint32_t flags;
const int64_t desiredPresentTime;
+ cached_buffer_t buffer;
const int64_t postTime;
bool privileged;
};
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index db78f1d..c4ab066 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -28,46 +28,56 @@
namespace android {
-void SurfaceTracing::mainLoop() {
- bool enabled = true;
- // Upon activation, logs the first frame
- traceLayers("tracing.enable");
- do {
- std::unique_lock<std::mutex> sfLock(mFlinger.mDrawingStateLock);
- mConditionalVariable.wait(sfLock);
- LayersTraceProto entry = traceLayersLocked(mWhere);
- sfLock.unlock();
- {
- std::scoped_lock bufferLock(mTraceLock);
- mBuffer.emplace(std::move(entry));
- if (mWriteToFile) {
- writeProtoFileLocked();
- mWriteToFile = false;
- }
+SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger)
+ : mFlinger(flinger), mSfLock(flinger.mDrawingStateLock) {}
- enabled = mEnabled;
- }
- } while (enabled);
+void SurfaceTracing::mainLoop() {
+ addFirstEntry();
+ bool enabled = true;
+ while (enabled) {
+ LayersTraceProto entry = traceWhenNotified();
+ enabled = addTraceToBuffer(entry);
+ }
}
-void SurfaceTracing::traceLayers(const char* where) {
- std::unique_lock<std::mutex> sfLock(mFlinger.mDrawingStateLock);
- LayersTraceProto entry = traceLayersLocked(where);
- sfLock.unlock();
- std::scoped_lock bufferLock(mTraceLock);
+void SurfaceTracing::addFirstEntry() {
+ LayersTraceProto entry;
+ {
+ std::scoped_lock lock(mSfLock);
+ entry = traceLayersLocked("tracing.enable");
+ }
+ addTraceToBuffer(entry);
+}
+
+LayersTraceProto SurfaceTracing::traceWhenNotified() {
+ std::unique_lock<std::mutex> lock(mSfLock);
+ mCanStartTrace.wait(lock);
+ android::base::ScopedLockAssertion assumeLock(mSfLock);
+ LayersTraceProto entry = traceLayersLocked(mWhere);
+ lock.unlock();
+ return entry;
+}
+
+bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) {
+ std::scoped_lock lock(mTraceLock);
mBuffer.emplace(std::move(entry));
+ if (mWriteToFile) {
+ writeProtoFileLocked();
+ mWriteToFile = false;
+ }
+ return mEnabled;
}
void SurfaceTracing::notify(const char* where) {
- std::lock_guard<std::mutex> sfLock(mFlinger.mDrawingStateLock);
+ std::scoped_lock lock(mSfLock);
mWhere = where;
- mConditionalVariable.notify_one();
+ mCanStartTrace.notify_one();
}
void SurfaceTracing::writeToFileAsync() {
- std::lock_guard<std::mutex> bufferLock(mTraceLock);
+ std::scoped_lock lock(mTraceLock);
mWriteToFile = true;
- mConditionalVariable.notify_one();
+ mCanStartTrace.notify_one();
}
void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
@@ -102,12 +112,11 @@
}
void SurfaceTracing::enable() {
- std::lock_guard<std::mutex> bufferLock(mTraceLock);
+ std::scoped_lock lock(mTraceLock);
if (mEnabled) {
return;
}
-
mBuffer.reset(mBufferSize);
mEnabled = true;
mThread = std::thread(&SurfaceTracing::mainLoop, this);
@@ -119,7 +128,7 @@
}
bool SurfaceTracing::disable() {
- std::lock_guard<std::mutex> bufferLock(mTraceLock);
+ std::scoped_lock lock(mTraceLock);
if (!mEnabled) {
return false;
@@ -127,28 +136,33 @@
mEnabled = false;
mWriteToFile = true;
- mConditionalVariable.notify_all();
+ mCanStartTrace.notify_all();
return true;
}
bool SurfaceTracing::isEnabled() const {
- std::lock_guard<std::mutex> bufferLock(mTraceLock);
+ std::scoped_lock lock(mTraceLock);
return mEnabled;
}
void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
- std::lock_guard<std::mutex> bufferLock(mTraceLock);
+ std::scoped_lock lock(mTraceLock);
mBufferSize = bufferSizeInByte;
mBuffer.setSize(bufferSizeInByte);
}
+void SurfaceTracing::setTraceFlags(uint32_t flags) {
+ std::scoped_lock lock(mSfLock);
+ mTraceFlags = flags;
+}
+
LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
ATRACE_CALL();
LayersTraceProto entry;
entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry.set_where(where);
- LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing));
+ LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags));
entry.mutable_layers()->Swap(&layers);
return entry;
@@ -179,8 +193,7 @@
}
void SurfaceTracing::dump(std::string& result) const {
- std::lock_guard<std::mutex> bufferLock(mTraceLock);
-
+ std::scoped_lock lock(mTraceLock);
base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 9484480..4be2ee9 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -41,7 +41,7 @@
*/
class SurfaceTracing {
public:
- SurfaceTracing(SurfaceFlinger& flinger) : mFlinger(flinger) {}
+ SurfaceTracing(SurfaceFlinger& flinger);
void enable();
bool disable();
status_t writeToFile();
@@ -52,6 +52,14 @@
void writeToFileAsync();
void dump(std::string& result) const;
+ enum : uint32_t {
+ TRACE_CRITICAL = 1 << 0,
+ TRACE_INPUT = 1 << 1,
+ TRACE_EXTRA = 1 << 2,
+ TRACE_ALL = 0xffffffff
+ };
+ void setTraceFlags(uint32_t flags);
+
private:
static constexpr auto kDefaultBufferCapInByte = 100_MB;
static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb";
@@ -74,18 +82,24 @@
};
void mainLoop();
- void traceLayers(const char* where);
- LayersTraceProto traceLayersLocked(const char* where);
+ void addFirstEntry();
+ LayersTraceProto traceWhenNotified();
+ LayersTraceProto traceLayersLocked(const char* where) REQUIRES(mSfLock);
+
+ // Returns true if trace is enabled.
+ bool addTraceToBuffer(LayersTraceProto& entry);
void writeProtoFileLocked() REQUIRES(mTraceLock);
const SurfaceFlinger& mFlinger;
-
- const char* mWhere = "";
status_t mLastErr = NO_ERROR;
std::thread mThread;
- std::condition_variable mConditionalVariable;
- mutable std::mutex mTraceLock;
+ std::condition_variable mCanStartTrace;
+ std::mutex& mSfLock;
+ uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_ALL;
+ const char* mWhere GUARDED_BY(mSfLock) = "";
+
+ mutable std::mutex mTraceLock;
LayersTraceBuffer mBuffer GUARDED_BY(mTraceLock);
size_t mBufferSize GUARDED_BY(mTraceLock) = kDefaultBufferCapInByte;
bool mEnabled GUARDED_BY(mTraceLock) = false;
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index fd4695e..b097505 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -96,6 +96,8 @@
FloatRectProto source_bounds = 44;
FloatRectProto bounds = 45;
FloatRectProto screen_bounds = 46;
+
+ InputWindowInfoProto input_window_info = 47;
}
message PositionProto {
@@ -155,3 +157,24 @@
// frame number the barrier is waiting on.
uint64 frame_number = 2;
}
+
+message InputWindowInfoProto {
+ uint32 layout_params_flags = 1;
+ uint32 layout_params_type = 2;
+ RectProto frame = 3;
+ RegionProto touchable_region = 4;
+
+ uint32 surface_inset = 5;
+ bool visible = 6;
+ bool can_receive_keys = 7;
+ bool has_focus = 8;
+ bool has_wallpaper = 9;
+
+ float global_scale_factor = 10;
+ float window_x_scale = 11;
+ float window_y_scale = 12;
+
+ uint32 crop_layer_id = 13;
+ bool replace_touchable_region_with_crop = 14;
+ RectProto touchable_region_crop = 15;
+}