Commit 13ae206a authored by Roman Stratiienko's avatar Roman Stratiienko
Browse files

drm_hwcomposer: Isolate HAL frontend part 1



Start calling DrmHwcTwo.{cpp,h} - Frontend

Limit responsibility of HWC2 frontend:
1. Deliver information from/to client and convert between android/internal
   data types.
2. Use internal API to communicate with displays/compositors. Remove any
   composition logic from frontend module. (out of scope)
3. Minimize ModeList logic in frontend. (out of scope)

Define Internal Data Types:
- Internal data types should be minimalistic and suffitient to compose
using DRM API and V4L2 in the future.
- Use 'Internal' prefix instead of 'DrmHwc' to make code hacking easier.

Signed-off-by: Roman Stratiienko's avatarRoman Stratiienko <r.stratiienko@gmail.com>
parent d26d5949
Pipeline #407228 passed with stages
in 6 minutes and 43 seconds
......@@ -5,6 +5,7 @@
TIDY_FILES=(
ResourceManager.cpp
ResourceManager.h
InternalDataTypes.h
drm/DrmFbImporter.h
drm/DrmUnique.h
utils/UniqueFd.h
......
......@@ -9,6 +9,7 @@ Checks: >
-concurrency-mt-unsafe,
-cppcoreguidelines-pro-type-vararg, -hicpp-vararg,
-hicpp-signed-bitwise,
-altera*,
# Turn all the warnings from the checks above into errors.
WarningsAsErrors: "*"
......@@ -50,8 +51,10 @@ CheckOptions:
value: '^[A-Z]+(_[A-Z]+)*_$'
- key: readability-identifier-naming.MemberCase
value: lower_case
- key: readability-identifier-naming.MemberSuffix
- key: readability-identifier-naming.PrivateMemberSuffix
value: _
- key: readability-identifier-naming.PublicMemberSuffix
value: ''
- key: readability-identifier-naming.NamespaceCase
value: lower_case
- key: readability-identifier-naming.ParameterCase
......@@ -64,3 +67,10 @@ CheckOptions:
value: lower_case
- key: readability-identifier-naming.IgnoreMainLikeFunctions
value: 1
- key: readability-magic-numbers.IgnorePowersOf2IntegerValues
value: 1
- key: cppcoreguidelines-avoid-magic-numbers.IgnorePowersOf2IntegerValues
value: 1
- key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: 1
......@@ -22,7 +22,6 @@ cc_library_static {
include_dirs: [
"external/drm_hwcomposer",
"external/drm_hwcomposer/include",
],
cflags: [
......@@ -53,7 +52,6 @@ cc_defaults {
include_dirs: [
"external/drm_hwcomposer",
"external/drm_hwcomposer/include",
],
static_libs: ["libdrmhwc_utils"],
......@@ -104,7 +102,6 @@ cc_library_static {
"drm/VSyncWorker.cpp",
"utils/autolock.cpp",
"utils/hwcutils.cpp",
"backend/Backend.cpp",
"backend/BackendClient.cpp",
......
......@@ -33,6 +33,8 @@
#include "backend/BackendManager.h"
#include "bufferinfo/BufferInfoGetter.h"
#include "compositor/DrmDisplayComposition.h"
#include "drm/DrmDevice.h"
#include "drm/DrmFbImporter.h"
#include "utils/log.h"
#include "utils/properties.h"
......@@ -310,8 +312,6 @@ void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback(
HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() {
supported(__func__);
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
l.second.accept_type_change();
return HWC2::Error::None;
}
......@@ -347,11 +347,11 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetChangedCompositionTypes(
supported(__func__);
uint32_t num_changes = 0;
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
if (l.second.type_changed()) {
if (l.second.internal_layer_->force_client) {
if (layers && num_changes < *num_elements)
layers[num_changes] = l.first;
if (types && num_changes < *num_elements)
types[num_changes] = static_cast<int32_t>(l.second.validated_type());
types[num_changes] = int(HWC2::Composition::Client);
++num_changes;
}
}
......@@ -629,47 +629,39 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) {
// order the layers by z-order
bool use_client_layer = false;
uint32_t client_z_order = UINT32_MAX;
std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
std::map<uint32_t, SharedInternalLayer> z_map;
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
switch (l.second.validated_type()) {
case HWC2::Composition::Device:
z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
break;
case HWC2::Composition::Client:
// Place it at the z_order of the lowest client layer
use_client_layer = true;
client_z_order = std::min(client_z_order, l.second.z_order());
break;
default:
continue;
if (!l.second.internal_layer_->force_client) {
z_map.emplace(std::make_pair(l.second.internal_layer_->z_pos,
l.second.internal_layer_));
} else {
// Place it at the z_order of the lowest client layer
use_client_layer = true;
client_z_order = std::min(client_z_order,
l.second.internal_layer_->z_pos);
}
}
if (use_client_layer)
z_map.emplace(std::make_pair(client_z_order, &client_layer_));
z_map.emplace(std::make_pair(client_z_order, client_layer_));
if (z_map.empty())
return HWC2::Error::BadLayer;
std::vector<DrmHwcLayer> composition_layers;
std::vector<SharedInternalLayer> composition_layers;
// now that they're ordered by z, add them to the composition
for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
DrmHwcLayer layer;
l.second->PopulateDrmLayer(&layer);
int ret = layer.ImportBuffer(drm_);
if (ret) {
ALOGE("Failed to import layer, ret=%d", ret);
return HWC2::Error::NoResources;
}
composition_layers.emplace_back(std::move(layer));
for (std::pair<const uint32_t, SharedInternalLayer> &l : z_map) {
l.second->fb_id_handle = drm_->GetDrmFbImporter().GetOrCreateFbId(
l.second->buffer_info.get());
composition_layers.emplace_back(std::make_shared<InternalLayer>(*l.second));
}
auto composition = std::make_unique<DrmDisplayComposition>(crtc_,
planner_.get());
// TODO(nobody): Don't always assume geometry changed
int ret = composition->SetLayers(composition_layers.data(),
composition_layers.size(), true);
int ret = composition->SetLayers(composition_layers, true);
if (ret) {
ALOGE("Failed to set layers in the composition ret=%d", ret);
return HWC2::Error::BadLayer;
......@@ -761,11 +753,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) {
connector_->set_active_mode(*mode);
// Setup the client layer's dimensions
hwc_rect_t display_frame = {.left = 0,
.top = 0,
.right = static_cast<int>(mode->h_display()),
.bottom = static_cast<int>(mode->v_display())};
client_layer_.SetLayerDisplayFrame(display_frame);
client_layer_->LayoutChangingUpdate(&client_layer_->disp_rect.left, 0);
client_layer_->LayoutChangingUpdate(&client_layer_->disp_rect.top, 0);
client_layer_->LayoutChangingUpdate(&client_layer_->disp_rect.width,
static_cast<int>(mode->h_display()));
client_layer_->LayoutChangingUpdate(&client_layer_->disp_rect.height,
static_cast<int>(mode->v_display()));
return HWC2::Error::None;
}
......@@ -775,24 +768,30 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) {
*/
HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target,
int32_t acquire_fence,
int32_t dataspace,
int32_t /*dataspace*/,
hwc_region_t /*damage*/) {
supported(__func__);
client_layer_.set_buffer(target);
client_layer_.acquire_fence_ = UniqueFd(acquire_fence);
client_layer_.SetLayerDataspace(dataspace);
InternalBufferInfo buffer_info{};
int err = BufferInfoGetter::GetInstance()->ConvertBoInfo(target,
&buffer_info);
if (err) {
ALOGE("Can not retrieve buffer information for client layer!!!");
}
client_layer_->UpdateBufferInfo(buffer_info);
/* TODO: Do not update source_crop every call.
* It makes sense to do it once after every hotplug event. */
hwc_drm_bo bo{};
BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo);
client_layer_->buffer_info->acquire_fence = UniqueFd(acquire_fence);
hwc_frect_t source_crop = {.left = 0.0F,
.top = 0.0F,
.right = static_cast<float>(bo.width),
.bottom = static_cast<float>(bo.height)};
client_layer_.SetLayerSourceCrop(source_crop);
client_layer_->LayoutChangingUpdate(&client_layer_->src_rect.left, 0);
client_layer_->LayoutChangingUpdate(&client_layer_->src_rect.top, 0);
client_layer_->LayoutChangingUpdate(&client_layer_->src_rect.width,
int(client_layer_->buffer_info->width
<< 16));
client_layer_->LayoutChangingUpdate(&client_layer_->src_rect.height,
int(client_layer_->buffer_info->height
<< 16));
return HWC2::Error::None;
}
......@@ -888,7 +887,7 @@ DrmHwcTwo::HwcDisplay::GetOrderLayersByZPos() {
std::sort(std::begin(ordered_layers), std::end(ordered_layers),
[](const DrmHwcTwo::HwcLayer *lhs, const DrmHwcTwo::HwcLayer *rhs) {
return lhs->z_order() < rhs->z_order();
return lhs->internal_layer_->z_pos < rhs->internal_layer_->z_pos;
});
return ordered_layers;
......@@ -1045,16 +1044,28 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetColorModeWithIntent(int32_t mode,
#endif /* PLATFORM_SDK_VERSION > 27 */
HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t /*x*/,
int32_t /*y*/) {
supported(__func__);
cursor_x_ = x;
cursor_y_ = y;
// TODO(rsglobal): Not implemented, but cursor is working. Investigate why.
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBlendMode(int32_t mode) {
supported(__func__);
blending_ = static_cast<HWC2::BlendMode>(mode);
switch (static_cast<HWC2::BlendMode>(mode)) {
case HWC2::BlendMode::Coverage:
internal_layer_->LayoutChangingUpdate(&internal_layer_->blend_mode,
InternalBlendMode::kCoverage);
break;
case HWC2::BlendMode::Premultiplied:
internal_layer_->LayoutChangingUpdate(&internal_layer_->blend_mode,
InternalBlendMode::kPreMult);
break;
default:
internal_layer_->LayoutChangingUpdate(&internal_layer_->blend_mode,
InternalBlendMode::kNone);
}
return HWC2::Error::None;
}
......@@ -1065,38 +1076,111 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
int32_t acquire_fence) {
supported(__func__);
set_buffer(buffer);
acquire_fence_ = UniqueFd(acquire_fence);
InternalBufferInfo buffer_info{};
int err = BufferInfoGetter::GetInstance()->ConvertBoInfo(buffer,
&buffer_info);
if (err) {
ALOGW("Can not retrieve buffer information for native_handle!");
internal_layer_->force_client = true;
}
internal_layer_->UpdateBufferInfo(buffer_info);
internal_layer_->buffer_info->acquire_fence = UniqueFd(acquire_fence);
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t color) {
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t /*color*/) {
// TODO(nobody): Put to client composition here?
supported(__func__);
layer_color_ = color;
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerCompositionType(int32_t type) {
sf_type_ = static_cast<HWC2::Composition>(type);
internal_layer_->force_client = false;
switch (static_cast<HWC2::Composition>(type)) {
case HWC2::Composition::Device:
internal_layer_->LayoutChangingUpdate(&internal_layer_->layer_type,
InternalLayerType::kNormal);
break;
case HWC2::Composition::Cursor:
internal_layer_->LayoutChangingUpdate(&internal_layer_->layer_type,
InternalLayerType::kCursor);
break;
default:
internal_layer_->LayoutChangingUpdate(&internal_layer_->layer_type,
InternalLayerType::kUndefined);
internal_layer_->LayoutChangingUpdate(&internal_layer_->force_client,
true);
}
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDataspace(int32_t dataspace) {
supported(__func__);
dataspace_ = static_cast<android_dataspace_t>(dataspace);
switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
case HAL_DATASPACE_STANDARD_BT709:
internal_layer_->LayoutChangingUpdate(&internal_layer_->color_space,
InternalColorSpace::kItuRec709);
break;
case HAL_DATASPACE_STANDARD_BT601_625:
case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
case HAL_DATASPACE_STANDARD_BT601_525:
case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
internal_layer_->LayoutChangingUpdate(&internal_layer_->color_space,
InternalColorSpace::kItuRec601);
break;
case HAL_DATASPACE_STANDARD_BT2020:
case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
internal_layer_->LayoutChangingUpdate(&internal_layer_->color_space,
InternalColorSpace::kItuRec2020);
break;
default:
internal_layer_->LayoutChangingUpdate(&internal_layer_->color_space,
InternalColorSpace::kUndefined);
}
switch (dataspace & HAL_DATASPACE_RANGE_MASK) {
case HAL_DATASPACE_RANGE_FULL:
internal_layer_->LayoutChangingUpdate(&internal_layer_->sample_range,
InternalSampleRange::kFullRange);
break;
case HAL_DATASPACE_RANGE_LIMITED:
internal_layer_->LayoutChangingUpdate(&internal_layer_->sample_range,
InternalSampleRange::kNarrowRange);
break;
default:
internal_layer_->LayoutChangingUpdate(&internal_layer_->sample_range,
InternalSampleRange::kUndefined);
}
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
supported(__func__);
display_frame_ = frame;
internal_layer_->LayoutChangingUpdate(&internal_layer_->disp_rect.left,
frame.left);
internal_layer_->LayoutChangingUpdate(&internal_layer_->disp_rect.top,
frame.top);
internal_layer_->LayoutChangingUpdate(&internal_layer_->disp_rect.width,
frame.right - frame.left);
internal_layer_->LayoutChangingUpdate(&internal_layer_->disp_rect.height,
frame.bottom - frame.top);
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerPlaneAlpha(float alpha) {
supported(__func__);
alpha_ = alpha;
// Alpha may change layout only for from-to-opaque transitions
if (internal_layer_->alpha != alpha &&
(internal_layer_->alpha == 1.0F || alpha == 1.0F))
internal_layer_->layout_updated = true;
internal_layer_->alpha = alpha;
return HWC2::Error::None;
}
......@@ -1109,7 +1193,16 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSidebandStream(
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSourceCrop(hwc_frect_t crop) {
supported(__func__);
source_crop_ = crop;
internal_layer_->LayoutChangingUpdate(&internal_layer_->src_rect.left,
int(crop.left * 65536.0));
internal_layer_->LayoutChangingUpdate(&internal_layer_->src_rect.top,
int(crop.top * 65536.0));
internal_layer_->LayoutChangingUpdate(&internal_layer_->src_rect.width,
int((crop.right - crop.left) *
65536.0));
internal_layer_->LayoutChangingUpdate(&internal_layer_->src_rect.height,
int((crop.bottom - crop.top) *
65536.0));
return HWC2::Error::None;
}
......@@ -1120,9 +1213,28 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerTransform(int32_t transform) {
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerTransform(int32_t sf_transform) {
supported(__func__);
transform_ = static_cast<HWC2::Transform>(transform);
uint32_t transform = 0;
// 270* and 180* cannot be combined with flips. More specifically, they
// already contain both horizontal and vertical flips, so those fields are
// redundant in this case. 90* rotation can be combined with either horizontal
// flip or vertical flip, so treat it differently
if (sf_transform == HWC_TRANSFORM_ROT_270) {
transform = InternalTransform::kRotate270;
} else if (sf_transform == HWC_TRANSFORM_ROT_180) {
transform = InternalTransform::kRotate180;
} else {
if (sf_transform & HWC_TRANSFORM_FLIP_H)
transform |= InternalTransform::kFlipH;
if (sf_transform & HWC_TRANSFORM_FLIP_V)
transform |= InternalTransform::kFlipV;
if (sf_transform & HWC_TRANSFORM_ROT_90)
transform |= InternalTransform::kRotate90;
}
internal_layer_->LayoutChangingUpdate(&internal_layer_->transform, transform);
return HWC2::Error::None;
}
......@@ -1135,38 +1247,10 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerVisibleRegion(hwc_region_t visible) {
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerZOrder(uint32_t order) {
supported(__func__);
z_order_ = order;
internal_layer_->LayoutChangingUpdate(&internal_layer_->z_pos, order);
return HWC2::Error::None;
}
void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) {
supported(__func__);
switch (blending_) {
case HWC2::BlendMode::None:
layer->blending = DrmHwcBlending::kNone;
break;
case HWC2::BlendMode::Premultiplied:
layer->blending = DrmHwcBlending::kPreMult;
break;
case HWC2::BlendMode::Coverage:
layer->blending = DrmHwcBlending::kCoverage;
break;
default:
ALOGE("Unknown blending mode b=%d", blending_);
layer->blending = DrmHwcBlending::kNone;
break;
}
layer->sf_handle = buffer_;
// TODO(rsglobal): Avoid extra fd duplication
layer->acquire_fence = UniqueFd(fcntl(acquire_fence_.Get(), F_DUPFD_CLOEXEC));
layer->display_frame = display_frame_;
layer->alpha = lround(65535.0F * alpha_);
layer->source_crop = source_crop_;
layer->SetTransform(static_cast<int32_t>(transform_));
layer->dataspace = dataspace_;
}
void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
const std::lock_guard<std::mutex> lock(hotplug_callback_lock);
......
......@@ -23,11 +23,11 @@
#include <array>
#include <map>
#include "InternalDataTypes.h"
#include "ResourceManager.h"
#include "compositor/DrmDisplayCompositor.h"
#include "compositor/Planner.h"
#include "drm/VSyncWorker.h"
#include "drmhwcomposer.h"
namespace android {
......@@ -53,54 +53,11 @@ class DrmHwcTwo : public hwc2_device_t {
hotplug_callback_hook_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(hook);
}
class HwcDisplay;
class HwcLayer {
public:
HWC2::Composition sf_type() const {
return sf_type_;
}
HWC2::Composition validated_type() const {
return validated_type_;
}
void accept_type_change() {
sf_type_ = validated_type_;
}
void set_validated_type(HWC2::Composition type) {
validated_type_ = type;
}
bool type_changed() const {
return sf_type_ != validated_type_;
}
uint32_t z_order() const {
return z_order_;
}
buffer_handle_t buffer() {
return buffer_;
}
void set_buffer(buffer_handle_t buffer) {
buffer_ = buffer;
}
hwc_rect_t display_frame() {
return display_frame_;
}
void PopulateDrmLayer(DrmHwcLayer *layer);
bool RequireScalingOrPhasing() {
float src_width = source_crop_.right - source_crop_.left;
float src_height = source_crop_.bottom - source_crop_.top;
float dest_width = display_frame_.right - display_frame_.left;
float dest_height = display_frame_.bottom - display_frame_.top;
bool scaling = src_width != dest_width || src_height != dest_height;
bool phasing = (source_crop_.left - floor(source_crop_.left) != 0) ||
(source_crop_.top - floor(source_crop_.top) != 0);
return scaling || phasing;
}
friend class DrmHwcTwo::HwcDisplay;
public:
// Layer hooks
HWC2::Error SetCursorPosition(int32_t x, int32_t y);
HWC2::Error SetLayerBlendMode(int32_t mode);
......@@ -117,7 +74,12 @@ class DrmHwcTwo : public hwc2_device_t {
HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
HWC2::Error SetLayerZOrder(uint32_t order);
UniqueFd acquire_fence_;
SharedInternalLayer getInternalLayer() {
return internal_layer_;
}
private:
SharedInternalLayer internal_layer_ = std::make_shared<InternalLayer>();
/*
* Release fence is not used.
......@@ -126,24 +88,6 @@ class DrmHwcTwo : public hwc2_device_t {
* the next frame present fence is signaled.
*/
UniqueFd release_fence_;
private:
// sf_type_ stores the initial type given to us by surfaceflinger,
// validated_type_ stores the type after running ValidateDisplay
HWC2::Composition sf_type_ = HWC2::Composition::Invalid;
HWC2::Composition validated_type_ = HWC2::Composition::Invalid;
HWC2::BlendMode blending_ = HWC2::BlendMode::None;
buffer_handle_t buffer_ = NULL;
hwc_rect_t display_frame_;
float alpha_ = 1.0f;
hwc_frect_t source_crop_;
int32_t cursor_x_;
int32_t cursor_y_;
hwc_color_t layer_color_;
HWC2::Transform transform_ = HWC2::Transform::None;
uint32_t z_order_ = 0;
android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN;
};
class HwcDisplay {
......@@ -323,7 +267,7 @@ class DrmHwcTwo : public hwc2_device_t {
HWC2::DisplayType type_;
uint32_t layer_idx_ = 0;
std::map<hwc2_layer_t, HwcLayer> layers_;
HwcLayer client_layer_;
SharedInternalLayer client_layer_ = std::make_shared<InternalLayer>();
UniqueFd present_fence_;
int32_t color_mode_{};
std::array<float, MATRIX_SIZE> color_transform_matrix_{};
......
/*
* Copyright (C) 2021 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.
*/
#ifndef INTERNALDATATYPES_H_
#define INTERNALDATATYPES_H_
#include <array>
#include <cmath>
#include <cstdint>
#include <vector>
#include "utils/UniqueFd.h"
const int kBoMaxPlanes = 4;
namespace android {