Merge "bufferhubd: Add DetachedBufferChannel" into pi-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 57745ef..0701450 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -774,22 +774,10 @@
return ok;
}
-// Set all the kernel tracing settings to the desired state for this trace
-// capture.
-static bool setUpTrace()
+static bool setUpUserspaceTracing()
{
bool ok = true;
- // Set up the tracing options.
- ok &= setCategoriesEnableFromFile(g_categoriesFile);
- ok &= setTraceOverwriteEnable(g_traceOverwrite);
- ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
- // TODO: Re-enable after stabilization
- //ok &= setCmdlineSize();
- ok &= setClock();
- ok &= setPrintTgidEnableIfPresent(true);
- ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
-
// Set up the tags property.
uint64_t tags = 0;
for (size_t i = 0; i < arraysize(k_categories); i++) {
@@ -827,6 +815,37 @@
ok &= ServiceUtility::PokeServices();
}
+ return ok;
+}
+
+static void cleanUpUserspaceTracing()
+{
+ setTagsProperty(0);
+ clearAppProperties();
+ pokeBinderServices();
+
+ if (g_tracePdx) {
+ ServiceUtility::PokeServices();
+ }
+}
+
+
+// Set all the kernel tracing settings to the desired state for this trace
+// capture.
+static bool setUpKernelTracing()
+{
+ bool ok = true;
+
+ // Set up the tracing options.
+ ok &= setCategoriesEnableFromFile(g_categoriesFile);
+ ok &= setTraceOverwriteEnable(g_traceOverwrite);
+ ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
+ // TODO: Re-enable after stabilization
+ //ok &= setCmdlineSize();
+ ok &= setClock();
+ ok &= setPrintTgidEnableIfPresent(true);
+ ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
+
// Disable all the sysfs enables. This is done as a separate loop from
// the enables to allow the same enable to exist in multiple categories.
ok &= disableKernelTraceEvents();
@@ -854,20 +873,11 @@
}
// Reset all the kernel tracing settings to their default state.
-static void cleanUpTrace()
+static void cleanUpKernelTracing()
{
// Disable all tracing that we're able to.
disableKernelTraceEvents();
- // Reset the system properties.
- setTagsProperty(0);
- clearAppProperties();
- pokeBinderServices();
-
- if (g_tracePdx) {
- ServiceUtility::PokeServices();
- }
-
// Set the options back to their defaults.
setTraceOverwriteEnable(true);
setTraceBufferSizeKB(1);
@@ -875,7 +885,6 @@
setKernelTraceFuncs(NULL);
}
-
// Enable tracing in the kernel.
static bool startTrace()
{
@@ -1107,6 +1116,7 @@
bool traceStop = true;
bool traceDump = true;
bool traceStream = false;
+ bool onlyUserspace = false;
if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
showHelp(argv[0]);
@@ -1122,12 +1132,13 @@
int ret;
int option_index = 0;
static struct option long_options[] = {
- {"async_start", no_argument, 0, 0 },
- {"async_stop", no_argument, 0, 0 },
- {"async_dump", no_argument, 0, 0 },
- {"list_categories", no_argument, 0, 0 },
- {"stream", no_argument, 0, 0 },
- { 0, 0, 0, 0 }
+ {"async_start", no_argument, 0, 0 },
+ {"async_stop", no_argument, 0, 0 },
+ {"async_dump", no_argument, 0, 0 },
+ {"only_userspace", no_argument, 0, 0 },
+ {"list_categories", no_argument, 0, 0 },
+ {"stream", no_argument, 0, 0 },
+ { 0, 0, 0, 0 }
};
ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
@@ -1197,6 +1208,8 @@
async = true;
traceStart = false;
traceStop = false;
+ } else if (!strcmp(long_options[option_index].name, "only_userspace")) {
+ onlyUserspace = true;
} else if (!strcmp(long_options[option_index].name, "stream")) {
traceStream = true;
traceDump = false;
@@ -1214,6 +1227,14 @@
}
}
+ if (onlyUserspace) {
+ if (!async || !(traceStart || traceStop)) {
+ fprintf(stderr, "--only_userspace can only be used with "
+ "--async_start or --async_stop\n");
+ exit(1);
+ }
+ }
+
registerSigHandler();
if (g_initialSleepSecs > 0) {
@@ -1221,13 +1242,19 @@
}
bool ok = true;
+
if (traceStart) {
- ok &= setUpTrace();
+ ok &= setUpUserspaceTracing();
+ }
+
+ if (ok && traceStart && !onlyUserspace) {
+ ok &= setUpKernelTracing();
ok &= startTrace();
}
if (ok && traceStart) {
- if (!traceStream) {
+
+ if (!traceStream && !onlyUserspace) {
printf("capturing trace...");
fflush(stdout);
}
@@ -1237,9 +1264,12 @@
// contain entries from only one CPU can cause "begin" entries without a
// matching "end" entry to show up if a task gets migrated from one CPU to
// another.
- ok = clearTrace();
+ if (!onlyUserspace)
+ ok = clearTrace();
- writeClockSyncMarker();
+ if (!onlyUserspace)
+ writeClockSyncMarker();
+
if (ok && !async && !traceStream) {
// Sleep to allow the trace to be captured.
struct timespec timeLeft;
@@ -1258,10 +1288,10 @@
}
// Stop the trace and restore the default settings.
- if (traceStop)
+ if (traceStop && !onlyUserspace)
stopTrace();
- if (ok && traceDump) {
+ if (ok && traceDump && !onlyUserspace) {
if (!g_traceAborted) {
printf(" done\n");
fflush(stdout);
@@ -1288,8 +1318,11 @@
}
// Reset the trace buffer size to 1.
- if (traceStop)
- cleanUpTrace();
+ if (traceStop) {
+ cleanUpUserspaceTracing();
+ if (!onlyUserspace)
+ cleanUpKernelTracing();
+ }
return g_traceAborted ? 1 : 0;
}
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index 819d5b9..33e35f7 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <grp.h>
+#include <poll.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
@@ -35,6 +36,7 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <log/log.h>
uint64_t Nanotime() {
@@ -154,22 +156,16 @@
return 0;
}
bool newline = false;
- fd_set read_set;
- timeval tm;
while (true) {
- FD_ZERO(&read_set);
- FD_SET(fd, &read_set);
- /* Timeout if no data is read for 30 seconds. */
- tm.tv_sec = 30;
- tm.tv_usec = 0;
- uint64_t elapsed = Nanotime();
- int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, nullptr, nullptr, &tm));
+ uint64_t start_time = Nanotime();
+ pollfd fds[] = { { .fd = fd, .events = POLLIN } };
+ int ret = TEMP_FAILURE_RETRY(poll(fds, arraysize(fds), 30 * 1000));
if (ret == -1) {
- dprintf(out_fd, "*** %s: select failed: %s\n", path, strerror(errno));
+ dprintf(out_fd, "*** %s: poll failed: %s\n", path, strerror(errno));
newline = true;
break;
} else if (ret == 0) {
- elapsed = Nanotime() - elapsed;
+ uint64_t elapsed = Nanotime() - start_time;
dprintf(out_fd, "*** %s: Timed out after %.3fs\n", path, (float)elapsed / NANOS_PER_SEC);
newline = true;
break;
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 10f252f..fd2fccb 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -112,19 +112,6 @@
static const std::string ANR_DIR = "/data/anr/";
static const std::string ANR_FILE_PREFIX = "anr_";
-struct DumpData {
- std::string name;
- int fd;
- time_t mtime;
-};
-
-static bool operator<(const DumpData& d1, const DumpData& d2) {
- return d1.mtime > d2.mtime;
-}
-
-static std::unique_ptr<std::vector<DumpData>> tombstone_data;
-static std::unique_ptr<std::vector<DumpData>> anr_data;
-
// TODO: temporary variables and functions used during C++ refactoring
static Dumpstate& ds = Dumpstate::GetInstance();
static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
@@ -167,20 +154,20 @@
* is set, the vector only contains files that were written in the last 30 minutes.
* If |limit_by_count| is set, the vector only contains the ten latest files.
*/
-static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
- const std::string& file_prefix,
- bool limit_by_mtime,
- bool limit_by_count = true) {
+static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
+ const std::string& file_prefix,
+ bool limit_by_mtime,
+ bool limit_by_count = true) {
const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
- std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
if (dump_dir == nullptr) {
MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
- return dump_data.release();
+ return std::vector<DumpData>();
}
+ std::vector<DumpData> dump_data;
struct dirent* entry = nullptr;
while ((entry = readdir(dump_dir.get()))) {
if (entry->d_type != DT_REG) {
@@ -211,18 +198,19 @@
continue;
}
- DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
-
- dump_data->push_back(data);
+ dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
}
- std::sort(dump_data->begin(), dump_data->end());
+ // Sort in descending modification time so that we only keep the newest
+ // reports if |limit_by_count| is true.
+ std::sort(dump_data.begin(), dump_data.end(),
+ [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
- if (limit_by_count && dump_data->size() > 10) {
- dump_data->erase(dump_data->begin() + 10, dump_data->end());
+ if (limit_by_count && dump_data.size() > 10) {
+ dump_data.erase(dump_data.begin() + 10, dump_data.end());
}
- return dump_data.release();
+ return dump_data;
}
static bool AddDumps(const std::vector<DumpData>::const_iterator start,
@@ -257,12 +245,6 @@
return dumped;
}
-static void CloseDumpFds(const std::vector<DumpData>* dumps) {
- for (auto it = dumps->begin(); it != dumps->end(); ++it) {
- close(it->fd);
- }
-}
-
// for_each_pid() callback to get mount info about a process.
void do_mountinfo(int pid, const char* name __attribute__((unused))) {
char path[PATH_MAX];
@@ -1007,15 +989,15 @@
}
// Add a specific message for the first ANR Dump.
- if (anr_data->size() > 0) {
- AddDumps(anr_data->begin(), anr_data->begin() + 1,
+ if (ds.anr_data_.size() > 0) {
+ AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
"VM TRACES AT LAST ANR", add_to_zip);
// The "last" ANR will always be included as separate entry in the zip file. In addition,
// it will be present in the body of the main entry if |add_to_zip| == false.
//
// Historical ANRs are always included as separate entries in the bugreport zip file.
- AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(),
+ AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
"HISTORICAL ANR", true /* add_to_zip */);
} else {
printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
@@ -1362,7 +1344,7 @@
// NOTE: tombstones are always added as separate entries in the zip archive
// and are not interspersed with the main report.
- const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
+ const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
"TOMBSTONE", true /* add_to_zip */);
if (!tombstones_dumped) {
printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
@@ -2114,8 +2096,8 @@
dump_traces_path = dump_traces();
/* Run some operations that require root. */
- tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
- anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
+ ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
+ ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
ds.AddDir(RECOVERY_DIR, true);
ds.AddDir(RECOVERY_DATA_DIR, true);
@@ -2288,8 +2270,8 @@
close(ds.control_socket_fd_);
}
- CloseDumpFds(tombstone_data.get());
- CloseDumpFds(anr_data.get());
+ ds.tombstone_data_.clear();
+ ds.anr_data_.clear();
return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index ea4fccd..b220013 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -26,6 +26,7 @@
#include <vector>
#include <android-base/macros.h>
+#include <android-base/unique_fd.h>
#include <android/os/IDumpstateListener.h>
#include <utils/StrongPointer.h>
#include <ziparchive/zip_writer.h>
@@ -159,6 +160,20 @@
static std::string VERSION_DEFAULT = "default";
/*
+ * Structure that contains the information of an open dump file.
+ */
+struct DumpData {
+ // Path of the file.
+ std::string name;
+
+ // Open file descriptor for the file.
+ android::base::unique_fd fd;
+
+ // Modification time of the file.
+ time_t mtime;
+};
+
+/*
* Main class driving a bugreport generation.
*
* Currently, it only contains variables that are accessed externally, but gradually the functions
@@ -350,6 +365,12 @@
std::string notification_title;
std::string notification_description;
+ // List of open tombstone dump files.
+ std::vector<DumpData> tombstone_data_;
+
+ // List of open ANR dump files.
+ std::vector<DumpData> anr_data_;
+
private:
// Used by GetInstance() only.
Dumpstate(const std::string& version = VERSION_CURRENT);
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index 4b90765..bbf157b 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -427,14 +427,15 @@
* use cases, corresponding to index OMX_IndexParamVideoAndroidImageGrid.
*
* OMX_VIDEO_CodingImageHEIC encoders must handle this param type. When this param is set
- * on the component with bEnabled set to true, nGrid* indicates the desired grid config
- * by the client. The component can use this as a heuristic, but is free to choose any
- * suitable grid configs, and the client shall always get the actual from the component
- * after the param is set. Encoder will receive each input image in full, and shall encode
- * it into tiles in row-major, top-row first, left-to-right order, and send each encoded
- * tile in a separate output buffer. All output buffers for the same input buffer shall
- * carry the same timestamp as the input buffer. If the input buffer is marked EOS,
- * the EOS should only appear on the last output buffer for that input buffer.
+ * on the component with bEnabled set to true, nTileWidth, nTileHeight, nGridRows,
+ * nGridCols indicates the desired grid config by the client. The component can use this
+ * as a heuristic, and is free to choose any suitable grid configs. The client shall
+ * always get the actual from the component after the param is set. Encoder will receive
+ * each input image in full, and shall encode it into tiles in row-major, top-row first,
+ * left-to-right order, and send each encoded tile in a separate output buffer. All output
+ * buffers for the same input buffer shall carry the same timestamp as the input buffer.
+ * If the input buffer is marked EOS, the EOS should only appear on the last output buffer
+ * for that input buffer.
*
* OMX_VIDEO_CodingHEVC encoders might also receive this param when it's used for image
* encoding, although in this case the param only serves as a hint. The encoder will
@@ -446,10 +447,10 @@
* nSize : Size of the structure in bytes
* nVersion : OMX specification version information
* nPortIndex : Port that this structure applies to (output port for encoders)
- * bEnabled : Whether grid is enabled. If true, nGrid* specifies the grid
- * config; otherwise nGrid* shall be ignored.
- * nGridWidth : Width of each tile.
- * nGridHeight : Height of each tile.
+ * bEnabled : Whether grid is enabled. If true, the other parameters
+ * specifies the grid config; otherwise they shall be ignored.
+ * nTileWidth : Width of each tile.
+ * nTileHeight : Height of each tile.
* nGridRows : Number of rows in the grid.
* nGridCols : Number of cols in the grid.
*/
@@ -458,8 +459,8 @@
OMX_VERSIONTYPE nVersion;
OMX_U32 nPortIndex;
OMX_BOOL bEnabled;
- OMX_U32 nGridWidth;
- OMX_U32 nGridHeight;
+ OMX_U32 nTileWidth;
+ OMX_U32 nTileHeight;
OMX_U32 nGridRows;
OMX_U32 nGridCols;
} OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index a1a0928..2768ad8 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -122,6 +122,7 @@
],
shared_libs: [
+ "android.hardware.graphics.common@1.1",
"libsync",
"libbinder",
"libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
@@ -154,6 +155,7 @@
"libui",
"android.hidl.token@1.0-utils",
"android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.common@1.1",
],
export_header_lib_headers: [
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index beda778..0244bb5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -350,7 +350,7 @@
}
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) {
+ Vector<ColorMode>* outColorModes) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -373,34 +373,34 @@
outColorModes->clear();
outColorModes->resize(numModes);
for (size_t i = 0; i < numModes; ++i) {
- outColorModes->replaceAt(static_cast<android_color_mode_t>(reply.readInt32()), i);
+ outColorModes->replaceAt(static_cast<ColorMode>(reply.readInt32()), i);
}
}
return result;
}
- virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) {
+ virtual ColorMode getActiveColorMode(const sp<IBinder>& display) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result);
- return static_cast<android_color_mode_t>(result);
+ return static_cast<ColorMode>(result);
}
result = data.writeStrongBinder(display);
if (result != NO_ERROR) {
ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result);
- return static_cast<android_color_mode_t>(result);
+ return static_cast<ColorMode>(result);
}
result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply);
if (result != NO_ERROR) {
ALOGE("getActiveColorMode failed to transact: %d", result);
- return static_cast<android_color_mode_t>(result);
+ return static_cast<ColorMode>(result);
}
- return static_cast<android_color_mode_t>(reply.readInt32());
+ return static_cast<ColorMode>(reply.readInt32());
}
virtual status_t setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) {
+ ColorMode colorMode) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -412,7 +412,7 @@
ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
return result;
}
- result = data.writeInt32(colorMode);
+ result = data.writeInt32(static_cast<int32_t>(colorMode));
if (result != NO_ERROR) {
ALOGE("setActiveColorMode failed to writeInt32: %d", result);
return result;
@@ -739,7 +739,7 @@
}
case GET_DISPLAY_COLOR_MODES: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- Vector<android_color_mode_t> colorModes;
+ Vector<ColorMode> colorModes;
sp<IBinder> display = nullptr;
status_t result = data.readStrongBinder(&display);
if (result != NO_ERROR) {
@@ -751,7 +751,7 @@
if (result == NO_ERROR) {
reply->writeUint32(static_cast<uint32_t>(colorModes.size()));
for (size_t i = 0; i < colorModes.size(); ++i) {
- reply->writeInt32(colorModes[i]);
+ reply->writeInt32(static_cast<int32_t>(colorModes[i]));
}
}
return NO_ERROR;
@@ -764,7 +764,7 @@
ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
return result;
}
- android_color_mode_t colorMode = getActiveColorMode(display);
+ ColorMode colorMode = getActiveColorMode(display);
result = reply->writeInt32(static_cast<int32_t>(colorMode));
return result;
}
@@ -783,7 +783,7 @@
return result;
}
result = setActiveColorMode(display,
- static_cast<android_color_mode_t>(colorModeInt));
+ static_cast<ColorMode>(colorModeInt));
result = reply->writeInt32(result);
return result;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e08d6b0..2e1c24b 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -326,7 +326,7 @@
sp<IBinder> display(
composerService()->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- Vector<android_color_mode_t> colorModes;
+ Vector<ColorMode> colorModes;
status_t err =
composerService()->getDisplayColorModes(display, &colorModes);
@@ -338,11 +338,11 @@
&ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
*supported = false;
- for (android_color_mode_t colorMode : colorModes) {
+ for (ColorMode colorMode : colorModes) {
switch (colorMode) {
- case HAL_COLOR_MODE_DISPLAY_P3:
- case HAL_COLOR_MODE_ADOBE_RGB:
- case HAL_COLOR_MODE_DCI_P3:
+ case ColorMode::DISPLAY_P3:
+ case ColorMode::ADOBE_RGB:
+ case ColorMode::DCI_P3:
if (wideColorBoardConfig) {
*supported = true;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 0d7ffc3..38f0eb7 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -612,7 +612,25 @@
uint32_t windowType,
uint32_t ownerUid)
{
+ sp<SurfaceControl> s;
+ createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid);
+ return s;
+}
+
+status_t SurfaceComposerClient::createSurfaceChecked(
+ const String8& name,
+ uint32_t w,
+ uint32_t h,
+ PixelFormat format,
+ sp<SurfaceControl>* outSurface,
+ uint32_t flags,
+ SurfaceControl* parent,
+ uint32_t windowType,
+ uint32_t ownerUid)
+{
sp<SurfaceControl> sur;
+ status_t err = NO_ERROR;
+
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
@@ -621,14 +639,14 @@
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
- status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle,
+ err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
- sur = new SurfaceControl(this, handle, gbp, true /* owned */);
+ *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
}
}
- return sur;
+ return err;
}
status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
@@ -698,16 +716,16 @@
}
status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) {
+ Vector<ColorMode>* outColorModes) {
return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
}
-android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
+ColorMode SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
return ComposerService::getComposerService()->getActiveColorMode(display);
}
status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) {
+ ColorMode colorMode) {
return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 5ab6445..afe9358 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -30,6 +30,7 @@
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
#include <ui/GraphicBuffer.h>
+#include <ui/GraphicsTypes.h>
#include <vector>
@@ -160,10 +161,10 @@
virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) = 0;
- virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) = 0;
+ Vector<ColorMode>* outColorModes) = 0;
+ virtual ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
virtual status_t setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) = 0;
+ ColorMode colorMode) = 0;
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index fe46146..5ce20ad 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -29,6 +29,7 @@
#include <utils/threads.h>
#include <ui/FrameStats.h>
+#include <ui/GraphicsTypes.h>
#include <ui/PixelFormat.h>
#include <gui/CpuConsumer.h>
@@ -88,13 +89,13 @@
// Gets the list of supported color modes for the given display
static status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes);
+ Vector<ColorMode>* outColorModes);
// Gets the active color mode for the given display
- static android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+ static ColorMode getActiveColorMode(const sp<IBinder>& display);
// Sets the active color mode for the given display
- static status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
+ static status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode);
/* Triggers screen on/off or low power mode and waits for it to complete */
static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
@@ -114,6 +115,18 @@
uint32_t ownerUid = 0 // UID of the task
);
+ status_t createSurfaceChecked(
+ const String8& name,// name of the surface
+ uint32_t w, // width in pixel
+ uint32_t h, // height in pixel
+ PixelFormat format, // pixel-format desired
+ sp<SurfaceControl>* outSurface,
+ uint32_t flags = 0, // usage flags
+ SurfaceControl* parent = nullptr, // parent
+ uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+ uint32_t ownerUid = 0 // UID of the task
+ );
+
//! Create a virtual display
static sp<IBinder> createDisplay(const String8& displayName, bool secure);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 4fb51e1..66d5595 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -577,15 +577,15 @@
return NO_ERROR;
}
status_t getDisplayColorModes(const sp<IBinder>& /*display*/,
- Vector<android_color_mode_t>* /*outColorModes*/) override {
+ Vector<ColorMode>* /*outColorModes*/) override {
return NO_ERROR;
}
- android_color_mode_t getActiveColorMode(const sp<IBinder>& /*display*/)
+ ColorMode getActiveColorMode(const sp<IBinder>& /*display*/)
override {
- return HAL_COLOR_MODE_NATIVE;
+ return ColorMode::NATIVE;
}
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
- android_color_mode_t /*colorMode*/) override { return NO_ERROR; }
+ ColorMode /*colorMode*/) override { return NO_ERROR; }
status_t captureScreen(const sp<IBinder>& /*display*/,
sp<GraphicBuffer>* /*outBuffer*/,
Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 17ebf80..d7e191d 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -22,6 +22,7 @@
#include <string>
using android::base::StringPrintf;
+using android::ColorMode;
std::string decodeStandard(android_dataspace dataspace) {
const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
@@ -197,37 +198,37 @@
decodeRange(dataspace).c_str());
}
-std::string decodeColorMode(android_color_mode colorMode) {
+std::string decodeColorMode(ColorMode colorMode) {
switch (colorMode) {
- case HAL_COLOR_MODE_NATIVE:
- return std::string("HAL_COLOR_MODE_NATIVE");
+ case ColorMode::NATIVE:
+ return std::string("ColorMode::NATIVE");
- case HAL_COLOR_MODE_STANDARD_BT601_625:
- return std::string("HAL_COLOR_MODE_BT601_625");
+ case ColorMode::STANDARD_BT601_625:
+ return std::string("ColorMode::BT601_625");
- case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
- return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED");
+ case ColorMode::STANDARD_BT601_625_UNADJUSTED:
+ return std::string("ColorMode::BT601_625_UNADJUSTED");
- case HAL_COLOR_MODE_STANDARD_BT601_525:
- return std::string("HAL_COLOR_MODE_BT601_525");
+ case ColorMode::STANDARD_BT601_525:
+ return std::string("ColorMode::BT601_525");
- case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
- return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED");
+ case ColorMode::STANDARD_BT601_525_UNADJUSTED:
+ return std::string("ColorMode::BT601_525_UNADJUSTED");
- case HAL_COLOR_MODE_STANDARD_BT709:
- return std::string("HAL_COLOR_MODE_BT709");
+ case ColorMode::STANDARD_BT709:
+ return std::string("ColorMode::BT709");
- case HAL_COLOR_MODE_DCI_P3:
- return std::string("HAL_COLOR_MODE_DCI_P3");
+ case ColorMode::DCI_P3:
+ return std::string("ColorMode::DCI_P3");
- case HAL_COLOR_MODE_SRGB:
- return std::string("HAL_COLOR_MODE_SRGB");
+ case ColorMode::SRGB:
+ return std::string("ColorMode::SRGB");
- case HAL_COLOR_MODE_ADOBE_RGB:
- return std::string("HAL_COLOR_MODE_ADOBE_RGB");
+ case ColorMode::ADOBE_RGB:
+ return std::string("ColorMode::ADOBE_RGB");
- case HAL_COLOR_MODE_DISPLAY_P3:
- return std::string("HAL_COLOR_MODE_DISPLAY_P3");
+ case ColorMode::DISPLAY_P3:
+ return std::string("ColorMode::DISPLAY_P3");
}
return android::base::StringPrintf("Unknown color mode %d", colorMode);
diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h
index dad9446..3370107 100644
--- a/libs/ui/include/ui/DebugUtils.h
+++ b/libs/ui/include/ui/DebugUtils.h
@@ -16,7 +16,7 @@
#pragma once
-#include <system/graphics.h>
+#include <ui/GraphicsTypes.h>
#include <ui/PixelFormat.h>
#include <string>
@@ -29,6 +29,6 @@
std::string decodeTransfer(android_dataspace dataspace);
std::string decodeRange(android_dataspace dataspace);
std::string dataspaceDetails(android_dataspace dataspace);
-std::string decodeColorMode(android_color_mode colormode);
+std::string decodeColorMode(android::ColorMode colormode);
std::string decodePixelFormat(android::PixelFormat format);
std::string to_string(const android::Rect& rect);
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicsTypes.h
new file mode 100644
index 0000000..fa9a812
--- /dev/null
+++ b/libs/ui/include/ui/GraphicsTypes.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/common/1.1/types.h>
+#include <system/graphics.h>
+
+namespace android {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+
+} // namespace android
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 3e4a42c..4dc669b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -72,6 +72,7 @@
srcs: sourceFiles,
export_include_dirs: includeFiles,
+ clang: true,
cflags: [
"-DLOG_TAG=\"vr_flinger\"",
"-DTRACE=0",
@@ -83,6 +84,9 @@
"-Wno-error=sign-compare", // to fix later
"-Wno-unused-variable",
],
+ cppflags: [
+ "-std=c++1z"
+ ],
shared_libs: sharedLibraries,
whole_static_libs: staticLibraries,
header_libs: headerLibraries,
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index a18ff1a..87162c0 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -177,12 +177,12 @@
Status<display::Metrics> DisplayService::OnGetMetrics(
pdx::Message& /*message*/) {
- return {{static_cast<uint32_t>(GetDisplayMetrics().width),
- static_cast<uint32_t>(GetDisplayMetrics().height),
- static_cast<uint32_t>(GetDisplayMetrics().dpi.x),
- static_cast<uint32_t>(GetDisplayMetrics().dpi.y),
- static_cast<uint32_t>(
- hardware_composer_.native_display_metrics().vsync_period_ns),
+ const auto& params = hardware_composer_.GetPrimaryDisplayParams();
+ return {{static_cast<uint32_t>(params.width),
+ static_cast<uint32_t>(params.height),
+ static_cast<uint32_t>(params.dpi.x),
+ static_cast<uint32_t>(params.dpi.y),
+ static_cast<uint32_t>(params.vsync_period_ns),
0,
0,
0,
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 316f15a..3090bd1 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -65,10 +65,6 @@
hardware_composer_.SetVSyncCallback(callback);
}
- HWCDisplayMetrics GetDisplayMetrics() {
- return hardware_composer_.display_metrics();
- }
-
void GrantDisplayOwnership() { hardware_composer_.Enable(); }
void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
void OnBootFinished() { hardware_composer_.OnBootFinished(); }
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 5b49645..44ce78c 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -50,9 +50,17 @@
const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
+const char kUseExternalDisplayProperty[] = "persist.vr.use_external_display";
+
// How long to wait after boot finishes before we turn the display off.
constexpr int kBootFinishedDisplayOffTimeoutSec = 10;
+constexpr int kDefaultDisplayWidth = 1920;
+constexpr int kDefaultDisplayHeight = 1080;
+constexpr int64_t kDefaultVsyncPeriodNs = 16666667;
+// Hardware composer reports dpi as dots per thousand inches (dpi * 1000).
+constexpr int kDefaultDpi = 400000;
+
// Get time offset from a vsync to when the pose for that vsync should be
// predicted out to. For example, if scanout gets halfway through the frame
// at the halfway point between vsyncs, then this could be half the period.
@@ -109,6 +117,11 @@
#define TRACE_FORMAT(format, ...) \
TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ }
+// Returns "primary" or "external". Useful for writing more readable logs.
+const char* GetDisplayName(bool is_primary) {
+ return is_primary ? "primary" : "external";
+}
+
} // anonymous namespace
HardwareComposer::HardwareComposer()
@@ -132,42 +145,7 @@
request_display_callback_ = request_display_callback;
- HWC::Error error = HWC::Error::None;
-
- Hwc2::Config config;
- error = composer->getActiveConfig(primary_display_id, &config);
-
- if (error != HWC::Error::None) {
- ALOGE("HardwareComposer: Failed to get current display config : %d",
- config);
- return false;
- }
-
- error = GetDisplayMetrics(composer, primary_display_id, config,
- &native_display_metrics_);
-
- if (error != HWC::Error::None) {
- ALOGE(
- "HardwareComposer: Failed to get display attributes for current "
- "configuration : %d",
- error.value);
- return false;
- }
-
- ALOGI(
- "HardwareComposer: primary display attributes: width=%d height=%d "
- "vsync_period_ns=%d DPI=%dx%d",
- native_display_metrics_.width, native_display_metrics_.height,
- native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
- native_display_metrics_.dpi.y);
-
- // Set the display metrics but never use rotation to avoid the long latency of
- // rotation processing in hwc.
- display_transform_ = HWC_TRANSFORM_NONE;
- display_metrics_ = native_display_metrics_;
-
- // Setup the display metrics used by all Layer instances.
- Layer::SetDisplayMetrics(native_display_metrics_);
+ primary_display_ = GetDisplayParams(composer, primary_display_id, true);
post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
LOG_ALWAYS_FATAL_IF(
@@ -236,43 +214,38 @@
}
}
-void HardwareComposer::OnPostThreadResumed() {
- // Phones create a new composer client on resume and destroy it on pause.
- // Standalones only create the composer client once and then use SetPowerMode
- // to control the screen on pause/resume.
- if (!is_standalone_device_ || !composer_) {
- composer_.reset(new Hwc2::impl::Composer("default"));
- composer_callback_ = new ComposerCallback;
- composer_->registerCallback(composer_callback_);
- LOG_ALWAYS_FATAL_IF(!composer_callback_->HasDisplayId(),
- "Registered composer callback but didn't get primary display");
- Layer::SetComposer(composer_.get());
- Layer::SetDisplayId(composer_callback_->GetDisplayId());
- } else {
- SetPowerMode(true);
- }
+void HardwareComposer::CreateComposer() {
+ if (composer_)
+ return;
+ composer_.reset(new Hwc2::impl::Composer("default"));
+ composer_callback_ = new ComposerCallback;
+ composer_->registerCallback(composer_callback_);
+ LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(),
+ "Registered composer callback but didn't get hotplug for primary"
+ " display");
+}
- EnableVsync(true);
+void HardwareComposer::OnPostThreadResumed() {
+ ALOGI("OnPostThreadResumed");
+ EnableDisplay(*target_display_, true);
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "performance");
}
void HardwareComposer::OnPostThreadPaused() {
+ ALOGI("OnPostThreadPaused");
retire_fence_fds_.clear();
layers_.clear();
- if (composer_) {
- EnableVsync(false);
- }
-
+ // Phones create a new composer client on resume and destroy it on pause.
+ // Standalones only create the composer client once and then use SetPowerMode
+ // to control the screen on pause/resume.
if (!is_standalone_device_) {
composer_callback_ = nullptr;
composer_.reset(nullptr);
- Layer::SetComposer(nullptr);
- Layer::SetDisplayId(0);
} else {
- SetPowerMode(false);
+ EnableDisplay(*target_display_, false);
}
// Trigger target-specific performance mode change.
@@ -305,28 +278,55 @@
composer_->validateDisplay(display, &num_types, &num_requests);
if (error == HWC2_ERROR_HAS_CHANGES) {
- // TODO(skiazyk): We might need to inspect the requested changes first, but
- // so far it seems like we shouldn't ever hit a bad state.
- // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
- // display);
+ ALOGE("Hardware composer has requested composition changes, "
+ "which we don't support.");
+ // Accept the changes anyway and see if we can get something on the screen.
error = composer_->acceptDisplayChanges(display);
}
return error;
}
-HWC::Error HardwareComposer::EnableVsync(bool enabled) {
- return composer_->setVsyncEnabled(
- composer_callback_->GetDisplayId(),
+bool HardwareComposer::EnableVsync(const DisplayParams& display, bool enabled) {
+ HWC::Error error = composer_->setVsyncEnabled(display.id,
(Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
: HWC2_VSYNC_DISABLE));
+ if (error != HWC::Error::None) {
+ ALOGE("Error attempting to %s vsync on %s display: %s",
+ enabled ? "enable" : "disable", GetDisplayName(display.is_primary),
+ error.to_string().c_str());
+ }
+ return error == HWC::Error::None;
}
-HWC::Error HardwareComposer::SetPowerMode(bool active) {
+bool HardwareComposer::SetPowerMode(const DisplayParams& display, bool active) {
+ ALOGI("Turning %s display %s", GetDisplayName(display.is_primary),
+ active ? "on" : "off");
HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
- return composer_->setPowerMode(
- composer_callback_->GetDisplayId(),
+ HWC::Error error = composer_->setPowerMode(display.id,
power_mode.cast<Hwc2::IComposerClient::PowerMode>());
+ if (error != HWC::Error::None) {
+ ALOGE("Error attempting to turn %s display %s: %s",
+ GetDisplayName(display.is_primary), active ? "on" : "off",
+ error.to_string().c_str());
+ }
+ return error == HWC::Error::None;
+}
+
+bool HardwareComposer::EnableDisplay(const DisplayParams& display,
+ bool enabled) {
+ bool power_result;
+ bool vsync_result;
+ // When turning a display on, we set the power state then set vsync. When
+ // turning a display off we do it in the opposite order.
+ if (enabled) {
+ power_result = SetPowerMode(display, enabled);
+ vsync_result = EnableVsync(display, enabled);
+ } else {
+ vsync_result = EnableVsync(display, enabled);
+ power_result = SetPowerMode(display, enabled);
+ }
+ return power_result && vsync_result;
}
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
@@ -345,78 +345,105 @@
return error;
}
-HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* composer,
- hwc2_display_t display,
- hwc2_config_t config,
- hwc2_attribute_t attribute,
- int32_t* out_value) const {
- return composer->getDisplayAttribute(
- display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
-}
+DisplayParams HardwareComposer::GetDisplayParams(
+ Hwc2::Composer* composer, hwc2_display_t display, bool is_primary) {
+ DisplayParams params;
+ params.id = display;
+ params.is_primary = is_primary;
-HWC::Error HardwareComposer::GetDisplayMetrics(
- Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config,
- HWCDisplayMetrics* out_metrics) const {
- HWC::Error error;
+ Hwc2::Config config;
+ HWC::Error error = composer->getActiveConfig(display, &config);
- error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_WIDTH,
- &out_metrics->width);
- if (error != HWC::Error::None) {
- ALOGE(
- "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
- error.to_string().c_str());
- return error;
+ if (error == HWC::Error::None) {
+ auto get_attr = [&](hwc2_attribute_t attr, const char* attr_name)
+ -> std::optional<int32_t> {
+ int32_t val;
+ HWC::Error error = composer->getDisplayAttribute(
+ display, config, (Hwc2::IComposerClient::Attribute)attr, &val);
+ if (error != HWC::Error::None) {
+ ALOGE("Failed to get %s display attr %s: %s",
+ GetDisplayName(is_primary), attr_name,
+ error.to_string().c_str());
+ return std::nullopt;
+ }
+ return val;
+ };
+
+ auto width = get_attr(HWC2_ATTRIBUTE_WIDTH, "width");
+ auto height = get_attr(HWC2_ATTRIBUTE_HEIGHT, "height");
+
+ if (width && height) {
+ params.width = *width;
+ params.height = *height;
+ } else {
+ ALOGI("Failed to get width and/or height for %s display. Using default"
+ " size %dx%d.", GetDisplayName(is_primary), kDefaultDisplayWidth,
+ kDefaultDisplayHeight);
+ params.width = kDefaultDisplayWidth;
+ params.height = kDefaultDisplayHeight;
+ }
+
+ auto vsync_period = get_attr(HWC2_ATTRIBUTE_VSYNC_PERIOD, "vsync period");
+ if (vsync_period) {
+ params.vsync_period_ns = *vsync_period;
+ } else {
+ ALOGI("Failed to get vsync period for %s display. Using default vsync"
+ " period %.2fms", GetDisplayName(is_primary),
+ static_cast<float>(kDefaultVsyncPeriodNs) / 1000000);
+ params.vsync_period_ns = kDefaultVsyncPeriodNs;
+ }
+
+ auto dpi_x = get_attr(HWC2_ATTRIBUTE_DPI_X, "DPI X");
+ auto dpi_y = get_attr(HWC2_ATTRIBUTE_DPI_Y, "DPI Y");
+ if (dpi_x && dpi_y) {
+ params.dpi.x = *dpi_x;
+ params.dpi.y = *dpi_y;
+ } else {
+ ALOGI("Failed to get dpi_x and/or dpi_y for %s display. Using default"
+ " dpi %d.", GetDisplayName(is_primary), kDefaultDpi);
+ params.dpi.x = kDefaultDpi;
+ params.dpi.y = kDefaultDpi;
+ }
+ } else {
+ ALOGE("HardwareComposer: Failed to get current %s display config: %d."
+ " Using default display values.",
+ GetDisplayName(is_primary), error.value);
+ params.width = kDefaultDisplayWidth;
+ params.height = kDefaultDisplayHeight;
+ params.dpi.x = kDefaultDpi;
+ params.dpi.y = kDefaultDpi;
+ params.vsync_period_ns = kDefaultVsyncPeriodNs;
}
- error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_HEIGHT,
- &out_metrics->height);
- if (error != HWC::Error::None) {
- ALOGE(
- "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
- error.to_string().c_str());
- return error;
- }
+ ALOGI(
+ "HardwareComposer: %s display attributes: width=%d height=%d "
+ "vsync_period_ns=%d DPI=%dx%d",
+ GetDisplayName(is_primary),
+ params.width,
+ params.height,
+ params.vsync_period_ns,
+ params.dpi.x,
+ params.dpi.y);
- error = GetDisplayAttribute(composer, display, config,
- HWC2_ATTRIBUTE_VSYNC_PERIOD,
- &out_metrics->vsync_period_ns);
- if (error != HWC::Error::None) {
- ALOGE(
- "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
- error.to_string().c_str());
- return error;
- }
-
- error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_X,
- &out_metrics->dpi.x);
- if (error != HWC::Error::None) {
- ALOGE(
- "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
- error.to_string().c_str());
- return error;
- }
-
- error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_Y,
- &out_metrics->dpi.y);
- if (error != HWC::Error::None) {
- ALOGE(
- "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
- error.to_string().c_str());
- return error;
- }
-
- return HWC::Error::None;
+ return params;
}
std::string HardwareComposer::Dump() {
std::unique_lock<std::mutex> lock(post_thread_mutex_);
std::ostringstream stream;
- stream << "Display metrics: " << display_metrics_.width << "x"
- << display_metrics_.height << " " << (display_metrics_.dpi.x / 1000.0)
- << "x" << (display_metrics_.dpi.y / 1000.0) << " dpi @ "
- << (1000000000.0 / display_metrics_.vsync_period_ns) << " Hz"
- << std::endl;
+ auto print_display_metrics = [&](const DisplayParams& params) {
+ stream << GetDisplayName(params.is_primary)
+ << " display metrics: " << params.width << "x"
+ << params.height << " " << (params.dpi.x / 1000.0)
+ << "x" << (params.dpi.y / 1000.0) << " dpi @ "
+ << (1000000000.0 / params.vsync_period_ns) << " Hz"
+ << std::endl;
+ };
+
+ print_display_metrics(primary_display_);
+ if (external_display_)
+ print_display_metrics(*external_display_);
stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
stream << "Active layers: " << layers_.size() << std::endl;
@@ -439,7 +466,7 @@
return stream.str();
}
-void HardwareComposer::PostLayers() {
+void HardwareComposer::PostLayers(hwc2_display_t display) {
ATRACE_NAME("HardwareComposer::PostLayers");
// Setup the hardware composer layers with current buffers.
@@ -487,14 +514,14 @@
}
#endif
- HWC::Error error = Validate(composer_callback_->GetDisplayId());
+ HWC::Error error = Validate(display);
if (error != HWC::Error::None) {
- ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
- error.to_string().c_str());
+ ALOGE("HardwareComposer::PostLayers: Validate failed: %s display=%" PRIu64,
+ error.to_string().c_str(), display);
return;
}
- error = Present(composer_callback_->GetDisplayId());
+ error = Present(display);
if (error != HWC::Error::None) {
ALOGE("HardwareComposer::PostLayers: Present failed: %s",
error.to_string().c_str());
@@ -503,7 +530,7 @@
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- error = composer_->getReleaseFences(composer_callback_->GetDisplayId(),
+ error = composer_->getReleaseFences(display,
&out_layers, &out_fences);
ALOGE_IF(error != HWC::Error::None,
"HardwareComposer::PostLayers: Failed to get release fences: %s",
@@ -527,7 +554,8 @@
const bool display_idle = surfaces.size() == 0;
{
std::unique_lock<std::mutex> lock(post_thread_mutex_);
- pending_surfaces_ = std::move(surfaces);
+ surfaces_ = std::move(surfaces);
+ surfaces_changed_ = true;
}
if (request_display_callback_ && !is_standalone_device_)
@@ -643,13 +671,11 @@
}
}
-// Waits for the next vsync and returns the timestamp of the vsync event. If
-// vsync already passed since the last call, returns the latest vsync timestamp
-// instead of blocking.
-Status<int64_t> HardwareComposer::WaitForVSync() {
- const int64_t predicted_vsync_time =
- last_vsync_timestamp_ +
- display_metrics_.vsync_period_ns * vsync_prediction_interval_;
+// Sleep until the next predicted vsync, returning the predicted vsync
+// timestamp.
+Status<int64_t> HardwareComposer::WaitForPredictedVSync() {
+ const int64_t predicted_vsync_time = last_vsync_timestamp_ +
+ (target_display_->vsync_period_ns * vsync_prediction_interval_);
const int error = SleepUntil(predicted_vsync_time);
if (error < 0) {
ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s",
@@ -695,20 +721,28 @@
"HardwareComposer: Failed to create vsync sleep timerfd: %s",
strerror(errno));
- const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
- const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
-
- // TODO(jbates) Query vblank time from device, when such an API is available.
- // This value (6.3%) was measured on A00 in low persistence mode.
- int64_t vblank_ns = ns_per_frame * 63 / 1000;
- int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2;
-
- // Check property for overriding right eye offset value.
- right_eye_photon_offset_ns =
- property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
-
+ struct VsyncEyeOffsets { int64_t left_ns, right_ns; };
bool was_running = false;
+ auto get_vsync_eye_offsets = [this]() -> VsyncEyeOffsets {
+ VsyncEyeOffsets offsets;
+ offsets.left_ns =
+ GetPosePredictionTimeOffset(target_display_->vsync_period_ns);
+
+ // TODO(jbates) Query vblank time from device, when such an API is
+ // available. This value (6.3%) was measured on A00 in low persistence mode.
+ int64_t vblank_ns = target_display_->vsync_period_ns * 63 / 1000;
+ offsets.right_ns = (target_display_->vsync_period_ns - vblank_ns) / 2;
+
+ // Check property for overriding right eye offset value.
+ offsets.right_ns =
+ property_get_int64(kRightEyeOffsetProperty, offsets.right_ns);
+
+ return offsets;
+ };
+
+ VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets();
+
if (is_standalone_device_) {
// First, wait until boot finishes.
std::unique_lock<std::mutex> lock(post_thread_mutex_);
@@ -727,8 +761,8 @@
"Vr flinger should own the display by now.");
post_thread_resumed_ = true;
post_thread_ready_.notify_all();
- OnPostThreadResumed();
- was_running = true;
+ if (!composer_)
+ CreateComposer();
}
while (1) {
@@ -741,10 +775,8 @@
std::unique_lock<std::mutex> lock(post_thread_mutex_);
ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
- // Tear down resources if necessary.
- if (was_running)
- OnPostThreadPaused();
-
+ // Tear down resources.
+ OnPostThreadPaused();
was_running = false;
post_thread_resumed_ = false;
post_thread_ready_.notify_all();
@@ -761,10 +793,18 @@
ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
}
- if (!was_running) {
- // Setup resources.
+ if (!composer_)
+ CreateComposer();
+
+ bool target_display_changed = UpdateTargetDisplay();
+ bool just_resumed_running = !was_running;
+ was_running = true;
+
+ if (target_display_changed)
+ vsync_eye_offsets = get_vsync_eye_offsets();
+
+ if (just_resumed_running) {
OnPostThreadResumed();
- was_running = true;
// Try to setup the scheduler policy if it failed during startup. Only
// attempt to do this on transitions from inactive to active to avoid
@@ -773,12 +813,16 @@
thread_policy_setup =
SetThreadPolicy("graphics:high", "/system/performance");
}
+ }
+ if (target_display_changed || just_resumed_running) {
// Initialize the last vsync timestamp with the current time. The
// predictor below uses this time + the vsync interval in absolute time
// units for the initial delay. Once the driver starts reporting vsync the
// predictor will sync up with the real vsync.
last_vsync_timestamp_ = GetSystemClockNs();
+ vsync_prediction_interval_ = 1;
+ retire_fence_fds_.clear();
}
int64_t vsync_timestamp = 0;
@@ -788,7 +832,7 @@
vsync_count_ + 1, last_vsync_timestamp_,
vsync_prediction_interval_);
- auto status = WaitForVSync();
+ auto status = WaitForPredictedVSync();
ALOGE_IF(
!status,
"HardwareComposer::PostThread: Failed to wait for vsync event: %s",
@@ -809,16 +853,16 @@
if (vsync_prediction_interval_ == 1)
++vsync_count_;
- const bool layer_config_changed = UpdateLayerConfig();
+ UpdateLayerConfig();
// Publish the vsync event.
if (vsync_ring_) {
DvrVsync vsync;
vsync.vsync_count = vsync_count_;
vsync.vsync_timestamp_ns = vsync_timestamp;
- vsync.vsync_left_eye_offset_ns = photon_offset_ns;
- vsync.vsync_right_eye_offset_ns = right_eye_photon_offset_ns;
- vsync.vsync_period_ns = ns_per_frame;
+ vsync.vsync_left_eye_offset_ns = vsync_eye_offsets.left_ns;
+ vsync.vsync_right_eye_offset_ns = vsync_eye_offsets.right_ns;
+ vsync.vsync_period_ns = target_display_->vsync_period_ns;
vsync_ring_->Publish(vsync);
}
@@ -832,7 +876,8 @@
// Sleep until shortly before vsync.
ATRACE_NAME("sleep");
- const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
+ const int64_t display_time_est_ns =
+ vsync_timestamp + target_display_->vsync_period_ns;
const int64_t now_ns = GetSystemClockNs();
const int64_t sleep_time_ns = display_time_est_ns - now_ns -
post_thread_config_.frame_post_offset_ns;
@@ -853,11 +898,7 @@
}
{
- auto status = composer_callback_->GetVsyncTime();
- if (!status) {
- ALOGE("HardwareComposer::PostThread: Failed to get VSYNC time: %s",
- status.GetErrorMessage().c_str());
- }
+ auto status = composer_callback_->GetVsyncTime(target_display_->id);
// If we failed to read vsync there might be a problem with the driver.
// Since there's nothing we can do just behave as though we didn't get an
@@ -884,20 +925,84 @@
}
}
- PostLayers();
+ PostLayers(target_display_->id);
}
}
+bool HardwareComposer::UpdateTargetDisplay() {
+ bool target_display_changed = false;
+ auto displays = composer_callback_->GetDisplays();
+ if (displays.external_display_was_hotplugged) {
+ bool was_using_external_display = !target_display_->is_primary;
+ if (was_using_external_display) {
+ // The external display was hotplugged, so make sure to ignore any bad
+ // display errors as we destroy the layers.
+ for (auto& layer: layers_)
+ layer.IgnoreBadDisplayErrorsOnDestroy(true);
+ }
+
+ if (displays.external_display) {
+ // External display was connected
+ external_display_ = GetDisplayParams(composer_.get(),
+ *displays.external_display, /*is_primary*/ false);
+
+ if (property_get_bool(kUseExternalDisplayProperty, false)) {
+ ALOGI("External display connected. Switching to external display.");
+ target_display_ = &(*external_display_);
+ target_display_changed = true;
+ } else {
+ ALOGI("External display connected, but sysprop %s is unset, so"
+ " using primary display.", kUseExternalDisplayProperty);
+ if (was_using_external_display) {
+ target_display_ = &primary_display_;
+ target_display_changed = true;
+ }
+ }
+ } else {
+ // External display was disconnected
+ external_display_ = std::nullopt;
+ if (was_using_external_display) {
+ ALOGI("External display disconnected. Switching to primary display.");
+ target_display_ = &primary_display_;
+ target_display_changed = true;
+ }
+ }
+ }
+
+ if (target_display_changed) {
+ // If we're switching to the external display, turn the primary display off.
+ if (!target_display_->is_primary) {
+ EnableDisplay(primary_display_, false);
+ }
+ // If we're switching to the primary display, and the external display is
+ // still connected, turn the external display off.
+ else if (target_display_->is_primary && external_display_) {
+ EnableDisplay(*external_display_, false);
+ }
+
+ // Turn the new target display on.
+ EnableDisplay(*target_display_, true);
+
+ // When we switch displays we need to recreate all the layers, so clear the
+ // current list, which will trigger layer recreation.
+ layers_.clear();
+ }
+
+ return target_display_changed;
+}
+
// Checks for changes in the surface stack and updates the layer config to
// accomodate the new stack.
-bool HardwareComposer::UpdateLayerConfig() {
+void HardwareComposer::UpdateLayerConfig() {
std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
{
std::unique_lock<std::mutex> lock(post_thread_mutex_);
- if (pending_surfaces_.empty())
- return false;
- surfaces = std::move(pending_surfaces_);
+ if (!surfaces_changed_ && (!layers_.empty() || surfaces_.empty()))
+ return;
+
+ surfaces = surfaces_;
+ surfaces_changed_ = false;
}
ATRACE_NAME("UpdateLayerConfig_HwLayers");
@@ -934,8 +1039,8 @@
layers_.erase(search);
} else {
// Insert a layer for the new surface.
- layers.emplace_back(surface, blending, display_transform_,
- HWC::Composition::Device, layer_index);
+ layers.emplace_back(composer_.get(), *target_display_, surface, blending,
+ HWC::Composition::Device, layer_index);
}
ALOGI_IF(
@@ -956,7 +1061,6 @@
ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
layers_.size());
- return true;
}
void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
@@ -965,15 +1069,27 @@
Return<void> HardwareComposer::ComposerCallback::onHotplug(
Hwc2::Display display, IComposerCallback::Connection conn) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ ALOGI("onHotplug display=%" PRIu64 " conn=%d", display, conn);
+
+ bool is_primary = !got_first_hotplug_ || display == primary_display_.id;
+
// Our first onHotplug callback is always for the primary display.
- //
- // Ignore any other hotplug callbacks since the primary display is never
- // disconnected and we don't care about other displays.
- if (!has_display_id_) {
+ if (!got_first_hotplug_) {
LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED,
"Initial onHotplug callback should be primary display connected");
- has_display_id_ = true;
- display_id_ = display;
+ got_first_hotplug_ = true;
+ } else if (is_primary) {
+ ALOGE("Ignoring unexpected onHotplug() call for primary display");
+ return Void();
+ }
+
+ if (conn == IComposerCallback::Connection::CONNECTED) {
+ if (!is_primary)
+ external_display_ = DisplayInfo();
+ DisplayInfo& display_info = is_primary ?
+ primary_display_ : *external_display_;
+ display_info.id = display;
std::array<char, 1024> buffer;
snprintf(buffer.data(), buffer.size(),
@@ -983,15 +1099,20 @@
"HardwareComposer::ComposerCallback::onHotplug: Driver supports "
"vsync_event node for display %" PRIu64,
display);
- driver_vsync_event_fd_ = std::move(handle);
+ display_info.driver_vsync_event_fd = std::move(handle);
} else {
ALOGI(
"HardwareComposer::ComposerCallback::onHotplug: Driver does not "
"support vsync_event node for display %" PRIu64,
display);
}
+ } else if (conn == IComposerCallback::Connection::DISCONNECTED) {
+ external_display_ = std::nullopt;
}
+ if (!is_primary)
+ external_display_was_hotplugged_ = true;
+
return Void();
}
@@ -1002,23 +1123,45 @@
Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
int64_t timestamp) {
- // Ignore any onVsync callbacks for the non-primary display.
- if (has_display_id_ && display == display_id_) {
+ DisplayInfo* display_info = GetDisplayInfo(display);
+ if (display_info) {
TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
display, timestamp);
- callback_vsync_timestamp_ = timestamp;
+ display_info->callback_vsync_timestamp = timestamp;
}
+
return Void();
}
-Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime() {
+HardwareComposer::ComposerCallback::Displays
+HardwareComposer::ComposerCallback::GetDisplays() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ Displays displays;
+ displays.primary_display = primary_display_.id;
+ if (external_display_)
+ displays.external_display = external_display_->id;
+ if (external_display_was_hotplugged_) {
+ external_display_was_hotplugged_ = false;
+ displays.external_display_was_hotplugged = true;
+ }
+ return displays;
+}
+
+Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
+ hwc2_display_t display) {
+ DisplayInfo* display_info = GetDisplayInfo(display);
+ if (!display_info) {
+ ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display);
+ return ErrorStatus(EINVAL);
+ }
+
// See if the driver supports direct vsync events.
- LocalHandle& event_fd = driver_vsync_event_fd_;
+ LocalHandle& event_fd = display_info->driver_vsync_event_fd;
if (!event_fd) {
// Fall back to returning the last timestamp returned by the vsync
// callback.
- std::lock_guard<std::mutex> autolock(vsync_mutex_);
- return callback_vsync_timestamp_;
+ std::lock_guard<std::mutex> autolock(mutex_);
+ return display_info->callback_vsync_timestamp;
}
// When the driver supports the vsync_event sysfs node we can use it to
@@ -1066,19 +1209,32 @@
return {timestamp};
}
-Hwc2::Composer* Layer::composer_{nullptr};
-HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
-hwc2_display_t Layer::display_id_{0};
+HardwareComposer::ComposerCallback::DisplayInfo*
+HardwareComposer::ComposerCallback::GetDisplayInfo(hwc2_display_t display) {
+ if (display == primary_display_.id) {
+ return &primary_display_;
+ } else if (external_display_ && display == external_display_->id) {
+ return &(*external_display_);
+ }
+ return nullptr;
+}
void Layer::Reset() {
if (hardware_composer_layer_) {
- composer_->destroyLayer(display_id_, hardware_composer_layer_);
+ HWC::Error error =
+ composer_->destroyLayer(display_params_.id, hardware_composer_layer_);
+ if (error != HWC::Error::None &&
+ (!ignore_bad_display_errors_on_destroy_ ||
+ error != HWC::Error::BadDisplay)) {
+ ALOGE("destroyLayer() failed for display %" PRIu64 ", layer %" PRIu64
+ ". error: %s", display_params_.id, hardware_composer_layer_,
+ error.to_string().c_str());
+ }
hardware_composer_layer_ = 0;
}
z_order_ = 0;
blending_ = HWC::BlendMode::None;
- transform_ = HWC::Transform::None;
composition_type_ = HWC::Composition::Invalid;
target_composition_type_ = composition_type_;
source_ = EmptyVariant{};
@@ -1086,25 +1242,29 @@
surface_rect_functions_applied_ = false;
pending_visibility_settings_ = true;
cached_buffer_map_.clear();
+ ignore_bad_display_errors_on_destroy_ = false;
}
-Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order)
- : z_order_{z_order},
+Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
+ const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Composition composition_type,
+ size_t z_order)
+ : composer_(composer),
+ display_params_(display_params),
+ z_order_{z_order},
blending_{blending},
- transform_{transform},
target_composition_type_{composition_type},
source_{SourceSurface{surface}} {
CommonLayerSetup();
}
-Layer::Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order)
- : z_order_{z_order},
+Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
+ const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Composition composition_type, size_t z_order)
+ : composer_(composer),
+ display_params_(display_params),
+ z_order_{z_order},
blending_{blending},
- transform_{transform},
target_composition_type_{composition_type},
source_{SourceBuffer{buffer}} {
CommonLayerSetup();
@@ -1118,10 +1278,11 @@
if (this != &other) {
Reset();
using std::swap;
+ swap(composer_, other.composer_);
+ swap(display_params_, other.display_params_);
swap(hardware_composer_layer_, other.hardware_composer_layer_);
swap(z_order_, other.z_order_);
swap(blending_, other.blending_);
- swap(transform_, other.transform_);
swap(composition_type_, other.composition_type_);
swap(target_composition_type_, other.target_composition_type_);
swap(source_, other.source_);
@@ -1130,6 +1291,8 @@
other.surface_rect_functions_applied_);
swap(pending_visibility_settings_, other.pending_visibility_settings_);
swap(cached_buffer_map_, other.cached_buffer_map_);
+ swap(ignore_bad_display_errors_on_destroy_,
+ other.ignore_bad_display_errors_on_destroy_);
}
return *this;
}
@@ -1169,14 +1332,14 @@
HWC::Error error;
error = composer_->setLayerBlendMode(
- display_id_, hardware_composer_layer_,
+ display_params_.id, hardware_composer_layer_,
blending_.cast<Hwc2::IComposerClient::BlendMode>());
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
error.to_string().c_str());
- error = composer_->setLayerZOrder(display_id_, hardware_composer_layer_,
- z_order_);
+ error = composer_->setLayerZOrder(display_params_.id,
+ hardware_composer_layer_, z_order_);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting z_ order: %s",
error.to_string().c_str());
@@ -1191,28 +1354,28 @@
// TODO(eieio): Use surface attributes or some other mechanism to control
// the layer display frame.
error = composer_->setLayerDisplayFrame(
- display_id_, hardware_composer_layer_,
- {0, 0, display_metrics_.width, display_metrics_.height});
+ display_params_.id, hardware_composer_layer_,
+ {0, 0, display_params_.width, display_params_.height});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer display frame: %s",
error.to_string().c_str());
error = composer_->setLayerVisibleRegion(
- display_id_, hardware_composer_layer_,
- {{0, 0, display_metrics_.width, display_metrics_.height}});
+ display_params_.id, hardware_composer_layer_,
+ {{0, 0, display_params_.width, display_params_.height}});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer visible region: %s",
error.to_string().c_str());
- error = composer_->setLayerPlaneAlpha(display_id_, hardware_composer_layer_,
- 1.0f);
+ error = composer_->setLayerPlaneAlpha(display_params_.id,
+ hardware_composer_layer_, 1.0f);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
error.to_string().c_str());
}
void Layer::CommonLayerSetup() {
- HWC::Error error = composer_->createLayer(display_id_,
+ HWC::Error error = composer_->createLayer(display_params_.id,
&hardware_composer_layer_);
ALOGE_IF(error != HWC::Error::None,
"Layer::CommonLayerSetup: Failed to create layer on primary "
@@ -1257,10 +1420,10 @@
if (composition_type_ == HWC::Composition::Invalid) {
composition_type_ = HWC::Composition::SolidColor;
composer_->setLayerCompositionType(
- display_id_, hardware_composer_layer_,
+ display_params_.id, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
- composer_->setLayerColor(display_id_, hardware_composer_layer_,
+ composer_->setLayerColor(display_params_.id, hardware_composer_layer_,
layer_color);
} else {
// The composition type is already set. Nothing else to do until a
@@ -1270,7 +1433,7 @@
if (composition_type_ != target_composition_type_) {
composition_type_ = target_composition_type_;
composer_->setLayerCompositionType(
- display_id_, hardware_composer_layer_,
+ display_params_.id, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
@@ -1281,7 +1444,7 @@
HWC::Error error{HWC::Error::None};
error =
- composer_->setLayerBuffer(display_id_, hardware_composer_layer_,
+ composer_->setLayerBuffer(display_params_.id, hardware_composer_layer_,
slot, handle, acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
@@ -1291,7 +1454,7 @@
if (!surface_rect_functions_applied_) {
const float float_right = right;
const float float_bottom = bottom;
- error = composer_->setLayerSourceCrop(display_id_,
+ error = composer_->setLayerSourceCrop(display_params_.id,
hardware_composer_layer_,
{0, 0, float_right, float_bottom});
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 4a503f8..1d8d463 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -13,6 +13,7 @@
#include <condition_variable>
#include <memory>
#include <mutex>
+#include <optional>
#include <thread>
#include <tuple>
#include <vector>
@@ -35,16 +36,19 @@
namespace android {
namespace dvr {
-// Basic display metrics for physical displays. Dimensions and densities are
-// relative to the physical display orientation, which may be different from the
-// logical display orientation exposed to applications.
-struct HWCDisplayMetrics {
+// Basic display metrics for physical displays.
+struct DisplayParams {
+ hwc2_display_t id;
+ bool is_primary;
+
int width;
int height;
+
struct {
int x;
int y;
} dpi;
+
int vsync_period_ns;
};
@@ -58,26 +62,29 @@
// automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
// every frame.
//
+ // |composer| The composer instance.
+ // |display_params| Info about the display to use.
// |blending| receives HWC_BLENDING_* values.
- // |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
// |index| is the index of this surface in the DirectDisplaySurface array.
- Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_roder);
+ Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
+ const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Composition composition_type,
+ size_t z_order);
// Sets up the layer to use a direct buffer as its content source. No special
// handling of the buffer is performed; responsibility for updating or
// changing the buffer each frame is on the caller.
//
+ // |composer| The composer instance.
+ // |display_params| Info about the display to use.
// |blending| receives HWC_BLENDING_* values.
- // |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order);
+ Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
+ const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Composition composition_type, size_t z_order);
Layer(Layer&&);
Layer& operator=(Layer&&);
@@ -144,17 +151,8 @@
}
bool operator<(int surface_id) const { return GetSurfaceId() < surface_id; }
- // Sets the composer instance used by all Layer instances.
- static void SetComposer(Hwc2::Composer* composer) { composer_ = composer; }
-
- // Sets the display metrics used by all Layer instances.
- static void SetDisplayMetrics(HWCDisplayMetrics display_metrics) {
- display_metrics_ = display_metrics;
- }
-
- // Sets the display id used by all Layer instances.
- static void SetDisplayId(hwc2_display_t display_id) {
- display_id_ = display_id;
+ void IgnoreBadDisplayErrorsOnDestroy(bool ignore) {
+ ignore_bad_display_errors_on_destroy_ = ignore;
}
private:
@@ -174,21 +172,11 @@
// associated and always returns false.
bool CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id);
- // Composer instance shared by all instances of Layer. This must be set
- // whenever a new instance of the Composer is created. This may be set to
- // nullptr as long as there are no instances of Layer that might need to use
- // it.
- static Hwc2::Composer* composer_;
+ // Composer instance.
+ Hwc2::Composer* composer_ = nullptr;
- // Display metrics shared by all instances of Layer. This must be set at least
- // once during VrFlinger initialization and is expected to remain constant
- // thereafter.
- static HWCDisplayMetrics display_metrics_;
-
- // Id of the primary display. Shared by all instances of Layer. This must be
- // set whenever the primary display id changes. This can be left unset as long
- // as there are no instances of Layer that might need to use it.
- static hwc2_display_t display_id_;
+ // Parameters of the display to use for this layer.
+ DisplayParams display_params_;
// The hardware composer layer and metrics to use during the prepare cycle.
hwc2_layer_t hardware_composer_layer_ = 0;
@@ -197,7 +185,6 @@
// Prepare phase.
size_t z_order_ = 0;
HWC::BlendMode blending_ = HWC::BlendMode::None;
- HWC::Transform transform_ = HWC::Transform::None;
HWC::Composition composition_type_ = HWC::Composition::Invalid;
HWC::Composition target_composition_type_ = HWC::Composition::Device;
@@ -293,6 +280,12 @@
// importing a buffer HWC already knows about.
std::map<std::size_t, int> cached_buffer_map_;
+ // When calling destroyLayer() on an external display that's been removed we
+ // typically get HWC2_ERROR_BAD_DISPLAY errors. If
+ // ignore_bad_display_errors_on_destroy_ is true, don't log the bad display
+ // errors, since they're expected.
+ bool ignore_bad_display_errors_on_destroy_ = false;
+
Layer(const Layer&) = delete;
void operator=(const Layer&) = delete;
};
@@ -330,22 +323,12 @@
// Called on a binder thread.
void OnBootFinished();
- // Get the HMD display metrics for the current display.
- display::Metrics GetHmdDisplayMetrics() const;
-
std::string Dump();
void SetVSyncCallback(VSyncCallback callback);
- // Metrics of the logical display, which is always landscape.
- int DisplayWidth() const { return display_metrics_.width; }
- int DisplayHeight() const { return display_metrics_.height; }
- HWCDisplayMetrics display_metrics() const { return display_metrics_; }
-
- // Metrics of the native display, which depends on the specific hardware
- // implementation of the display.
- HWCDisplayMetrics native_display_metrics() const {
- return native_display_metrics_;
+ const DisplayParams& GetPrimaryDisplayParams() const {
+ return primary_display_;
}
// Sets the display surfaces to compose the hardware layer stack.
@@ -356,16 +339,16 @@
void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
private:
- HWC::Error GetDisplayAttribute(Hwc2::Composer* composer,
- hwc2_display_t display, hwc2_config_t config,
- hwc2_attribute_t attributes,
- int32_t* out_value) const;
- HWC::Error GetDisplayMetrics(Hwc2::Composer* composer, hwc2_display_t display,
- hwc2_config_t config,
- HWCDisplayMetrics* out_metrics) const;
+ DisplayParams GetDisplayParams(Hwc2::Composer* composer,
+ hwc2_display_t display, bool is_primary);
- HWC::Error EnableVsync(bool enabled);
- HWC::Error SetPowerMode(bool active);
+ // Turn display vsync on/off. Returns true on success, false on failure.
+ bool EnableVsync(const DisplayParams& display, bool enabled);
+ // Turn display power on/off. Returns true on success, false on failure.
+ bool SetPowerMode(const DisplayParams& display, bool active);
+ // Convenience function to turn a display on/off. Turns both power and vsync
+ // on/off. Returns true on success, false on failure.
+ bool EnableDisplay(const DisplayParams& display, bool enabled);
class ComposerCallback : public Hwc2::IComposerCallback {
public:
@@ -376,22 +359,38 @@
hardware::Return<void> onVsync(Hwc2::Display display,
int64_t timestamp) override;
- bool HasDisplayId() { return has_display_id_; }
- hwc2_display_t GetDisplayId() { return display_id_; }
- pdx::Status<int64_t> GetVsyncTime();
+ bool GotFirstHotplug() { return got_first_hotplug_; }
+
+ struct Displays {
+ hwc2_display_t primary_display = 0;
+ std::optional<hwc2_display_t> external_display;
+ bool external_display_was_hotplugged = false;
+ };
+
+ Displays GetDisplays();
+ pdx::Status<int64_t> GetVsyncTime(hwc2_display_t display);
private:
- std::mutex vsync_mutex_;
- bool has_display_id_ = false;
- hwc2_display_t display_id_;
- pdx::LocalHandle driver_vsync_event_fd_;
- int64_t callback_vsync_timestamp_{0};
+ struct DisplayInfo {
+ hwc2_display_t id = 0;
+ pdx::LocalHandle driver_vsync_event_fd;
+ int64_t callback_vsync_timestamp{0};
+ };
+
+ DisplayInfo* GetDisplayInfo(hwc2_display_t display);
+
+ std::mutex mutex_;
+
+ bool got_first_hotplug_ = false;
+ DisplayInfo primary_display_;
+ std::optional<DisplayInfo> external_display_;
+ bool external_display_was_hotplugged_ = false;
};
HWC::Error Validate(hwc2_display_t display);
HWC::Error Present(hwc2_display_t display);
- void PostLayers();
+ void PostLayers(hwc2_display_t display);
void PostThread();
// The post thread has two controlling states:
@@ -419,16 +418,24 @@
int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
int requested_events, int timeout_ms);
- // WaitForVSync and SleepUntil are blocking calls made on the post thread that
- // can be interrupted by a control thread. If interrupted, these calls return
- // kPostThreadInterrupted.
+ // WaitForPredictedVSync and SleepUntil are blocking calls made on the post
+ // thread that can be interrupted by a control thread. If interrupted, these
+ // calls return kPostThreadInterrupted.
int ReadWaitPPState();
- pdx::Status<int64_t> WaitForVSync();
+ pdx::Status<int64_t> WaitForPredictedVSync();
int SleepUntil(int64_t wakeup_timestamp);
+ // Initialize any newly connected displays, and set target_display_ to the
+ // display we should render to. Returns true if target_display_
+ // changed. Called only from the post thread.
+ bool UpdateTargetDisplay();
+
// Reconfigures the layer stack if the display surfaces changed since the last
// frame. Called only from the post thread.
- bool UpdateLayerConfig();
+ void UpdateLayerConfig();
+
+ // Called on the post thread to create the Composer instance.
+ void CreateComposer();
// Called on the post thread when the post thread is resumed.
void OnPostThreadResumed();
@@ -459,18 +466,19 @@
sp<ComposerCallback> composer_callback_;
RequestDisplayCallback request_display_callback_;
- // Display metrics of the physical display.
- HWCDisplayMetrics native_display_metrics_;
- // Display metrics of the logical display, adjusted so that orientation is
- // landscape.
- HWCDisplayMetrics display_metrics_;
- // Transform required to get from native to logical display orientation.
- HWC::Transform display_transform_ = HWC::Transform::None;
+ DisplayParams primary_display_;
+ std::optional<DisplayParams> external_display_;
+ DisplayParams* target_display_ = &primary_display_;
- // Pending surface list. Set by the display service when DirectSurfaces are
- // added, removed, or change visibility. Written by the message dispatch
- // thread and read by the post thread.
- std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
+ // The list of surfaces we should draw. Set by the display service when
+ // DirectSurfaces are added, removed, or change visibility. Written by the
+ // message dispatch thread and read by the post thread.
+ std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces_;
+ // Set to true by the dispatch thread whenever surfaces_ changes. Set to false
+ // by the post thread when the new list of surfaces is processed.
+ bool surfaces_changed_ = false;
+
+ std::vector<std::shared_ptr<DirectDisplaySurface>> current_surfaces_;
// Layer set for handling buffer flow into hardware composer layers. This
// vector must be sorted by surface_id in ascending order.
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index d40666e..92d5e21 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -99,7 +99,7 @@
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
- mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ mActiveColorMode = ColorMode::NATIVE;
mDisplayHasWideColor = supportWideColor;
mDisplayHasHdr = supportHdr;
@@ -292,11 +292,11 @@
}
// ----------------------------------------------------------------------------
-void DisplayDevice::setActiveColorMode(android_color_mode_t mode) {
+void DisplayDevice::setActiveColorMode(ColorMode mode) {
mActiveColorMode = mode;
}
-android_color_mode_t DisplayDevice::getActiveColorMode() const {
+ColorMode DisplayDevice::getActiveColorMode() const {
return mActiveColorMode;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d5ed15f..737971f 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -31,6 +31,7 @@
#include <gui/ISurfaceComposer.h>
#include <hardware/hwcomposer_defs.h>
+#include <ui/GraphicsTypes.h>
#include "RenderArea.h"
#include "RenderEngine/Surface.h"
@@ -155,8 +156,8 @@
void setPowerMode(int mode);
bool isDisplayOn() const;
- android_color_mode_t getActiveColorMode() const;
- void setActiveColorMode(android_color_mode_t mode);
+ ColorMode getActiveColorMode() const;
+ void setActiveColorMode(ColorMode mode);
void setCompositionDataSpace(android_dataspace dataspace);
/* ------------------------------------------------------------------------
@@ -230,7 +231,7 @@
// Current active config
int mActiveConfig;
// current active color mode
- android_color_mode_t mActiveColorMode;
+ ColorMode mActiveColorMode;
// Need to know if display is wide-color capable or not.
// Initialized by SurfaceFlinger when the DisplayDevice is created.
@@ -279,7 +280,7 @@
bool needsFiltering() const override { return mDevice->needsFiltering(); }
Rect getSourceCrop() const override { return mSourceCrop; }
bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
- android_color_mode_t getActiveColorMode() const override {
+ ColorMode getActiveColorMode() const override {
return mDevice->getActiveColorMode();
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index f14c2fe..b7bf964 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -362,9 +362,9 @@
return Error::None;
}
-Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
+Error Display::getColorModes(std::vector<android::ColorMode>* outModes) const
{
- std::vector<Hwc2::ColorMode> modes;
+ std::vector<android::ColorMode> modes;
auto intError = mComposer.getColorModes(mId, &modes);
uint32_t numModes = modes.size();
auto error = static_cast<Error>(intError);
@@ -374,7 +374,7 @@
outModes->resize(numModes);
for (size_t i = 0; i < numModes; i++) {
- (*outModes)[i] = static_cast<android_color_mode_t>(modes[i]);
+ (*outModes)[i] = modes[i];
}
return Error::None;
}
@@ -537,10 +537,9 @@
return static_cast<Error>(intError);
}
-Error Display::setColorMode(android_color_mode_t mode)
+Error Display::setColorMode(android::ColorMode mode)
{
- auto intError = mComposer.setColorMode(
- mId, static_cast<Hwc2::ColorMode>(mode));
+ auto intError = mComposer.setColorMode(mId, mode);
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index e74f00d..0fc37ec 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -25,6 +25,7 @@
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
+#include <ui/GraphicsTypes.h>
#include <ui/HdrCapabilities.h>
#include <utils/Log.h>
@@ -209,7 +210,7 @@
[[clang::warn_unused_result]] Error getChangedCompositionTypes(
std::unordered_map<Layer*, Composition>* outTypes);
[[clang::warn_unused_result]] Error getColorModes(
- std::vector<android_color_mode_t>* outModes) const;
+ std::vector<android::ColorMode>* outModes) const;
// Doesn't call into the HWC2 device, so no errors are possible
std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -233,7 +234,7 @@
uint32_t slot, const android::sp<android::GraphicBuffer>& target,
const android::sp<android::Fence>& acquireFence,
android_dataspace_t dataspace);
- [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
+ [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode);
[[clang::warn_unused_result]] Error setColorTransform(
const android::mat4& matrix, android_color_transform_t hint);
[[clang::warn_unused_result]] Error setOutputBuffer(
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 2cafd8e..6d5917d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -311,8 +311,8 @@
return config;
}
-std::vector<android_color_mode_t> HWComposer::getColorModes(int32_t displayId) const {
- std::vector<android_color_mode_t> modes;
+std::vector<ColorMode> HWComposer::getColorModes(int32_t displayId) const {
+ std::vector<ColorMode> modes;
if (!isValidDisplay(displayId)) {
ALOGE("getColorModes: Attempted to access invalid display %d",
@@ -324,13 +324,13 @@
if (error != HWC2::Error::None) {
ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
- return std::vector<android_color_mode_t>();
+ return std::vector<ColorMode>();
}
return modes;
}
-status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) {
+status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) {
if (!isValidDisplay(displayId)) {
ALOGE("setActiveColorMode: Display %d is not valid", displayId);
return BAD_INDEX;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b75dc6a..c442b2f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <ui/Fence.h>
+#include <ui/GraphicsTypes.h>
#include <utils/BitSet.h>
#include <utils/Condition.h>
@@ -158,9 +159,9 @@
std::shared_ptr<const HWC2::Display::Config>
getActiveConfig(int32_t displayId) const;
- std::vector<android_color_mode_t> getColorModes(int32_t displayId) const;
+ std::vector<ColorMode> getColorModes(int32_t displayId) const;
- status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode);
+ status_t setActiveColorMode(int32_t displayId, ColorMode mode);
bool isUsingVrComposer() const;
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 940a34c..b9c4909 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,5 +1,7 @@
#pragma once
+#include <ui/GraphicsTypes.h>
+
#include "Transform.h"
#include <functional>
@@ -30,7 +32,7 @@
int getReqWidth() const { return mReqWidth; };
Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
virtual bool getWideColorSupport() const = 0;
- virtual android_color_mode_t getActiveColorMode() const = 0;
+ virtual ColorMode getActiveColorMode() const = 0;
status_t updateDimensions();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 38b93b1..11658e8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -260,6 +260,11 @@
mLayerTripleBufferingDisabled = atoi(value);
ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
+ // TODO (b/74616334): Reduce the default value once we isolate the leak
+ const size_t defaultListSize = 4 * MAX_LAYERS;
+ auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
+ mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
+
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
// comes online to attempt to read the property. The property is
@@ -913,7 +918,7 @@
return NO_ERROR;
}
status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) {
+ Vector<ColorMode>* outColorModes) {
if ((outColorModes == nullptr) || (display.get() == nullptr)) {
return BAD_VALUE;
}
@@ -934,7 +939,7 @@
return type;
}
- std::vector<android_color_mode_t> modes;
+ std::vector<ColorMode> modes;
{
ConditionalLock _l(mStateLock,
std::this_thread::get_id() != mMainThreadId);
@@ -946,18 +951,18 @@
return NO_ERROR;
}
-android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
sp<const DisplayDevice> device(getDisplayDevice(display));
if (device != nullptr) {
return device->getActiveColorMode();
}
- return static_cast<android_color_mode_t>(BAD_VALUE);
+ return static_cast<ColorMode>(BAD_VALUE);
}
void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
- android_color_mode_t mode) {
+ ColorMode mode) {
int32_t type = hw->getDisplayType();
- android_color_mode_t currentMode = hw->getActiveColorMode();
+ ColorMode currentMode = hw->getActiveColorMode();
if (mode == currentMode) {
return;
@@ -977,20 +982,20 @@
status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) {
+ ColorMode colorMode) {
class MessageSetActiveColorMode: public MessageBase {
SurfaceFlinger& mFlinger;
sp<IBinder> mDisplay;
- android_color_mode_t mMode;
+ ColorMode mMode;
public:
MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp<IBinder>& disp,
- android_color_mode_t mode) :
+ ColorMode mode) :
mFlinger(flinger), mDisplay(disp) { mMode = mode; }
virtual bool handler() {
- Vector<android_color_mode_t> modes;
+ Vector<ColorMode> modes;
mFlinger.getDisplayColorModes(mDisplay, &modes);
bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
- if (mMode < 0 || !exists) {
+ if (mMode < ColorMode::NATIVE || !exists) {
ALOGE("Attempt to set invalid active color mode %s (%d) for display %p",
decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
return true;
@@ -1783,9 +1788,9 @@
// pickColorMode translates a given dataspace into the best available color mode.
// Currently only support sRGB and Display-P3.
-android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const {
+ColorMode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const {
if (mForceNativeColorMode) {
- return HAL_COLOR_MODE_NATIVE;
+ return ColorMode::NATIVE;
}
switch (dataSpace) {
@@ -1794,18 +1799,18 @@
case HAL_DATASPACE_UNKNOWN:
case HAL_DATASPACE_SRGB:
case HAL_DATASPACE_V0_SRGB:
- return HAL_COLOR_MODE_SRGB;
+ return ColorMode::SRGB;
break;
case HAL_DATASPACE_DISPLAY_P3:
- return HAL_COLOR_MODE_DISPLAY_P3;
+ return ColorMode::DISPLAY_P3;
break;
default:
// TODO (courtneygo): Do we want to assert an error here?
ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(),
dataSpace);
- return HAL_COLOR_MODE_SRGB;
+ return ColorMode::SRGB;
break;
}
}
@@ -1927,7 +1932,7 @@
}
if (hasWideColorDisplay) {
- android_color_mode newColorMode;
+ ColorMode newColorMode;
android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
@@ -2269,13 +2274,13 @@
if (dispSurface != nullptr) {
bool hasWideColorSupport = false;
if (hasWideColorDisplay) {
- std::vector<android_color_mode_t> modes =
+ std::vector<ColorMode> modes =
getHwComposer().getColorModes(state.type);
- for (android_color_mode_t colorMode : modes) {
+ for (ColorMode colorMode : modes) {
switch (colorMode) {
- case HAL_COLOR_MODE_DISPLAY_P3:
- case HAL_COLOR_MODE_ADOBE_RGB:
- case HAL_COLOR_MODE_DCI_P3:
+ case ColorMode::DISPLAY_P3:
+ case ColorMode::ADOBE_RGB:
+ case ColorMode::DCI_P3:
hasWideColorSupport = true;
break;
default:
@@ -2298,9 +2303,9 @@
dispSurface, producer, hasWideColorSupport,
hasHdrSupport);
- android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+ ColorMode defaultColorMode = ColorMode::NATIVE;
if (hasWideColorSupport) {
- defaultColorMode = HAL_COLOR_MODE_SRGB;
+ defaultColorMode = ColorMode::SRGB;
}
setActiveColorModeInternal(hw, defaultColorMode);
hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
@@ -2741,7 +2746,7 @@
android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN;
if (displayDevice->getWideColorSupport() &&
- displayDevice->getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) {
+ displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) {
outputDataspace = HAL_DATASPACE_DISPLAY_P3;
}
getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
@@ -2896,8 +2901,11 @@
}
mGraphicBufferProducerList.insert(IInterface::asBinder(gbc).get());
- LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > MAX_LAYERS,
- "Suspected IGBP leak");
+ // TODO (b/74616334): Change this back to a fatal assert once the leak is fixed
+ ALOGE_IF(mGraphicBufferProducerList.size() > mMaxGraphicBufferProducerListSize,
+ "Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers",
+ mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize,
+ mNumLayers);
mLayersAdded = true;
mNumLayers++;
}
@@ -3879,12 +3887,12 @@
}
result.appendFormat("Display %d color modes:\n", hwcId);
- std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(hwcId);
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
for (auto&& mode : modes) {
result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode);
}
- android_color_mode_t currentMode = displayDevice->getActiveColorMode();
+ ColorMode currentMode = displayDevice->getActiveColorMode();
result.appendFormat(" Current color mode: %s (%d)\n",
decodeColorMode(currentMode).c_str(), currentMode);
}
@@ -3966,6 +3974,8 @@
*/
colorizer.bold(result);
result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
+ result.appendFormat("GraphicBufferProducers: %zu, max %zu\n",
+ mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize);
colorizer.reset(result);
LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
@@ -4410,6 +4420,8 @@
if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
+ if (CC_UNLIKELY(device == 0)) return BAD_VALUE;
+
DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
@@ -4476,7 +4488,7 @@
}
}
bool getWideColorSupport() const override { return false; }
- android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; }
+ ColorMode getActiveColorMode() const override { return ColorMode::NATIVE; }
private:
const sp<Layer> mLayer;
@@ -4650,7 +4662,7 @@
android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN;
if (renderArea.getWideColorSupport() &&
- renderArea.getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) {
+ renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) {
outputDataspace = HAL_DATASPACE_DISPLAY_P3;
}
getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 33786e8..51001e5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -394,9 +394,9 @@
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* configs);
- virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
- virtual status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
+ Vector<ColorMode>* configs);
+ virtual ColorMode getActiveColorMode(const sp<IBinder>& display);
+ virtual status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode);
virtual void setPowerMode(const sp<IBinder>& display, int mode);
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
virtual status_t clearAnimationFrameStats();
@@ -446,7 +446,7 @@
bool stateLockHeld);
// Called on the main thread in response to setActiveColorMode()
- void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
+ void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ColorMode colorMode);
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -619,7 +619,7 @@
// Given a dataSpace, returns the appropriate color_mode to use
// to display that dataSpace.
- android_color_mode pickColorMode(android_dataspace dataSpace) const;
+ ColorMode pickColorMode(android_dataspace dataSpace) const;
android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b,
bool hasHdr) const;
@@ -720,6 +720,7 @@
// Can't be unordered_set because wp<> isn't hashable
std::set<wp<IBinder>> mGraphicBufferProducerList;
+ size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved;
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index 485090c..ac147fe 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -10,6 +10,7 @@
],
shared_libs: [
+ "android.hardware.graphics.common@1.1",
"libui",
"libprotobuf-cpp-lite",
"libbase",
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 4878c14..86e2e1e 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -22,6 +22,7 @@
#include <android-base/unique_fd.h>
#include <hardware/hardware.h>
#include <sync/sync.h>
+#include <ui/GraphicsTypes.h>
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
@@ -34,6 +35,8 @@
#include "Hwc2TestClientTarget.h"
#include "Hwc2TestVirtualDisplay.h"
+using android::ColorMode;
+
void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
hwc2_display_t display, int32_t connected);
void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
@@ -865,7 +868,7 @@
}
void getColorModes(hwc2_display_t display,
- std::vector<android_color_mode_t>* outColorModes,
+ std::vector<ColorMode>* outColorModes,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_COLOR_MODES>(
@@ -892,7 +895,7 @@
}
}
- void setColorMode(hwc2_display_t display, android_color_mode_t colorMode,
+ void setColorMode(hwc2_display_t display, ColorMode colorMode,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_MODE>(
@@ -905,7 +908,7 @@
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode "
- << colorMode;
+ << static_cast<int>(colorMode);
}
}
@@ -4252,33 +4255,33 @@
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
-static const std::array<android_color_mode, 9> androidColorModes = {{
- HAL_COLOR_MODE_NATIVE,
- HAL_COLOR_MODE_STANDARD_BT601_625,
- HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED,
- HAL_COLOR_MODE_STANDARD_BT601_525,
- HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED,
- HAL_COLOR_MODE_STANDARD_BT709,
- HAL_COLOR_MODE_DCI_P3,
- HAL_COLOR_MODE_SRGB,
- HAL_COLOR_MODE_ADOBE_RGB,
+static const std::array<ColorMode, 9> androidColorModes = {{
+ ColorMode::NATIVE,
+ ColorMode::STANDARD_BT601_625,
+ ColorMode::STANDARD_BT601_625_UNADJUSTED,
+ ColorMode::STANDARD_BT601_525,
+ ColorMode::STANDARD_BT601_525_UNADJUSTED,
+ ColorMode::STANDARD_BT709,
+ ColorMode::DCI_P3,
+ ColorMode::SRGB,
+ ColorMode::ADOBE_RGB,
}};
/* TESTCASE: Tests that the HWC2 can get the color modes for a display. The
- * display must support HAL_COLOR_MODE_NATIVE */
+ * display must support ColorMode::NATIVE */
TEST_F(Hwc2Test, GET_COLOR_MODES)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
- std::vector<android_color_mode_t> colorModes;
+ std::vector<ColorMode> colorModes;
ASSERT_NO_FATAL_FAILURE(test->getColorModes(display,
&colorModes));
EXPECT_NE(std::count(colorModes.begin(), colorModes.end(),
- HAL_COLOR_MODE_NATIVE), 0) << "all displays"
- " must support HAL_COLOR_MODE_NATIVE";
+ ColorMode::NATIVE), 0) << "all displays"
+ " must support ColorMode::NATIVE";
}
));
}
@@ -4287,7 +4290,7 @@
TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display)
{
hwc2_display_t display;
- std::vector<android_color_mode_t> colorModes;
+ std::vector<ColorMode> colorModes;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
@@ -4302,7 +4305,7 @@
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
- const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE;
+ const ColorMode colorMode = ColorMode::NATIVE;
EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode));
}
@@ -4313,7 +4316,7 @@
TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display)
{
hwc2_display_t display;
- const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE;
+ const ColorMode colorMode = ColorMode::NATIVE;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
@@ -4328,8 +4331,7 @@
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
- const android_color_mode_t colorMode =
- static_cast<android_color_mode_t>(-1);
+ const ColorMode colorMode = static_cast<ColorMode>(-1);
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode,
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index fafc54e..21590df 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -165,9 +165,7 @@
EXPECT_CALL(*mComposer, getActiveConfig(DisplayDevice::DISPLAY_PRIMARY, _))
.WillOnce(DoAll(SetArgPointee<1>(0), Return(Error::NONE)));
- EXPECT_CALL(*mComposer, getColorModes(DisplayDevice::DISPLAY_PRIMARY, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>({ColorMode::NATIVE})),
- Return(Error::NONE)));
+ EXPECT_CALL(*mComposer, getColorModes(DisplayDevice::DISPLAY_PRIMARY, _)).Times(0);
EXPECT_CALL(*mComposer, getHdrCapabilities(DisplayDevice::DISPLAY_PRIMARY, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 35c6e59..a49b6dd 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -45,6 +45,12 @@
sdk_version: "24",
}
+llndk_library {
+ name: "libvulkan",
+ symbol_file: "libvulkan/libvulkan.map.txt",
+ export_include_dirs: ["include"],
+}
+
subdirs = [
"nulldrv",
"libvulkan",