Merge "Fix vector read buffer size."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5fe4835..eddb989 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -36,6 +36,7 @@
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
+#include <android-base/file.h>
#include <cutils/properties.h>
#include "private/android_filesystem_config.h"
@@ -184,6 +185,118 @@
closedir(d);
}
+// return pid of a userspace process. If not found or error, return 0.
+static unsigned int pid_of_process(const char* ps_name) {
+ DIR *proc_dir;
+ struct dirent *ps;
+ unsigned int pid;
+ std::string cmdline;
+
+ if (!(proc_dir = opendir("/proc"))) {
+ MYLOGE("Can't open /proc\n");
+ return 0;
+ }
+
+ while ((ps = readdir(proc_dir))) {
+ if (!(pid = atoi(ps->d_name))) {
+ continue;
+ }
+ android::base::ReadFileToString("/proc/"
+ + std::string(ps->d_name) + "/cmdline", &cmdline);
+ if (cmdline.find(ps_name) == std::string::npos) {
+ continue;
+ } else {
+ closedir(proc_dir);
+ return pid;
+ }
+ }
+ closedir(proc_dir);
+ return 0;
+}
+
+// dump anrd's trace and add to the zip file.
+// 1. check if anrd is running on this device.
+// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
+// 3. wait until the trace generation completes and add to the zip file.
+static bool dump_anrd_trace() {
+ unsigned int pid;
+ char buf[50], path[PATH_MAX];
+ struct dirent *trace;
+ struct stat st;
+ DIR *trace_dir;
+ long max_ctime = 0;
+ long long cur_size = 0;
+ const char *trace_path = "/data/misc/anrd/";
+
+ if (!zip_writer) {
+ MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
+ return false;
+ }
+
+ // find anrd's pid if it is running.
+ pid = pid_of_process("/system/xbin/anrd");
+
+ if (pid > 0) {
+ // send SIGUSR1 to the anrd to generate a trace.
+ sprintf(buf, "%u", pid);
+ if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
+ MYLOGE("anrd signal timed out. Please manually collect trace\n");
+ return false;
+ }
+
+ // identify the trace file by its creation time.
+ if (!(trace_dir = opendir(trace_path))) {
+ MYLOGE("Can't open trace file under %s\n", trace_path);
+ }
+ while ((trace = readdir(trace_dir))) {
+ if (strcmp(trace->d_name, ".") == 0
+ || strcmp(trace->d_name, "..") == 0) {
+ continue;
+ }
+ sprintf(path, "%s%s", trace_path, trace->d_name);
+ if (stat(path, &st) == 0) {
+ if (st.st_ctime > max_ctime) {
+ max_ctime = st.st_ctime;
+ sprintf(buf, "%s", trace->d_name);
+ }
+ }
+ }
+ closedir(trace_dir);
+
+ // Wait until the dump completes by checking the size of the trace.
+ if (max_ctime > 0) {
+ sprintf(path, "%s%s", trace_path, buf);
+ while(true) {
+ sleep(1);
+ if (stat(path, &st) == 0) {
+ if (st.st_size == cur_size) {
+ break;
+ } else if (st.st_size > cur_size) {
+ cur_size = st.st_size;
+ } else {
+ return false;
+ }
+ } else {
+ MYLOGE("Cant stat() %s anymore\n", path);
+ return false;
+ }
+ }
+ // Add to the zip file.
+ if (!add_zip_entry("anrd_trace.txt", path)) {
+ MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
+ } else {
+ if (remove(path)) {
+ MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
+ }
+ return true;
+ }
+ } else {
+ MYLOGE("Can't stats any trace file under %s\n", trace_path);
+ }
+ }
+ return false;
+}
+
static void dump_systrace() {
if (!zip_writer) {
MYLOGD("Not dumping systrace because zip_writer is not set\n");
@@ -278,11 +391,12 @@
std::string timeout_string = std::to_string(timeout_seconds);
- const char *dumpsys_args[ARG_MAX] = { "/system/bin/dumpsys", "-t", timeout_string.c_str()};
+ const char *dumpsys_args[MAX_ARGS_ARRAY_SIZE] =
+ { "/system/bin/dumpsys", "-t", timeout_string.c_str()};
int index = 3; // 'dumpsys' '-t' 'TIMEOUT'
for (const std::string& arg : args) {
- if (index > ARG_MAX - 2) {
+ if (index > MAX_ARGS_ARRAY_SIZE - 2) {
MYLOGE("Too many arguments for '%s': %d\n", title.c_str(), (int) args.size());
return;
}
@@ -1042,7 +1156,7 @@
printf("== Final progress (pid %d): %d/%d (originally %d)\n",
getpid(), progress, weight_total, WEIGHT_TOTAL);
printf("========================================================\n");
- printf("== dumpstate: done\n");
+ printf("== dumpstate: done (id %lu)\n", id);
printf("========================================================\n");
}
@@ -1079,6 +1193,13 @@
*/
static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
const std::string& log_path, time_t now) {
+ // Final timestamp
+ char date[80];
+ time_t the_real_now_please_stand_up = time(nullptr);
+ strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
+ MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", id, date,
+ the_real_now_please_stand_up - now);
+
if (!add_zip_entry(bugreport_name, bugreport_path)) {
MYLOGE("Failed to add text entry to .zip file\n");
return false;
@@ -1165,7 +1286,7 @@
int is_remote_mode = 0;
std::string version = VERSION_DEFAULT;
- now = time(NULL);
+ now = time(nullptr);
MYLOGI("begin\n");
@@ -1417,7 +1538,11 @@
print_header(version);
// Dumps systrace right away, otherwise it will be filled with unnecessary events.
- dump_systrace();
+ // First try to dump anrd trace if the daemon is running. Otherwise, dump
+ // the raw trace.
+ if (!dump_anrd_trace()) {
+ dump_systrace();
+ }
// TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
dump_raft();
@@ -1567,7 +1692,7 @@
}
MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
- MYLOGI("done\n");
+ MYLOGI("done (id %lu)\n", id);
if (is_redirecting) {
fclose(stderr);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 0b87368..2dddda0 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -37,6 +37,11 @@
#define SU_PATH "/system/xbin/su"
+// Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
+// std::vector<std::string>
+#define MAX_ARGS_ARRAY_SIZE 1000
+
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4076f6a..3e4d343 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -655,7 +655,7 @@
DurationReporter duration_reporter(title);
fflush(stdout);
- const char *args[ARG_MAX] = {command};
+ const char *args[MAX_ARGS_ARRAY_SIZE] = {command};
size_t arg;
va_list ap;
va_start(ap, command);
@@ -696,7 +696,7 @@
DurationReporter duration_reporter(title);
fflush(stdout);
- const char *args[ARG_MAX] = {command};
+ const char *args[MAX_ARGS_ARRAY_SIZE] = {command};
size_t arg;
va_list ap;
va_start(ap, command);
@@ -888,11 +888,11 @@
MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
return;
}
- const char *am_args[ARG_MAX] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
+ const char *am_args[MAX_ARGS_ARRAY_SIZE] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
action.c_str() };
size_t am_index = 5; // Starts at the index of last initial value above.
for (const std::string& arg : args) {
- if (am_index > ARG_MAX - 2) {
+ if (am_index > MAX_ARGS_ARRAY_SIZE - 2) {
MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
return;
}
@@ -1416,7 +1416,7 @@
if (args[1] == nullptr) return;
string->append(" ");
- for (int arg = 1; arg <= 1000; ++arg) {
+ for (int arg = 1; arg <= MAX_ARGS_ARRAY_SIZE; ++arg) {
if (args[arg] == nullptr) return;
string->append(args[arg]);
if (args[arg+1] != nullptr) {
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index 8af4a90..f950276 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -24,6 +24,19 @@
# Maximum number of packages/steps.
MAXIMUM_PACKAGES=1000
+# First ensure the system is booted. This is to work around issues when cmd would
+# infinitely loop trying to get a service manager (which will never come up in that
+# mode). b/30797145
+BOOT_PROPERTY_NAME="dev.bootcomplete"
+
+BOOT_COMPLETE=$(getprop $BOOT_PROPERTY_NAME)
+if [ "$BOOT_COMPLETE" != "1" ] ; then
+ echo "Error: boot-complete not detected."
+ # We must return 0 to not block sideload.
+ exit 0
+fi
+
+
# Compute target slot suffix.
# TODO: Once bootctl is not restricted, we should query from there. Or get this from
# update_engine as a parameter.
diff --git a/cmds/installd/otapreopt_slot.sh b/cmds/installd/otapreopt_slot.sh
index d51ab70..b5786e9 100644
--- a/cmds/installd/otapreopt_slot.sh
+++ b/cmds/installd/otapreopt_slot.sh
@@ -22,10 +22,13 @@
if test -n "$SLOT_SUFFIX" ; then
if test -d /data/ota/$SLOT_SUFFIX/dalvik-cache ; then
log -p i -t otapreopt_slot "Moving A/B artifacts for slot ${SLOT_SUFFIX}."
+ OLD_SIZE=$(du -h -s /data/dalvik-cache)
rm -rf /data/dalvik-cache/*
+ NEW_SIZE=$(du -h -s /data/ota/$SLOT_SUFFIX/dalvik-cache)
mv /data/ota/$SLOT_SUFFIX/dalvik-cache/* /data/dalvik-cache/
rmdir /data/ota/$SLOT_SUFFIX/dalvik-cache
rmdir /data/ota/$SLOT_SUFFIX
+ log -p i -t otapreopt_slot "Moved ${NEW_SIZE} over ${OLD_SIZE}"
else
log -p i -t otapreopt_slot "No A/B artifacts found for slot ${SLOT_SUFFIX}."
fi
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index ce08ecf..45060af 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -5,42 +5,46 @@
}
message Increment {
- required int64 time_stamp = 1;
+ required int64 time_stamp = 1;
oneof increment {
- Transaction transaction = 2;
- Create create = 3;
- Delete delete = 4;
- BufferUpdate buffer_update = 5;
- VSyncEvent vsync_event = 6;
+ Transaction transaction = 2;
+ SurfaceCreation surface_creation = 3;
+ SurfaceDeletion surface_deletion = 4;
+ BufferUpdate buffer_update = 5;
+ VSyncEvent vsync_event = 6;
+ DisplayCreation display_creation = 7;
+ DisplayDeletion display_deletion = 8;
+ PowerModeUpdate power_mode_update = 9;
}
}
message Transaction {
- repeated Change change = 1;
+ repeated SurfaceChange surface_change = 1;
+ repeated DisplayChange display_change = 2;
- required bool synchronous = 2;
- required bool animation = 3;
+ required bool synchronous = 3;
+ required bool animation = 4;
}
-message Change {
- required uint32 id = 1;
+message SurfaceChange {
+ required int32 id = 1;
- oneof Change {
- PositionChange position = 2;
- SizeChange size = 3;
- AlphaChange alpha = 4;
- LayerChange layer = 5;
- CropChange crop = 6;
- FinalCropChange final_crop = 7;
- MatrixChange matrix = 8;
- OverrideScalingModeChange override_scaling_mode = 9;
- TransparentRegionHintChange transparent_region_hint = 10;
- LayerStackChange layer_stack = 11;
- HiddenFlagChange hidden_flag = 12;
- OpaqueFlagChange opaque_flag = 13;
- SecureFlagChange secure_flag = 14;
- DeferredTransactionChange deferred_transaction = 15;
+ oneof SurfaceChange {
+ PositionChange position = 2;
+ SizeChange size = 3;
+ AlphaChange alpha = 4;
+ LayerChange layer = 5;
+ CropChange crop = 6;
+ FinalCropChange final_crop = 7;
+ MatrixChange matrix = 8;
+ OverrideScalingModeChange override_scaling_mode = 9;
+ TransparentRegionHintChange transparent_region_hint = 10;
+ LayerStackChange layer_stack = 11;
+ HiddenFlagChange hidden_flag = 12;
+ OpaqueFlagChange opaque_flag = 13;
+ SecureFlagChange secure_flag = 14;
+ DeferredTransactionChange deferred_transaction = 15;
}
}
@@ -102,10 +106,32 @@
}
message DeferredTransactionChange {
- required uint32 layer_id = 1;
+ required int32 layer_id = 1;
required uint64 frame_number = 2;
}
+message DisplayChange {
+ required int32 id = 1;
+
+ oneof DisplayChange {
+ DispSurfaceChange surface = 2;
+ LayerStackChange layer_stack = 3;
+ SizeChange size = 4;
+ ProjectionChange projection = 5;
+ }
+}
+
+message DispSurfaceChange {
+ required uint64 buffer_queue_id = 1;
+ required string buffer_queue_name = 2;
+}
+
+message ProjectionChange {
+ required int32 orientation = 1;
+ required Rectangle viewport = 2;
+ required Rectangle frame = 3;
+}
+
message Rectangle {
required int32 left = 1;
required int32 top = 2;
@@ -113,24 +139,40 @@
required int32 bottom = 4;
}
-message Create {
- required uint32 id = 1;
- required string name = 2;
- required uint32 w = 3;
- required uint32 h = 4;
+message SurfaceCreation {
+ required int32 id = 1;
+ required string name = 2;
+ required uint32 w = 3;
+ required uint32 h = 4;
}
-message Delete {
- required uint32 id = 1;
+message SurfaceDeletion {
+ required int32 id = 1;
}
message BufferUpdate {
- required uint32 id = 1;
- required uint32 w = 2;
- required uint32 h = 3;
- required uint64 frame_number = 4;
+ required int32 id = 1;
+ required uint32 w = 2;
+ required uint32 h = 3;
+ required uint64 frame_number = 4;
}
message VSyncEvent {
required int64 when = 1;
}
+
+message DisplayCreation {
+ required int32 id = 1;
+ required string name = 2;
+ required int32 type = 3;
+ required bool is_secure = 4;
+}
+
+message DisplayDeletion {
+ required int32 id = 1;
+}
+
+message PowerModeUpdate {
+ required int32 id = 1;
+ required int32 mode = 2;
+}
diff --git a/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp b/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp
index cad11a0..77de8dc 100644
--- a/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp
+++ b/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp
@@ -23,7 +23,7 @@
using namespace android;
BufferQueueScheduler::BufferQueueScheduler(
- const sp<SurfaceControl>& surfaceControl, const RGB& color, int id)
+ const sp<SurfaceControl>& surfaceControl, const HSV& color, int id)
: mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {}
void BufferQueueScheduler::startScheduling() {
@@ -44,6 +44,7 @@
bufferUpdate(event.dimensions);
fillSurface(event.event);
+ mColor.modulate();
lock.lock();
mBufferEvents.pop();
}
@@ -64,7 +65,7 @@
}
void BufferQueueScheduler::setSurfaceControl(
- const sp<SurfaceControl>& surfaceControl, const RGB& color) {
+ const sp<SurfaceControl>& surfaceControl, const HSV& color) {
std::lock_guard<std::mutex> lock(mMutex);
mSurfaceControl = surfaceControl;
mColor = color;
@@ -76,7 +77,7 @@
s->setBuffersDimensions(dimensions.width, dimensions.height);
}
-void BufferQueueScheduler::fillSurface(std::shared_ptr<Event> event) {
+void BufferQueueScheduler::fillSurface(const std::shared_ptr<Event>& event) {
ANativeWindow_Buffer outBuffer;
sp<Surface> s = mSurfaceControl->getSurface();
@@ -87,13 +88,15 @@
return;
}
+ auto color = mColor.getRGB();
+
auto img = reinterpret_cast<uint8_t*>(outBuffer.bits);
for (int y = 0; y < outBuffer.height; y++) {
for (int x = 0; x < outBuffer.width; x++) {
uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
- pixel[0] = mColor.r;
- pixel[1] = mColor.g;
- pixel[2] = mColor.b;
+ pixel[0] = color.r;
+ pixel[1] = color.g;
+ pixel[2] = color.b;
pixel[3] = LAYER_ALPHA;
}
}
diff --git a/cmds/surfacereplayer/replayer/BufferQueueScheduler.h b/cmds/surfacereplayer/replayer/BufferQueueScheduler.h
index fc8e20c..cb20fcc 100644
--- a/cmds/surfacereplayer/replayer/BufferQueueScheduler.h
+++ b/cmds/surfacereplayer/replayer/BufferQueueScheduler.h
@@ -52,23 +52,23 @@
class BufferQueueScheduler {
public:
- BufferQueueScheduler(const sp<SurfaceControl>& surfaceControl, const RGB& color, int id);
+ BufferQueueScheduler(const sp<SurfaceControl>& surfaceControl, const HSV& color, int id);
void startScheduling();
void addEvent(const BufferEvent&);
void stopScheduling();
- void setSurfaceControl(const sp<SurfaceControl>& surfaceControl, const RGB& color);
+ void setSurfaceControl(const sp<SurfaceControl>& surfaceControl, const HSV& color);
private:
void bufferUpdate(const Dimensions& dimensions);
// Lock and fill the surface, block until the event is signaled by the main loop,
// then unlock and post the buffer.
- void fillSurface(std::shared_ptr<Event>);
+ void fillSurface(const std::shared_ptr<Event>& event);
sp<SurfaceControl> mSurfaceControl;
- RGB mColor;
+ HSV mColor;
const int mSurfaceId;
bool mContinueScheduling;
diff --git a/cmds/surfacereplayer/replayer/Color.h b/cmds/surfacereplayer/replayer/Color.h
index d644b8d..ce644be 100644
--- a/cmds/surfacereplayer/replayer/Color.h
+++ b/cmds/surfacereplayer/replayer/Color.h
@@ -22,76 +22,96 @@
namespace android {
-typedef struct RGB {
- RGB() = default;
+constexpr double modulateFactor = .0001;
+constexpr double modulateLimit = .80;
+
+struct RGB {
RGB(uint8_t rIn, uint8_t gIn, uint8_t bIn) : r(rIn), g(gIn), b(bIn) {}
uint8_t r = 0;
uint8_t g = 0;
uint8_t b = 0;
-} RGB;
+};
-typedef struct HSV {
+struct HSV {
HSV() = default;
HSV(double hIn, double sIn, double vIn) : h(hIn), s(sIn), v(vIn) {}
double h = 0;
double s = 0;
double v = 0;
-} HSV;
-static inline RGB HSVToRGB(HSV hsv) {
+ RGB getRGB() const;
+
+ bool modulateUp = false;
+
+ void modulate();
+};
+
+void inline HSV::modulate() {
+ if(modulateUp) {
+ v += modulateFactor;
+ } else {
+ v -= modulateFactor;
+ }
+
+ if(v <= modulateLimit || v >= 1) {
+ modulateUp = !modulateUp;
+ }
+}
+
+inline RGB HSV::getRGB() const {
using namespace std;
double r = 0, g = 0, b = 0;
- if (hsv.s == 0) {
- r = hsv.v;
- g = hsv.v;
- b = hsv.v;
+ if (s == 0) {
+ r = v;
+ g = v;
+ b = v;
} else {
- hsv.h = static_cast<int>(hsv.h) % 360;
- hsv.h = hsv.h / 60;
+ auto tempHue = static_cast<int>(h) % 360;
+ tempHue = tempHue / 60;
- int i = static_cast<int>(trunc(hsv.h));
- double f = hsv.h - i;
+ int i = static_cast<int>(trunc(tempHue));
+ double f = h - i;
- double x = hsv.v * (1.0 - hsv.s);
- double y = hsv.v * (1.0 - (hsv.s * f));
- double z = hsv.v * (1.0 - (hsv.s * (1.0 - f)));
+ double x = v * (1.0 - s);
+ double y = v * (1.0 - (s * f));
+ double z = v * (1.0 - (s * (1.0 - f)));
switch (i) {
case 0:
- r = hsv.v;
+ r = v;
g = z;
b = x;
break;
case 1:
r = y;
- g = hsv.v;
+ g = v;
b = x;
break;
case 2:
r = x;
- g = hsv.v;
+ g = v;
b = z;
break;
case 3:
r = x;
g = y;
- b = hsv.v;
+ b = v;
break;
case 4:
r = z;
g = x;
- b = hsv.v;
+ b = v;
break;
default:
- r = hsv.v;
+ r = v;
g = x;
b = y;
break;
diff --git a/cmds/surfacereplayer/replayer/Main.cpp b/cmds/surfacereplayer/replayer/Main.cpp
index bf5da52..dd1dd7d 100644
--- a/cmds/surfacereplayer/replayer/Main.cpp
+++ b/cmds/surfacereplayer/replayer/Main.cpp
@@ -41,9 +41,16 @@
std::cout << " -m Stops the replayer at the start of the trace and switches ";
"to manual replay\n";
- std::cout << " -t [Number of Threads] Specifies the number of threads to be used while "
+ std::cout << "\n -t [Number of Threads] Specifies the number of threads to be used while "
"replaying (default is " << android::DEFAULT_THREADS << ")\n";
+ std::cout << "\n -s [Timestamp] Specify at what timestamp should the replayer switch "
+ "to manual replay\n";
+
+ std::cout << " -n Ignore timestamps and run through trace as fast as possible\n";
+
+ std::cout << " -l Indefinitely loop the replayer\n";
+
std::cout << " -h Display help menu\n";
std::cout << std::endl;
@@ -51,11 +58,14 @@
int main(int argc, char** argv) {
std::string filename;
+ bool loop = false;
+ bool wait = true;
bool pauseBeginning = false;
int numThreads = DEFAULT_THREADS;
+ long stopHere = -1;
int opt = 0;
- while ((opt = getopt(argc, argv, "pt:h?")) != -1) {
+ while ((opt = getopt(argc, argv, "mt:s:nlh?")) != -1) {
switch (opt) {
case 'm':
pauseBeginning = true;
@@ -63,6 +73,15 @@
case 't':
numThreads = atoi(optarg);
break;
+ case 's':
+ stopHere = atol(optarg);
+ break;
+ case 'n':
+ wait = false;
+ break;
+ case 'l':
+ loop = true;
+ break;
case 'h':
case '?':
printHelpMenu();
@@ -81,8 +100,11 @@
}
filename.assign(input[0]);
- android::Replayer r(filename, pauseBeginning, numThreads);
- auto status = r.replay();
+ status_t status = NO_ERROR;
+ do {
+ android::Replayer r(filename, pauseBeginning, numThreads, wait, stopHere);
+ status = r.replay();
+ } while(loop);
if (status == NO_ERROR) {
std::cout << "Successfully finished replaying trace" << std::endl;
diff --git a/cmds/surfacereplayer/replayer/README.md b/cmds/surfacereplayer/replayer/README.md
new file mode 100644
index 0000000..893f0dc
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/README.md
@@ -0,0 +1,262 @@
+SurfaceReplayer Documentation
+===================
+
+[go/SurfaceReplayer](go/SurfaceReplayer)
+
+SurfaceReplayer is a playback mechanism that allows the replaying of traces recorded by
+[SurfaceInterceptor](go/SurfaceInterceptor) from SurfaceFlinger. It specifically replays
+
+* Creation and deletion of surfaces/displays
+* Alterations to the surfaces/displays called Transactions
+* Buffer Updates to surfaces
+* VSync events
+
+At their specified times to be as close to the original trace.
+
+Usage
+--------
+
+###Creating a trace
+
+SurfaceInterceptor is the mechanism used to create traces. The device needs to be rooted in order to
+utilize it. To allow it to write to the device, run
+
+`setenforce 0`
+
+To start recording a trace, run
+
+`service call SurfaceFlinger 1020 i32 1`
+
+To stop recording, run
+
+`service call SurfaceFlinger 1020 i32 0`
+
+The default location for the trace is `/data/SurfaceTrace.dat`
+
+###Executable
+
+To replay a specific trace, execute
+
+`/data/local/tmp/surfacereplayer /absolute/path/to/trace`
+
+inside the android shell. This will replay the full trace and then exit. Running this command
+outside of the shell by prepending `adb shell` will not allow for manual control and will not turn
+off VSync injections if it interrupted in any way other than fully replaying the trace
+
+The replay will not fill surfaces with their contents during the capture. Rather they are given a
+random color which will be the same every time the trace is replayed. Surfaces modulate their color
+at buffer updates.
+
+**Options:**
+
+- -m pause the replayer at the start of the trace for manual replay
+- -t [Number of Threads] uses specified number of threads to queue up actions (default is 3)
+- -s [Timestamp] switches to manual replay at specified timestamp
+- -n Ignore timestamps and run through trace as fast as possible
+- -l Indefinitely loop the replayer
+- -h displays help menu
+
+**Manual Replay:**
+When replaying, if the user presses CTRL-C, the replay will stop and can be manually controlled
+by the user. Pressing CTRL-C again will exit the replayer.
+
+Manual replaying is similar to debugging in gdb. A prompt is presented and the user is able to
+input commands to choose how to proceed by hitting enter after inputting a command. Pressing enter
+without inputting a command repeats the previous command.
+
+- n - steps the replayer to the next VSync event
+- ni - steps the replayer to the next increment
+- c - continues normal replaying
+- c [milliseconds] - continue until specified number of milliseconds have passed
+- s [timestamp] - continue and stop at specified timestamp
+- l - list out timestamp of current increment
+- h - displays help menu
+
+###Shared Library
+
+To use the shared library include these shared libraries
+
+`libsurfacereplayer`
+`libprotobuf-cpp-full`
+`libutils`
+
+And the static library
+
+`libtrace_proto`
+
+Include the replayer header at the top of your file
+
+`#include <replayer/Replayer.h>`
+
+There are two constructors for the replayer
+
+`Replayer(std::string& filename, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)`
+`Replayer(Trace& trace, ... ditto ...)`
+
+The first constructor takes in the filepath where the trace is located and loads in the trace
+object internally.
+- replayManually - **True**: if the replayer will immediately switch to manual replay at the start
+- numThreads - Number of worker threads the replayer will use.
+- wait - **False**: Replayer ignores waits in between increments
+- stopHere - Time stamp of where the replayer should run to then switch to manual replay
+
+The second constructor includes all of the same parameters but takes in a preloaded trace object.
+To use add
+
+`#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>`
+
+To your file
+
+After initializing the Replayer call
+
+ replayer.replay();
+
+And the trace will start replaying. Once the trace is finished replaying, the function will return.
+The layers that are visible at the end of the trace will remain on screen until the program
+terminates.
+
+
+**If VSyncs are broken after running the replayer** that means `enableVSyncInjections(false)` was
+never executed. This can be fixed by executing
+
+`service call SurfaceFlinger 23 i32 0`
+
+in the android shell
+
+Code Breakdown
+-------------
+
+The Replayer is composed of 5 components.
+
+- The data format of the trace (Trace.proto)
+- The Replayer object (Replayer.cpp)
+- The synchronization mechanism to signal threads within the Replayer (Event.cpp)
+- The scheduler for buffer updates per surface (BufferQueueScheduler.cpp)
+- The Main executable (Main.cpp)
+
+### Traces
+
+Traces are represented as a protobuf message located in surfacereplayer/proto/src.
+
+**Traces** contain *repeated* **Increments** (events that have occurred in SurfaceFlinger).
+**Increments** contain the time stamp of when it occurred and a *oneof* which can be a
+
+ - Transaction
+ - SurfaceCreation
+ - SurfaceDeletion
+ - DisplayCreation
+ - DisplayDeleteion
+ - BufferUpdate
+ - VSyncEvent
+ - PowerModeUpdate
+
+**Transactions** contain whether the transaction was synchronous or animated and *repeated*
+**SurfaceChanges** and **DisplayChanges**
+
+- **SurfaceChanges** contain an id of the surface being manipulated and can be changes such as
+position, alpha, hidden, size, etc.
+- **DisplayChanges** contain the id of the display being manipulated and can be changes such as
+size, layer stack, projection, etc.
+
+**Surface/Display Creation** contain the id of the surface/display and the name of the
+surface/display
+
+**Surface/Display Deletion** contain the id of the surface/display to be deleted
+
+**Buffer Updates** contain the id of the surface who's buffer is being updated, the size of the
+buffer, and the frame number.
+
+**VSyncEvents** contain when the VSync event has occurred.
+
+**PowerModeUpdates** contain the id of the display being updated and what mode it is being
+changed to.
+
+To output the contents of a trace in a readable format, execute
+
+`**aprotoc** --decode=Trace \
+-I=$ANDROID_BUILD_TOP/frameworks/native/cmds/surfacereplayer/proto/src \
+$ANDROID_BUILD_TOP/frameworks/native/cmds/surfacereplayer/proto/src/trace.proto \
+ < **YourTraceFile.dat** > **YourOutputName.txt**`
+
+
+###Replayer
+
+Fundamentally the replayer loads a trace and iterates through each increment, waiting the required
+amount of time until the increment should be executed, then executing the increment. The first
+increment in a trace does not start at 0, rather the replayer treats its time stamp as time 0 and
+goes from there.
+
+Increments from the trace are played asynchronously rather than one by one, being dispatched by
+the main thread, queued up in a thread pool and completed when the main thread deems they are
+ready to finish execution.
+
+When an increment is dispatched, it completes as much work as it can before it has to be
+synchronized (e.g. prebaking a buffer for a BufferUpdate). When it gets to a critical action
+(e.g. locking and pushing a buffer), it waits for the main thread to complete it using an Event
+object. The main thread holds a queue of these Event objects and completes the
+corresponding Event base on its time stamp. After completing an increment, the main thread will
+dispatch another increment and continue.
+
+The main thread's execution flow is outlined below
+
+ initReplay() //queue up the initial increments
+ while(!pendingIncrements.empty()) { //while increments remaining
+ event = pendingIncrement.pop();
+ wait(event.time_stamp(); //waitUntil it is time to complete this increment
+
+ event.complete() //signal to let event finish
+ if(increments remaing()) {
+ dispatchEvent() //queue up another increment
+ }
+ }
+
+A worker thread's flow looks like so
+
+ //dispatched!
+ Execute non-time sensitive work here
+ ...
+ event.readyToExecute() //time sensitive point...waiting for Main Thread
+ ...
+ Finish execution
+
+
+### Event
+
+An Event is a simple synchronization mechanism used to facilitate communication between the main
+and worker threads. Every time an increment is dispatched, an Event object is also created.
+
+An Event can be in 4 different states:
+
+- **SettingUp** - The worker is in the process of completing all non-time sensitive work
+- **Waiting** - The worker is waiting on the main thread to signal it.
+- **Signaled** - The worker has just been signaled by the main thread
+- **Running** - The worker is running again and finishing the rest of its work.
+
+When the main thread wants to finish the execution of a worker, the worker can either still be
+**SettingUp**, in which the main thread will wait, or the worker will be **Waiting**, in which the
+main thread will **Signal** it to complete. The worker thread changes itself to the **Running**
+state once **Signaled**. This last step exists in order to communicate back to the main thread that
+the worker thread has actually started completing its execution, rather than being preempted right
+after signalling. Once this happens, the main thread schedules the next worker. This makes sure
+there is a constant amount of workers running at one time.
+
+This activity is encapsulated in the `readyToExecute()` and `complete()` functions called by the
+worker and main thread respectively.
+
+### BufferQueueScheduler
+
+During a **BuferUpdate**, the worker thread will wait until **Signaled** to unlock and post a
+buffer that has been prefilled during the **SettingUp** phase. However if there are two sequential
+**BufferUpdates** that act on the same surface, both threads will try to lock a buffer and fill it,
+which isn't possible and will cause a deadlock. The BufferQueueScheduler solves this problem by
+handling when **BufferUpdates** should be scheduled, making sure that they don't overlap.
+
+When a surface is created, a BufferQueueScheduler is also created along side it. Whenever a
+**BufferUpdate** is read, it schedules the event onto its own internal queue and then schedules one
+every time an Event is completed.
+
+### Main
+
+The main exectuable reads in the command line arguments. Creates the Replayer using those
+arguments. Executes `replay()` on the Replayer. If there are no errors while replaying it will exit
+gracefully, if there are then it will report the error and then exit.
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 950ebbb..ace10d1 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -22,6 +22,7 @@
#include <binder/IMemory.h>
+#include <gui/BufferQueue.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <private/gui/ComposerService.h>
@@ -40,15 +41,24 @@
#include <functional>
#include <iostream>
#include <mutex>
+#include <sstream>
#include <string>
#include <thread>
+#include <vector>
using namespace android;
std::atomic_bool Replayer::sReplayingManually(false);
-Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads)
- : mTrace(), mLoaded(false), mIncrementIndex(0), mCurrentTime(0), mNumThreads(numThreads) {
+Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads, bool wait,
+ nsecs_t stopHere)
+ : mTrace(),
+ mLoaded(false),
+ mIncrementIndex(0),
+ mCurrentTime(0),
+ mNumThreads(numThreads),
+ mWaitForTimeStamps(wait),
+ mStopTimeStamp(stopHere) {
srand(RAND_COLOR_SEED);
std::fstream input(filename, std::ios::in | std::ios::binary);
@@ -62,19 +72,32 @@
mCurrentTime = mTrace.increment(0).time_stamp();
sReplayingManually.store(replayManually);
+
+ if (stopHere < 0) {
+ mHasStopped = true;
+ }
}
-Replayer::Replayer(const Trace& t, bool replayManually, int numThreads)
- : mTrace(t), mLoaded(true), mIncrementIndex(0), mCurrentTime(0), mNumThreads(numThreads) {
+Replayer::Replayer(const Trace& t, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)
+ : mTrace(t),
+ mLoaded(true),
+ mIncrementIndex(0),
+ mCurrentTime(0),
+ mNumThreads(numThreads),
+ mWaitForTimeStamps(wait),
+ mStopTimeStamp(stopHere) {
srand(RAND_COLOR_SEED);
mCurrentTime = mTrace.increment(0).time_stamp();
sReplayingManually.store(replayManually);
+
+ if (stopHere < 0) {
+ mHasStopped = true;
+ }
}
status_t Replayer::replay() {
- // for manual control
- signal(SIGINT, Replayer::stopAutoReplayHandler);
+ signal(SIGINT, Replayer::stopAutoReplayHandler); //for manual control
ALOGV("There are %d increments.", mTrace.increment_size());
@@ -91,11 +114,18 @@
ALOGV("Starting actual Replay!");
while (!mPendingIncrements.empty()) {
+ mCurrentIncrement = mTrace.increment(mIncrementIndex);
+
+ if (mHasStopped == false && mCurrentIncrement.time_stamp() >= mStopTimeStamp) {
+ mHasStopped = true;
+ sReplayingManually.store(true);
+ }
+
waitForConsoleCommmand();
- auto pastIncrement = mTrace.increment(mIncrementIndex);
-
- waitUntilTimestamp(pastIncrement.time_stamp());
+ if (mWaitForTimeStamps) {
+ waitUntilTimestamp(mCurrentIncrement.time_stamp());
+ }
auto event = mPendingIncrements.front();
mPendingIncrements.pop();
@@ -116,7 +146,7 @@
}
mIncrementIndex++;
- mCurrentTime = pastIncrement.time_stamp();
+ mCurrentTime = mCurrentIncrement.time_stamp();
}
SurfaceComposerClient::enableVSyncInjections(false);
@@ -146,6 +176,21 @@
sReplayingManually.store(true);
}
+std::vector<std::string> split(const std::string& s, const char delim) {
+ std::vector<std::string> elems;
+ std::stringstream ss(s);
+ std::string item;
+ while (getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+ return elems;
+}
+
+bool isNumber(const std::string& s) {
+ return !s.empty() &&
+ std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
+}
+
void Replayer::waitForConsoleCommmand() {
if (!sReplayingManually || mWaitingForNextVSync) {
return;
@@ -158,18 +203,65 @@
if (input.empty()) {
input = mLastInput;
+ } else {
+ mLastInput = input;
}
- input = mLastInput;
- if (input == "n") { // next vsync
+ if (mLastInput.empty()) {
+ continue;
+ }
+
+ std::vector<std::string> inputs = split(input, ' ');
+
+ if (inputs[0] == "n") { // next vsync
mWaitingForNextVSync = true;
break;
- } else if (input == "c") { // continue
+
+ } else if (inputs[0] == "ni") { // next increment
+ break;
+
+ } else if (inputs[0] == "c") { // continue
+ if (inputs.size() > 1 && isNumber(inputs[1])) {
+ long milliseconds = stoi(inputs[1]);
+ std::thread([&] {
+ std::cout << "Started!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
+ sReplayingManually.store(true);
+ std::cout << "Should have stopped!" << std::endl;
+ }).detach();
+ }
sReplayingManually.store(false);
mWaitingForNextVSync = false;
break;
- } else if (input == "h") { // help
- // add help menu
+
+ } else if (inputs[0] == "s") { // stop at this timestamp
+ if (inputs.size() < 1) {
+ std::cout << "No time stamp given" << std::endl;
+ continue;
+ }
+ sReplayingManually.store(false);
+ mStopTimeStamp = stol(inputs[1]);
+ mHasStopped = false;
+ break;
+ } else if (inputs[0] == "l") { // list
+ std::cout << "Time stamp: " << mCurrentIncrement.time_stamp() << "\n";
+ continue;
+ } else if (inputs[0] == "q") { // quit
+ SurfaceComposerClient::enableVSyncInjections(false);
+ exit(0);
+
+ } else if (inputs[0] == "h") { // help
+ // add help menu
+ std::cout << "Manual Replay options:\n";
+ std::cout << " n - Go to next VSync\n";
+ std::cout << " ni - Go to next increment\n";
+ std::cout << " c - Continue\n";
+ std::cout << " c [milliseconds] - Continue until specified number of milliseconds\n";
+ std::cout << " s [timestamp] - Continue and stop at specified timestamp\n";
+ std::cout << " l - List out timestamp of current increment\n";
+ std::cout << " h - Display help menu\n";
+ std::cout << std::endl;
+ continue;
}
std::cout << "Invalid Command" << std::endl;
@@ -186,11 +278,13 @@
case increment.kTransaction: {
std::thread(&Replayer::doTransaction, this, increment.transaction(), event).detach();
} break;
- case increment.kCreate: {
- std::thread(&Replayer::createSurfaceControl, this, increment.create(), event).detach();
+ case increment.kSurfaceCreation: {
+ std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event)
+ .detach();
} break;
- case increment.kDelete: {
- std::thread(&Replayer::deleteSurfaceControl, this, increment.delete_(), event).detach();
+ case increment.kSurfaceDeletion: {
+ std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event)
+ .detach();
} break;
case increment.kBufferUpdate: {
std::lock_guard<std::mutex> lock1(mLayerLock);
@@ -216,6 +310,18 @@
case increment.kVsyncEvent: {
std::thread(&Replayer::injectVSyncEvent, this, increment.vsync_event(), event).detach();
} break;
+ case increment.kDisplayCreation: {
+ std::thread(&Replayer::createDisplay, this, increment.display_creation(), event)
+ .detach();
+ } break;
+ case increment.kDisplayDeletion: {
+ std::thread(&Replayer::deleteDisplay, this, increment.display_deletion(), event)
+ .detach();
+ } break;
+ case increment.kPowerModeUpdate: {
+ std::thread(&Replayer::updatePowerMode, this, increment.power_mode_update(), event)
+ .detach();
+ } break;
default:
ALOGE("Unknown Increment Type: %d", increment.increment_case());
status = BAD_VALUE;
@@ -228,83 +334,12 @@
status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
ALOGV("Started Transaction");
- if (t.change_size() == 0) {
- event->readyToExecute();
- return NO_ERROR;
- }
-
- Change change = t.change(0);
-
- std::unique_lock<std::mutex> lock(mLayerLock);
- if (mLayers[change.id()] == nullptr) {
- mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
- }
- lock.unlock();
-
SurfaceComposerClient::openGlobalTransaction();
status_t status = NO_ERROR;
- for (const Change& change : t.change()) {
- std::unique_lock<std::mutex> lock(mLayerLock);
- if (mLayers[change.id()] == nullptr) {
- mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
- }
-
- switch (change.Change_case()) {
- case Change::ChangeCase::kPosition:
- status = setPosition(change.id(), change.position());
- break;
- case Change::ChangeCase::kSize:
- status = setSize(change.id(), change.size());
- break;
- case Change::ChangeCase::kAlpha:
- status = setAlpha(change.id(), change.alpha());
- break;
- case Change::ChangeCase::kLayer:
- status = setLayer(change.id(), change.layer());
- break;
- case Change::ChangeCase::kCrop:
- status = setCrop(change.id(), change.crop());
- break;
- case Change::ChangeCase::kMatrix:
- status = setMatrix(change.id(), change.matrix());
- break;
- case Change::ChangeCase::kFinalCrop:
- status = setFinalCrop(change.id(), change.final_crop());
- break;
- case Change::ChangeCase::kOverrideScalingMode:
- status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
- break;
- case Change::ChangeCase::kTransparentRegionHint:
- status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
- break;
- case Change::ChangeCase::kLayerStack:
- status = setLayerStack(change.id(), change.layer_stack());
- break;
- case Change::ChangeCase::kHiddenFlag:
- status = setHiddenFlag(change.id(), change.hidden_flag());
- break;
- case Change::ChangeCase::kOpaqueFlag:
- status = setOpaqueFlag(change.id(), change.opaque_flag());
- break;
- case Change::ChangeCase::kSecureFlag:
- status = setSecureFlag(change.id(), change.secure_flag());
- break;
- case Change::ChangeCase::kDeferredTransaction:
- waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
- status = setDeferredTransaction(change.id(), change.deferred_transaction());
- break;
- default:
- status = NO_ERROR;
- break;
- }
-
- if (status != NO_ERROR) {
- ALOGE("SET TRANSACTION FAILED");
- return status;
- }
- }
+ status = doSurfaceTransaction(t.surface_change());
+ doDisplayTransaction(t.display_change());
if (t.animation()) {
SurfaceComposerClient::setAnimationTransaction();
@@ -319,27 +354,120 @@
return status;
}
-status_t Replayer::setPosition(uint32_t id, const PositionChange& pc) {
+status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) {
+ status_t status = NO_ERROR;
+
+ for (const SurfaceChange& change : surfaceChanges) {
+ std::unique_lock<std::mutex> lock(mLayerLock);
+ if (mLayers[change.id()] == nullptr) {
+ mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
+ }
+
+ switch (change.SurfaceChange_case()) {
+ case SurfaceChange::SurfaceChangeCase::kPosition:
+ status = setPosition(change.id(), change.position());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kSize:
+ status = setSize(change.id(), change.size());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kAlpha:
+ status = setAlpha(change.id(), change.alpha());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kLayer:
+ status = setLayer(change.id(), change.layer());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kCrop:
+ status = setCrop(change.id(), change.crop());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kMatrix:
+ status = setMatrix(change.id(), change.matrix());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kFinalCrop:
+ status = setFinalCrop(change.id(), change.final_crop());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
+ status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
+ status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kLayerStack:
+ status = setLayerStack(change.id(), change.layer_stack());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
+ status = setHiddenFlag(change.id(), change.hidden_flag());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
+ status = setOpaqueFlag(change.id(), change.opaque_flag());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kSecureFlag:
+ status = setSecureFlag(change.id(), change.secure_flag());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
+ waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
+ status = setDeferredTransaction(change.id(), change.deferred_transaction());
+ break;
+ default:
+ status = NO_ERROR;
+ break;
+ }
+
+ if (status != NO_ERROR) {
+ ALOGE("SET TRANSACTION FAILED");
+ return status;
+ }
+ }
+ return status;
+}
+
+void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) {
+ for (const DisplayChange& change : displayChanges) {
+ ALOGV("Doing display transaction");
+ std::unique_lock<std::mutex> lock(mDisplayLock);
+ if (mDisplays[change.id()] == nullptr) {
+ mDisplayCond.wait(lock, [&] { return (mDisplays[change.id()] != nullptr); });
+ }
+
+ switch (change.DisplayChange_case()) {
+ case DisplayChange::DisplayChangeCase::kSurface:
+ setDisplaySurface(change.id(), change.surface());
+ break;
+ case DisplayChange::DisplayChangeCase::kLayerStack:
+ setDisplayLayerStack(change.id(), change.layer_stack());
+ break;
+ case DisplayChange::DisplayChangeCase::kSize:
+ setDisplaySize(change.id(), change.size());
+ break;
+ case DisplayChange::DisplayChangeCase::kProjection:
+ setDisplayProjection(change.id(), change.projection());
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+status_t Replayer::setPosition(layer_id id, const PositionChange& pc) {
ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
return mLayers[id]->setPosition(pc.x(), pc.y());
}
-status_t Replayer::setSize(uint32_t id, const SizeChange& sc) {
+status_t Replayer::setSize(layer_id id, const SizeChange& sc) {
ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
return mLayers[id]->setSize(sc.w(), sc.h());
}
-status_t Replayer::setLayer(uint32_t id, const LayerChange& lc) {
+status_t Replayer::setLayer(layer_id id, const LayerChange& lc) {
ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
return mLayers[id]->setLayer(lc.layer());
}
-status_t Replayer::setAlpha(uint32_t id, const AlphaChange& ac) {
+status_t Replayer::setAlpha(layer_id id, const AlphaChange& ac) {
ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
return mLayers[id]->setAlpha(ac.alpha());
}
-status_t Replayer::setCrop(uint32_t id, const CropChange& cc) {
+status_t Replayer::setCrop(layer_id id, const CropChange& cc) {
ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
cc.rectangle().bottom());
@@ -349,7 +477,7 @@
return mLayers[id]->setCrop(r);
}
-status_t Replayer::setFinalCrop(uint32_t id, const FinalCropChange& fcc) {
+status_t Replayer::setFinalCrop(layer_id id, const FinalCropChange& fcc) {
ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
fcc.rectangle().bottom());
@@ -358,18 +486,18 @@
return mLayers[id]->setFinalCrop(r);
}
-status_t Replayer::setMatrix(uint32_t id, const MatrixChange& mc) {
+status_t Replayer::setMatrix(layer_id id, const MatrixChange& mc) {
ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
mc.dtdx(), mc.dsdy(), mc.dtdy());
return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
}
-status_t Replayer::setOverrideScalingMode(uint32_t id, const OverrideScalingModeChange& osmc) {
+status_t Replayer::setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc) {
ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode());
return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode());
}
-status_t Replayer::setTransparentRegionHint(uint32_t id, const TransparentRegionHintChange& trhc) {
+status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trhc) {
ALOGV("Setting Transparent Region Hint");
Region re = Region();
@@ -381,33 +509,33 @@
return mLayers[id]->setTransparentRegionHint(re);
}
-status_t Replayer::setLayerStack(uint32_t id, const LayerStackChange& lsc) {
+status_t Replayer::setLayerStack(layer_id id, const LayerStackChange& lsc) {
ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
return mLayers[id]->setLayerStack(lsc.layer_stack());
}
-status_t Replayer::setHiddenFlag(uint32_t id, const HiddenFlagChange& hfc) {
+status_t Replayer::setHiddenFlag(layer_id id, const HiddenFlagChange& hfc) {
ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
- uint32_t flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
+ layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden);
}
-status_t Replayer::setOpaqueFlag(uint32_t id, const OpaqueFlagChange& ofc) {
+status_t Replayer::setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc) {
ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
- uint32_t flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
+ layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque);
}
-status_t Replayer::setSecureFlag(uint32_t id, const SecureFlagChange& sfc) {
+status_t Replayer::setSecureFlag(layer_id id, const SecureFlagChange& sfc) {
ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
- uint32_t flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
+ layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure);
}
-status_t Replayer::setDeferredTransaction(uint32_t id, const DeferredTransactionChange& dtc) {
+status_t Replayer::setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc) {
ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
"frame_number=%llu",
id, dtc.layer_id(), dtc.frame_number());
@@ -421,7 +549,32 @@
return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number());
}
-status_t Replayer::createSurfaceControl(const Create& create, const std::shared_ptr<Event>& event) {
+void Replayer::setDisplaySurface(display_id id, const DispSurfaceChange& /*dsc*/) {
+ sp<IGraphicBufferProducer> outProducer;
+ sp<IGraphicBufferConsumer> outConsumer;
+ BufferQueue::createBufferQueue(&outProducer, &outConsumer);
+
+ SurfaceComposerClient::setDisplaySurface(mDisplays[id], outProducer);
+}
+
+void Replayer::setDisplayLayerStack(display_id id, const LayerStackChange& lsc) {
+ SurfaceComposerClient::setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
+}
+
+void Replayer::setDisplaySize(display_id id, const SizeChange& sc) {
+ SurfaceComposerClient::setDisplaySize(mDisplays[id], sc.w(), sc.h());
+}
+
+void Replayer::setDisplayProjection(display_id id, const ProjectionChange& pc) {
+ Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(),
+ pc.viewport().bottom());
+ Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom());
+
+ SurfaceComposerClient::setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
+}
+
+status_t Replayer::createSurfaceControl(
+ const SurfaceCreation& create, const std::shared_ptr<Event>& event) {
event->readyToExecute();
ALOGV("Creating Surface Control: ID: %d", create.id());
@@ -437,7 +590,7 @@
auto& layer = mLayers[create.id()];
layer = surfaceControl;
- mColors[create.id()] = HSVToRGB(HSV(rand() % 360, 1, 1));
+ mColors[create.id()] = HSV(rand() % 360, 1, 1);
mLayerCond.notify_all();
@@ -451,7 +604,7 @@
}
status_t Replayer::deleteSurfaceControl(
- const Delete& delete_, const std::shared_ptr<Event>& event) {
+ const SurfaceDeletion& delete_, const std::shared_ptr<Event>& event) {
ALOGV("Deleting %d Surface Control", delete_.id());
event->readyToExecute();
@@ -459,13 +612,15 @@
mLayersPendingRemoval.push_back(delete_.id());
- auto iterator = mBufferQueueSchedulers.find(delete_.id());
+ const auto& iterator = mBufferQueueSchedulers.find(delete_.id());
if (iterator != mBufferQueueSchedulers.end()) {
(*iterator).second->stopScheduling();
}
std::lock_guard<std::mutex> lock2(mLayerLock);
- mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
+ if (mLayers[delete_.id()] != nullptr) {
+ mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
+ }
return NO_ERROR;
}
@@ -496,6 +651,35 @@
return NO_ERROR;
}
+void Replayer::createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event) {
+ ALOGV("Creating display");
+ event->readyToExecute();
+
+ std::lock_guard<std::mutex> lock(mDisplayLock);
+ sp<IBinder> display = SurfaceComposerClient::createDisplay(
+ String8(create.name().c_str()), create.is_secure());
+ mDisplays[create.id()] = display;
+
+ mDisplayCond.notify_all();
+
+ ALOGV("Done creating display");
+}
+
+void Replayer::deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event) {
+ ALOGV("Delete display");
+ event->readyToExecute();
+
+ std::lock_guard<std::mutex> lock(mDisplayLock);
+ SurfaceComposerClient::destroyDisplay(mDisplays[delete_.id()]);
+ mDisplays.erase(delete_.id());
+}
+
+void Replayer::updatePowerMode(const PowerModeUpdate& pmu, const std::shared_ptr<Event>& event) {
+ ALOGV("Updating power mode");
+ event->readyToExecute();
+ SurfaceComposerClient::setDisplayPowerMode(mDisplays[pmu.id()], pmu.mode());
+}
+
void Replayer::waitUntilTimestamp(int64_t timestamp) {
ALOGV("Waiting for %lld nanoseconds...", static_cast<int64_t>(timestamp - mCurrentTime));
std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime));
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index ff951d1..f757fc3 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -40,16 +40,21 @@
namespace android {
const auto DEFAULT_PATH = "/data/local/tmp/SurfaceTrace.dat";
-const auto RAND_COLOR_SEED = 1000;
+const auto RAND_COLOR_SEED = 700;
const auto DEFAULT_THREADS = 3;
-typedef uint32_t layer_id;
+typedef int32_t layer_id;
+typedef int32_t display_id;
+
+typedef google::protobuf::RepeatedPtrField<SurfaceChange> SurfaceChanges;
+typedef google::protobuf::RepeatedPtrField<DisplayChange> DisplayChanges;
class Replayer {
public:
Replayer(const std::string& filename, bool replayManually = false,
- int numThreads = DEFAULT_THREADS);
- Replayer(const Trace& trace, bool replayManually = false, int numThreads = DEFAULT_THREADS);
+ int numThreads = DEFAULT_THREADS, bool wait = true, nsecs_t stopHere = -1);
+ Replayer(const Trace& trace, bool replayManually = false, int numThreads = DEFAULT_THREADS,
+ bool wait = true, nsecs_t stopHere = -1);
status_t replay();
@@ -62,24 +67,37 @@
status_t dispatchEvent(int index);
status_t doTransaction(const Transaction& transaction, const std::shared_ptr<Event>& event);
- status_t createSurfaceControl(const Create& create, const std::shared_ptr<Event>& event);
- status_t deleteSurfaceControl(const Delete& delete_, const std::shared_ptr<Event>& event);
+ status_t createSurfaceControl(const SurfaceCreation& create,
+ const std::shared_ptr<Event>& event);
+ status_t deleteSurfaceControl(const SurfaceDeletion& delete_,
+ const std::shared_ptr<Event>& event);
status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr<Event>& event);
+ void createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event);
+ void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event);
+ void updatePowerMode(const PowerModeUpdate& update, const std::shared_ptr<Event>& event);
- status_t setPosition(uint32_t id, const PositionChange& pc);
- status_t setSize(uint32_t id, const SizeChange& sc);
- status_t setAlpha(uint32_t id, const AlphaChange& ac);
- status_t setLayer(uint32_t id, const LayerChange& lc);
- status_t setCrop(uint32_t id, const CropChange& cc);
- status_t setFinalCrop(uint32_t id, const FinalCropChange& fcc);
- status_t setMatrix(uint32_t id, const MatrixChange& mc);
- status_t setOverrideScalingMode(uint32_t id, const OverrideScalingModeChange& osmc);
- status_t setTransparentRegionHint(uint32_t id, const TransparentRegionHintChange& trgc);
- status_t setLayerStack(uint32_t id, const LayerStackChange& lsc);
- status_t setHiddenFlag(uint32_t id, const HiddenFlagChange& hfc);
- status_t setOpaqueFlag(uint32_t id, const OpaqueFlagChange& ofc);
- status_t setSecureFlag(uint32_t id, const SecureFlagChange& sfc);
- status_t setDeferredTransaction(uint32_t id, const DeferredTransactionChange& dtc);
+ status_t doSurfaceTransaction(const SurfaceChanges& surfaceChange);
+ void doDisplayTransaction(const DisplayChanges& displayChange);
+
+ status_t setPosition(layer_id id, const PositionChange& pc);
+ status_t setSize(layer_id id, const SizeChange& sc);
+ status_t setAlpha(layer_id id, const AlphaChange& ac);
+ status_t setLayer(layer_id id, const LayerChange& lc);
+ status_t setCrop(layer_id id, const CropChange& cc);
+ status_t setFinalCrop(layer_id id, const FinalCropChange& fcc);
+ status_t setMatrix(layer_id id, const MatrixChange& mc);
+ status_t setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc);
+ status_t setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trgc);
+ status_t setLayerStack(layer_id id, const LayerStackChange& lsc);
+ status_t setHiddenFlag(layer_id id, const HiddenFlagChange& hfc);
+ status_t setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc);
+ status_t setSecureFlag(layer_id id, const SecureFlagChange& sfc);
+ status_t setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc);
+
+ void setDisplaySurface(display_id id, const DispSurfaceChange& dsc);
+ void setDisplayLayerStack(display_id id, const LayerStackChange& lsc);
+ void setDisplaySize(display_id id, const SizeChange& sc);
+ void setDisplayProjection(display_id id, const ProjectionChange& pc);
void doDeleteSurfaceControls();
void waitUntilTimestamp(int64_t timestamp);
@@ -93,15 +111,20 @@
int64_t mCurrentTime = 0;
int32_t mNumThreads = DEFAULT_THREADS;
+ Increment mCurrentIncrement;
+
std::string mLastInput;
static atomic_bool sReplayingManually;
bool mWaitingForNextVSync;
+ bool mWaitForTimeStamps;
+ nsecs_t mStopTimeStamp;
+ bool mHasStopped;
std::mutex mLayerLock;
std::condition_variable mLayerCond;
std::unordered_map<layer_id, sp<SurfaceControl>> mLayers;
- std::unordered_map<layer_id, RGB> mColors;
+ std::unordered_map<layer_id, HSV> mColors;
std::mutex mPendingLayersLock;
std::vector<layer_id> mLayersPendingRemoval;
@@ -109,6 +132,10 @@
std::mutex mBufferQueueSchedulerLock;
std::unordered_map<layer_id, std::shared_ptr<BufferQueueScheduler>> mBufferQueueSchedulers;
+ std::mutex mDisplayLock;
+ std::condition_variable mDisplayCond;
+ std::unordered_map<display_id, sp<IBinder>> mDisplays;
+
sp<SurfaceComposerClient> mComposerClient;
std::queue<std::shared_ptr<Event>> mPendingIncrements;
};
diff --git a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py
new file mode 100644
index 0000000..a892e46
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py
@@ -0,0 +1,294 @@
+#!/usr/bin/python
+from subprocess import call
+import os
+proto_path = os.environ['ANDROID_BUILD_TOP'] + "/frameworks/native/cmds/surfacereplayer/proto/src/"
+call(["aprotoc", "-I=" + proto_path, "--python_out=.", proto_path + "trace.proto"])
+
+from trace_pb2 import *
+
+trace = Trace()
+
+def main():
+ global trace
+ while(1):
+ option = main_menu()
+
+ if option == 0:
+ break
+
+ increment = trace.increment.add()
+ increment.time_stamp = int(input("Time stamp of action: "))
+
+ if option == 1:
+ transaction(increment)
+ elif option == 2:
+ surface_create(increment)
+ elif option == 3:
+ surface_delete(increment)
+ elif option == 4:
+ display_create(increment)
+ elif option == 5:
+ display_delete(increment)
+ elif option == 6:
+ buffer_update(increment)
+ elif option == 7:
+ vsync_event(increment)
+ elif option == 8:
+ power_mode_update(increment)
+
+ seralizeTrace()
+
+def seralizeTrace():
+ with open("trace.dat", 'wb') as f:
+ f.write(trace.SerializeToString())
+
+
+def main_menu():
+ print ("")
+ print ("What would you like to do?")
+ print ("1. Add transaction")
+ print ("2. Add surface creation")
+ print ("3. Add surface deletion")
+ print ("4. Add display creation")
+ print ("5. Add display deletion")
+ print ("6. Add buffer update")
+ print ("7. Add VSync event")
+ print ("8. Add power mode update")
+ print ("0. Finish and serialize")
+ print ("")
+
+ return int(input("> "))
+
+def transaction_menu():
+ print ("")
+ print ("What kind of transaction?")
+ print ("1. Position Change")
+ print ("2. Size Change")
+ print ("3. Alpha Change")
+ print ("4. Layer Change")
+ print ("5. Crop Change")
+ print ("6. Final Crop Change")
+ print ("7. Matrix Change")
+ print ("8. Override Scaling Mode Change")
+ print ("9. Transparent Region Hint Change")
+ print ("10. Layer Stack Change")
+ print ("11. Hidden Flag Change")
+ print ("12. Opaque Flag Change")
+ print ("13. Secure Flag Change")
+ print ("14. Deferred Transaction Change")
+ print ("15. Display - Surface Change")
+ print ("16. Display - Layer Stack Change")
+ print ("17. Display - Size Change")
+ print ("18. Display - Projection Change")
+ print ("0. Finished adding Changes to this transaction")
+ print ("")
+
+ return int(input("> "))
+
+def transaction(increment):
+ global trace
+
+ increment.transaction.synchronous \
+ = bool(input("Is transaction synchronous (True/False): "))
+ increment.transaction.animation \
+ = bool(input("Is transaction animated (True/False): "))
+
+ while(1):
+ option = transaction_menu()
+
+ if option == 0:
+ break
+
+ change = None
+ if option <= 14:
+ change = increment.transaction.surface_change.add()
+ elif option >= 15 and option <= 18:
+ change = increment.transaction.display_change.add()
+
+ change.id = int(input("ID of layer/display to undergo a change: "))
+
+ if option == 1:
+ change.position.x, change.position.y = position()
+ elif option == 2:
+ change.size.w, change.size.h = size()
+ elif option == 3:
+ change.alpha.alpha = alpha()
+ elif option == 4:
+ change.layer.layer = layer()
+ elif option == 5:
+ change.crop.rectangle.left, change.crop.rectangle.top, \
+ change.crop.rectangle.right, change.crop.rectangle.bottom = crop()
+ elif option == 6:
+ change.final_crop.rectangle.left, \
+ change.final_crop.rectangle.top, \
+ change.final_crop.rectangle.right,\
+ change.final_crop.rectangle.bottom = final_crop()
+ elif option == 7:
+ change.matrix.dsdx,\
+ change.matrix.dtdx,\
+ change.matrix.dsdy,\
+ change.matrix.dtdy = layer()
+ elif option == 8:
+ change.override_scaling_mode.override_scaling_mode \
+ = override_scaling_mode()
+ elif option == 9:
+ for rect in transparent_region_hint():
+ new = increment.transparent_region_hint.region.add()
+ new.left = rect[0]
+ new.top = rect[1]
+ new.right = rect[2]
+ new.bottom = rect[3]
+ elif option == 10:
+ change.layer_stack.layer_stack = layer_stack()
+ elif option == 11:
+ change.hidden_flag.hidden_flag = hidden_flag()
+ elif option == 12:
+ change.opaque_flag.opaque_flag = opaque_flag()
+ elif option == 13:
+ change.secure_flag.secure_flag = secure_flag()
+ elif option == 14:
+ change.deferred_transaction.layer_id, \
+ change.deferred_transaction.frame_number = deferred_transaction()
+ elif option == 15:
+ change.surface.buffer_queue_id, \
+ change.surface.buffer_queue_name = surface()
+ elif option == 16:
+ change.layer_stack.layer_stack = layer_stack()
+ elif option == 17:
+ change.size.w, change.size.h = size()
+ elif option == 18:
+ projection(change)
+
+def surface_create(increment):
+ increment.surface_creation.id = int(input("Enter id: "))
+ n = str(raw_input("Enter name: "))
+ increment.surface_creation.name = n
+ increment.surface_creation.w = input("Enter w: ")
+ increment.surface_creation.h = input("Enter h: ")
+
+def surface_delete(increment):
+ increment.surface_deletion.id = int(input("Enter id: "))
+
+def display_create(increment):
+ increment.display_creation.id = int(input("Enter id: "))
+ increment.display_creation.name = str(raw_input("Enter name: "))
+ increment.display_creation.type = int(input("Enter type: "))
+ increment.display_creation.is_secure = bool(input("Enter if secure: "))
+
+def display_delete(increment):
+ increment.surface_deletion.id = int(input("Enter id: "))
+
+def buffer_update(increment):
+ increment.buffer_update.id = int(input("Enter id: "))
+ increment.buffer_update.w = int(input("Enter w: "))
+ increment.buffer_update.h = int(input("Enter h: "))
+ increment.buffer_update.frame_number = int(input("Enter frame_number: "))
+
+def vsync_event(increment):
+ increment.vsync_event.when = int(input("Enter when: "))
+
+def power_mode_update(increment):
+ increment.power_mode_update.id = int(input("Enter id: "))
+ increment.power_mode_update.mode = int(input("Enter mode: "))
+
+def position():
+ x = input("Enter x: ")
+ y = input("Enter y: ")
+
+ return float(x), float(y)
+
+def size():
+ w = input("Enter w: ")
+ h = input("Enter h: ")
+
+ return int(w), int(h)
+
+def alpha():
+ alpha = input("Enter alpha: ")
+
+ return float(alpha)
+
+def layer():
+ layer = input("Enter layer: ")
+
+ return int(layer)
+
+def crop():
+ return rectangle()
+
+def final_crop():
+ return rectangle()
+
+def matrix():
+ dsdx = input("Enter dsdx: ")
+ dtdx = input("Enter dtdx: ")
+ dsdy = input("Enter dsdy: ")
+ dtdy = input("Enter dtdy: ")
+
+ return float(dsdx)
+
+def override_scaling_mode():
+ mode = input("Enter override scaling mode: ")
+
+ return int(mode)
+
+def transparent_region_hint():
+ num = input("Enter number of rectangles in region: ")
+
+ return [rectangle() in range(x)]
+
+def layer_stack():
+ layer_stack = input("Enter layer stack: ")
+
+ return int(layer_stack)
+
+def hidden_flag():
+ flag = input("Enter hidden flag state (True/False): ")
+
+ return bool(flag)
+
+def opaque_flag():
+ flag = input("Enter opaque flag state (True/False): ")
+
+ return bool(flag)
+
+def secure_flag():
+ flag = input("Enter secure flag state (True/False): ")
+
+ return bool(flag)
+
+def deferred_transaction():
+ layer_id = input("Enter layer_id: ")
+ frame_number = input("Enter frame_number: ")
+
+ return int(layer_id), int(frame_number)
+
+def surface():
+ id = input("Enter id: ")
+ name = raw_input("Enter name: ")
+
+ return int(id), str(name)
+
+def projection(change):
+ change.projection.orientation = input("Enter orientation: ")
+ print("Enter rectangle for viewport")
+ change.projection.viewport.left, \
+ change.projection.viewport.top, \
+ change.projection.viewport.right,\
+ change.projection.viewport.bottom = rectangle()
+ print("Enter rectangle for frame")
+ change.projection.frame.left, \
+ change.projection.frame.top, \
+ change.projection.frame.right,\
+ change.projection.frame.bottom = rectangle()
+
+def rectangle():
+ left = input("Enter left: ")
+ top = input("Enter top: ")
+ right = input("Enter right: ")
+ bottom = input("Enter bottom: ")
+
+ return int(left), int(top), int(right), int(bottom)
+
+if __name__ == "__main__":
+ main()
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 55ad6cc..790fa8c 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "IMemory"
+#include <atomic>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -29,7 +30,6 @@
#include <cutils/log.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
-#include <utils/Atomic.h>
#include <binder/Parcel.h>
#include <utils/CallStack.h>
@@ -56,12 +56,15 @@
struct heap_info_t {
sp<IMemoryHeap> heap;
int32_t count;
+ // Note that this cannot be meaningfully copied.
};
void free_heap(const wp<IBinder>& binder);
- Mutex mHeapCacheLock;
+ Mutex mHeapCacheLock; // Protects entire vector below.
KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
+ // We do not use the copy-on-write capabilities of KeyedVector.
+ // TODO: Reimplemement based on standard C++ container?
};
static sp<HeapCache> gHeapCache = new HeapCache();
@@ -105,7 +108,7 @@
void assertMapped() const;
void assertReallyMapped() const;
- mutable volatile int32_t mHeapId;
+ mutable std::atomic<int32_t> mHeapId;
mutable void* mBase;
mutable size_t mSize;
mutable uint32_t mFlags;
@@ -248,8 +251,9 @@
}
BpMemoryHeap::~BpMemoryHeap() {
- if (mHeapId != -1) {
- close(mHeapId);
+ int32_t heapId = mHeapId.load(memory_order_relaxed);
+ if (heapId != -1) {
+ close(heapId);
if (mRealHeap) {
// by construction we're the last one
if (mBase != MAP_FAILED) {
@@ -257,7 +261,7 @@
if (VERBOSE) {
ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
- binder.get(), this, mSize, mHeapId);
+ binder.get(), this, mSize, heapId);
CallStack stack(LOG_TAG);
}
@@ -273,17 +277,21 @@
void BpMemoryHeap::assertMapped() const
{
- if (mHeapId == -1) {
+ int32_t heapId = mHeapId.load(memory_order_acquire);
+ if (heapId == -1) {
sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
heap->assertReallyMapped();
if (heap->mBase != MAP_FAILED) {
Mutex::Autolock _l(mLock);
- if (mHeapId == -1) {
+ if (mHeapId.load(memory_order_relaxed) == -1) {
mBase = heap->mBase;
mSize = heap->mSize;
mOffset = heap->mOffset;
- android_atomic_write( dup( heap->mHeapId ), &mHeapId );
+ int fd = dup(heap->mHeapId.load(memory_order_relaxed));
+ ALOGE_IF(fd==-1, "cannot dup fd=%d",
+ heap->mHeapId.load(memory_order_relaxed));
+ mHeapId.store(fd, memory_order_release);
}
} else {
// something went wrong
@@ -294,7 +302,8 @@
void BpMemoryHeap::assertReallyMapped() const
{
- if (mHeapId == -1) {
+ int32_t heapId = mHeapId.load(memory_order_acquire);
+ if (heapId == -1) {
// remote call without mLock held, worse case scenario, we end up
// calling transact() from multiple threads, but that's not a problem,
@@ -313,7 +322,7 @@
parcel_fd, size, err, strerror(-err));
Mutex::Autolock _l(mLock);
- if (mHeapId == -1) {
+ if (mHeapId.load(memory_order_relaxed) == -1) {
int fd = dup( parcel_fd );
ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
parcel_fd, size, err, strerror(errno));
@@ -322,7 +331,6 @@
if (!(flags & READ_ONLY)) {
access |= PROT_WRITE;
}
-
mRealHeap = true;
mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
@@ -333,7 +341,7 @@
mSize = size;
mFlags = flags;
mOffset = offset;
- android_atomic_write(fd, &mHeapId);
+ mHeapId.store(fd, memory_order_release);
}
}
}
@@ -341,7 +349,8 @@
int BpMemoryHeap::getHeapID() const {
assertMapped();
- return mHeapId;
+ // We either stored mHeapId ourselves, or loaded it with acquire semantics.
+ return mHeapId.load(memory_order_relaxed);
}
void* BpMemoryHeap::getBase() const {
@@ -418,9 +427,10 @@
"found binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
binder.get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
- static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
+ static_cast<BpMemoryHeap*>(info.heap.get())
+ ->mHeapId.load(memory_order_relaxed),
info.count);
- android_atomic_inc(&info.count);
+ ++info.count;
return info.heap;
} else {
heap_info_t info;
@@ -445,13 +455,13 @@
ssize_t i = mHeapCache.indexOfKey(binder);
if (i>=0) {
heap_info_t& info(mHeapCache.editValueAt(i));
- int32_t c = android_atomic_dec(&info.count);
- if (c == 1) {
+ if (--info.count == 0) {
ALOGD_IF(VERBOSE,
"removing binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
binder.unsafe_get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
- static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
+ static_cast<BpMemoryHeap*>(info.heap.get())
+ ->mHeapId.load(memory_order_relaxed),
info.count);
rel = mHeapCache.valueAt(i).heap;
mHeapCache.removeItemsAt(i);
@@ -482,7 +492,7 @@
ALOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%zu)",
mHeapCache.keyAt(i).unsafe_get(),
info.heap.get(), info.count,
- h->mHeapId, h->mBase, h->mSize);
+ h->mHeapId.load(memory_order_relaxed), h->mBase, h->mSize);
}
}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 319d1d9..d42bb82 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -16,8 +16,6 @@
#define LOG_TAG "ProcessState"
-#include <cutils/process_name.h>
-
#include <binder/ProcessState.h>
#include <utils/Atomic.h>
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index 81d5a57..308bd7d 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -115,13 +115,13 @@
EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255));
EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
- EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255));
- EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255));
- EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255));
- EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255));
- EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255));
- EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255));
- EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255));
+ EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255, 3));
+ EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255, 3));
+ EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255, 3));
+ EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255, 3));
+ EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255, 3));
+ EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255, 3));
+ EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255, 3));
}
TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index c1e1bad..f2f1444 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -206,7 +206,7 @@
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch,
- SensorEventConnection const * const * mapFlushEventsToConnections) {
+ wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
// filter out events not for this connection
int count = 0;
Mutex::Autolock _l(mConnectionLock);
@@ -234,7 +234,7 @@
FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
// Check if there is a pending flush_complete event for this sensor on this connection.
if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
- this == mapFlushEventsToConnections[i]) {
+ mapFlushEventsToConnections[i] == this) {
flushInfo.mFirstFlushPending = false;
ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
buffer[i].meta_data.sensor);
@@ -255,7 +255,7 @@
// from the same sensor_handle AND the current connection is mapped to the
// corresponding flush_complete_event.
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
- if (this == mapFlushEventsToConnections[i]) {
+ if (mapFlushEventsToConnections[i] == this) {
scratch[count++] = buffer[i];
}
++i;
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index b796cc0..883c16e 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -52,7 +52,7 @@
bool isDataInjectionMode, const String16& opPackageName);
status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
- SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
+ wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL);
bool hasSensor(int32_t handle) const;
bool hasAnySensor() const;
bool hasOneShotSensors() const;
diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp
index 644cfb0..53fb9de 100644
--- a/services/sensorservice/SensorRecord.cpp
+++ b/services/sensorservice/SensorRecord.cpp
@@ -21,13 +21,13 @@
namespace android {
SensorService::SensorRecord::SensorRecord(
- const sp<SensorEventConnection>& connection)
+ const sp<const SensorEventConnection>& connection)
{
mConnections.add(connection);
}
bool SensorService::SensorRecord::addConnection(
- const sp<SensorEventConnection>& connection)
+ const sp<const SensorEventConnection>& connection)
{
if (mConnections.indexOf(connection) < 0) {
mConnections.add(connection);
@@ -37,16 +37,16 @@
}
bool SensorService::SensorRecord::removeConnection(
- const wp<SensorEventConnection>& connection)
+ const wp<const SensorEventConnection>& connection)
{
ssize_t index = mConnections.indexOf(connection);
if (index >= 0) {
mConnections.removeItemsAt(index, 1);
}
// Remove this connections from the queue of flush() calls made on this sensor.
- for (Vector< wp<SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
+ for (Vector< wp<const SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
it != mPendingFlushConnections.end(); ) {
- if (it->unsafe_get() == connection.unsafe_get()) {
+ if (*it == connection) {
it = mPendingFlushConnections.erase(it);
} else {
++it;
@@ -56,7 +56,7 @@
}
void SensorService::SensorRecord::addPendingFlushConnection(
- const sp<SensorEventConnection>& connection) {
+ const sp<const SensorEventConnection>& connection) {
mPendingFlushConnections.add(connection);
}
@@ -66,10 +66,10 @@
}
}
-SensorService::SensorEventConnection *
+wp<const SensorService::SensorEventConnection>
SensorService::SensorRecord::getFirstPendingFlushConnection() {
if (mPendingFlushConnections.size() > 0) {
- return mPendingFlushConnections[0].unsafe_get();
+ return mPendingFlushConnections[0];
}
return NULL;
}
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 29b970d..5a35410 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,20 +25,20 @@
class SensorService::SensorRecord {
public:
- SensorRecord(const sp<SensorEventConnection>& connection);
- bool addConnection(const sp<SensorEventConnection>& connection);
- bool removeConnection(const wp<SensorEventConnection>& connection);
+ SensorRecord(const sp<const SensorEventConnection>& connection);
+ bool addConnection(const sp<const SensorEventConnection>& connection);
+ bool removeConnection(const wp<const SensorEventConnection>& connection);
size_t getNumConnections() const { return mConnections.size(); }
- void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+ void addPendingFlushConnection(const sp<const SensorEventConnection>& connection);
void removeFirstPendingFlushConnection();
- SensorEventConnection * getFirstPendingFlushConnection();
+ wp<const SensorEventConnection> getFirstPendingFlushConnection();
void clearAllPendingFlushConnections();
private:
- SortedVector< wp<SensorEventConnection> > mConnections;
+ SortedVector< wp<const SensorEventConnection> > mConnections;
// A queue of all flush() calls made on this sensor. Flush complete events
// will be sent in this order.
- Vector< wp<SensorEventConnection> > mPendingFlushConnections;
+ Vector< wp<const SensorEventConnection> > mPendingFlushConnections;
};
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index a24740b..dbd0624 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -260,7 +260,7 @@
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
- mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
+ mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];
mCurrentOperatingMode = NORMAL;
mNextSensorRegIndex = 0;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 343796a..e969d8a 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -237,7 +237,7 @@
SortedVector< wp<SensorEventConnection> > mActiveConnections;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
- SensorEventConnection const **mMapFlushEventsToConnections;
+ wp<const SensorEventConnection> * mMapFlushEventsToConnections;
std::unordered_map<int, RecentEventLogger*> mRecentEvent;
Mode mCurrentOperatingMode;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5c2c0ad..6c18ef7 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -613,3 +613,17 @@
mDisplaySurface->dumpAsString(surfaceDump);
result.append(surfaceDump);
}
+
+std::atomic<int32_t> DisplayDeviceState::nextDisplayId(1);
+
+DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure)
+ : type(type),
+ layerStack(DisplayDevice::NO_LAYER_STACK),
+ orientation(0),
+ width(0),
+ height(0),
+ isSecure(isSecure)
+{
+ viewport.makeInvalid();
+ frame.makeInvalid();
+}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 105e980..92ede08 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -263,6 +263,28 @@
#endif
};
+struct DisplayDeviceState {
+ DisplayDeviceState() = default;
+ DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
+
+ bool isValid() const { return type >= 0; }
+ bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
+ bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
+
+ static std::atomic<int32_t> nextDisplayId;
+ int32_t displayId = nextDisplayId++;
+ DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_ID_INVALID;
+ sp<IGraphicBufferProducer> surface;
+ uint32_t layerStack = DisplayDevice::NO_LAYER_STACK;
+ Rect viewport;
+ Rect frame;
+ uint8_t orientation = 0;
+ uint32_t width = 0;
+ uint32_t height = 0;
+ String8 displayName;
+ bool isSecure = false;
+};
+
}; // namespace android
#endif // ANDROID_DISPLAY_DEVICE_H
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index bdd94e3..d1bc7eb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -44,13 +44,14 @@
return;
}
-EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger)
+EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger, bool interceptVSyncs)
: mVSyncSource(src),
mFlinger(flinger),
mUseSoftwareVSync(false),
mVsyncEnabled(false),
mDebugVsyncEnabled(false),
- mVsyncHintSent(false) {
+ mVsyncHintSent(false),
+ mInterceptVSyncs(interceptVSyncs) {
for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
@@ -226,7 +227,9 @@
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
- mFlinger.mInterceptor.saveVSyncEvent(timestamp);
+ if (mInterceptVSyncs) {
+ mFlinger.mInterceptor.saveVSyncEvent(timestamp);
+ }
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 34654fa..f1f89f8 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -77,7 +77,7 @@
public:
- EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger);
+ EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger, bool interceptVSyncs);
sp<Connection> createEventConnection() const;
status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -132,6 +132,7 @@
bool mDebugVsyncEnabled;
bool mVsyncHintSent;
+ const bool mInterceptVSyncs;
timer_t mTimerId;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 320f416..c15b4bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -198,6 +198,10 @@
property_get("debug.sf.disable_backpressure", value, "0");
mPropagateBackpressure = !atoi(value);
ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
+
+ property_get("debug.sf.disable_hwc_vds", value, "0");
+ mUseHwcVirtualDisplays = !atoi(value);
+ ALOGI_IF(!mUseHwcVirtualDisplays, "Disabling HWC virtual displays");
}
void SurfaceFlinger::onFirstRef()
@@ -257,7 +261,7 @@
DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
info.displayName = displayName;
mCurrentState.displays.add(token, info);
-
+ mInterceptor.saveDisplayCreation(info);
return token;
}
@@ -275,7 +279,7 @@
ALOGE("destroyDisplay called for non-virtual display");
return;
}
-
+ mInterceptor.saveDisplayDeletion(info.displayId);
mCurrentState.displays.removeItemsAt(idx);
setTransactionFlags(eDisplayTransactionNeeded);
}
@@ -288,6 +292,7 @@
// All non-virtual displays are currently considered secure.
DisplayDeviceState info(type, true);
mCurrentState.displays.add(mBuiltinDisplays[type], info);
+ mInterceptor.saveDisplayCreation(info);
}
sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
@@ -498,10 +503,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc, *this);
+ mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc, *this);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
// set SFEventThread to SCHED_FIFO to minimize jitter
@@ -891,7 +896,7 @@
ALOGV("VSync Injections enabled");
if (mVSyncInjector.get() == nullptr) {
mVSyncInjector = new InjectVSyncSource();
- mInjectorEventThread = new EventThread(mVSyncInjector, *this);
+ mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
}
mEventQueue.setEventThread(mInjectorEventThread);
} else {
@@ -1655,26 +1660,28 @@
// etc.) but no internal state (i.e. a DisplayDevice).
if (state.surface != NULL) {
- int width = 0;
- int status = state.surface->query(
- NATIVE_WINDOW_WIDTH, &width);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query width (%d)", status);
- int height = 0;
- status = state.surface->query(
- NATIVE_WINDOW_HEIGHT, &height);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query height (%d)", status);
- int intFormat = 0;
- status = state.surface->query(
- NATIVE_WINDOW_FORMAT, &intFormat);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query format (%d)", status);
- auto format = static_cast<android_pixel_format_t>(
- intFormat);
+ if (mUseHwcVirtualDisplays) {
+ int width = 0;
+ int status = state.surface->query(
+ NATIVE_WINDOW_WIDTH, &width);
+ ALOGE_IF(status != NO_ERROR,
+ "Unable to query width (%d)", status);
+ int height = 0;
+ status = state.surface->query(
+ NATIVE_WINDOW_HEIGHT, &height);
+ ALOGE_IF(status != NO_ERROR,
+ "Unable to query height (%d)", status);
+ int intFormat = 0;
+ status = state.surface->query(
+ NATIVE_WINDOW_FORMAT, &intFormat);
+ ALOGE_IF(status != NO_ERROR,
+ "Unable to query format (%d)", status);
+ auto format = static_cast<android_pixel_format_t>(
+ intFormat);
- mHwc->allocateVirtualDisplay(width, height, &format,
- &hwcId);
+ mHwc->allocateVirtualDisplay(width, height, &format,
+ &hwcId);
+ }
// TODO: Plumb requested format back up to consumer
@@ -2371,7 +2378,9 @@
}
if (transactionFlags) {
- mInterceptor.saveLayerUpdates(state, flags);
+ if (mInterceptor.isEnabled()) {
+ mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags);
+ }
// this triggers the transaction
setTransactionFlags(transactionFlags);
@@ -2567,7 +2576,7 @@
if (result != NO_ERROR) {
return result;
}
- mInterceptor.saveLayerCreate(layer);
+ mInterceptor.saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
return result;
@@ -2615,7 +2624,7 @@
status_t err = NO_ERROR;
sp<Layer> l(client->getLayerUser(handle));
if (l != NULL) {
- mInterceptor.saveLayerDelete(l);
+ mInterceptor.saveSurfaceDeletion(l);
err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -2687,6 +2696,16 @@
return;
}
+ if (mInterceptor.isEnabled()) {
+ Mutex::Autolock _l(mStateLock);
+ ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
+ if (idx < 0) {
+ ALOGW("Surface Interceptor SavePowerMode: invalid display token");
+ return;
+ }
+ mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
+ }
+
if (currentMode == HWC_POWER_MODE_OFF) {
// Turn on the display
getHwComposer().setPowerMode(type, mode);
@@ -3356,7 +3375,7 @@
n = data.readInt32();
if (n) {
ALOGV("Interceptor enabled");
- mInterceptor.enable(mDrawingState.layersSortedByZ);
+ mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
}
else{
ALOGV("Interceptor disabled");
@@ -3364,6 +3383,11 @@
}
return NO_ERROR;
}
+ case 1021: { // Disable HWC virtual displays
+ n = data.readInt32();
+ mUseHwcVirtualDisplays = !n;
+ return NO_ERROR;
+ }
}
}
return err;
@@ -3884,31 +3908,6 @@
return l->sequence - r->sequence;
}
-// ---------------------------------------------------------------------------
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
- : type(DisplayDevice::DISPLAY_ID_INVALID),
- layerStack(DisplayDevice::NO_LAYER_STACK),
- orientation(0),
- width(0),
- height(0),
- isSecure(false) {
-}
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
- DisplayDevice::DisplayType type, bool isSecure)
- : type(type),
- layerStack(DisplayDevice::NO_LAYER_STACK),
- orientation(0),
- width(0),
- height(0),
- isSecure(isSecure) {
- viewport.makeInvalid();
- frame.makeInvalid();
-}
-
-// ---------------------------------------------------------------------------
-
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 00790b1..6449e57 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -175,23 +175,6 @@
virtual int do_compare(const void* lhs, const void* rhs) const;
};
- struct DisplayDeviceState {
- DisplayDeviceState();
- DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
- bool isValid() const { return type >= 0; }
- bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
- bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
- DisplayDevice::DisplayType type;
- sp<IGraphicBufferProducer> surface;
- uint32_t layerStack;
- Rect viewport;
- Rect frame;
- uint8_t orientation;
- uint32_t width, height;
- String8 displayName;
- bool isSecure;
- };
-
struct State {
LayerVector layersSortedByZ;
DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
@@ -539,6 +522,7 @@
bool mPropagateBackpressure = true;
#endif
SurfaceInterceptor mInterceptor;
+ bool mUseHwcVirtualDisplays = true;
// these are thread safe
mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index bccefe8..97ad9b2 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -196,6 +196,10 @@
}
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+
+ property_get("debug.sf.disable_hwc_vds", value, "0");
+ mUseHwcVirtualDisplays = !atoi(value);
+ ALOGI_IF(!mUseHwcVirtualDisplays, "Disabling HWC virtual displays");
}
void SurfaceFlinger::onFirstRef()
@@ -255,7 +259,7 @@
DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
info.displayName = displayName;
mCurrentState.displays.add(token, info);
-
+ mInterceptor.saveDisplayCreation(info);
return token;
}
@@ -273,7 +277,7 @@
ALOGE("destroyDisplay called for non-virtual display");
return;
}
-
+ mInterceptor.saveDisplayDeletion(info.displayId);
mCurrentState.displays.removeItemsAt(idx);
setTransactionFlags(eDisplayTransactionNeeded);
}
@@ -285,6 +289,7 @@
// All non-virtual displays are currently considered secure.
DisplayDeviceState info(type, true);
mCurrentState.displays.add(mBuiltinDisplays[type], info);
+ mInterceptor.saveDisplayCreation(info);
}
sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
@@ -494,10 +499,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc, *this);
+ mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc, *this);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
// set SFEventThread to SCHED_FIFO to minimize jitter
@@ -854,7 +859,7 @@
ALOGV("VSync Injections enabled");
if (mVSyncInjector.get() == nullptr) {
mVSyncInjector = new InjectVSyncSource();
- mInjectorEventThread = new EventThread(mVSyncInjector, *this);
+ mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
}
mEventQueue.setEventThread(mInjectorEventThread);
} else {
@@ -1581,9 +1586,10 @@
NATIVE_WINDOW_HEIGHT, &height);
ALOGE_IF(status != NO_ERROR,
"Unable to query height (%d)", status);
- if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
+ if (mUseHwcVirtualDisplays &&
+ (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
(width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
- height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+ height <= MAX_VIRTUAL_DISPLAY_DIMENSION))) {
hwcDisplayId = allocateHwcDisplayId(state.type);
}
@@ -2288,7 +2294,9 @@
}
if (transactionFlags) {
- mInterceptor.saveLayerUpdates(state, flags);
+ if (mInterceptor.isEnabled()) {
+ mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags);
+ }
// this triggers the transaction
setTransactionFlags(transactionFlags);
@@ -2484,7 +2492,7 @@
if (result != NO_ERROR) {
return result;
}
- mInterceptor.saveLayerCreate(layer);
+ mInterceptor.saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
return result;
@@ -2532,7 +2540,7 @@
status_t err = NO_ERROR;
sp<Layer> l(client->getLayerUser(handle));
if (l != NULL) {
- mInterceptor.saveLayerDelete(l);
+ mInterceptor.saveSurfaceDeletion(l);
err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -2604,6 +2612,16 @@
return;
}
+ if (mInterceptor.isEnabled()) {
+ Mutex::Autolock _l(mStateLock);
+ ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
+ if (idx < 0) {
+ ALOGW("Surface Interceptor SavePowerMode: invalid display token");
+ return;
+ }
+ mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
+ }
+
if (currentMode == HWC_POWER_MODE_OFF) {
// Turn on the display
getHwComposer().setPowerMode(type, mode);
@@ -3270,7 +3288,7 @@
n = data.readInt32();
if (n) {
ALOGV("Interceptor enabled");
- mInterceptor.enable(mDrawingState.layersSortedByZ);
+ mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
}
else{
ALOGV("Interceptor disabled");
@@ -3278,6 +3296,11 @@
}
return NO_ERROR;
}
+ case 1021: { // Disable HWC virtual displays
+ n = data.readInt32();
+ mUseHwcVirtualDisplays = !n;
+ return NO_ERROR;
+ }
}
}
return err;
@@ -3792,31 +3815,6 @@
return l->sequence - r->sequence;
}
-// ---------------------------------------------------------------------------
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
- : type(DisplayDevice::DISPLAY_ID_INVALID),
- layerStack(DisplayDevice::NO_LAYER_STACK),
- orientation(0),
- width(0),
- height(0),
- isSecure(false) {
-}
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
- DisplayDevice::DisplayType type, bool isSecure)
- : type(type),
- layerStack(DisplayDevice::NO_LAYER_STACK),
- orientation(0),
- width(0),
- height(0),
- isSecure(isSecure) {
- viewport.makeInvalid();
- frame.makeInvalid();
-}
-
-// ---------------------------------------------------------------------------
-
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index c860228..4ae3580 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#undef LOG_TAG
#define LOG_TAG "SurfaceInterceptor"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -21,7 +20,6 @@
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "SurfaceInterceptor.h"
-
#include <cutils/log.h>
#include <utils/Trace.h>
@@ -32,20 +30,24 @@
// ----------------------------------------------------------------------------
-void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers) {
- ATRACE_CALL();
+void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers,
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays)
+{
if (mEnabled) {
return;
}
+ ATRACE_CALL();
mEnabled = true;
- saveExistingLayers(layers);
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ saveExistingDisplaysLocked(displays);
+ saveExistingSurfacesLocked(layers);
}
void SurfaceInterceptor::disable() {
- ATRACE_CALL();
if (!mEnabled) {
return;
}
+ ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
mEnabled = false;
status_t err(writeProtoFileLocked());
@@ -54,21 +56,32 @@
mTrace.Clear();
}
-void SurfaceInterceptor::saveExistingLayers(const SortedVector<sp<Layer>>& layers) {
+bool SurfaceInterceptor::isEnabled() {
+ return mEnabled;
+}
+
+void SurfaceInterceptor::saveExistingDisplaysLocked(
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays)
+{
+ // Caveat: The initial snapshot does not capture the power mode of the existing displays
ATRACE_CALL();
- std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- for (const auto& layer : layers) {
- saveLayerCreateLocked(layer);
- saveInitialLayerStateLocked(layer);
+ for (size_t i = 0 ; i < displays.size() ; i++) {
+ addDisplayCreationLocked(createTraceIncrementLocked(), displays[i]);
+ addInitialDisplayStateLocked(createTraceIncrementLocked(), displays[i]);
}
}
-void SurfaceInterceptor::saveInitialLayerStateLocked(const sp<const Layer>& layer) {
+void SurfaceInterceptor::saveExistingSurfacesLocked(const SortedVector<sp<Layer>>& layers) {
ATRACE_CALL();
- if (layer == nullptr) {
- return;
+ for (const auto& layer : layers) {
+ addSurfaceCreationLocked(createTraceIncrementLocked(), layer);
+ addInitialSurfaceStateLocked(createTraceIncrementLocked(), layer);
}
- Increment* increment(addTraceIncrementLocked());
+}
+
+void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment,
+ const sp<const Layer>& layer)
+{
Transaction* transaction(increment->mutable_transaction());
transaction->set_synchronous(layer->mTransactionFlags & BnSurfaceComposer::eSynchronous);
transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation);
@@ -77,13 +90,11 @@
addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(),
layer->mCurrentState.active.transform.ty());
addDepthLocked(transaction, layerId, layer->mCurrentState.z);
- addSizeLocked(transaction, layerId, layer->mCurrentState.active.w,
- layer->mCurrentState.active.h);
addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha);
addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion);
addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
addCropLocked(transaction, layerId, layer->mCurrentState.crop);
- if (layer->mCurrentState.handle != NULL) {
+ if (layer->mCurrentState.handle != nullptr) {
addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.handle,
layer->mCurrentState.frameNumber);
}
@@ -92,6 +103,20 @@
addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
}
+void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
+ const DisplayDeviceState& display)
+{
+ Transaction* transaction(increment->mutable_transaction());
+ transaction->set_synchronous(false);
+ transaction->set_animation(false);
+
+ addDisplaySurfaceLocked(transaction, display.displayId, display.surface);
+ addDisplayLayerStackLocked(transaction, display.displayId, display.layerStack);
+ addDisplaySizeLocked(transaction, display.displayId, display.width, display.height);
+ addDisplayProjectionLocked(transaction, display.displayId, display.orientation,
+ display.viewport, display.frame);
+}
+
status_t SurfaceInterceptor::writeProtoFileLocked() {
ATRACE_CALL();
std::ofstream output(mOutputFileName, std::ios::out | std::ios::trunc | std::ios::binary);
@@ -105,11 +130,8 @@
return NO_ERROR;
}
-void SurfaceInterceptor::setOutputFileName(const std::string& outputFileName) {
- mOutputFileName = outputFileName;
-}
-
-const sp<const Layer> SurfaceInterceptor::getLayer(const sp<const IBinder>& handle) {
+const sp<const Layer> SurfaceInterceptor::getLayer(const wp<const IBinder>& weakHandle) {
+ const sp<const IBinder>& handle(weakHandle.promote());
const auto layerHandle(static_cast<const Layer::Handle*>(handle.get()));
const sp<const Layer> layer(layerHandle->owner.promote());
// layer could be a nullptr at this point
@@ -124,18 +146,28 @@
return layer->sequence;
}
-Increment* SurfaceInterceptor::addTraceIncrementLocked() {
+Increment* SurfaceInterceptor::createTraceIncrementLocked() {
Increment* increment(mTrace.add_increment());
increment->set_time_stamp(systemTime());
return increment;
}
-Change* SurfaceInterceptor::addChangeLocked(Transaction* transaction, int32_t layerId) {
- Change* change(transaction->add_change());
+SurfaceChange* SurfaceInterceptor::createSurfaceChangeLocked(Transaction* transaction,
+ int32_t layerId)
+{
+ SurfaceChange* change(transaction->add_surface_change());
change->set_id(layerId);
return change;
}
+DisplayChange* SurfaceInterceptor::createDisplayChangeLocked(Transaction* transaction,
+ int32_t displayId)
+{
+ DisplayChange* dispChange(transaction->add_display_change());
+ dispChange->set_id(displayId);
+ return dispChange;
+}
+
void SurfaceInterceptor::setProtoRectLocked(Rectangle* protoRect, const Rect& rect) {
protoRect->set_left(rect.left);
protoRect->set_top(rect.top);
@@ -143,17 +175,19 @@
protoRect->set_bottom(rect.bottom);
}
-void SurfaceInterceptor::addPositionLocked(Transaction* transaction, int32_t layerId, float x,
- float y)
+void SurfaceInterceptor::addPositionLocked(Transaction* transaction, int32_t layerId,
+ float x, float y)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
PositionChange* posChange(change->mutable_position());
posChange->set_x(x);
posChange->set_y(y);
}
-void SurfaceInterceptor::addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z) {
- Change* change(addChangeLocked(transaction, layerId));
+void SurfaceInterceptor::addDepthLocked(Transaction* transaction, int32_t layerId,
+ uint32_t z)
+{
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
LayerChange* depthChange(change->mutable_layer());
depthChange->set_layer(z);
}
@@ -161,14 +195,16 @@
void SurfaceInterceptor::addSizeLocked(Transaction* transaction, int32_t layerId, uint32_t w,
uint32_t h)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
SizeChange* sizeChange(change->mutable_size());
sizeChange->set_w(w);
sizeChange->set_h(h);
}
-void SurfaceInterceptor::addAlphaLocked(Transaction* transaction, int32_t layerId, float alpha) {
- Change* change(addChangeLocked(transaction, layerId));
+void SurfaceInterceptor::addAlphaLocked(Transaction* transaction, int32_t layerId,
+ float alpha)
+{
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
AlphaChange* alphaChange(change->mutable_alpha());
alphaChange->set_alpha(alpha);
}
@@ -176,7 +212,7 @@
void SurfaceInterceptor::addMatrixLocked(Transaction* transaction, int32_t layerId,
const layer_state_t::matrix22_t& matrix)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
MatrixChange* matrixChange(change->mutable_matrix());
matrixChange->set_dsdx(matrix.dsdx);
matrixChange->set_dtdx(matrix.dtdx);
@@ -184,10 +220,10 @@
matrixChange->set_dtdy(matrix.dtdy);
}
-void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction, int32_t layerId,
- const Region& transRegion)
+void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction,
+ int32_t layerId, const Region& transRegion)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
TransparentRegionHintChange* transparentChange(change->mutable_transparent_region_hint());
for (const auto& rect : transRegion) {
@@ -196,20 +232,22 @@
}
}
-void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags) {
+void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId,
+ uint8_t flags)
+{
// There can be multiple flags changed
if (flags & layer_state_t::eLayerHidden) {
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
HiddenFlagChange* flagChange(change->mutable_hidden_flag());
flagChange->set_hidden_flag(true);
}
if (flags & layer_state_t::eLayerOpaque) {
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
OpaqueFlagChange* flagChange(change->mutable_opaque_flag());
flagChange->set_opaque_flag(true);
}
if (flags & layer_state_t::eLayerSecure) {
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
SecureFlagChange* flagChange(change->mutable_secure_flag());
flagChange->set_secure_flag(true);
}
@@ -218,7 +256,7 @@
void SurfaceInterceptor::addLayerStackLocked(Transaction* transaction, int32_t layerId,
uint32_t layerStack)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
LayerStackChange* layerStackChange(change->mutable_layer_stack());
layerStackChange->set_layer_stack(layerStack);
}
@@ -226,7 +264,7 @@
void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId,
const Rect& rect)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
CropChange* cropChange(change->mutable_crop());
Rectangle* protoRect(cropChange->mutable_rectangle());
setProtoRectLocked(protoRect, rect);
@@ -235,17 +273,17 @@
void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId,
const Rect& rect)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
FinalCropChange* finalCropChange(change->mutable_final_crop());
Rectangle* protoRect(finalCropChange->mutable_rectangle());
setProtoRectLocked(protoRect, rect);
}
void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
- const sp<const IBinder>& handle, uint64_t frameNumber)
+ const wp<const IBinder>& weakHandle, uint64_t frameNumber)
{
- Change* change(addChangeLocked(transaction, layerId));
- const sp<const Layer> layer(getLayer(handle));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+ const sp<const Layer> layer(getLayer(weakHandle));
if (layer == nullptr) {
ALOGE("An existing layer could not be retrieved with the handle"
" for the deferred transaction");
@@ -256,15 +294,15 @@
deferTransaction->set_frame_number(frameNumber);
}
-void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
- int32_t overrideScalingMode)
+void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction,
+ int32_t layerId, int32_t overrideScalingMode)
{
- Change* change(addChangeLocked(transaction, layerId));
+ SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
OverrideScalingModeChange* overrideChange(change->mutable_override_scaling_mode());
overrideChange->set_override_scaling_mode(overrideScalingMode);
}
-void SurfaceInterceptor::addChangedPropertiesLocked(Transaction* transaction,
+void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction,
const layer_state_t& state)
{
const sp<const Layer> layer(getLayer(state.surface));
@@ -314,31 +352,62 @@
}
}
-void SurfaceInterceptor::addUpdatedLayersLocked(Increment* increment, uint32_t flags,
- const Vector<ComposerState>& stateUpdates)
+void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,
+ const DisplayState& state, int32_t displayId)
{
- Transaction* transaction(increment->mutable_transaction());
- transaction->set_synchronous(flags & BnSurfaceComposer::eSynchronous);
- transaction->set_animation(flags & BnSurfaceComposer::eAnimation);
- for (const auto& compState: stateUpdates) {
- addChangedPropertiesLocked(transaction, compState.state);
+ if (state.what & DisplayState::eSurfaceChanged) {
+ addDisplaySurfaceLocked(transaction, displayId, state.surface);
+ }
+ if (state.what & DisplayState::eLayerStackChanged) {
+ addDisplayLayerStackLocked(transaction, displayId, state.layerStack);
+ }
+ if (state.what & DisplayState::eDisplaySizeChanged) {
+ addDisplaySizeLocked(transaction, displayId, state.width, state.height);
+ }
+ if (state.what & DisplayState::eDisplayProjectionChanged) {
+ addDisplayProjectionLocked(transaction, displayId, state.orientation, state.viewport,
+ state.frame);
}
}
-void SurfaceInterceptor::addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer) {
- Create* create(increment->mutable_create());
- create->set_id(getLayerId(layer));
- create->set_name(getLayerName(layer));
- create->set_w(layer->mCurrentState.active.w);
- create->set_h(layer->mCurrentState.active.h);
+void SurfaceInterceptor::addTransactionLocked(Increment* increment,
+ const Vector<ComposerState>& stateUpdates,
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+ const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags)
+{
+ Transaction* transaction(increment->mutable_transaction());
+ transaction->set_synchronous(transactionFlags & BnSurfaceComposer::eSynchronous);
+ transaction->set_animation(transactionFlags & BnSurfaceComposer::eAnimation);
+ for (const auto& compState: stateUpdates) {
+ addSurfaceChangesLocked(transaction, compState.state);
+ }
+ for (const auto& disp: changedDisplays) {
+ ssize_t dpyIdx = displays.indexOfKey(disp.token);
+ if (dpyIdx >= 0) {
+ const DisplayDeviceState& dispState(displays.valueAt(dpyIdx));
+ addDisplayChangesLocked(transaction, disp, dispState.displayId);
+ }
+ }
}
-void SurfaceInterceptor::addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer) {
- Delete* deleteLayer(increment->mutable_delete_());
- deleteLayer->set_id(getLayerId(layer));
+void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment,
+ const sp<const Layer>& layer)
+{
+ SurfaceCreation* creation(increment->mutable_surface_creation());
+ creation->set_id(getLayerId(layer));
+ creation->set_name(getLayerName(layer));
+ creation->set_w(layer->mCurrentState.active.w);
+ creation->set_h(layer->mCurrentState.active.h);
}
-void SurfaceInterceptor::addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer,
+void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment,
+ const sp<const Layer>& layer)
+{
+ SurfaceDeletion* deletion(increment->mutable_surface_deletion());
+ deletion->set_id(getLayerId(layer));
+}
+
+void SurfaceInterceptor::addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer,
uint32_t width, uint32_t height, uint64_t frameNumber)
{
BufferUpdate* update(increment->mutable_buffer_update());
@@ -348,56 +417,123 @@
update->set_frame_number(frameNumber);
}
-void SurfaceInterceptor::addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp) {
+void SurfaceInterceptor::addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp) {
VSyncEvent* event(increment->mutable_vsync_event());
event->set_when(timestamp);
}
-void SurfaceInterceptor::saveLayerUpdates(const Vector<ComposerState>& stateUpdates,
- uint32_t flags)
+void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId,
+ const sp<const IGraphicBufferProducer>& surface)
{
- ATRACE_CALL();
- if (!mEnabled || stateUpdates.size() <= 0) {
+ if (surface == nullptr) {
return;
}
- std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addUpdatedLayersLocked(addTraceIncrementLocked(), flags, stateUpdates);
+ uint64_t bufferQueueId = 0;
+ status_t err(surface->getUniqueId(&bufferQueueId));
+ if (err == NO_ERROR) {
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ DispSurfaceChange* surfaceChange(dispChange->mutable_surface());
+ surfaceChange->set_buffer_queue_id(bufferQueueId);
+ surfaceChange->set_buffer_queue_name(surface->getConsumerName().string());
+ }
+ else {
+ ALOGE("invalid graphic buffer producer received while tracing a display change (%s)",
+ strerror(-err));
+ }
}
-void SurfaceInterceptor::saveLayerCreate(const sp<const Layer>& layer) {
+void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction,
+ int32_t displayId, uint32_t layerStack)
+{
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ LayerStackChange* layerStackChange(dispChange->mutable_layer_stack());
+ layerStackChange->set_layer_stack(layerStack);
+}
+
+void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t displayId,
+ uint32_t w, uint32_t h)
+{
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ SizeChange* sizeChange(dispChange->mutable_size());
+ sizeChange->set_w(w);
+ sizeChange->set_h(h);
+}
+
+void SurfaceInterceptor::addDisplayProjectionLocked(Transaction* transaction,
+ int32_t displayId, int32_t orientation, const Rect& viewport, const Rect& frame)
+{
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ ProjectionChange* projectionChange(dispChange->mutable_projection());
+ projectionChange->set_orientation(orientation);
+ Rectangle* viewportRect(projectionChange->mutable_viewport());
+ setProtoRectLocked(viewportRect, viewport);
+ Rectangle* frameRect(projectionChange->mutable_frame());
+ setProtoRectLocked(frameRect, frame);
+}
+
+void SurfaceInterceptor::addDisplayCreationLocked(Increment* increment,
+ const DisplayDeviceState& info)
+{
+ DisplayCreation* creation(increment->mutable_display_creation());
+ creation->set_id(info.displayId);
+ creation->set_name(info.displayName);
+ creation->set_type(info.type);
+ creation->set_is_secure(info.isSecure);
+}
+
+void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t displayId) {
+ DisplayDeletion* deletion(increment->mutable_display_deletion());
+ deletion->set_id(displayId);
+}
+
+void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t displayId,
+ int32_t mode)
+{
+ PowerModeUpdate* powerModeUpdate(increment->mutable_power_mode_update());
+ powerModeUpdate->set_id(displayId);
+ powerModeUpdate->set_mode(mode);
+}
+
+void SurfaceInterceptor::saveTransaction(const Vector<ComposerState>& stateUpdates,
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+ const Vector<DisplayState>& changedDisplays, uint32_t flags)
+{
+ if (!mEnabled || (stateUpdates.size() <= 0 && changedDisplays.size() <= 0)) {
+ return;
+ }
ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ addTransactionLocked(createTraceIncrementLocked(), stateUpdates, displays, changedDisplays,
+ flags);
+}
+
+void SurfaceInterceptor::saveSurfaceCreation(const sp<const Layer>& layer) {
if (!mEnabled || layer == nullptr) {
return;
}
- std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addCreatedLayerLocked(addTraceIncrementLocked(), layer);
-}
-
-void SurfaceInterceptor::saveLayerCreateLocked(const sp<const Layer>& layer) {
- if (!mEnabled || layer == nullptr) {
- return;
- }
- addCreatedLayerLocked(addTraceIncrementLocked(), layer);
-}
-
-void SurfaceInterceptor::saveLayerDelete(const sp<const Layer>& layer) {
ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ addSurfaceCreationLocked(createTraceIncrementLocked(), layer);
+}
+
+void SurfaceInterceptor::saveSurfaceDeletion(const sp<const Layer>& layer) {
if (!mEnabled || layer == nullptr) {
return;
}
+ ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addDeletedLayerLocked(addTraceIncrementLocked(), layer);
+ addSurfaceDeletionLocked(createTraceIncrementLocked(), layer);
}
void SurfaceInterceptor::saveBufferUpdate(const sp<const Layer>& layer, uint32_t width,
uint32_t height, uint64_t frameNumber)
{
- ATRACE_CALL();
if (!mEnabled || layer == nullptr) {
return;
}
+ ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addUpdatedBufferLocked(addTraceIncrementLocked(), layer, width, height, frameNumber);
+ addBufferUpdateLocked(createTraceIncrementLocked(), layer, width, height, frameNumber);
}
void SurfaceInterceptor::saveVSyncEvent(nsecs_t timestamp) {
@@ -405,7 +541,35 @@
return;
}
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addUpdatedVsyncLocked(addTraceIncrementLocked(), timestamp);
+ addVSyncUpdateLocked(createTraceIncrementLocked(), timestamp);
}
+void SurfaceInterceptor::saveDisplayCreation(const DisplayDeviceState& info) {
+ if (!mEnabled) {
+ return;
+ }
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ addDisplayCreationLocked(createTraceIncrementLocked(), info);
+}
+
+void SurfaceInterceptor::saveDisplayDeletion(int32_t displayId) {
+ if (!mEnabled) {
+ return;
+ }
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ addDisplayDeletionLocked(createTraceIncrementLocked(), displayId);
+}
+
+void SurfaceInterceptor::savePowerModeUpdate(int32_t displayId, int32_t mode) {
+ if (!mEnabled) {
+ return;
+ }
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ addPowerModeUpdateLocked(createTraceIncrementLocked(), displayId, mode);
+}
+
+
} // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index bc8174c..4695138 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -25,6 +25,7 @@
class BufferItem;
class Layer;
+struct DisplayState;
struct layer_state_t;
constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
@@ -35,37 +36,56 @@
*/
class SurfaceInterceptor {
public:
- // The layer vector is used to capture the inital snapshot in the trace
- void enable(const SortedVector<sp<Layer>>& layers);
+ // Both vectors are used to capture the current state of SF as the initial snapshot in the trace
+ void enable(const SortedVector<sp<Layer>>& layers,
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays);
void disable();
- void setOutputFileName(const std::string& OutputFileName);
+ bool isEnabled();
- void saveLayerUpdates(const Vector<ComposerState>& state, uint32_t flags);
- void saveLayerCreate(const sp<const Layer>& layer);
- void saveLayerDelete(const sp<const Layer>& layer);
+ // Intercept display and surface transactions
+ void saveTransaction(const Vector<ComposerState>& stateUpdates,
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+ const Vector<DisplayState>& changedDisplays, uint32_t flags);
+
+ // Intercept surface data
+ void saveSurfaceCreation(const sp<const Layer>& layer);
+ void saveSurfaceDeletion(const sp<const Layer>& layer);
void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
uint64_t frameNumber);
+
+ // Intercept display data
+ void saveDisplayCreation(const DisplayDeviceState& info);
+ void saveDisplayDeletion(int32_t displayId);
+ void savePowerModeUpdate(int32_t displayId, int32_t mode);
void saveVSyncEvent(nsecs_t timestamp);
private:
- void saveExistingLayers(const SortedVector<sp<Layer>>& layers);
- void saveInitialLayerStateLocked(const sp<const Layer>& layer);
- void saveLayerCreateLocked(const sp<const Layer>& layer);
+ // The creation increments of Surfaces and Displays do not contain enough information to capture
+ // the initial state of each object, so a transaction with all of the missing properties is
+ // performed at the initial snapshot for each display and surface.
+ void saveExistingDisplaysLocked(
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays);
+ void saveExistingSurfacesLocked(const SortedVector<sp<Layer>>& layers);
+ void addInitialSurfaceStateLocked(Increment* increment, const sp<const Layer>& layer);
+ void addInitialDisplayStateLocked(Increment* increment, const DisplayDeviceState& display);
+
status_t writeProtoFileLocked();
- const sp<const Layer> getLayer(const sp<const IBinder>& handle);
+ const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle);
const std::string getLayerName(const sp<const Layer>& layer);
int32_t getLayerId(const sp<const Layer>& layer);
- Increment* addTraceIncrementLocked();
- void addUpdatedLayersLocked(Increment* increment, uint32_t flags,
- const Vector<ComposerState>& stateUpdates);
- void addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer);
- void addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer);
- void addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width,
+ Increment* createTraceIncrementLocked();
+ void addSurfaceCreationLocked(Increment* increment, const sp<const Layer>& layer);
+ void addSurfaceDeletionLocked(Increment* increment, const sp<const Layer>& layer);
+ void addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width,
uint32_t height, uint64_t frameNumber);
- void addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp);
+ void addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp);
+ void addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info);
+ void addDisplayDeletionLocked(Increment* increment, int32_t displayId);
+ void addPowerModeUpdateLocked(Increment* increment, int32_t displayId, int32_t mode);
- Change* addChangeLocked(Transaction* transaction, int32_t layerId);
+ // Add surface transactions to the trace
+ SurfaceChange* createSurfaceChangeLocked(Transaction* transaction, int32_t layerId);
void setProtoRectLocked(Rectangle* protoRect, const Rect& rect);
void addPositionLocked(Transaction* transaction, int32_t layerId, float x, float y);
void addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z);
@@ -79,11 +99,28 @@
void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
void addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
- const sp<const IBinder>& handle, uint64_t frameNumber);
+ const wp<const IBinder>& weakHandle, uint64_t frameNumber);
void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
int32_t overrideScalingMode);
- void addChangedPropertiesLocked(Transaction* transaction, const layer_state_t& state);
+ void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state);
+ void addTransactionLocked(Increment* increment, const Vector<ComposerState>& stateUpdates,
+ const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+ const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags);
+
+ // Add display transactions to the trace
+ DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t displayId);
+ void addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId,
+ const sp<const IGraphicBufferProducer>& surface);
+ void addDisplayLayerStackLocked(Transaction* transaction, int32_t displayId,
+ uint32_t layerStack);
+ void addDisplaySizeLocked(Transaction* transaction, int32_t displayId, uint32_t w,
+ uint32_t h);
+ void addDisplayProjectionLocked(Transaction* transaction, int32_t displayId,
+ int32_t orientation, const Rect& viewport, const Rect& frame);
+ void addDisplayChangesLocked(Transaction* transaction,
+ const DisplayState& state, int32_t displayId);
+
bool mEnabled {false};
std::string mOutputFileName {DEFAULT_FILENAME};
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index ebc4dd1..1a3f89f 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <frameworks/native/cmds/surfacecapturereplay/proto/src/trace.pb.h>
+#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>
#include <gtest/gtest.h>
@@ -23,6 +23,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
#include <private/gui/LayerState.h>
#include <ui/DisplayInfo.h>
@@ -42,6 +43,7 @@
constexpr float POSITION_UPDATE = 121;
const Rect CROP_UPDATE(16, 16, 32, 32);
+const String8 DISPLAY_NAME("SurfaceInterceptor Display Test");
constexpr auto LAYER_NAME = "Layer Create and Delete Test";
constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
@@ -81,16 +83,16 @@
system("service call SurfaceFlinger 1020 i32 0 > /dev/null");
}
-uint32_t getLayerId(const std::string& layerName) {
+int32_t getSurfaceId(const std::string& surfaceName) {
enableInterceptor();
disableInterceptor();
Trace capturedTrace;
readProtoFile(&capturedTrace);
- uint32_t layerId = 0;
+ int32_t layerId = 0;
for (const auto& increment : *capturedTrace.mutable_increment()) {
- if (increment.increment_case() == increment.kCreate) {
- if (increment.create().name() == layerName) {
- layerId = increment.create().id();
+ if (increment.increment_case() == increment.kSurfaceCreation) {
+ if (increment.surface_creation().name() == surfaceName) {
+ layerId = increment.surface_creation().id();
break;
}
}
@@ -98,6 +100,23 @@
return layerId;
}
+int32_t getDisplayId(const std::string& displayName) {
+ enableInterceptor();
+ disableInterceptor();
+ Trace capturedTrace;
+ readProtoFile(&capturedTrace);
+ int32_t displayId = 0;
+ for (const auto& increment : *capturedTrace.mutable_increment()) {
+ if (increment.increment_case() == increment.kDisplayCreation) {
+ if (increment.display_creation().name() == displayName) {
+ displayId = increment.display_creation().id();
+ break;
+ }
+ }
+ }
+ return displayId;
+}
+
class SurfaceInterceptorTest : public ::testing::Test {
protected:
virtual void SetUp() {
@@ -120,7 +139,7 @@
PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(mBGSurfaceControl != NULL);
ASSERT_TRUE(mBGSurfaceControl->isValid());
- mBGLayerId = getLayerId("BG Interceptor Test Surface");
+ mBGLayerId = getSurfaceId("BG Interceptor Test Surface");
SurfaceComposerClient::openGlobalTransaction();
mComposerClient->setDisplayLayerStack(display, 0);
@@ -137,35 +156,43 @@
sp<SurfaceComposerClient> mComposerClient;
sp<SurfaceControl> mBGSurfaceControl;
- uint32_t mBGLayerId;
+ int32_t mBGLayerId;
+ // Used to verify creation and destruction of surfaces and displays
+ int32_t mTargetId;
public:
void captureTest(void (SurfaceInterceptorTest::* action)(void),
bool (SurfaceInterceptorTest::* verification)(Trace *));
- void captureTest(void (SurfaceInterceptorTest::* action)(void), Change::ChangeCase changeCase);
+ void captureTest(void (SurfaceInterceptorTest::* action)(void),
+ SurfaceChange::SurfaceChangeCase changeCase);
+ void captureTest(void (SurfaceInterceptorTest::* action)(void),
+ Increment::IncrementCase incrementCase);
void runInTransaction(void (SurfaceInterceptorTest::* action)(void), bool intercepted = false);
// Verification of changes to a surface
- bool positionUpdateFound(const Change& change, bool foundPosition);
- bool sizeUpdateFound(const Change& change, bool foundSize);
- bool alphaUpdateFound(const Change& change, bool foundAlpha);
- bool layerUpdateFound(const Change& change, bool foundLayer);
- bool cropUpdateFound(const Change& change, bool foundCrop);
- bool finalCropUpdateFound(const Change& change, bool foundFinalCrop);
- bool matrixUpdateFound(const Change& change, bool foundMatrix);
- bool scalingModeUpdateFound(const Change& change, bool foundScalingMode);
- bool transparentRegionHintUpdateFound(const Change& change, bool foundTransparentRegion);
- bool layerStackUpdateFound(const Change& change, bool foundLayerStack);
- bool hiddenFlagUpdateFound(const Change& change, bool foundHiddenFlag);
- bool opaqueFlagUpdateFound(const Change& change, bool foundOpaqueFlag);
- bool secureFlagUpdateFound(const Change& change, bool foundSecureFlag);
- bool deferredTransactionUpdateFound(const Change& change, bool foundDeferred);
- bool surfaceUpdateFound(Trace* trace, Change::ChangeCase changeCase);
+ bool positionUpdateFound(const SurfaceChange& change, bool foundPosition);
+ bool sizeUpdateFound(const SurfaceChange& change, bool foundSize);
+ bool alphaUpdateFound(const SurfaceChange& change, bool foundAlpha);
+ bool layerUpdateFound(const SurfaceChange& change, bool foundLayer);
+ bool cropUpdateFound(const SurfaceChange& change, bool foundCrop);
+ bool finalCropUpdateFound(const SurfaceChange& change, bool foundFinalCrop);
+ bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix);
+ bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode);
+ bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion);
+ bool layerStackUpdateFound(const SurfaceChange& change, bool foundLayerStack);
+ bool hiddenFlagUpdateFound(const SurfaceChange& change, bool foundHiddenFlag);
+ bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag);
+ bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag);
+ bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
+ bool surfaceUpdateFound(Trace* trace, SurfaceChange::SurfaceChangeCase changeCase);
void assertAllUpdatesFound(Trace* trace);
// Verification of creation and deletion of a surface
- bool surfaceCreateFound(Trace* trace);
- bool surfaceDeleteFound(Trace* trace, uint32_t targetLayerId);
+ bool surfaceCreationFound(const Increment& increment, bool foundSurface);
+ bool surfaceDeletionFound(const Increment& increment, bool foundSurface);
+ bool displayCreationFound(const Increment& increment, bool foundDisplay);
+ bool displayDeletionFound(const Increment& increment, bool foundDisplay);
+ bool singleIncrementFound(Trace* trace, Increment::IncrementCase incrementCase);
// Verification of buffer updates
bool bufferUpdatesFound(Trace* trace);
@@ -186,8 +213,10 @@
void secureFlagUpdate();
void deferredTransactionUpdate();
void runAllUpdates();
- void surfaceCreate();
+ void surfaceCreation();
void nBufferUpdates();
+ void displayCreation();
+ void displayDeletion();
};
void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
@@ -200,7 +229,16 @@
}
void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
- Change::ChangeCase changeCase)
+ Increment::IncrementCase incrementCase)
+{
+ runInTransaction(action, true);
+ Trace capturedTrace;
+ ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
+ ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase));
+}
+
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+ SurfaceChange::SurfaceChangeCase changeCase)
{
runInTransaction(action, true);
Trace capturedTrace;
@@ -279,6 +317,17 @@
mBGSurfaceControl->deferTransactionUntil(mBGSurfaceControl->getHandle(), DEFERRED_UPDATE);
}
+void SurfaceInterceptorTest::displayCreation() {
+ sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+ SurfaceComposerClient::destroyDisplay(testDisplay);
+}
+
+void SurfaceInterceptorTest::displayDeletion() {
+ sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
+ mTargetId = getDisplayId(DISPLAY_NAME.string());
+ SurfaceComposerClient::destroyDisplay(testDisplay);
+}
+
void SurfaceInterceptorTest::runAllUpdates() {
runInTransaction(&SurfaceInterceptorTest::positionUpdate);
runInTransaction(&SurfaceInterceptorTest::sizeUpdate);
@@ -296,7 +345,7 @@
runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
}
-void SurfaceInterceptorTest::surfaceCreate() {
+void SurfaceInterceptorTest::surfaceCreation() {
mComposerClient->createSurface(String8(LAYER_NAME), SIZE_UPDATE, SIZE_UPDATE,
PIXEL_FORMAT_RGBA_8888, 0);
}
@@ -311,7 +360,7 @@
}
}
-bool SurfaceInterceptorTest::positionUpdateFound(const Change& change, bool foundPosition) {
+bool SurfaceInterceptorTest::positionUpdateFound(const SurfaceChange& change, bool foundPosition) {
// There should only be one position transaction with x and y = POSITION_UPDATE
bool hasX(change.position().x() == POSITION_UPDATE);
bool hasY(change.position().y() == POSITION_UPDATE);
@@ -325,7 +374,7 @@
return foundPosition;
}
-bool SurfaceInterceptorTest::sizeUpdateFound(const Change& change, bool foundSize) {
+bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange& change, bool foundSize) {
bool hasWidth(change.size().h() == SIZE_UPDATE);
bool hasHeight(change.size().w() == SIZE_UPDATE);
if (hasWidth && hasHeight && !foundSize) {
@@ -337,7 +386,7 @@
return foundSize;
}
-bool SurfaceInterceptorTest::alphaUpdateFound(const Change& change, bool foundAlpha) {
+bool SurfaceInterceptorTest::alphaUpdateFound(const SurfaceChange& change, bool foundAlpha) {
bool hasAlpha(change.alpha().alpha() == ALPHA_UPDATE);
if (hasAlpha && !foundAlpha) {
foundAlpha = true;
@@ -348,7 +397,7 @@
return foundAlpha;
}
-bool SurfaceInterceptorTest::layerUpdateFound(const Change& change, bool foundLayer) {
+bool SurfaceInterceptorTest::layerUpdateFound(const SurfaceChange& change, bool foundLayer) {
bool hasLayer(change.layer().layer() == LAYER_UPDATE);
if (hasLayer && !foundLayer) {
foundLayer = true;
@@ -359,7 +408,7 @@
return foundLayer;
}
-bool SurfaceInterceptorTest::cropUpdateFound(const Change& change, bool foundCrop) {
+bool SurfaceInterceptorTest::cropUpdateFound(const SurfaceChange& change, bool foundCrop) {
bool hasLeft(change.crop().rectangle().left() == CROP_UPDATE.left);
bool hasTop(change.crop().rectangle().top() == CROP_UPDATE.top);
bool hasRight(change.crop().rectangle().right() == CROP_UPDATE.right);
@@ -373,7 +422,9 @@
return foundCrop;
}
-bool SurfaceInterceptorTest::finalCropUpdateFound(const Change& change, bool foundFinalCrop) {
+bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change,
+ bool foundFinalCrop)
+{
bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left);
bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top);
bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right);
@@ -387,7 +438,7 @@
return foundFinalCrop;
}
-bool SurfaceInterceptorTest::matrixUpdateFound(const Change& change, bool foundMatrix) {
+bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) {
bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2);
bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2);
bool hasSy((float)change.matrix().dsdy() == (float)-M_SQRT1_2);
@@ -401,7 +452,9 @@
return foundMatrix;
}
-bool SurfaceInterceptorTest::scalingModeUpdateFound(const Change& change, bool foundScalingMode) {
+bool SurfaceInterceptorTest::scalingModeUpdateFound(const SurfaceChange& change,
+ bool foundScalingMode)
+{
bool hasScalingUpdate(change.override_scaling_mode().override_scaling_mode() == SCALING_UPDATE);
if (hasScalingUpdate && !foundScalingMode) {
foundScalingMode = true;
@@ -412,7 +465,7 @@
return foundScalingMode;
}
-bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const Change& change,
+bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const SurfaceChange& change,
bool foundTransparentRegion)
{
auto traceRegion = change.transparent_region_hint().region(0);
@@ -429,7 +482,9 @@
return foundTransparentRegion;
}
-bool SurfaceInterceptorTest::layerStackUpdateFound(const Change& change, bool foundLayerStack) {
+bool SurfaceInterceptorTest::layerStackUpdateFound(const SurfaceChange& change,
+ bool foundLayerStack)
+{
bool hasLayerStackUpdate(change.layer_stack().layer_stack() == STACK_UPDATE);
if (hasLayerStackUpdate && !foundLayerStack) {
foundLayerStack = true;
@@ -440,7 +495,9 @@
return foundLayerStack;
}
-bool SurfaceInterceptorTest::hiddenFlagUpdateFound(const Change& change, bool foundHiddenFlag) {
+bool SurfaceInterceptorTest::hiddenFlagUpdateFound(const SurfaceChange& change,
+ bool foundHiddenFlag)
+{
bool hasHiddenFlag(change.hidden_flag().hidden_flag());
if (hasHiddenFlag && !foundHiddenFlag) {
foundHiddenFlag = true;
@@ -451,7 +508,9 @@
return foundHiddenFlag;
}
-bool SurfaceInterceptorTest::opaqueFlagUpdateFound(const Change& change, bool foundOpaqueFlag) {
+bool SurfaceInterceptorTest::opaqueFlagUpdateFound(const SurfaceChange& change,
+ bool foundOpaqueFlag)
+{
bool hasOpaqueFlag(change.opaque_flag().opaque_flag());
if (hasOpaqueFlag && !foundOpaqueFlag) {
foundOpaqueFlag = true;
@@ -462,7 +521,9 @@
return foundOpaqueFlag;
}
-bool SurfaceInterceptorTest::secureFlagUpdateFound(const Change& change, bool foundSecureFlag) {
+bool SurfaceInterceptorTest::secureFlagUpdateFound(const SurfaceChange& change,
+ bool foundSecureFlag)
+{
bool hasSecureFlag(change.secure_flag().secure_flag());
if (hasSecureFlag && !foundSecureFlag) {
foundSecureFlag = true;
@@ -473,12 +534,11 @@
return foundSecureFlag;
}
-bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const Change& change,
+bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& change,
bool foundDeferred)
{
bool hasId(change.deferred_transaction().layer_id() == mBGLayerId);
- bool hasFrameNumber(change.deferred_transaction().frame_number() ==
- DEFERRED_UPDATE);
+ bool hasFrameNumber(change.deferred_transaction().frame_number() == DEFERRED_UPDATE);
if (hasId && hasFrameNumber && !foundDeferred) {
foundDeferred = true;
}
@@ -488,114 +548,158 @@
return foundDeferred;
}
-bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace, Change::ChangeCase changeCase) {
- bool updateFound = false;
+bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace,
+ SurfaceChange::SurfaceChangeCase changeCase)
+{
+ bool foundUpdate = false;
for (const auto& increment : *trace->mutable_increment()) {
if (increment.increment_case() == increment.kTransaction) {
- for (const auto& change : increment.transaction().change()) {
- if (change.id() == mBGLayerId && change.Change_case() == changeCase) {
+ for (const auto& change : increment.transaction().surface_change()) {
+ if (change.id() == mBGLayerId && change.SurfaceChange_case() == changeCase) {
switch (changeCase) {
- case Change::ChangeCase::kPosition:
- // updateFound is sent for the tests to fail on duplicated increments
- updateFound = positionUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kPosition:
+ // foundUpdate is sent for the tests to fail on duplicated increments
+ foundUpdate = positionUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kSize:
- updateFound = sizeUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kSize:
+ foundUpdate = sizeUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kAlpha:
- updateFound = alphaUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kAlpha:
+ foundUpdate = alphaUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kLayer:
- updateFound = layerUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kLayer:
+ foundUpdate = layerUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kCrop:
- updateFound = cropUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kCrop:
+ foundUpdate = cropUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kFinalCrop:
- updateFound = finalCropUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kFinalCrop:
+ foundUpdate = finalCropUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kMatrix:
- updateFound = matrixUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kMatrix:
+ foundUpdate = matrixUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kOverrideScalingMode:
- updateFound = scalingModeUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
+ foundUpdate = scalingModeUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kTransparentRegionHint:
- updateFound = transparentRegionHintUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
+ foundUpdate = transparentRegionHintUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kLayerStack:
- updateFound = layerStackUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kLayerStack:
+ foundUpdate = layerStackUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kHiddenFlag:
- updateFound = hiddenFlagUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
+ foundUpdate = hiddenFlagUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kOpaqueFlag:
- updateFound = opaqueFlagUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
+ foundUpdate = opaqueFlagUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kSecureFlag:
- updateFound = secureFlagUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kSecureFlag:
+ foundUpdate = secureFlagUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::kDeferredTransaction:
- updateFound = deferredTransactionUpdateFound(change, updateFound);
+ case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
+ foundUpdate = deferredTransactionUpdateFound(change, foundUpdate);
break;
- case Change::ChangeCase::CHANGE_NOT_SET:
+ case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET:
break;
}
}
}
}
}
- return updateFound;
+ return foundUpdate;
}
void SurfaceInterceptorTest::assertAllUpdatesFound(Trace* trace) {
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kPosition));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kSize));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kAlpha));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kLayer));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kCrop));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kFinalCrop));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kMatrix));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kOverrideScalingMode));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kTransparentRegionHint));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kLayerStack));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kHiddenFlag));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kOpaqueFlag));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kSecureFlag));
- ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kDeferredTransaction));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kPosition));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSize));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayer));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kCrop));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kFinalCrop));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kMatrix));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOverrideScalingMode));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayerStack));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kHiddenFlag));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag));
+ ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction));
}
-bool SurfaceInterceptorTest::surfaceCreateFound(Trace* trace) {
- bool foundLayer = false;
- for (const auto& inc : *trace->mutable_increment()) {
- if (inc.increment_case() == inc.kCreate) {
- bool isMatch(inc.create().name() == LAYER_NAME && inc.create().w() == SIZE_UPDATE &&
- inc.create().h() == SIZE_UPDATE);
- if (isMatch && !foundLayer) {
- foundLayer = true;
- }
- else if (isMatch && foundLayer) {
- return false;
- }
- }
+bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
+ bool isMatch(increment.surface_creation().name() == LAYER_NAME &&
+ increment.surface_creation().w() == SIZE_UPDATE &&
+ increment.surface_creation().h() == SIZE_UPDATE);
+ if (isMatch && !foundSurface) {
+ foundSurface = true;
}
- return foundLayer;
+ else if (isMatch && foundSurface) {
+ [] () { FAIL(); }();
+ }
+ return foundSurface;
}
-bool SurfaceInterceptorTest::surfaceDeleteFound(Trace* trace, uint32_t targetLayerId) {
- bool foundLayer = false;
+bool SurfaceInterceptorTest::surfaceDeletionFound(const Increment& increment, bool foundSurface) {
+ bool isMatch(increment.surface_deletion().id() == mTargetId);
+ if (isMatch && !foundSurface) {
+ foundSurface = true;
+ }
+ else if (isMatch && foundSurface) {
+ [] () { FAIL(); }();
+ }
+ return foundSurface;
+}
+
+bool SurfaceInterceptorTest::displayCreationFound(const Increment& increment, bool foundDisplay) {
+ bool isMatch(increment.display_creation().name() == DISPLAY_NAME.string() &&
+ increment.display_creation().is_secure());
+ if (isMatch && !foundDisplay) {
+ foundDisplay = true;
+ }
+ else if (isMatch && foundDisplay) {
+ [] () { FAIL(); }();
+ }
+ return foundDisplay;
+}
+
+bool SurfaceInterceptorTest::displayDeletionFound(const Increment& increment, bool foundDisplay) {
+ bool isMatch(increment.display_deletion().id() == mTargetId);
+ if (isMatch && !foundDisplay) {
+ foundDisplay = true;
+ }
+ else if (isMatch && foundDisplay) {
+ [] () { FAIL(); }();
+ }
+ return foundDisplay;
+}
+
+bool SurfaceInterceptorTest::singleIncrementFound(Trace* trace,
+ Increment::IncrementCase incrementCase)
+{
+ bool foundIncrement = false;
for (const auto& increment : *trace->mutable_increment()) {
- if (increment.increment_case() == increment.kDelete) {
- bool isMatch(increment.delete_().id() == targetLayerId);
- if (isMatch && !foundLayer) {
- foundLayer = true;
- }
- else if (isMatch && foundLayer) {
- return false;
+ if (increment.increment_case() == incrementCase) {
+ switch (incrementCase) {
+ case Increment::IncrementCase::kSurfaceCreation:
+ foundIncrement = surfaceCreationFound(increment, foundIncrement);
+ break;
+ case Increment::IncrementCase::kSurfaceDeletion:
+ foundIncrement = surfaceDeletionFound(increment, foundIncrement);
+ break;
+ case Increment::IncrementCase::kDisplayCreation:
+ foundIncrement = displayCreationFound(increment, foundIncrement);
+ break;
+ case Increment::IncrementCase::kDisplayDeletion:
+ foundIncrement = displayDeletionFound(increment, foundIncrement);
+ break;
+ default:
+ /* code */
+ break;
}
}
}
- return foundLayer;
+ return foundIncrement;
}
bool SurfaceInterceptorTest::bufferUpdatesFound(Trace* trace) {
@@ -609,62 +713,68 @@
}
TEST_F(SurfaceInterceptorTest, InterceptPositionUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::positionUpdate, Change::ChangeCase::kPosition);
+ captureTest(&SurfaceInterceptorTest::positionUpdate,
+ SurfaceChange::SurfaceChangeCase::kPosition);
}
TEST_F(SurfaceInterceptorTest, InterceptSizeUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::sizeUpdate, Change::ChangeCase::kSize);
+ captureTest(&SurfaceInterceptorTest::sizeUpdate, SurfaceChange::SurfaceChangeCase::kSize);
}
TEST_F(SurfaceInterceptorTest, InterceptAlphaUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::alphaUpdate, Change::ChangeCase::kAlpha);
+ captureTest(&SurfaceInterceptorTest::alphaUpdate, SurfaceChange::SurfaceChangeCase::kAlpha);
}
TEST_F(SurfaceInterceptorTest, InterceptLayerUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::layerUpdate, Change::ChangeCase::kLayer);
+ captureTest(&SurfaceInterceptorTest::layerUpdate, SurfaceChange::SurfaceChangeCase::kLayer);
}
TEST_F(SurfaceInterceptorTest, InterceptCropUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::cropUpdate, Change::ChangeCase::kCrop);
+ captureTest(&SurfaceInterceptorTest::cropUpdate, SurfaceChange::SurfaceChangeCase::kCrop);
}
TEST_F(SurfaceInterceptorTest, InterceptFinalCropUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::finalCropUpdate, Change::ChangeCase::kFinalCrop);
+ captureTest(&SurfaceInterceptorTest::finalCropUpdate,
+ SurfaceChange::SurfaceChangeCase::kFinalCrop);
}
TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::matrixUpdate, Change::ChangeCase::kMatrix);
+ captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix);
}
TEST_F(SurfaceInterceptorTest, InterceptOverrideScalingModeUpdateWorks) {
captureTest(&SurfaceInterceptorTest::overrideScalingModeUpdate,
- Change::ChangeCase::kOverrideScalingMode);
+ SurfaceChange::SurfaceChangeCase::kOverrideScalingMode);
}
TEST_F(SurfaceInterceptorTest, InterceptTransparentRegionHintUpdateWorks) {
captureTest(&SurfaceInterceptorTest::transparentRegionHintUpdate,
- Change::ChangeCase::kTransparentRegionHint);
+ SurfaceChange::SurfaceChangeCase::kTransparentRegionHint);
}
TEST_F(SurfaceInterceptorTest, InterceptLayerStackUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::layerStackUpdate, Change::ChangeCase::kLayerStack);
+ captureTest(&SurfaceInterceptorTest::layerStackUpdate,
+ SurfaceChange::SurfaceChangeCase::kLayerStack);
}
TEST_F(SurfaceInterceptorTest, InterceptHiddenFlagUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::hiddenFlagUpdate, Change::ChangeCase::kHiddenFlag);
+ captureTest(&SurfaceInterceptorTest::hiddenFlagUpdate,
+ SurfaceChange::SurfaceChangeCase::kHiddenFlag);
}
TEST_F(SurfaceInterceptorTest, InterceptOpaqueFlagUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::opaqueFlagUpdate, Change::ChangeCase::kOpaqueFlag);
+ captureTest(&SurfaceInterceptorTest::opaqueFlagUpdate,
+ SurfaceChange::SurfaceChangeCase::kOpaqueFlag);
}
TEST_F(SurfaceInterceptorTest, InterceptSecureFlagUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::secureFlagUpdate, Change::ChangeCase::kSecureFlag);
+ captureTest(&SurfaceInterceptorTest::secureFlagUpdate,
+ SurfaceChange::SurfaceChangeCase::kSecureFlag);
}
TEST_F(SurfaceInterceptorTest, InterceptDeferredTransactionUpdateWorks) {
captureTest(&SurfaceInterceptorTest::deferredTransactionUpdate,
- Change::ChangeCase::kDeferredTransaction);
+ SurfaceChange::SurfaceChangeCase::kDeferredTransaction);
}
TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) {
@@ -678,21 +788,32 @@
assertAllUpdatesFound(&capturedTrace);
}
-TEST_F(SurfaceInterceptorTest, InterceptLayerCreateWorks) {
- captureTest(&SurfaceInterceptorTest::surfaceCreate, &SurfaceInterceptorTest::surfaceCreateFound);
+TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) {
+ captureTest(&SurfaceInterceptorTest::surfaceCreation,
+ Increment::IncrementCase::kSurfaceCreation);
}
-TEST_F(SurfaceInterceptorTest, InterceptLayerDeleteWorks) {
+TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) {
sp<SurfaceControl> layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME),
SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0);
- uint32_t targetLayerId = getLayerId(LAYER_NAME);
+ this->mTargetId = getSurfaceId(LAYER_NAME);
enableInterceptor();
mComposerClient->destroySurface(layerToDelete->getHandle());
disableInterceptor();
Trace capturedTrace;
ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE(surfaceDeleteFound(&capturedTrace, targetLayerId));
+ ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceDeletion));
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) {
+ captureTest(&SurfaceInterceptorTest::displayCreation,
+ Increment::IncrementCase::kDisplayCreation);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptDisplayDeletionWorks) {
+ captureTest(&SurfaceInterceptorTest::displayDeletion,
+ Increment::IncrementCase::kDisplayDeletion);
}
TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) {
@@ -701,7 +822,8 @@
}
// If the interceptor is enabled while buffer updates are being pushed, the interceptor should
-// first create a snapshot of the existing surfaces and then start capturing the buffer updates
+// first create a snapshot of the existing displays and surfaces and then start capturing
+// the buffer updates
TEST_F(SurfaceInterceptorTest, InterceptWhileBufferUpdatesWorks) {
std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this);
enableInterceptor();
@@ -711,14 +833,14 @@
Trace capturedTrace;
ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
const auto& firstIncrement = capturedTrace.mutable_increment(0);
- ASSERT_EQ(firstIncrement->increment_case(), Increment::IncrementCase::kCreate);
+ ASSERT_EQ(firstIncrement->increment_case(), Increment::IncrementCase::kDisplayCreation);
}
TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) {
enableInterceptor();
std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this);
std::thread surfaceUpdates(&SurfaceInterceptorTest::runAllUpdates, this);
- runInTransaction(&SurfaceInterceptorTest::surfaceCreate);
+ runInTransaction(&SurfaceInterceptorTest::surfaceCreation);
bufferUpdates.join();
surfaceUpdates.join();
disableInterceptor();
@@ -728,7 +850,7 @@
assertAllUpdatesFound(&capturedTrace);
ASSERT_TRUE(bufferUpdatesFound(&capturedTrace));
- ASSERT_TRUE(surfaceCreateFound(&capturedTrace));
+ ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceCreation));
}
}