Merge "sdm: Fix topology after adding new mode"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 1727818..d64d904 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -287,6 +287,12 @@
*/
CONNECTOR_SET_ROI,
/*
+ * Op: Sets the connector to autorefresh mode.
+ * Arg: uint32_t - Connector ID
+ * uint32_t - Enable-1, Disable-0
+ */
+ CONNECTOR_SET_AUTOREFRESH,
+ /*
* Op: Set FB secure mode for Writeback connector.
* Arg: uint32_t - Connector ID
* uint32_t - FB Secure mode
diff --git a/liblight/lights.c b/liblight/lights.c
index 15db827..115b98c 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -48,6 +48,7 @@
static int g_last_backlight_mode = BRIGHTNESS_MODE_USER;
static int g_attention = 0;
static int g_brightness_max = 0;
+static bool g_has_persistence_node = false;
char const*const RED_LED_FILE
= "/sys/class/leds/red/brightness";
@@ -139,20 +140,23 @@
pthread_mutex_lock(&g_lock);
// Toggle low persistence mode state
- if ((g_last_backlight_mode != state->brightnessMode && lpEnabled) ||
- (!lpEnabled &&
- g_last_backlight_mode == BRIGHTNESS_MODE_LOW_PERSISTENCE)) {
- if ((err = write_int(PERSISTENCE_FILE, lpEnabled)) != 0) {
- ALOGE("%s: Failed to write to %s: %s\n", __FUNCTION__,
- PERSISTENCE_FILE, strerror(errno));
+ bool persistence_mode = ((g_last_backlight_mode != state->brightnessMode && lpEnabled) ||
+ (!lpEnabled &&
+ g_last_backlight_mode == BRIGHTNESS_MODE_LOW_PERSISTENCE));
+ bool cannot_handle_persistence = !g_has_persistence_node && persistence_mode;
+ if (g_has_persistence_node) {
+ if (persistence_mode) {
+ if ((err = write_int(PERSISTENCE_FILE, lpEnabled)) != 0) {
+ ALOGE("%s: Failed to write to %s: %s\n", __FUNCTION__,
+ PERSISTENCE_FILE, strerror(errno));
+ }
+ if (lpEnabled != 0) {
+ brightness = DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS;
+ }
}
- if (lpEnabled != 0) {
- brightness = DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS;
- }
+ g_last_backlight_mode = state->brightnessMode;
}
- g_last_backlight_mode = state->brightnessMode;
-
if (!err) {
if (!access(LCD_FILE, F_OK)) {
err = write_int(LCD_FILE, brightness);
@@ -162,7 +166,7 @@
}
pthread_mutex_unlock(&g_lock);
- return err;
+ return cannot_handle_persistence ? -ENOSYS : err;
}
static int
@@ -355,8 +359,10 @@
g_brightness_max = atoi(property);
set_brightness_ext_init();
set_light = set_light_backlight_ext;
- } else
+ } else {
+ g_has_persistence_node = !access(PERSISTENCE_FILE, F_OK);
set_light = set_light_backlight;
+ }
} else if (0 == strcmp(LIGHT_ID_BATTERY, name))
set_light = set_light_battery;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 65498be..96ad8a3 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -360,14 +360,24 @@
}
DisplayError HWDeviceDRM::Deinit() {
- PowerOff();
+ DisplayError err = kErrorNone;
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, 0);
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, nullptr);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+ int ret = drm_atomic_intf_->Commit(true /* synchronous */, false /* retain_planes */);
+ if (ret) {
+ DLOGE("Commit failed with error: %d", ret);
+ err = kErrorHardware;
+ }
+
delete hw_scale_;
registry_.Clear();
display_attributes_ = {};
drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_);
drm_atomic_intf_ = {};
drm_mgr_intf_->UnregisterDisplay(token_);
- return kErrorNone;
+ return err;
}
void HWDeviceDRM::InitializeConfigs() {
@@ -915,6 +925,10 @@
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_IDLE_TIMEOUT, token_.crtc_id,
hw_layer_info.set_idle_time_ms);
}
+
+ if (hw_panel_info_.mode == kModeCommand) {
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_AUTOREFRESH, token_.conn_id, autorefresh_);
+ }
}
void HWDeviceDRM::AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha) {
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 0a8b722..e0b7fc1 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -90,7 +90,7 @@
virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y);
virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
virtual DisplayError GetPanelBrightness(int *level);
- virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
+ virtual DisplayError SetAutoRefresh(bool enable) { autorefresh_ = enable; return kErrorNone; }
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
@@ -184,6 +184,7 @@
bool resolution_switch_enabled_ = false;
uint32_t vrefresh_ = 0;
bool switch_mode_ = false;
+ bool autorefresh_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 08e502e..b2075a8 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -152,13 +152,6 @@
return kErrorNone;
}
-/* overriding display state funcs to have special or NO OP implementation for TVs */
-DisplayError HWTVDRM::Deinit() {
- drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
-
- return HWDeviceDRM::Deinit();
-}
-
DisplayError HWTVDRM::PowerOff() {
DTRACE_SCOPED();
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 985499e..ff07ac2 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -41,7 +41,6 @@
protected:
virtual DisplayError Init();
- virtual DisplayError Deinit();
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
virtual DisplayError PowerOff();
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index c69e615..e1d7ba1 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -190,6 +190,7 @@
(void)hdr_reset_start_;
(void)hdr_reset_end_;
(void)reset_hdr_flag_;
+ (void)cdm_color_space_;
}
DisplayError HWHDMI::Init() {
@@ -440,8 +441,19 @@
if (error != kErrorNone) {
return error;
}
+ if (cdm_color_space_commit_) {
+#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ mdp_commit.cdm_color_space = cdm_color_space_;
+ mdp_commit.flags |= MDP_COMMIT_UPDATE_CDM_COLOR_SPACE;
+#endif
+ }
- return HWDevice::Commit(hw_layers);
+ error = HWDevice::Commit(hw_layers);
+ if (cdm_color_space_commit_)
+ cdm_color_space_commit_ = false;
+
+ return error;
}
DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
@@ -1032,6 +1044,10 @@
hdr_ctrl.hdr_stream.max_average_light_level = light_level.minPicAverageLightLevel;
hdr_ctrl.hdr_state = HDR_ENABLE;
reset_hdr_flag_ = false;
+#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
+ HWDevice::SetCSC(layer_buffer->color_metadata, &cdm_color_space_);
+ cdm_color_space_commit_ = true;
+#endif
// DP related
int32_t pixel_encoding = GetPixelEncoding(hdr_layer.input_buffer);
hdr_ctrl.hdr_stream.pixel_encoding = (pixel_encoding < 0) ? 0 : UINT32(pixel_encoding);
@@ -1063,6 +1079,10 @@
hdr_ctrl.hdr_state = HDR_RESET;
reset_hdr_flag_ = true;
hdr_reset_start_ = time(NULL);
+#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
+ cdm_color_space_ = (mdp_color_space) MDP_CSC_DEFAULT;
+ cdm_color_space_commit_ = true;
+#endif
DLOGV_IF(kTagDriverConfig, "kReset: HDR Stream: HDR_RESET");
} else if (hdr_layer_info.operation == HWHDRLayerInfo::kNoOp) {
if (reset_hdr_flag_) {
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 80d289a..183e9db 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -121,6 +121,8 @@
uint32_t frame_rate_ = 0;
time_t hdr_reset_start_ = 0, hdr_reset_end_ = 0;
bool reset_hdr_flag_ = false;
+ mdp_color_space cdm_color_space_ = {};
+ bool cdm_color_space_commit_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index 1c264aa..e41a267 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -77,6 +77,8 @@
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_SET_PRODUCER_USAGE));
LockBuffer_ = reinterpret_cast<GRALLOC1_PFN_LOCK>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_LOCK));
+ UnlockBuffer_ = reinterpret_cast<GRALLOC1_PFN_UNLOCK>(
+ gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_UNLOCK));
Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
@@ -444,4 +446,8 @@
return kErrorNone;
}
+DisplayError HWCBufferAllocator::UnmapBuffer(const private_handle_t *handle, int* release_fence) {
+ return (DisplayError)(UnlockBuffer_(gralloc_device_, handle, release_fence));
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.h b/sdm/libs/hwc2/hwc_buffer_allocator.h
index 8a73ccb..7df88a4 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.h
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.h
@@ -61,6 +61,7 @@
uint32_t *num_planes);
int SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags);
DisplayError MapBuffer(const private_handle_t *handle, int acquire_fence);
+ DisplayError UnmapBuffer(const private_handle_t *handle, int* release_fence);
private:
gralloc1_device_t *gralloc_device_ = nullptr;
@@ -74,6 +75,7 @@
GRALLOC1_PFN_SET_CONSUMER_USAGE SetConsumerUsage_ = nullptr;
GRALLOC1_PFN_SET_PRODUCER_USAGE SetProducerUsage_ = nullptr;
GRALLOC1_PFN_LOCK LockBuffer_ = nullptr;
+ GRALLOC1_PFN_UNLOCK UnlockBuffer_ = nullptr;
GRALLOC1_PFN_PERFORM Perform_ = nullptr;
};
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 03e37aa..0c305be 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -94,11 +94,12 @@
HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
android_color_mode_t *out_modes) {
auto it = color_mode_transform_map_.begin();
- for (auto i = 0; it != color_mode_transform_map_.end(); it++, i++) {
+ *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_transform_map_.size()));
+ for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
out_modes[i] = it->first;
DLOGI("Supports color mode[%d] = %d", i, it->first);
}
- *out_num_modes = UINT32(color_mode_transform_map_.size());
+
return HWC2::Error::None;
}
@@ -131,11 +132,6 @@
}
HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
- if (!matrix || (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
- hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)) {
- return HWC2::Error::BadParameter;
- }
-
DTRACE_SCOPED();
double color_matrix[kColorTransformMatrixCount] = {0};
CopyColorTransformMatrix(matrix, color_matrix);
@@ -750,23 +746,28 @@
}
HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
- if (out_modes) {
+ if (out_modes == nullptr) {
+ *out_num_modes = 1;
+ } else if (out_modes && *out_num_modes > 0) {
+ *out_num_modes = 1;
out_modes[0] = HAL_COLOR_MODE_NATIVE;
}
- *out_num_modes = 1;
return HWC2::Error::None;
}
HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+ if (out_num_configs == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
if (out_configs == nullptr) {
*out_num_configs = num_configs_;
return HWC2::Error::None;
}
- *out_num_configs = num_configs_;
-
- for (uint32_t i = 0; i < num_configs_; i++) {
+ *out_num_configs = std::min(*out_num_configs, num_configs_);
+ for (uint32_t i = 0; i < *out_num_configs; i++) {
out_configs[i] = i;
}
@@ -817,27 +818,38 @@
HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
// TODO(user): Get panel name and EDID name and populate it here
- if (out_name == nullptr) {
- *out_size = 32;
- } else {
- std::string name;
- switch (id_) {
- case HWC_DISPLAY_PRIMARY:
- name = "Primary Display";
- break;
- case HWC_DISPLAY_EXTERNAL:
- name = "External Display";
- break;
- case HWC_DISPLAY_VIRTUAL:
- name = "Virtual Display";
- break;
- default:
- name = "Unknown";
- break;
- }
- std::strncpy(out_name, name.c_str(), name.size());
- *out_size = UINT32(name.size());
+ if (out_size == nullptr) {
+ return HWC2::Error::BadParameter;
}
+
+ std::string name;
+ switch (id_) {
+ case HWC_DISPLAY_PRIMARY:
+ name = "Primary Display";
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ name = "External Display";
+ break;
+ case HWC_DISPLAY_VIRTUAL:
+ name = "Virtual Display";
+ break;
+ default:
+ name = "Unknown";
+ break;
+ }
+
+ if (out_name == nullptr) {
+ *out_size = UINT32(name.size()) + 1;
+ } else {
+ *out_size = std::min((UINT32(name.size()) + 1), *out_size);
+ if (*out_size > 0) {
+ std::strncpy(out_name, name.c_str(), *out_size);
+ out_name[*out_size - 1] = '\0';
+ } else {
+ DLOGW("Invalid size requested");
+ }
+ }
+
return HWC2::Error::None;
}
@@ -1073,15 +1085,22 @@
HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
int32_t *out_fences) {
+ if (out_num_elements == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
if (out_layers != nullptr && out_fences != nullptr) {
- int i = 0;
- for (auto hwc_layer : layer_set_) {
+ *out_num_elements = std::min(*out_num_elements, UINT32(layer_set_.size()));
+ auto it = layer_set_.begin();
+ for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
+ auto hwc_layer = *it;
out_layers[i] = hwc_layer->GetId();
out_fences[i] = hwc_layer->PopReleaseFence();
- i++;
}
+ } else {
+ *out_num_elements = UINT32(layer_set_.size());
}
- *out_num_elements = UINT32(layer_set_.size());
+
return HWC2::Error::None;
}
@@ -1092,6 +1111,10 @@
return HWC2::Error::None;
}
+ if (out_display_requests == nullptr || out_num_elements == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
// No display requests for now
// Use for sharing blit buffers and
// writing wfd buffer directly to output if there is full GPU composition
@@ -1102,14 +1125,15 @@
}
*out_display_requests = 0;
- *out_num_elements = UINT32(layer_requests_.size());
if (out_layers != nullptr && out_layer_requests != nullptr) {
- int i = 0;
- for (auto &request : layer_requests_) {
- out_layers[i] = request.first;
- out_layer_requests[i] = INT32(request.second);
- i++;
+ *out_num_elements = std::min(*out_num_elements, UINT32(layer_requests_.size()));
+ auto it = layer_requests_.begin();
+ for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
+ out_layers[i] = it->first;
+ out_layer_requests[i] = INT32(it->second);
}
+ } else {
+ *out_num_elements = UINT32(layer_requests_.size());
}
auto client_target_layer = client_target_->GetSDMLayer();
@@ -1124,6 +1148,11 @@
float *out_max_luminance,
float *out_max_average_luminance,
float *out_min_luminance) {
+ if (out_num_types == nullptr || out_max_luminance == nullptr ||
+ out_max_average_luminance == nullptr || out_min_luminance == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
DisplayConfigFixedInfo fixed_info = {};
display_intf_->GetConfig(&fixed_info);
@@ -1460,32 +1489,50 @@
auto acquire_fence_fd = layer->input_buffer.acquire_fence_fd;
if (acquire_fence_fd >= 0) {
- DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, acquire_fence_fd);
- if (error != kErrorNone) {
- continue;
+ int error = sync_wait(acquire_fence_fd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
}
}
-
DLOGI("Dump layer[%d] of %d pvt_handle %x pvt_handle->base %x", i, layer_stack_.layers.size(),
pvt_handle, pvt_handle? pvt_handle->base : 0);
- if (pvt_handle && pvt_handle->base) {
- char dump_file_name[PATH_MAX];
- size_t result = 0;
-
- snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
- dir_path, i, pvt_handle->width, pvt_handle->height,
- qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
-
- FILE *fp = fopen(dump_file_name, "w+");
- if (fp) {
- result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
- fclose(fp);
- }
-
- DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+ if (!pvt_handle) {
+ DLOGE("Buffer handle is null");
+ return;
}
+
+ if (!pvt_handle->base) {
+ DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, -1);
+ if (error != kErrorNone) {
+ DLOGE("Failed to map buffer, error = %d", error);
+ return;
+ }
+ }
+
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+ dir_path, i, pvt_handle->width, pvt_handle->height,
+ qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+ FILE *fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+ fclose(fp);
+ }
+
+ int release_fence = -1;
+ DisplayError error = buffer_allocator_->UnmapBuffer(pvt_handle, &release_fence);
+ if (error != kErrorNone) {
+ DLOGE("Failed to unmap buffer, error = %d", error);
+ return;
+ }
+
+ DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
}
}
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 719167a..e1949ba 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -133,12 +133,22 @@
}
}
}
+
+ if (layer_set_.empty()) {
+ DLOGI("Skipping Validate and Commit");
+ return status;
+ }
status = PrepareLayerStack(out_num_types, out_num_requests);
return status;
}
HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
+
+ if (!output_buffer_->buffer_id) {
+ return HWC2::Error::NoResources;
+ }
+
if (display_paused_) {
DisplayError error = display_intf_->Flush();
validated_ = false;
@@ -149,10 +159,18 @@
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
if (dump_frame_count_ && !flush_ && dump_output_layer_) {
- if (output_handle_ && output_handle_->base) {
+ if (output_handle_) {
BufferInfo buffer_info;
const private_handle_t *output_handle =
reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
+ DisplayError error = kErrorNone;
+ if (!output_handle->base) {
+ error = buffer_allocator_->MapBuffer(output_handle, -1);
+ if (error != kErrorNone) {
+ DLOGE("Failed to map output buffer, error = %d", error);
+ return HWC2::Error::BadParameter;
+ }
+ }
buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
buffer_info.buffer_config.format =
@@ -160,6 +178,13 @@
buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
layer_stack_.retire_fence_fd);
+
+ int release_fence = -1;
+ error = buffer_allocator_->UnmapBuffer(output_handle, &release_fence);
+ if (error != kErrorNone) {
+ DLOGE("Failed to unmap buffer, error = %d", error);
+ return HWC2::Error::BadParameter;
+ }
}
}
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 31e61f0..624105b 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -446,6 +446,9 @@
static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
int32_t /*android_color_mode_t*/ *int_out_modes) {
auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
+ if (out_num_modes == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
out_modes);
}
@@ -453,6 +456,10 @@
static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
hwc2_config_t config, int32_t int_attribute,
int32_t *out_value) {
+ if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
+ int_attribute > HWC2_ATTRIBUTE_DPI_Y) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
auto attribute = static_cast<HWC2::Attribute>(int_attribute);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
attribute, out_value);
@@ -510,6 +517,10 @@
}
static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
+ if (device == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
return 1;
}
@@ -528,7 +539,9 @@
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
-
+ if (out_retire_fence == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
auto status = HWC2::Error::BadDisplay;
// TODO(user): Handle virtual display/HDMI concurrency
if (hwc_session->hwc_display_[display]) {
@@ -544,10 +557,10 @@
int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer) {
- HWCSession *hwc_session = static_cast<HWCSession *>(device);
- if (!device) {
- return HWC2_ERROR_BAD_DISPLAY;
+ if (!device || pointer == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
}
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
SCOPE_LOCK(hwc_session->callbacks_lock_);
auto desc = static_cast<HWC2::Callback>(descriptor);
auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
@@ -575,6 +588,12 @@
int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
int32_t /*android_color_mode_t*/ int_mode) {
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (int_mode < HAL_COLOR_MODE_NATIVE || int_mode > HAL_COLOR_MODE_DISPLAY_P3) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
auto mode = static_cast<android_color_mode_t>(int_mode);
SCOPE_LOCK(locker_[display]);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
@@ -583,6 +602,13 @@
int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
const float *matrix,
int32_t /*android_color_transform_t*/ hint) {
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
+ hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
SCOPE_LOCK(locker_[display]);
android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
@@ -603,6 +629,9 @@
static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
int32_t int_mode) {
+ if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
auto mode = static_cast<HWC2::BlendMode>(int_mode);
return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
}
@@ -760,6 +789,7 @@
if (hwc_session->need_invalidate_) {
hwc_session->Refresh(display);
+ hwc_session->need_invalidate_ = false;
}
if (hwc_session->color_mgr_) {
@@ -1693,11 +1723,7 @@
}
} else {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
- // Do not return error if external display is not in connected status.
- // Due to virtual display concurrency, external display connection might be still pending
- // but hdmi got disconnected before pending connection could be processed.
if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
notify_hotplug = true;
}
external_pending_connect_ = false;
@@ -1705,6 +1731,7 @@
} while (0);
if (connected) {
+ // In connect case, we send hotplug after we create display
Refresh(0);
if (!hdmi_is_primary_) {
@@ -1713,13 +1740,35 @@
uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
usleep(vsync_period * 2 / 1000);
}
+ if (notify_hotplug) {
+ HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
+ HWC2::Connection::Connected);
+ }
+ } else {
+ // In disconnect case, we notify hotplug first to let the listener state update happen first
+ // Then we can destroy the underlying display object
+ if (notify_hotplug) {
+ HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
+ HWC2::Connection::Disconnected);
+ }
+ Refresh(0);
+ if (!hdmi_is_primary_) {
+ uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
+ usleep(vsync_period * 2 / 1000);
+ }
+ // Now disconnect the display
+ {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
+ // Do not return error if external display is not in connected status.
+ // Due to virtual display concurrency, external display connection might be still pending
+ // but hdmi got disconnected before pending connection could be processed.
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
+ }
+ }
}
// notify client
- if (notify_hotplug) {
- HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
- connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
- }
qservice_->onHdmiHotplug(INT(connected));