diff options
author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-10-19 19:19:05 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-10-19 19:19:05 -0700 |
commit | cb1ff73e8edb9b9d105bac42abbce61390858986 (patch) | |
tree | 7464429d6fd365be523b18d05b44ceeed9bdbe12 /sdm/libs/hwc2 | |
parent | 59f05790f1d7efee8453bd82b71c8747cb0f17d7 (diff) | |
parent | 2c23e58cd29cff24886737f07153e3b4ec659797 (diff) | |
download | display-cb1ff73e8edb9b9d105bac42abbce61390858986.tar.gz |
Merge "hwc2: Parameter validation and bounds checks"
Diffstat (limited to 'sdm/libs/hwc2')
-rw-r--r-- | sdm/libs/hwc2/hwc_display.h | 2 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_layers.cpp | 11 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.cpp | 50 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.h | 4 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session_services.cpp | 17 |
5 files changed, 68 insertions, 16 deletions
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h index e90dbddd..1555b1b9 100644 --- a/sdm/libs/hwc2/hwc_display.h +++ b/sdm/libs/hwc2/hwc_display.h @@ -160,7 +160,7 @@ class HWCDisplay : public DisplayEventHandler { int GetVisibleDisplayRect(hwc_rect_t *rect); void BuildLayerStack(void); void BuildSolidFillStack(void); - HWCLayer *GetHWCLayer(hwc2_layer_t layer); + HWCLayer *GetHWCLayer(hwc2_layer_t layer_id); void ResetValidation() { validated_ = false; } uint32_t GetGeometryChanges() { return geometry_changes_; } diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp index 1881ccad..2599f18d 100644 --- a/sdm/libs/hwc2/hwc_layers.cpp +++ b/sdm/libs/hwc2/hwc_layers.cpp @@ -410,8 +410,13 @@ HWC2::Error HWCLayer::SetCursorPosition(int32_t x, int32_t y) { } HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) { - // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter + if (alpha < 0.0f || alpha > 1.0f) { + return HWC2::Error::BadParameter; + } + + // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha)); + if (layer_->plane_alpha != plane_alpha) { geometry_changes_ |= kPlaneAlpha; layer_->plane_alpha = plane_alpha; @@ -461,8 +466,10 @@ HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) { layer_transform.flip_vertical = true; break; case HWC2::Transform::None: - // do nothing break; + default: + // bad transform + return HWC2::Error::BadParameter; } if (layer_transform_ != layer_transform) { diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp index f8a0d28b..99fbc1a3 100644 --- a/sdm/libs/hwc2/hwc_session.cpp +++ b/sdm/libs/hwc2/hwc_session.cpp @@ -483,14 +483,20 @@ static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int } static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) { + if (!device || !out_support) { + return HWC2_ERROR_BAD_PARAMETER; + } + + if (display >= HWC_NUM_DISPLAY_TYPES) { + return HWC2_ERROR_BAD_DISPLAY; + } + if (display == HWC_DISPLAY_PRIMARY) { *out_support = 1; } else { - // TODO(user): Port over connect_display_ from HWC1 - // Return no error for connected displays *out_support = 0; - return HWC2_ERROR_BAD_DISPLAY; } + return HWC2_ERROR_NONE; } @@ -663,14 +669,19 @@ static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t displ int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, uint32_t z) { + if (display >= HWC_NUM_DISPLAY_TYPES) { + return HWC2_ERROR_BAD_DISPLAY; + } + SCOPE_LOCK(locker_[display]); + return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z); } int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display, buffer_handle_t buffer, int32_t releaseFence) { if (!device) { - return HWC2_ERROR_BAD_DISPLAY; + return HWC2_ERROR_BAD_PARAMETER; } if (display != HWC_DISPLAY_VIRTUAL) { @@ -689,24 +700,51 @@ int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t displa } int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) { + if (display >= HWC_NUM_DISPLAY_TYPES) { + return HWC2_ERROR_BAD_DISPLAY; + } + + // validate device and also avoid undefined behavior in cast to HWC2::PowerMode + if (!device || int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) { + return HWC2_ERROR_BAD_PARAMETER; + } + auto mode = static_cast<HWC2::PowerMode>(int_mode); + + // all displays support on/off. Check for doze modes + int support = 0; + GetDozeSupport(device, display, &support); + if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) { + return HWC2_ERROR_UNSUPPORTED; + } + SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]); return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode); } static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) { + // avoid undefined behavior in cast to HWC2::Vsync + if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) { + return HWC2_ERROR_BAD_PARAMETER; + } + auto enabled = static_cast<HWC2::Vsync>(int_enabled); return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled); } int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_types, uint32_t *out_num_requests) { - DTRACE_SCOPED(); - HWCSession *hwc_session = static_cast<HWCSession *>(device); + // out_num_types and out_num_requests will be non-NULL if (!device) { + return HWC2_ERROR_BAD_PARAMETER; + } + + if (display >= HWC_NUM_DISPLAY_TYPES) { return HWC2_ERROR_BAD_DISPLAY; } + DTRACE_SCOPED(); + HWCSession *hwc_session = static_cast<HWCSession *>(device); // TODO(user): Handle secure session, handle QDCM solid fill // Handle external_pending_connect_ in CreateVirtualDisplay auto status = HWC2::Error::BadDisplay; diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h index 36593706..df58093e 100644 --- a/sdm/libs/hwc2/hwc_session.h +++ b/sdm/libs/hwc2/hwc_session.h @@ -99,6 +99,10 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...), Args... args) { if (!device) { + return HWC2_ERROR_BAD_PARAMETER; + } + + if (display >= HWC_NUM_DISPLAY_TYPES) { return HWC2_ERROR_BAD_DISPLAY; } diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp index a5cf66a9..52eaf7ad 100644 --- a/sdm/libs/hwc2/hwc_session_services.cpp +++ b/sdm/libs/hwc2/hwc_session_services.cpp @@ -94,22 +94,25 @@ Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy, isDisplayConnected_cb _hidl_cb) { int32_t error = -EINVAL; bool connected = false; - int disp_id = MapDisplayType(dpy); - SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]); - if (disp_id >= 0) { - connected = hwc_display_[disp_id]; - error = 0; + if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) { + _hidl_cb(error, connected); + return Void(); } - _hidl_cb(error, connected); + SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]); + connected = hwc_display_[disp_id]; + error = 0; + + _hidl_cb(error, connected); return Void(); } int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) { - if (disp_id < 0) { + if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) { + DLOGE("Invalid display = %d", disp_id); return -EINVAL; } |