Merge "CameraHardwareInterface: Reconnect preview in HAL set_buffer_count" into nyc-dev
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 6aeab98..8ab9a65 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -295,9 +295,8 @@
// If preview has been already started, register preview buffers now.
if (mHardware->previewEnabled()) {
if (window != 0) {
- native_window_set_scaling_mode(window.get(),
- NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- native_window_set_buffers_transform(window.get(), mOrientation);
+ mHardware->setPreviewScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ mHardware->setPreviewTransform(mOrientation);
result = mHardware->setPreviewWindow(window);
}
}
@@ -404,10 +403,9 @@
}
if (mPreviewWindow != 0) {
- native_window_set_scaling_mode(mPreviewWindow.get(),
- NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- native_window_set_buffers_transform(mPreviewWindow.get(),
- mOrientation);
+ mHardware->setPreviewScalingMode(
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ mHardware->setPreviewTransform(mOrientation);
}
mHardware->setPreviewWindow(mPreviewWindow);
result = mHardware->startPreview();
@@ -641,8 +639,7 @@
if (mOrientation != orientation) {
mOrientation = orientation;
if (mPreviewWindow != 0) {
- native_window_set_buffers_transform(mPreviewWindow.get(),
- mOrientation);
+ mHardware->setPreviewTransform(mOrientation);
}
}
return OK;
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 7f14cd4..0fe76e5 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -73,10 +73,18 @@
class CameraHardwareInterface : public virtual RefBase {
public:
- CameraHardwareInterface(const char *name)
+ CameraHardwareInterface(const char *name):
+ mDevice(nullptr),
+ mName(name),
+ mPreviewScalingMode(NOT_SET),
+ mPreviewTransform(NOT_SET),
+ mPreviewWidth(NOT_SET),
+ mPreviewHeight(NOT_SET),
+ mPreviewFormat(NOT_SET),
+ mPreviewUsage(0),
+ mPreviewSwapInterval(NOT_SET),
+ mPreviewCrop{NOT_SET,NOT_SET,NOT_SET,NOT_SET}
{
- mDevice = 0;
- mName = name;
}
~CameraHardwareInterface()
@@ -118,9 +126,16 @@
status_t setPreviewWindow(const sp<ANativeWindow>& buf)
{
ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
-
if (mDevice->ops->set_preview_window) {
mPreviewWindow = buf;
+ if (buf != nullptr) {
+ if (mPreviewScalingMode != NOT_SET) {
+ setPreviewScalingMode(mPreviewScalingMode);
+ }
+ if (mPreviewTransform != NOT_SET) {
+ setPreviewTransform(mPreviewTransform);
+ }
+ }
mHalPreviewWindow.user = this;
ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
&mHalPreviewWindow, mHalPreviewWindow.user);
@@ -130,6 +145,27 @@
return INVALID_OPERATION;
}
+ status_t setPreviewScalingMode(int scalingMode)
+ {
+ int rc = OK;
+ mPreviewScalingMode = scalingMode;
+ if (mPreviewWindow != nullptr) {
+ rc = native_window_set_scaling_mode(mPreviewWindow.get(),
+ scalingMode);
+ }
+ return rc;
+ }
+
+ status_t setPreviewTransform(int transform) {
+ int rc = OK;
+ mPreviewTransform = transform;
+ if (mPreviewWindow != nullptr) {
+ rc = native_window_set_buffers_transform(mPreviewWindow.get(),
+ mPreviewTransform);
+ }
+ return rc;
+ }
+
/** Set the notification and data callbacks */
void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
@@ -569,6 +605,8 @@
return __this->mPreviewWindow.get();
}
#define anw(n) __to_anw(((struct camera_preview_window *)n)->user)
+#define hwi(n) reinterpret_cast<CameraHardwareInterface *>(\
+ ((struct camera_preview_window *)n)->user)
static int __dequeue_buffer(struct preview_stream_ops* w,
buffer_handle_t** buffer, int *stride)
@@ -617,6 +655,44 @@
static int __set_buffer_count(struct preview_stream_ops* w, int count)
{
ANativeWindow *a = anw(w);
+
+ if (a != nullptr) {
+ // Workaround for b/27039775
+ // Previously, setting the buffer count would reset the buffer
+ // queue's flag that allows for all buffers to be dequeued on the
+ // producer side, instead of just the producer's declared max count,
+ // if no filled buffers have yet been queued by the producer. This
+ // reset no longer happens, but some HALs depend on this behavior,
+ // so it needs to be maintained for HAL backwards compatibility.
+ // Simulate the prior behavior by disconnecting/reconnecting to the
+ // window and setting the values again. This has the drawback of
+ // actually causing memory reallocation, which may not have happened
+ // in the past.
+ CameraHardwareInterface *hw = hwi(w);
+ native_window_api_disconnect(a, NATIVE_WINDOW_API_CAMERA);
+ native_window_api_connect(a, NATIVE_WINDOW_API_CAMERA);
+ if (hw->mPreviewScalingMode != NOT_SET) {
+ native_window_set_scaling_mode(a, hw->mPreviewScalingMode);
+ }
+ if (hw->mPreviewTransform != NOT_SET) {
+ native_window_set_buffers_transform(a, hw->mPreviewTransform);
+ }
+ if (hw->mPreviewWidth != NOT_SET) {
+ native_window_set_buffers_dimensions(a,
+ hw->mPreviewWidth, hw->mPreviewHeight);
+ native_window_set_buffers_format(a, hw->mPreviewFormat);
+ }
+ if (hw->mPreviewUsage != 0) {
+ native_window_set_usage(a, hw->mPreviewUsage);
+ }
+ if (hw->mPreviewSwapInterval != NOT_SET) {
+ a->setSwapInterval(a, hw->mPreviewSwapInterval);
+ }
+ if (hw->mPreviewCrop.left != NOT_SET) {
+ native_window_set_crop(a, &(hw->mPreviewCrop));
+ }
+ }
+
return native_window_set_buffer_count(a, count);
}
@@ -625,7 +701,10 @@
{
int rc;
ANativeWindow *a = anw(w);
-
+ CameraHardwareInterface *hw = hwi(w);
+ hw->mPreviewWidth = width;
+ hw->mPreviewHeight = height;
+ hw->mPreviewFormat = format;
rc = native_window_set_buffers_dimensions(a, width, height);
if (!rc) {
rc = native_window_set_buffers_format(a, format);
@@ -637,12 +716,12 @@
int left, int top, int right, int bottom)
{
ANativeWindow *a = anw(w);
- android_native_rect_t crop;
- crop.left = left;
- crop.top = top;
- crop.right = right;
- crop.bottom = bottom;
- return native_window_set_crop(a, &crop);
+ CameraHardwareInterface *hw = hwi(w);
+ hw->mPreviewCrop.left = left;
+ hw->mPreviewCrop.top = top;
+ hw->mPreviewCrop.right = right;
+ hw->mPreviewCrop.bottom = bottom;
+ return native_window_set_crop(a, &(hw->mPreviewCrop));
}
static int __set_timestamp(struct preview_stream_ops *w,
@@ -654,12 +733,16 @@
static int __set_usage(struct preview_stream_ops* w, int usage)
{
ANativeWindow *a = anw(w);
+ CameraHardwareInterface *hw = hwi(w);
+ hw->mPreviewUsage = usage;
return native_window_set_usage(a, usage);
}
static int __set_swap_interval(struct preview_stream_ops *w, int interval)
{
ANativeWindow *a = anw(w);
+ CameraHardwareInterface *hw = hwi(w);
+ hw->mPreviewSwapInterval = interval;
return a->setSwapInterval(a, interval);
}
@@ -701,6 +784,17 @@
data_callback mDataCb;
data_callback_timestamp mDataCbTimestamp;
void *mCbUser;
+
+ // Cached values for preview stream parameters
+ static const int NOT_SET = -1;
+ int mPreviewScalingMode;
+ int mPreviewTransform;
+ int mPreviewWidth;
+ int mPreviewHeight;
+ int mPreviewFormat;
+ int mPreviewUsage;
+ int mPreviewSwapInterval;
+ android_native_rect_t mPreviewCrop;
};
}; // namespace android