summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/Android.mk1
-rw-r--r--camera/CameraParameters.cpp2
-rw-r--r--camera/ICameraService.cpp24
-rw-r--r--camera/ICameraServiceListener.cpp27
-rw-r--r--camera/camera2/ICameraDeviceUser.cpp50
-rw-r--r--camera/camera2/OutputConfiguration.cpp79
-rw-r--r--camera/tests/ProCameraTests.cpp8
-rw-r--r--include/camera/ICameraService.h16
-rw-r--r--include/camera/ICameraServiceListener.h26
-rw-r--r--include/camera/camera2/ICameraDeviceUser.h7
-rw-r--r--include/camera/camera2/OutputConfiguration.h51
-rw-r--r--services/camera/libcameraservice/Android.mk2
-rw-r--r--services/camera/libcameraservice/CameraFlashlight.cpp875
-rw-r--r--services/camera/libcameraservice/CameraFlashlight.h225
-rw-r--r--services/camera/libcameraservice/CameraService.cpp338
-rw-r--r--services/camera/libcameraservice/CameraService.h46
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.cpp4
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.h2
-rw-r--r--services/camera/libcameraservice/api1/CameraClient.cpp4
-rw-r--r--services/camera/libcameraservice/api1/CameraClient.h2
-rw-r--r--services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp4
-rw-r--r--services/camera/libcameraservice/api1/client2/JpegProcessor.cpp3
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.cpp6
-rw-r--r--services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp8
-rw-r--r--services/camera/libcameraservice/api1/client2/ZslProcessor.cpp4
-rw-r--r--services/camera/libcameraservice/api2/CameraDeviceClient.cpp28
-rw-r--r--services/camera/libcameraservice/api2/CameraDeviceClient.h12
-rw-r--r--services/camera/libcameraservice/api_pro/ProCamera2Client.cpp3
-rw-r--r--services/camera/libcameraservice/api_pro/ProCamera2Client.h2
-rw-r--r--services/camera/libcameraservice/common/Camera2ClientBase.cpp2
-rw-r--r--services/camera/libcameraservice/common/Camera2ClientBase.h3
-rw-r--r--services/camera/libcameraservice/common/CameraDeviceBase.h16
-rw-r--r--services/camera/libcameraservice/common/CameraModule.cpp144
-rw-r--r--services/camera/libcameraservice/common/CameraModule.h65
-rw-r--r--services/camera/libcameraservice/device1/CameraHardwareInterface.h16
-rw-r--r--services/camera/libcameraservice/device2/Camera2Device.cpp10
-rw-r--r--services/camera/libcameraservice/device2/Camera2Device.h5
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp20
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h5
-rw-r--r--services/camera/libcameraservice/device3/Camera3DummyStream.cpp2
-rw-r--r--services/camera/libcameraservice/device3/Camera3DummyStream.h2
-rw-r--r--services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp5
-rw-r--r--services/camera/libcameraservice/device3/Camera3IOStreamBase.h3
-rw-r--r--services/camera/libcameraservice/device3/Camera3InputStream.cpp4
-rw-r--r--services/camera/libcameraservice/device3/Camera3OutputStream.cpp24
-rw-r--r--services/camera/libcameraservice/device3/Camera3OutputStream.h9
-rw-r--r--services/camera/libcameraservice/device3/Camera3Stream.cpp9
-rw-r--r--services/camera/libcameraservice/device3/Camera3Stream.h10
-rw-r--r--services/camera/libcameraservice/device3/Camera3ZslStream.cpp3
49 files changed, 2035 insertions, 181 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
index da5ac59..df7279f 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -35,6 +35,7 @@ LOCAL_SRC_FILES:= \
camera2/ICameraDeviceUser.cpp \
camera2/ICameraDeviceCallbacks.cpp \
camera2/CaptureRequest.cpp \
+ camera2/OutputConfiguration.cpp \
ProCamera.cpp \
CameraBase.cpp \
CameraUtils.cpp \
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index e5e4e90..3dbf75e 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -526,7 +526,7 @@ int CameraParameters::previewFormatToEnum(const char* format) {
!strcmp(format, PIXEL_FORMAT_RGBA8888) ?
HAL_PIXEL_FORMAT_RGBA_8888 : // RGB8888
!strcmp(format, PIXEL_FORMAT_BAYER_RGGB) ?
- HAL_PIXEL_FORMAT_RAW_SENSOR : // Raw sensor data
+ HAL_PIXEL_FORMAT_RAW16 : // Raw sensor data
-1;
}
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 5485205..e3f9931 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -209,6 +209,20 @@ public:
return status;
}
+ virtual status_t setTorchMode(const String16& cameraId, bool enabled,
+ const sp<IBinder>& clientBinder)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+ data.writeString16(cameraId);
+ data.writeInt32(enabled ? 1 : 0);
+ data.writeStrongBinder(clientBinder);
+ remote()->transact(BnCameraService::SET_TORCH_MODE, data, &reply);
+
+ if (readExceptionCode(reply)) return -EPROTO;
+ return reply.readInt32();
+ }
+
// connect to camera service (pro client)
virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb, int cameraId,
const String16 &clientPackageName, int clientUid,
@@ -490,6 +504,16 @@ status_t BnCameraService::onTransact(
}
return NO_ERROR;
} break;
+ case SET_TORCH_MODE: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ String16 cameraId = data.readString16();
+ bool enabled = data.readInt32() != 0 ? true : false;
+ const sp<IBinder> clientBinder = data.readStrongBinder();
+ status_t status = setTorchMode(cameraId, enabled, clientBinder);
+ reply->writeNoException();
+ reply->writeInt32(status);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
index b2f1729..90a8bc2 100644
--- a/camera/ICameraServiceListener.cpp
+++ b/camera/ICameraServiceListener.cpp
@@ -29,6 +29,7 @@ namespace android {
namespace {
enum {
STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
+ TORCH_STATUS_CHANGED,
};
}; // namespace anonymous
@@ -54,8 +55,21 @@ public:
data,
&reply,
IBinder::FLAG_ONEWAY);
+ }
- reply.readExceptionCode();
+ virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(
+ ICameraServiceListener::getInterfaceDescriptor());
+
+ data.writeInt32(static_cast<int32_t>(status));
+ data.writeString16(cameraId);
+
+ remote()->transact(TORCH_STATUS_CHANGED,
+ data,
+ &reply,
+ IBinder::FLAG_ONEWAY);
}
};
@@ -75,7 +89,16 @@ status_t BnCameraServiceListener::onTransact(
int32_t cameraId = data.readInt32();
onStatusChanged(status, cameraId);
- reply->writeNoException();
+
+ return NO_ERROR;
+ } break;
+ case TORCH_STATUS_CHANGED: {
+ CHECK_INTERFACE(ICameraServiceListener, data, reply);
+
+ TorchStatus status = static_cast<TorchStatus>(data.readInt32());
+ String16 cameraId = data.readString16();
+
+ onTorchStatusChanged(status, cameraId);
return NO_ERROR;
} break;
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index ff4a0c2..16018dc 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -26,6 +26,7 @@
#include <gui/Surface.h>
#include <camera/CameraMetadata.h>
#include <camera/camera2/CaptureRequest.h>
+#include <camera/camera2/OutputConfiguration.h>
namespace android {
@@ -107,7 +108,7 @@ public:
}
}
- if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
@@ -147,7 +148,7 @@ public:
resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
- if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
@@ -167,7 +168,7 @@ public:
status_t resFrameNumber = BAD_VALUE;
if (reply.readInt32() != 0) {
if (lastFrameNumber != NULL) {
- res = reply.readInt64(lastFrameNumber);
+ resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
@@ -208,20 +209,17 @@ public:
return reply.readInt32();
}
- virtual status_t createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer)
+ virtual status_t createStream(const OutputConfiguration& outputConfiguration)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
- data.writeInt32(width);
- data.writeInt32(height);
- data.writeInt32(format);
-
- data.writeInt32(1); // marker that bufferProducer is not null
- data.writeString16(String16("unknown_name")); // name of surface
- sp<IBinder> b(bufferProducer->asBinder());
- data.writeStrongBinder(b);
+ if (outputConfiguration.getGraphicBufferProducer() != NULL) {
+ data.writeInt32(1); // marker that OutputConfiguration is not null. Mimic aidl behavior
+ outputConfiguration.writeToParcel(data);
+ } else {
+ data.writeInt32(0);
+ }
remote()->transact(CREATE_STREAM, data, &reply);
reply.readExceptionCode();
@@ -296,7 +294,7 @@ public:
status_t resFrameNumber = BAD_VALUE;
if (reply.readInt32() != 0) {
if (lastFrameNumber != NULL) {
- res = reply.readInt64(lastFrameNumber);
+ resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
@@ -396,31 +394,15 @@ status_t BnCameraDeviceUser::onTransact(
} break;
case CREATE_STREAM: {
CHECK_INTERFACE(ICameraDeviceUser, data, reply);
- int width, height, format;
-
- width = data.readInt32();
- ALOGV("%s: CREATE_STREAM: width = %d", __FUNCTION__, width);
- height = data.readInt32();
- ALOGV("%s: CREATE_STREAM: height = %d", __FUNCTION__, height);
- format = data.readInt32();
- ALOGV("%s: CREATE_STREAM: format = %d", __FUNCTION__, format);
- sp<IGraphicBufferProducer> bp;
+ status_t ret = BAD_VALUE;
if (data.readInt32() != 0) {
- String16 name = readMaybeEmptyString16(data);
- bp = interface_cast<IGraphicBufferProducer>(
- data.readStrongBinder());
-
- ALOGV("%s: CREATE_STREAM: bp = %p, name = %s", __FUNCTION__,
- bp.get(), String8(name).string());
+ OutputConfiguration outputConfiguration(data);
+ ret = createStream(outputConfiguration);
} else {
- ALOGV("%s: CREATE_STREAM: bp = unset, name = unset",
- __FUNCTION__);
+ ALOGE("%s: cannot take an empty OutputConfiguration", __FUNCTION__);
}
- status_t ret;
- ret = createStream(width, height, format, bp);
-
reply->writeNoException();
ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
reply->writeInt32(ret);
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
new file mode 100644
index 0000000..dab6a00
--- /dev/null
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -0,0 +1,79 @@
+/*
+**
+** Copyright 2015, 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.
+*/
+
+#define LOG_TAG "OutputConfiguration"
+#include <utils/Log.h>
+
+#include <camera/camera2/OutputConfiguration.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+
+const int OutputConfiguration::INVALID_ROTATION = -1;
+
+// Read empty strings without printing a false error message.
+String16 OutputConfiguration::readMaybeEmptyString16(const Parcel& parcel) {
+ size_t len;
+ const char16_t* str = parcel.readString16Inplace(&len);
+ if (str != NULL) {
+ return String16(str, len);
+ } else {
+ return String16();
+ }
+}
+
+sp<IGraphicBufferProducer> OutputConfiguration::getGraphicBufferProducer() const {
+ return mGbp;
+}
+
+int OutputConfiguration::getRotation() const {
+ return mRotation;
+}
+
+OutputConfiguration::OutputConfiguration(const Parcel& parcel) {
+ status_t err;
+ int rotation = 0;
+ if ((err = parcel.readInt32(&rotation)) != OK) {
+ ALOGE("%s: Failed to read rotation from parcel", __FUNCTION__);
+ mGbp = NULL;
+ mRotation = INVALID_ROTATION;
+ return;
+ }
+
+ String16 name = readMaybeEmptyString16(parcel);
+ const sp<IGraphicBufferProducer>& gbp =
+ interface_cast<IGraphicBufferProducer>(parcel.readStrongBinder());
+ mGbp = gbp;
+ mRotation = rotation;
+
+ ALOGV("%s: OutputConfiguration: bp = %p, name = %s", __FUNCTION__,
+ gbp.get(), String8(name).string());
+}
+
+status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
+
+ parcel.writeInt32(mRotation);
+ parcel.writeString16(String16("unknown_name")); // name of surface
+ sp<IBinder> b(mGbp->asBinder());
+ parcel.writeStrongBinder(b);
+
+ return OK;
+}
+
+}; // namespace android
+
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index 1f5867a..24b2327 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -89,6 +89,12 @@ struct ServiceListener : public BnCameraServiceListener {
mCondition.broadcast();
}
+ void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
+ dout << "On torch status changed: 0x" << std::hex
+ << (unsigned int) status << " cameraId " << cameraId.string()
+ << std::endl;
+ }
+
status_t waitForStatusChange(Status& newStatus) {
Mutex::Autolock al(mMutex);
@@ -469,7 +475,7 @@ protected:
CMP_STR(NV16, YCbCr_422_SP);
CMP_STR(NV21, YCrCb_420_SP);
CMP_STR(YUY2, YCbCr_422_I);
- CMP_STR(RAW, RAW_SENSOR);
+ CMP_STR(RAW, RAW16);
CMP_STR(RGBA, RGBA_8888);
std::cerr << "Unknown format string " << str << std::endl;
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index f7f06bb..194a646 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -53,6 +53,7 @@ public:
GET_LEGACY_PARAMETERS,
SUPPORTS_CAMERA_API,
CONNECT_LEGACY,
+ SET_TORCH_MODE,
};
enum {
@@ -142,6 +143,21 @@ public:
int clientUid,
/*out*/
sp<ICamera>& device) = 0;
+
+ /**
+ * Turn on or off a camera's torch mode. Torch mode will be turned off by
+ * camera service if the lastest client binder that turns it on dies.
+ *
+ * return values:
+ * 0: on a successful operation.
+ * -ENOSYS: the camera device doesn't support this operation. It it returned
+ * if and only if android.flash.into.available is false.
+ * -EBUSY: the camera device is opened.
+ * -EINVAL: camera_id is invalid or clientBinder is NULL when enabling a
+ * torch mode.
+ */
+ virtual status_t setTorchMode(const String16& cameraId, bool enabled,
+ const sp<IBinder>& clientBinder) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/camera/ICameraServiceListener.h b/include/camera/ICameraServiceListener.h
index 0a0e43a..709ff31 100644
--- a/include/camera/ICameraServiceListener.h
+++ b/include/camera/ICameraServiceListener.h
@@ -66,9 +66,35 @@ public:
STATUS_UNKNOWN = 0xFFFFFFFF,
};
+ /**
+ * The torch mode status of a camera.
+ *
+ * Initial status will be transmitted with onTorchStatusChanged immediately
+ * after this listener is added to the service listener list.
+ *
+ * The enums should be set to values matching
+ * include/hardware/camera_common.h
+ */
+ enum TorchStatus {
+ // The camera's torch mode has become not available to use via
+ // setTorchMode().
+ TORCH_STATUS_NOT_AVAILABLE = TORCH_MODE_STATUS_NOT_AVAILABLE,
+ // The camera's torch mode is off and available to be turned on via
+ // setTorchMode().
+ TORCH_STATUS_AVAILABLE_OFF = TORCH_MODE_STATUS_AVAILABLE_OFF,
+ // The camera's torch mode is on and available to be turned off via
+ // setTorchMode().
+ TORCH_STATUS_AVAILABLE_ON = TORCH_MODE_STATUS_AVAILABLE_ON,
+
+ // Use to initialize variables only
+ TORCH_STATUS_UNKNOWN = 0xFFFFFFFF,
+ };
+
DECLARE_META_INTERFACE(CameraServiceListener);
virtual void onStatusChanged(Status status, int32_t cameraId) = 0;
+
+ virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
index 35488bb..e9f1f5a 100644
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ b/include/camera/camera2/ICameraDeviceUser.h
@@ -27,9 +27,9 @@ namespace android {
class ICameraDeviceUserClient;
class IGraphicBufferProducer;
-class Surface;
class CaptureRequest;
class CameraMetadata;
+class OutputConfiguration;
enum {
NO_IN_FLIGHT_REPEATING_FRAMES = -1,
@@ -100,9 +100,8 @@ public:
virtual status_t endConfigure() = 0;
virtual status_t deleteStream(int streamId) = 0;
- virtual status_t createStream(
- int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+
+ virtual status_t createStream(const OutputConfiguration& outputConfiguration) = 0;
// Create a request object from a template.
virtual status_t createDefaultRequest(int templateId,
diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h
new file mode 100644
index 0000000..e6b679f
--- /dev/null
+++ b/include/camera/camera2/OutputConfiguration.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
+#define ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
+
+#include <utils/RefBase.h>
+#include <gui/IGraphicBufferProducer.h>
+
+namespace android {
+
+class Surface;
+
+class OutputConfiguration : public virtual RefBase {
+public:
+
+ static const int INVALID_ROTATION;
+ sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
+ int getRotation() const;
+
+ /**
+ * Keep impl up-to-date with OutputConfiguration.java in frameworks/base
+ */
+ status_t writeToParcel(Parcel& parcel) const;
+ // getGraphicBufferProducer will be NULL if error occurred
+ // getRotation will be INVALID_ROTATION if error occurred
+ OutputConfiguration(const Parcel& parcel);
+
+private:
+ sp<IGraphicBufferProducer> mGbp;
+ int mRotation;
+
+ // helper function
+ static String16 readMaybeEmptyString16(const Parcel& parcel);
+};
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index e184d97..5d6423a 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -23,8 +23,10 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
CameraService.cpp \
CameraDeviceFactory.cpp \
+ CameraFlashlight.cpp \
common/Camera2ClientBase.cpp \
common/CameraDeviceBase.cpp \
+ common/CameraModule.cpp \
common/FrameProcessorBase.cpp \
api1/CameraClient.cpp \
api1/Camera2Client.cpp \
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
new file mode 100644
index 0000000..b3449e2
--- /dev/null
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -0,0 +1,875 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "CameraFlashlight"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+// #define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <cutils/properties.h>
+
+#include "camera/CameraMetadata.h"
+#include "CameraFlashlight.h"
+#include "gui/IGraphicBufferConsumer.h"
+#include "gui/BufferQueue.h"
+#include "camera/camera2/CaptureRequest.h"
+#include "CameraDeviceFactory.h"
+
+
+namespace android {
+
+/////////////////////////////////////////////////////////////////////
+// CameraFlashlight implementation begins
+// used by camera service to control flashflight.
+/////////////////////////////////////////////////////////////////////
+CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks) :
+ mCameraModule(&cameraModule),
+ mCallbacks(&callbacks),
+ mFlashlightMapInitialized(false) {
+}
+
+CameraFlashlight::~CameraFlashlight() {
+}
+
+status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
+ ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
+ cameraId.string());
+ if (mFlashControl != NULL) {
+ return INVALID_OPERATION;
+ }
+
+ status_t res = OK;
+
+ if (mCameraModule->getRawModule()->module_api_version >=
+ CAMERA_MODULE_API_VERSION_2_4) {
+ mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
+ if (mFlashControl == NULL) {
+ ALOGV("%s: cannot create flash control for module api v2.4+",
+ __FUNCTION__);
+ return NO_MEMORY;
+ }
+ } else {
+ uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
+
+ if (mCameraModule->getRawModule()->module_api_version >=
+ CAMERA_MODULE_API_VERSION_2_0) {
+ camera_info info;
+ res = mCameraModule->getCameraInfo(
+ atoi(String8(cameraId).string()), &info);
+ if (res) {
+ ALOGE("%s: failed to get camera info for camera %s",
+ __FUNCTION__, cameraId.string());
+ return res;
+ }
+ deviceVersion = info.device_version;
+ }
+
+ if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
+ CameraDeviceClientFlashControl *flashControl =
+ new CameraDeviceClientFlashControl(*mCameraModule,
+ *mCallbacks);
+ if (!flashControl) {
+ return NO_MEMORY;
+ }
+
+ mFlashControl = flashControl;
+ } else {
+ mFlashControl =
+ new CameraHardwareInterfaceFlashControl(*mCameraModule,
+ *mCallbacks);
+ }
+ }
+
+ return OK;
+}
+
+status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
+ if (!mFlashlightMapInitialized) {
+ ALOGE("%s: findFlashUnits() must be called before this method.");
+ return NO_INIT;
+ }
+
+ ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
+ cameraId.string(), enabled);
+
+ status_t res = OK;
+ Mutex::Autolock l(mLock);
+
+ if (mFlashControl == NULL) {
+ if (enabled == false) {
+ return OK;
+ }
+
+ res = createFlashlightControl(cameraId);
+ if (res) {
+ return res;
+ }
+ res = mFlashControl->setTorchMode(cameraId, enabled);
+ return res;
+ }
+
+ // if flash control already exists, turning on torch mode may fail if it's
+ // tied to another camera device for module v2.3 and below.
+ res = mFlashControl->setTorchMode(cameraId, enabled);
+ if (res == BAD_INDEX) {
+ // flash control is tied to another camera device, need to close it and
+ // try again.
+ mFlashControl.clear();
+ res = createFlashlightControl(cameraId);
+ if (res) {
+ return res;
+ }
+ res = mFlashControl->setTorchMode(cameraId, enabled);
+ }
+
+ return res;
+}
+
+status_t CameraFlashlight::findFlashUnits() {
+ Mutex::Autolock l(mLock);
+ status_t res;
+ int32_t numCameras = mCameraModule->getNumberOfCameras();
+
+ mHasFlashlightMap.clear();
+ mFlashlightMapInitialized = false;
+
+ for (int32_t i = 0; i < numCameras; i++) {
+ bool hasFlash = false;
+ String8 id = String8::format("%d", i);
+
+ res = createFlashlightControl(id);
+ if (res) {
+ ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
+ id.string());
+ } else {
+ res = mFlashControl->hasFlashUnit(id, &hasFlash);
+ if (res == -EUSERS || res == -EBUSY) {
+ ALOGE("%s: failed to check if camera %s has a flash unit. Some "
+ "camera devices may be opened", __FUNCTION__,
+ id.string());
+ return res;
+ } else if (res) {
+ ALOGE("%s: failed to check if camera %s has a flash unit. %s"
+ " (%d)", __FUNCTION__, id.string(), strerror(-res),
+ res);
+ }
+
+ mFlashControl.clear();
+ }
+ mHasFlashlightMap.add(id, hasFlash);
+ }
+
+ mFlashlightMapInitialized = true;
+ return OK;
+}
+
+bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
+ status_t res;
+
+ Mutex::Autolock l(mLock);
+ return hasFlashUnitLocked(cameraId);
+}
+
+bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
+ if (!mFlashlightMapInitialized) {
+ ALOGE("%s: findFlashUnits() must be called before this method.");
+ return false;
+ }
+
+ ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
+ if (index == NAME_NOT_FOUND) {
+ ALOGE("%s: camera %s not present when findFlashUnits() was called",
+ __FUNCTION__, cameraId.string());
+ return false;
+ }
+
+ return mHasFlashlightMap.valueAt(index);
+}
+
+status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
+ ALOGV("%s: prepare for device open", __FUNCTION__);
+
+ Mutex::Autolock l(mLock);
+ if (!mFlashlightMapInitialized) {
+ ALOGE("%s: findFlashUnits() must be called before this method.");
+ return NO_INIT;
+ }
+
+ if (mCameraModule->getRawModule()->module_api_version <
+ CAMERA_MODULE_API_VERSION_2_4) {
+ // framework is going to open a camera device, all flash light control
+ // should be closed for backward compatible support.
+ mFlashControl.clear();
+
+ if (mOpenedCameraIds.size() == 0) {
+ // notify torch unavailable for all cameras with a flash
+ int numCameras = mCameraModule->getNumberOfCameras();
+ for (int i = 0; i < numCameras; i++) {
+ if (hasFlashUnitLocked(String8::format("%d", i))) {
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ String8::format("%d", i).string(),
+ TORCH_MODE_STATUS_NOT_AVAILABLE);
+ }
+ }
+ }
+
+ // close flash control that may be opened by calling hasFlashUnitLocked.
+ mFlashControl.clear();
+ }
+
+ if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
+ mOpenedCameraIds.add(cameraId);
+ }
+
+ return OK;
+}
+
+status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
+ ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
+
+ Mutex::Autolock l(mLock);
+ if (!mFlashlightMapInitialized) {
+ ALOGE("%s: findFlashUnits() must be called before this method.");
+ return NO_INIT;
+ }
+
+ ssize_t index = mOpenedCameraIds.indexOf(cameraId);
+ if (index == NAME_NOT_FOUND) {
+ ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
+ cameraId.string());
+ } else {
+ mOpenedCameraIds.removeAt(index);
+ }
+
+ // Cannot do anything until all cameras are closed.
+ if (mOpenedCameraIds.size() != 0)
+ return OK;
+
+ if (mCameraModule->getRawModule()->module_api_version <
+ CAMERA_MODULE_API_VERSION_2_4) {
+ // notify torch available for all cameras with a flash
+ int numCameras = mCameraModule->getNumberOfCameras();
+ for (int i = 0; i < numCameras; i++) {
+ if (hasFlashUnitLocked(String8::format("%d", i))) {
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ String8::format("%d", i).string(),
+ TORCH_MODE_STATUS_AVAILABLE_OFF);
+ }
+ }
+ }
+
+ return OK;
+}
+// CameraFlashlight implementation ends
+
+
+FlashControlBase::~FlashControlBase() {
+}
+
+/////////////////////////////////////////////////////////////////////
+// ModuleFlashControl implementation begins
+// Flash control for camera module v2.4 and above.
+/////////////////////////////////////////////////////////////////////
+ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks) :
+ mCameraModule(&cameraModule) {
+}
+
+ModuleFlashControl::~ModuleFlashControl() {
+}
+
+status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
+ if (!hasFlash) {
+ return BAD_VALUE;
+ }
+
+ *hasFlash = false;
+ Mutex::Autolock l(mLock);
+
+ camera_info info;
+ status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
+ &info);
+ if (res != 0) {
+ return res;
+ }
+
+ CameraMetadata metadata;
+ metadata = info.static_camera_characteristics;
+ camera_metadata_entry flashAvailable =
+ metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
+ if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
+ *hasFlash = true;
+ }
+
+ return OK;
+}
+
+status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
+ ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
+ cameraId.string(), enabled);
+
+ Mutex::Autolock l(mLock);
+ return mCameraModule->setTorchMode(cameraId.string(), enabled);
+}
+// ModuleFlashControl implementation ends
+
+/////////////////////////////////////////////////////////////////////
+// CameraDeviceClientFlashControl implementation begins
+// Flash control for camera module <= v2.3 and camera HAL v2-v3
+/////////////////////////////////////////////////////////////////////
+CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
+ CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks) :
+ mCameraModule(&cameraModule),
+ mCallbacks(&callbacks),
+ mTorchEnabled(false),
+ mMetadata(NULL),
+ mStreaming(false) {
+}
+
+CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
+ disconnectCameraDevice();
+ if (mMetadata) {
+ delete mMetadata;
+ }
+
+ mAnw.clear();
+ mSurfaceTexture.clear();
+ mProducer.clear();
+ mConsumer.clear();
+
+ if (mTorchEnabled) {
+ if (mCallbacks) {
+ ALOGV("%s: notify the framework that torch was turned off",
+ __FUNCTION__);
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+ }
+ }
+}
+
+status_t CameraDeviceClientFlashControl::initializeSurface(
+ sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
+ status_t res;
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+
+ mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
+ true, true);
+ if (mSurfaceTexture == NULL) {
+ return NO_MEMORY;
+ }
+
+ int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ res = mSurfaceTexture->setDefaultBufferSize(width, height);
+ if (res) {
+ return res;
+ }
+ res = mSurfaceTexture->setDefaultBufferFormat(format);
+ if (res) {
+ return res;
+ }
+
+ mAnw = new Surface(mProducer, /*useAsync*/ true);
+ if (mAnw == NULL) {
+ return NO_MEMORY;
+ }
+ res = device->createStream(mAnw, width, height, format,
+ HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
+ if (res) {
+ return res;
+ }
+
+ res = device->configureStreams();
+ if (res) {
+ return res;
+ }
+
+ return res;
+}
+
+status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
+ const camera_info& info, int32_t *width, int32_t *height) {
+ if (!width || !height) {
+ return BAD_VALUE;
+ }
+
+ int32_t w = INT32_MAX;
+ int32_t h = 1;
+
+ CameraMetadata metadata;
+ metadata = info.static_camera_characteristics;
+ camera_metadata_entry streamConfigs =
+ metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ for (size_t i = 0; i < streamConfigs.count; i += 4) {
+ int32_t fmt = streamConfigs.data.i32[i];
+ if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
+ int32_t ww = streamConfigs.data.i32[i + 1];
+ int32_t hh = streamConfigs.data.i32[i + 2];
+
+ if (w * h > ww * hh) {
+ w = ww;
+ h = hh;
+ }
+ }
+ }
+
+ // if stream configuration is not found, try available processed sizes.
+ if (streamConfigs.count == 0) {
+ camera_metadata_entry availableProcessedSizes =
+ metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
+ for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
+ int32_t ww = availableProcessedSizes.data.i32[i];
+ int32_t hh = availableProcessedSizes.data.i32[i + 1];
+ if (w * h > ww * hh) {
+ w = ww;
+ h = hh;
+ }
+ }
+ }
+
+ if (w == INT32_MAX) {
+ return NAME_NOT_FOUND;
+ }
+
+ *width = w;
+ *height = h;
+
+ return OK;
+}
+
+status_t CameraDeviceClientFlashControl::connectCameraDevice(
+ const String8& cameraId) {
+ camera_info info;
+ status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
+ if (res != 0) {
+ ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
+ cameraId.string());
+ return res;
+ }
+
+ sp<CameraDeviceBase> device =
+ CameraDeviceFactory::createDevice(atoi(cameraId.string()));
+ if (device == NULL) {
+ return NO_MEMORY;
+ }
+
+ res = device->initialize(mCameraModule);
+ if (res) {
+ return res;
+ }
+
+ int32_t width, height;
+ res = getSmallestSurfaceSize(info, &width, &height);
+ if (res) {
+ return res;
+ }
+ res = initializeSurface(device, width, height);
+ if (res) {
+ return res;
+ }
+
+ mCameraId = cameraId;
+ mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
+ mDevice = device;
+
+ return OK;
+}
+
+status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
+ if (mDevice != NULL) {
+ mDevice->disconnect();
+ mDevice.clear();
+ }
+
+ return OK;
+}
+
+
+
+status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
+ bool *hasFlash) {
+ ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
+ cameraId.string());
+
+ Mutex::Autolock l(mLock);
+ return hasFlashUnitLocked(cameraId, hasFlash);
+
+}
+
+status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
+ const String8& cameraId, bool *hasFlash) {
+ if (!hasFlash) {
+ return BAD_VALUE;
+ }
+
+ camera_info info;
+ status_t res = mCameraModule->getCameraInfo(
+ atoi(cameraId.string()), &info);
+ if (res != 0) {
+ ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
+ cameraId.string());
+ return res;
+ }
+
+ CameraMetadata metadata;
+ metadata = info.static_camera_characteristics;
+ camera_metadata_entry flashAvailable =
+ metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
+ if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
+ *hasFlash = true;
+ }
+
+ return OK;
+}
+
+status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
+ status_t res;
+
+ if (mMetadata == NULL) {
+ mMetadata = new CameraMetadata();
+ if (mMetadata == NULL) {
+ return NO_MEMORY;
+ }
+ res = mDevice->createDefaultRequest(
+ CAMERA3_TEMPLATE_PREVIEW, mMetadata);
+ if (res) {
+ return res;
+ }
+ }
+
+ uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
+ mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
+ mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
+
+ uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
+ mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+
+ int32_t requestId = 0;
+ mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
+
+ if (mStreaming) {
+ res = mDevice->setStreamingRequest(*mMetadata);
+ } else {
+ res = mDevice->capture(*mMetadata);
+ }
+ return res;
+}
+
+
+
+
+status_t CameraDeviceClientFlashControl::setTorchMode(
+ const String8& cameraId, bool enabled) {
+ bool hasFlash = false;
+
+ Mutex::Autolock l(mLock);
+ status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
+
+ // pre-check
+ if (enabled) {
+ // invalid camera?
+ if (res) {
+ return -EINVAL;
+ }
+ // no flash unit?
+ if (!hasFlash) {
+ return -ENOSYS;
+ }
+ // already opened for a different device?
+ if (mDevice != NULL && cameraId != mCameraId) {
+ return BAD_INDEX;
+ }
+ } else if (mDevice == NULL || cameraId != mCameraId) {
+ // disabling the torch mode of an un-opened or different device.
+ return OK;
+ } else {
+ // disabling the torch mode of currently opened device
+ disconnectCameraDevice();
+ mTorchEnabled = false;
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+ return OK;
+ }
+
+ if (mDevice == NULL) {
+ res = connectCameraDevice(cameraId);
+ if (res) {
+ return res;
+ }
+ }
+
+ res = submitTorchEnabledRequest();
+ if (res) {
+ return res;
+ }
+
+ mTorchEnabled = true;
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
+ return OK;
+}
+// CameraDeviceClientFlashControl implementation ends
+
+
+/////////////////////////////////////////////////////////////////////
+// CameraHardwareInterfaceFlashControl implementation begins
+// Flash control for camera module <= v2.3 and camera HAL v1
+/////////////////////////////////////////////////////////////////////
+CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
+ CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks) :
+ mCameraModule(&cameraModule),
+ mCallbacks(&callbacks),
+ mTorchEnabled(false) {
+
+}
+
+CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
+ disconnectCameraDevice();
+
+ mAnw.clear();
+ mSurfaceTexture.clear();
+ mProducer.clear();
+ mConsumer.clear();
+
+ if (mTorchEnabled) {
+ if (mCallbacks) {
+ ALOGV("%s: notify the framework that torch was turned off",
+ __FUNCTION__);
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+ }
+ }
+}
+
+status_t CameraHardwareInterfaceFlashControl::setTorchMode(
+ const String8& cameraId, bool enabled) {
+ Mutex::Autolock l(mLock);
+
+ // pre-check
+ status_t res;
+ if (enabled) {
+ bool hasFlash = false;
+ res = hasFlashUnitLocked(cameraId, &hasFlash);
+ // invalid camera?
+ if (res) {
+ // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
+ // another camera device.
+ return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
+ }
+ // no flash unit?
+ if (!hasFlash) {
+ return -ENOSYS;
+ }
+ } else if (mDevice == NULL || cameraId != mCameraId) {
+ // disabling the torch mode of an un-opened or different device.
+ return OK;
+ } else {
+ // disabling the torch mode of currently opened device
+ disconnectCameraDevice();
+ mTorchEnabled = false;
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+ return OK;
+ }
+
+ res = startPreviewAndTorch();
+ if (res) {
+ return res;
+ }
+
+ mTorchEnabled = true;
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
+ return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
+ const String8& cameraId, bool *hasFlash) {
+ Mutex::Autolock l(mLock);
+ return hasFlashUnitLocked(cameraId, hasFlash);
+}
+
+status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
+ const String8& cameraId, bool *hasFlash) {
+ if (!hasFlash) {
+ return BAD_VALUE;
+ }
+
+ status_t res;
+ if (mDevice == NULL) {
+ res = connectCameraDevice(cameraId);
+ if (res) {
+ return res;
+ }
+ }
+
+ if (cameraId != mCameraId) {
+ return BAD_INDEX;
+ }
+
+ const char *flashMode =
+ mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
+ if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
+ *hasFlash = true;
+ } else {
+ *hasFlash = false;
+ }
+
+ return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
+ status_t res = OK;
+ res = mDevice->startPreview();
+ if (res) {
+ ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+
+ mParameters.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_TORCH);
+
+ return mDevice->setParameters(mParameters);
+}
+
+status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
+ int32_t *width, int32_t *height) {
+ if (!width || !height) {
+ return BAD_VALUE;
+ }
+
+ int32_t w = INT32_MAX;
+ int32_t h = 1;
+ Vector<Size> sizes;
+
+ mParameters.getSupportedPreviewSizes(sizes);
+ for (size_t i = 0; i < sizes.size(); i++) {
+ Size s = sizes[i];
+ if (w * h > s.width * s.height) {
+ w = s.width;
+ h = s.height;
+ }
+ }
+
+ if (w == INT32_MAX) {
+ return NAME_NOT_FOUND;
+ }
+
+ *width = w;
+ *height = h;
+
+ return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
+ sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
+ status_t res;
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+
+ mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
+ true, true);
+ if (mSurfaceTexture == NULL) {
+ return NO_MEMORY;
+ }
+
+ int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ res = mSurfaceTexture->setDefaultBufferSize(width, height);
+ if (res) {
+ return res;
+ }
+ res = mSurfaceTexture->setDefaultBufferFormat(format);
+ if (res) {
+ return res;
+ }
+
+ mAnw = new Surface(mProducer, /*useAsync*/ true);
+ if (mAnw == NULL) {
+ return NO_MEMORY;
+ }
+
+ res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
+ if (res) {
+ ALOGE("%s: Unable to connect to native window", __FUNCTION__);
+ return res;
+ }
+
+ return device->setPreviewWindow(mAnw);
+}
+
+status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
+ const String8& cameraId) {
+ sp<CameraHardwareInterface> device =
+ new CameraHardwareInterface(cameraId.string());
+
+ status_t res = device->initialize(mCameraModule);
+ if (res) {
+ ALOGE("%s: initializing camera %s failed", __FUNCTION__,
+ cameraId.string());
+ return res;
+ }
+
+ // need to set __get_memory in set_callbacks().
+ device->setCallbacks(NULL, NULL, NULL, NULL);
+
+ mParameters = device->getParameters();
+
+ int32_t width, height;
+ res = getSmallestSurfaceSize(&width, &height);
+ if (res) {
+ ALOGE("%s: failed to get smallest surface size for camera %s",
+ __FUNCTION__, cameraId.string());
+ return res;
+ }
+
+ res = initializePreviewWindow(device, width, height);
+ if (res) {
+ ALOGE("%s: failed to initialize preview window for camera %s",
+ __FUNCTION__, cameraId.string());
+ return res;
+ }
+
+ mCameraId = cameraId;
+ mDevice = device;
+ return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
+ if (mDevice == NULL) {
+ return OK;
+ }
+
+ mParameters.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_OFF);
+ mDevice->setParameters(mParameters);
+ mDevice->stopPreview();
+ status_t res = native_window_api_disconnect(mAnw.get(),
+ NATIVE_WINDOW_API_CAMERA);
+ if (res) {
+ ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ mDevice->setPreviewWindow(NULL);
+ mDevice->release();
+
+ return OK;
+}
+// CameraHardwareInterfaceFlashControl implementation ends
+
+}
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
new file mode 100644
index 0000000..30f01f0
--- /dev/null
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_SERVERS_CAMERA_CAMERAFLASHLIGHT_H
+#define ANDROID_SERVERS_CAMERA_CAMERAFLASHLIGHT_H
+
+#include "hardware/camera_common.h"
+#include "utils/KeyedVector.h"
+#include "utils/SortedVector.h"
+#include "gui/GLConsumer.h"
+#include "gui/Surface.h"
+#include "common/CameraDeviceBase.h"
+#include "device1/CameraHardwareInterface.h"
+
+namespace android {
+
+/**
+ * FlashControlBase is a base class for flash control. It defines the functions
+ * that a flash control for each camera module/device version should implement.
+ */
+class FlashControlBase : public virtual VirtualLightRefBase {
+ public:
+ virtual ~FlashControlBase();
+
+ // Whether a camera device has a flash unit. Calling this function may
+ // cause the torch mode to be turned off in HAL v1 devices. If
+ // previously-on torch mode is turned off,
+ // callbacks.torch_mode_status_change() should be invoked.
+ virtual status_t hasFlashUnit(const String8& cameraId,
+ bool *hasFlash) = 0;
+
+ // set the torch mode to on or off.
+ virtual status_t setTorchMode(const String8& cameraId,
+ bool enabled) = 0;
+};
+
+/**
+ * CameraFlashlight can be used by camera service to control flashflight.
+ */
+class CameraFlashlight : public virtual VirtualLightRefBase {
+ public:
+ CameraFlashlight(CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks);
+ virtual ~CameraFlashlight();
+
+ // Find all flash units. This must be called before other methods. All
+ // camera devices must be closed when it's called because HAL v1 devices
+ // need to be opened to query available flash modes.
+ status_t findFlashUnits();
+
+ // Whether a camera device has a flash unit. Before findFlashUnits() is
+ // called, this function always returns false.
+ bool hasFlashUnit(const String8& cameraId);
+
+ // set the torch mode to on or off.
+ status_t setTorchMode(const String8& cameraId, bool enabled);
+
+ // Notify CameraFlashlight that camera service is going to open a camera
+ // device. CameraFlashlight will free the resources that may cause the
+ // camera open to fail. Camera service must call this function before
+ // opening a camera device.
+ status_t prepareDeviceOpen(const String8& cameraId);
+
+ // Notify CameraFlashlight that camera service has closed a camera
+ // device. CameraFlashlight may invoke callbacks for torch mode
+ // available depending on the implementation.
+ status_t deviceClosed(const String8& cameraId);
+
+ private:
+ // create flashlight control based on camera module API and camera
+ // device API versions.
+ status_t createFlashlightControl(const String8& cameraId);
+
+ // mLock should be locked.
+ bool hasFlashUnitLocked(const String8& cameraId);
+
+ sp<FlashControlBase> mFlashControl;
+ CameraModule *mCameraModule;
+ const camera_module_callbacks_t *mCallbacks;
+ SortedVector<String8> mOpenedCameraIds;
+
+ // camera id -> if it has a flash unit
+ KeyedVector<String8, bool> mHasFlashlightMap;
+ bool mFlashlightMapInitialized;
+
+ Mutex mLock; // protect CameraFlashlight API
+};
+
+/**
+ * Flash control for camera module v2.4 and above.
+ */
+class ModuleFlashControl : public FlashControlBase {
+ public:
+ ModuleFlashControl(CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks);
+ virtual ~ModuleFlashControl();
+
+ // FlashControlBase
+ status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
+ status_t setTorchMode(const String8& cameraId, bool enabled);
+
+ private:
+ CameraModule *mCameraModule;
+
+ Mutex mLock;
+};
+
+/**
+ * Flash control for camera module <= v2.3 and camera HAL v2-v3
+ */
+class CameraDeviceClientFlashControl : public FlashControlBase {
+ public:
+ CameraDeviceClientFlashControl(CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks);
+ virtual ~CameraDeviceClientFlashControl();
+
+ // FlashControlBase
+ status_t setTorchMode(const String8& cameraId, bool enabled);
+ status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
+
+ private:
+ // connect to a camera device
+ status_t connectCameraDevice(const String8& cameraId);
+ // disconnect and free mDevice
+ status_t disconnectCameraDevice();
+
+ // initialize a surface
+ status_t initializeSurface(sp<CameraDeviceBase>& device, int32_t width,
+ int32_t height);
+
+ // submit a request to enable the torch mode
+ status_t submitTorchEnabledRequest();
+
+ // get the smallest surface size of IMPLEMENTATION_DEFINED
+ status_t getSmallestSurfaceSize(const camera_info& info, int32_t *width,
+ int32_t *height);
+
+ // protected by mLock
+ status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash);
+
+ CameraModule *mCameraModule;
+ const camera_module_callbacks_t *mCallbacks;
+ String8 mCameraId;
+ bool mTorchEnabled;
+ CameraMetadata *mMetadata;
+ // WORKAROUND: will be set to true for HAL v2 devices where
+ // setStreamingRequest() needs to be call for torch mode settings to
+ // take effect.
+ bool mStreaming;
+
+ sp<CameraDeviceBase> mDevice;
+
+ sp<IGraphicBufferProducer> mProducer;
+ sp<IGraphicBufferConsumer> mConsumer;
+ sp<GLConsumer> mSurfaceTexture;
+ sp<ANativeWindow> mAnw;
+ int32_t mStreamId;
+
+ Mutex mLock;
+};
+
+/**
+ * Flash control for camera module <= v2.3 and camera HAL v1
+ */
+class CameraHardwareInterfaceFlashControl : public FlashControlBase {
+ public:
+ CameraHardwareInterfaceFlashControl(CameraModule& cameraModule,
+ const camera_module_callbacks_t& callbacks);
+ virtual ~CameraHardwareInterfaceFlashControl();
+
+ // FlashControlBase
+ status_t setTorchMode(const String8& cameraId, bool enabled);
+ status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
+
+ private:
+ // connect to a camera device
+ status_t connectCameraDevice(const String8& cameraId);
+
+ // disconnect and free mDevice
+ status_t disconnectCameraDevice();
+
+ // initialize the preview window
+ status_t initializePreviewWindow(sp<CameraHardwareInterface> device,
+ int32_t width, int32_t height);
+
+ // start preview and enable torch
+ status_t startPreviewAndTorch();
+
+ // get the smallest surface
+ status_t getSmallestSurfaceSize(int32_t *width, int32_t *height);
+
+ // protected by mLock
+ status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash);
+
+ CameraModule *mCameraModule;
+ const camera_module_callbacks_t *mCallbacks;
+ sp<CameraHardwareInterface> mDevice;
+ String8 mCameraId;
+ CameraParameters mParameters;
+ bool mTorchEnabled;
+
+ sp<IGraphicBufferProducer> mProducer;
+ sp<IGraphicBufferConsumer> mConsumer;
+ sp<GLConsumer> mSurfaceTexture;
+ sp<ANativeWindow> mAnw;
+
+ Mutex mLock;
+};
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 76428da..5ba3a5c 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -29,6 +29,7 @@
#include <binder/MemoryHeapBase.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
+#include <cutils/multiuser.h>
#include <gui/Surface.h>
#include <hardware/hardware.h>
#include <media/AudioSystem.h>
@@ -86,6 +87,38 @@ static void camera_device_status_change(
camera_id,
new_status);
}
+
+static void torch_mode_status_change(
+ const struct camera_module_callbacks* callbacks,
+ const char* camera_id,
+ int new_status) {
+ if (!callbacks || !camera_id) {
+ ALOGE("%s invalid parameters. callbacks %p, camera_id %p", __FUNCTION__,
+ callbacks, camera_id);
+ }
+ sp<CameraService> cs = const_cast<CameraService*>(
+ static_cast<const CameraService*>(callbacks));
+
+ ICameraServiceListener::TorchStatus status;
+ switch (new_status) {
+ case TORCH_MODE_STATUS_NOT_AVAILABLE:
+ status = ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE;
+ break;
+ case TORCH_MODE_STATUS_AVAILABLE_OFF:
+ status = ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF;
+ break;
+ case TORCH_MODE_STATUS_AVAILABLE_ON:
+ status = ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON;
+ break;
+ default:
+ ALOGE("Unknown torch status %d", new_status);
+ return;
+ }
+
+ cs->onTorchStatusChanged(
+ String8(camera_id),
+ status);
+}
} // extern "C"
// ----------------------------------------------------------------------------
@@ -95,7 +128,7 @@ static void camera_device_status_change(
static CameraService *gCameraService;
CameraService::CameraService()
- :mSoundRef(0), mModule(0)
+ :mSoundRef(0), mModule(0), mFlashlight(0)
{
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
@@ -105,6 +138,8 @@ CameraService::CameraService()
}
this->camera_device_status_change = android::camera_device_status_change;
+ this->torch_mode_status_change = android::torch_mode_status_change;
+
}
void CameraService::onFirstRef()
@@ -113,31 +148,47 @@ void CameraService::onFirstRef()
BnCameraService::onFirstRef();
+ camera_module_t *rawModule;
if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
- (const hw_module_t **)&mModule) < 0) {
+ (const hw_module_t **)&rawModule) < 0) {
ALOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
else {
- ALOGI("Loaded \"%s\" camera module", mModule->common.name);
- mNumberOfCameras = mModule->get_number_of_cameras();
+ mModule = new CameraModule(rawModule);
+ const hw_module_t *common = mModule->getRawModule();
+ ALOGI("Loaded \"%s\" cameraCa module", common->name);
+ mNumberOfCameras = mModule->getNumberOfCameras();
if (mNumberOfCameras > MAX_CAMERAS) {
ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
mNumberOfCameras = MAX_CAMERAS;
}
+
+ mFlashlight = new CameraFlashlight(*mModule, *this);
+ status_t res = mFlashlight->findFlashUnits();
+ if (res) {
+ // impossible because we haven't open any camera devices.
+ ALOGE("failed to find flash units.");
+ }
+
for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
+
+ String8 cameraName = String8::format("%d", i);
+ if (mFlashlight->hasFlashUnit(cameraName)) {
+ mTorchStatusMap.add(cameraName,
+ ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
+ }
}
- if (mModule->common.module_api_version >=
- CAMERA_MODULE_API_VERSION_2_1) {
- mModule->set_callbacks(this);
+ if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_1) {
+ mModule->setCallbacks(this);
}
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
- if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
+ if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
setUpVendorTags();
}
@@ -152,6 +203,9 @@ CameraService::~CameraService() {
}
}
+ if (mModule) {
+ delete mModule;
+ }
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
gCameraService = NULL;
}
@@ -159,7 +213,7 @@ CameraService::~CameraService() {
void CameraService::onDeviceStatusChanged(int cameraId,
int newStatus)
{
- ALOGI("%s: Status changed for cameraId=%d, newStatus=%d", __FUNCTION__,
+ ALOGV("%s: Status changed for cameraId=%d, newStatus=%d", __FUNCTION__,
cameraId, newStatus);
if (cameraId < 0 || cameraId >= MAX_CAMERAS) {
@@ -220,6 +274,43 @@ void CameraService::onDeviceStatusChanged(int cameraId,
}
+void CameraService::onTorchStatusChanged(const String8& cameraId,
+ ICameraServiceListener::TorchStatus newStatus) {
+ Mutex::Autolock al(mTorchStatusMutex);
+ onTorchStatusChangedLocked(cameraId, newStatus);
+}
+
+void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
+ ICameraServiceListener::TorchStatus newStatus) {
+ ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
+ __FUNCTION__, cameraId.string(), newStatus);
+
+ ICameraServiceListener::TorchStatus status;
+ status_t res = getTorchStatusLocked(cameraId, &status);
+ if (res) {
+ ALOGE("%s: cannot get torch status of camera %s", cameraId.string());
+ return;
+ }
+ if (status == newStatus) {
+ ALOGE("%s: Torch state transition to the same status 0x%x not allowed",
+ __FUNCTION__, (uint32_t)newStatus);
+ return;
+ }
+
+ res = setTorchStatusLocked(cameraId, newStatus);
+ if (res) {
+ ALOGE("%s: Failed to set the torch status", __FUNCTION__,
+ (uint32_t)newStatus);
+ return;
+ }
+
+ Vector<sp<ICameraServiceListener> >::const_iterator it;
+ for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
+ (*it)->onTorchStatusChanged(newStatus, String16(cameraId.string()));
+ }
+}
+
+
int32_t CameraService::getNumberOfCameras() {
return mNumberOfCameras;
}
@@ -236,7 +327,7 @@ status_t CameraService::getCameraInfo(int cameraId,
struct camera_info info;
status_t rc = filterGetInfoErrorCode(
- mModule->get_camera_info(cameraId, &info));
+ mModule->getCameraInfo(cameraId, &info));
cameraInfo->facing = info.facing;
cameraInfo->orientation = info.orientation;
return rc;
@@ -347,7 +438,7 @@ status_t CameraService::getCameraCharacteristics(int cameraId,
int facing;
status_t ret = OK;
- if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
+ if (mModule->getRawModule()->module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1 ) {
/**
* Backwards compatibility mode for old HALs:
@@ -368,7 +459,7 @@ status_t CameraService::getCameraCharacteristics(int cameraId,
* Normal HAL 2.1+ codepath.
*/
struct camera_info info;
- ret = filterGetInfoErrorCode(mModule->get_camera_info(cameraId, &info));
+ ret = filterGetInfoErrorCode(mModule->getCameraInfo(cameraId, &info));
*cameraInfo = info.static_camera_characteristics;
}
@@ -387,12 +478,12 @@ status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescript
int CameraService::getDeviceVersion(int cameraId, int* facing) {
struct camera_info info;
- if (mModule->get_camera_info(cameraId, &info) != OK) {
+ if (mModule->getCameraInfo(cameraId, &info) != OK) {
return -1;
}
int deviceVersion;
- if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
+ if (mModule->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
deviceVersion = info.device_version;
} else {
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
@@ -405,19 +496,6 @@ int CameraService::getDeviceVersion(int cameraId, int* facing) {
return deviceVersion;
}
-status_t CameraService::filterOpenErrorCode(status_t err) {
- switch(err) {
- case NO_ERROR:
- case -EBUSY:
- case -EINVAL:
- case -EUSERS:
- return err;
- default:
- break;
- }
- return -ENODEV;
-}
-
status_t CameraService::filterGetInfoErrorCode(status_t err) {
switch(err) {
case NO_ERROR:
@@ -433,13 +511,13 @@ bool CameraService::setUpVendorTags() {
vendor_tag_ops_t vOps = vendor_tag_ops_t();
// Check if vendor operations have been implemented
- if (mModule->get_vendor_tag_ops == NULL) {
+ if (!mModule->isVendorTagDefined()) {
ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__);
return false;
}
ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops");
- mModule->get_vendor_tag_ops(&vOps);
+ mModule->getVendorTagOps(&vOps);
ATRACE_END();
// Ensure all vendor operations are present
@@ -592,7 +670,10 @@ status_t CameraService::validateConnect(int cameraId,
}
char value[PROPERTY_VALUE_MAX];
- property_get("sys.secpolicy.camera.disabled", value, "0");
+ char key[PROPERTY_KEY_MAX];
+ int clientUserId = multiuser_get_user_id(clientUid);
+ snprintf(key, PROPERTY_KEY_MAX, "sys.secpolicy.camera.off_%d", clientUserId);
+ property_get(key, value, "0");
if (strcmp(value, "1") == 0) {
// Camera is disabled by DevicePolicyManager.
ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
@@ -671,6 +752,9 @@ status_t CameraService::connectHelperLocked(
int halVersion,
bool legacyMode) {
+ // give flashlight a chance to close devices if necessary.
+ mFlashlight->prepareDeviceOpen(String8::format("%d", cameraId));
+
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
@@ -789,8 +873,9 @@ status_t CameraService::connectLegacy(
/*out*/
sp<ICamera>& device) {
+ int apiVersion = mModule->getRawModule()->module_api_version;
if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
- mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_3) {
+ apiVersion < CAMERA_MODULE_API_VERSION_2_3) {
/*
* Either the HAL version is unspecified in which case this just creates
* a camera client selected by the latest device version, or
@@ -798,7 +883,7 @@ status_t CameraService::connectLegacy(
* the open_legacy call
*/
ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
- __FUNCTION__, mModule->common.module_api_version);
+ __FUNCTION__, apiVersion);
return INVALID_OPERATION;
}
@@ -846,6 +931,97 @@ status_t CameraService::connectLegacy(
return OK;
}
+bool CameraService::validCameraIdForSetTorchMode(const String8& cameraId) {
+ // invalid string for int
+ if (cameraId.string() == NULL) {
+ return false;
+ }
+ errno = 0;
+ char *endptr;
+ long id = strtol(cameraId.string(), &endptr, 10); // base 10
+ if (errno || id > INT_MAX || id < INT_MIN || *endptr != 0) {
+ return false;
+ }
+
+ // id matches one of the plugged-in devices?
+ ICameraServiceListener::Status deviceStatus = getStatus(id);
+ if (deviceStatus != ICameraServiceListener::STATUS_PRESENT &&
+ deviceStatus != ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+ return false;
+ }
+
+ return true;
+}
+
+status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
+ const sp<IBinder>& clientBinder) {
+ if (enabled && clientBinder == NULL) {
+ ALOGE("%s: torch client binder is NULL", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ String8 id = String8(cameraId.string());
+
+ // verify id is valid.
+ if (validCameraIdForSetTorchMode(id) == false) {
+ ALOGE("%s: camera id is invalid %s", id.string());
+ return -EINVAL;
+ }
+
+ {
+ Mutex::Autolock al(mTorchStatusMutex);
+ ICameraServiceListener::TorchStatus status;
+ status_t res = getTorchStatusLocked(id, &status);
+ if (res) {
+ ALOGE("%s: getting current torch status failed for camera %s",
+ __FUNCTION__, id.string());
+ return -EINVAL;
+ }
+
+ if (status == ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE) {
+ if (getStatus(atoi(id.string())) ==
+ ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+ ALOGE("%s: torch mode of camera %s is not available because "
+ "camera is in use", __FUNCTION__, id.string());
+ return -EBUSY;
+ } else {
+ ALOGE("%s: torch mode of camera %s is not available due to "
+ "insufficient resources", __FUNCTION__, id.string());
+ return -EUSERS;
+ }
+ }
+ }
+
+ status_t res = mFlashlight->setTorchMode(id, enabled);
+ if (res) {
+ ALOGE("%s: setting torch mode of camera %s to %d failed. %s (%d)",
+ __FUNCTION__, id.string(), enabled, strerror(-res), res);
+ return res;
+ }
+
+ {
+ // update the link to client's death
+ Mutex::Autolock al(mTorchClientMapMutex);
+ ssize_t index = mTorchClientMap.indexOfKey(id);
+ if (enabled) {
+ if (index == NAME_NOT_FOUND) {
+ mTorchClientMap.add(id, clientBinder);
+ } else {
+ const sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
+ oldBinder->unlinkToDeath(this);
+
+ mTorchClientMap.replaceValueAt(index, clientBinder);
+ }
+ clientBinder->linkToDeath(this);
+ } else if (index != NAME_NOT_FOUND) {
+ sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
+ oldBinder->unlinkToDeath(this);
+ }
+ }
+
+ return OK;
+}
+
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
const sp<IBinder>& remoteCallback) {
status_t status = client->initialize(mModule);
@@ -971,6 +1147,9 @@ status_t CameraService::connectDevice(
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
+ // give flashlight a chance to close devices if necessary.
+ mFlashlight->prepareDeviceOpen(String8::format("%d", cameraId));
+
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
ALOGW("Camera using old HAL version: %d", deviceVersion);
@@ -1042,6 +1221,16 @@ status_t CameraService::addListener(
}
}
+ /* Immediately signal current torch status to this listener only */
+ {
+ Mutex::Autolock al(mTorchStatusMutex);
+ for (size_t i = 0; i < mTorchStatusMap.size(); i++ ) {
+ String16 id = String16(mTorchStatusMap.keyAt(i).string());
+ listener->onTorchStatusChanged(mTorchStatusMap.valueAt(i), id);
+ }
+
+ }
+
return OK;
}
status_t CameraService::removeListener(
@@ -1475,6 +1664,9 @@ status_t CameraService::BasicClient::finishCameraOps() {
mCameraId,
&rejectSourceStates);
+ // Notify flashlight that a camera device is closed.
+ mCameraService->mFlashlight->deviceClosed(
+ String8::format("%d", mCameraId));
}
// Always stop watching, even if no camera op is active
mAppOpsManager.stopWatchingMode(mOpsCallback);
@@ -1630,14 +1822,11 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
return NO_ERROR;
}
- result = String8::format("Camera module HAL API version: 0x%x\n",
- mModule->common.hal_api_version);
- result.appendFormat("Camera module API version: 0x%x\n",
- mModule->common.module_api_version);
- result.appendFormat("Camera module name: %s\n",
- mModule->common.name);
- result.appendFormat("Camera module author: %s\n",
- mModule->common.author);
+ const hw_module_t* common = mModule->getRawModule();
+ result = String8::format("Camera module HAL API version: 0x%x\n", common->hal_api_version);
+ result.appendFormat("Camera module API version: 0x%x\n", common->module_api_version);
+ result.appendFormat("Camera module name: %s\n", common->name);
+ result.appendFormat("Camera module author: %s\n", common->author);
result.appendFormat("Number of camera devices: %d\n\n", mNumberOfCameras);
sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
@@ -1657,7 +1846,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
result = String8::format("Camera %d static information:\n", i);
camera_info info;
- status_t rc = mModule->get_camera_info(i, &info);
+ status_t rc = mModule->getCameraInfo(i, &info);
if (rc != OK) {
result.appendFormat(" Error reading static information!\n");
write(fd, result.string(), result.size());
@@ -1666,8 +1855,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
result.appendFormat(" Orientation: %d\n", info.orientation);
int deviceVersion;
- if (mModule->common.module_api_version <
- CAMERA_MODULE_API_VERSION_2_0) {
+ if (common->module_api_version < CAMERA_MODULE_API_VERSION_2_0) {
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
} else {
deviceVersion = info.device_version;
@@ -1722,6 +1910,24 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
return NO_ERROR;
}
+void CameraService::handleTorchClientBinderDied(const wp<IBinder> &who) {
+ Mutex::Autolock al(mTorchClientMapMutex);
+ for (size_t i = 0; i < mTorchClientMap.size(); i++) {
+ if (mTorchClientMap[i] == who) {
+ // turn off the torch mode that was turned on by dead client
+ String8 cameraId = mTorchClientMap.keyAt(i);
+ status_t res = mFlashlight->setTorchMode(cameraId, false);
+ if (res) {
+ ALOGE("%s: torch client died but couldn't turn off torch: "
+ "%s (%d)", __FUNCTION__, strerror(-res), res);
+ return;
+ }
+ mTorchClientMap.removeItemsAt(i);
+ break;
+ }
+ }
+}
+
/*virtual*/void CameraService::binderDied(
const wp<IBinder> &who) {
@@ -1732,6 +1938,10 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
ALOGV("java clients' binder died");
+ // check torch client
+ handleTorchClientBinderDied(who);
+
+ // check camera device client
sp<BasicClient> cameraClient = getClientByRemote(who);
if (cameraClient == 0) {
@@ -1808,6 +2018,19 @@ void CameraService::updateStatus(ICameraServiceListener::Status status,
}
}
+ if (status == ICameraServiceListener::STATUS_NOT_PRESENT ||
+ status == ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+ // update torch status to not available when the camera device
+ // becomes not present or not available.
+ onTorchStatusChanged(String8::format("%d", cameraId),
+ ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE);
+ } else if (status == ICameraServiceListener::STATUS_PRESENT) {
+ // update torch status to available when the camera device becomes
+ // present or available
+ onTorchStatusChanged(String8::format("%d", cameraId),
+ ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
+ }
+
Vector<sp<ICameraServiceListener> >::const_iterator it;
for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
(*it)->onStatusChanged(status, cameraId);
@@ -1825,4 +2048,33 @@ ICameraServiceListener::Status CameraService::getStatus(int cameraId) const {
return mStatusList[cameraId];
}
+status_t CameraService::getTorchStatusLocked(
+ const String8& cameraId,
+ ICameraServiceListener::TorchStatus *status) const {
+ if (!status) {
+ return BAD_VALUE;
+ }
+ ssize_t index = mTorchStatusMap.indexOfKey(cameraId);
+ if (index == NAME_NOT_FOUND) {
+ // invalid camera ID or the camera doesn't have a flash unit
+ return NAME_NOT_FOUND;
+ }
+
+ *status = mTorchStatusMap.valueAt(index);
+ return OK;
+}
+
+status_t CameraService::setTorchStatusLocked(const String8& cameraId,
+ ICameraServiceListener::TorchStatus status) {
+ ssize_t index = mTorchStatusMap.indexOfKey(cameraId);
+ if (index == NAME_NOT_FOUND) {
+ return BAD_VALUE;
+ }
+ ICameraServiceListener::TorchStatus& item =
+ mTorchStatusMap.editValueAt(index);
+ item = status;
+
+ return OK;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index a7328cf..5e2817d 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -36,6 +36,10 @@
#include <camera/CameraParameters.h>
#include <camera/ICameraServiceListener.h>
+#include "CameraFlashlight.h"
+
+
+#include "common/CameraModule.h"
/* This needs to be increased if we can have more cameras */
#define MAX_CAMERAS 2
@@ -68,6 +72,9 @@ public:
// HAL Callbacks
virtual void onDeviceStatusChanged(int cameraId,
int newStatus);
+ virtual void onTorchStatusChanged(const String8& cameraId,
+ ICameraServiceListener::TorchStatus
+ newStatus);
/////////////////////////////////////////////////////////////////////
// ICameraService
@@ -110,6 +117,9 @@ public:
/*out*/
String16* parameters);
+ virtual status_t setTorchMode(const String16& cameraId, bool enabled,
+ const sp<IBinder>& clientBinder);
+
// OK = supports api of that version, -EOPNOTSUPP = does not support
virtual status_t supportsCameraApi(
int cameraId, int apiVersion);
@@ -140,7 +150,6 @@ public:
/////////////////////////////////////////////////////////////////////
// Shared utilities
- static status_t filterOpenErrorCode(status_t err);
static status_t filterGetInfoErrorCode(status_t err);
/////////////////////////////////////////////////////////////////////
@@ -153,7 +162,7 @@ public:
class BasicClient : public virtual RefBase {
public:
- virtual status_t initialize(camera_module_t *module) = 0;
+ virtual status_t initialize(CameraModule *module) = 0;
virtual void disconnect();
// because we can't virtually inherit IInterface, which breaks
@@ -385,7 +394,7 @@ private:
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
int mSoundRef; // reference count (release all MediaPlayer when 0)
- camera_module_t *mModule;
+ CameraModule* mModule;
Vector<sp<ICameraServiceListener> >
mListenerList;
@@ -406,6 +415,37 @@ private:
int32_t cameraId,
const StatusVector *rejectSourceStates = NULL);
+ // flashlight control
+ sp<CameraFlashlight> mFlashlight;
+ // guard mTorchStatusMap
+ Mutex mTorchStatusMutex;
+ // guard mTorchClientMap
+ Mutex mTorchClientMapMutex;
+ // camera id -> torch status
+ KeyedVector<String8, ICameraServiceListener::TorchStatus> mTorchStatusMap;
+ // camera id -> torch client binder
+ // only store the last client that turns on each camera's torch mode
+ KeyedVector<String8, sp<IBinder> > mTorchClientMap;
+
+ // check and handle if torch client's process has died
+ void handleTorchClientBinderDied(const wp<IBinder> &who);
+
+ // handle torch mode status change and invoke callbacks. mTorchStatusMutex
+ // should be locked.
+ void onTorchStatusChangedLocked(const String8& cameraId,
+ ICameraServiceListener::TorchStatus newStatus);
+
+ // validate the camera id for use of setting a torch mode.
+ bool validCameraIdForSetTorchMode(const String8& cameraId);
+
+ // get a camera's torch status. mTorchStatusMutex should be locked.
+ status_t getTorchStatusLocked(const String8 &cameraId,
+ ICameraServiceListener::TorchStatus *status) const;
+
+ // set a camera's torch status. mTorchStatusMutex should be locked.
+ status_t setTorchStatusLocked(const String8 &cameraId,
+ ICameraServiceListener::TorchStatus status);
+
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder> &who);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index dcab4ad..5c631b1 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -67,7 +67,7 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
mLegacyMode = legacyMode;
}
-status_t Camera2Client::initialize(camera_module_t *module)
+status_t Camera2Client::initialize(CameraModule *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
@@ -1958,7 +1958,7 @@ size_t Camera2Client::calculateBufferSize(int width, int height,
return width * height * 2;
case HAL_PIXEL_FORMAT_RGBA_8888:
return width * height * 4;
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
return width * height * 2;
default:
ALOGE("%s: Unknown preview format: %x",
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index d68bb29..5a8241f 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -94,7 +94,7 @@ public:
virtual ~Camera2Client();
- status_t initialize(camera_module_t *module);
+ status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 1a4d9a6..5bdce9b 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -59,7 +59,7 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService,
LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}
-status_t CameraClient::initialize(camera_module_t *module) {
+status_t CameraClient::initialize(CameraModule *module) {
int callingPid = getCallingPid();
status_t res;
@@ -75,7 +75,7 @@ status_t CameraClient::initialize(camera_module_t *module) {
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
mHardware = new CameraHardwareInterface(camera_device_name);
- res = mHardware->initialize(&module->common);
+ res = mHardware->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 63a9d0f..95616b2 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -68,7 +68,7 @@ public:
bool legacyMode = false);
~CameraClient();
- status_t initialize(camera_module_t *module);
+ status_t initialize(CameraModule *module);
status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index eadaa00..5c8f750 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -154,8 +154,8 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
params.previewWidth, params.previewHeight,
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
- params.previewWidth, params.previewHeight,
- callbackFormat, &mCallbackStreamId);
+ params.previewWidth, params.previewHeight, callbackFormat,
+ HAL_DATASPACE_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index 2772267..34798bf 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -145,7 +145,8 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
// Create stream for HAL production
res = device->createStream(mCaptureWindow,
params.pictureWidth, params.pictureHeight,
- HAL_PIXEL_FORMAT_BLOB, &mCaptureStreamId);
+ HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_JFIF,
+ CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 4f4cfb0..87e0132 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -182,9 +182,9 @@ status_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) {
supportedPreviewFormats +=
CameraParameters::PIXEL_FORMAT_YUV420SP;
break;
- // Not advertizing JPEG, RAW_SENSOR, etc, for preview formats
+ // Not advertizing JPEG, RAW16, etc, for preview formats
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_BLOB:
addComma = false;
break;
@@ -2253,7 +2253,7 @@ const char* Parameters::formatEnumToString(int format) {
case HAL_PIXEL_FORMAT_RGBA_8888: // RGBA8888
fmt = CameraParameters::PIXEL_FORMAT_RGBA8888;
break;
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
ALOGW("Raw sensor preview format requested.");
fmt = CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
break;
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 470624b..423659c 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -181,7 +181,8 @@ status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
if (mPreviewStreamId == NO_STREAM) {
res = device->createStream(mPreviewWindow,
params.previewWidth, params.previewHeight,
- CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);
+ CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
+ CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
@@ -420,9 +421,12 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
if (mRecordingStreamId == NO_STREAM) {
mRecordingFrameCount = 0;
+ // Selecting BT.709 colorspace by default
+ // TODO: Wire this in from encoder side
res = device->createStream(mRecordingWindow,
params.videoWidth, params.videoHeight,
- CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mRecordingStreamId);
+ CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_BT709,
+ CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for recording: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 8b7e4b4..2e41db5 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -185,8 +185,8 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
(int)CAMERA2_HAL_PIXEL_FORMAT_ZSL :
(int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
res = device->createStream(mZslWindow,
- params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
- streamType, &mZslStreamId);
+ params.fastInfo.arrayWidth, params.fastInfo.arrayHeight, streamType,
+ HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e6865bb..d25344e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -65,7 +65,7 @@ CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
ALOGI("CameraDeviceClient %d: Opened", cameraId);
}
-status_t CameraDeviceClient::initialize(camera_module_t *module)
+status_t CameraDeviceClient::initialize(CameraModule *module)
{
ATRACE_CALL();
status_t res;
@@ -308,17 +308,17 @@ status_t CameraDeviceClient::deleteStream(int streamId) {
return res;
}
-status_t CameraDeviceClient::createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer)
+status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfiguration)
{
ATRACE_CALL();
- ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
Mutex::Autolock icl(mBinderSerializationLock);
+
+ sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
if (bufferProducer == NULL) {
ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
return BAD_VALUE;
@@ -368,7 +368,8 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
anw = new Surface(bufferProducer, useAsync);
}
- // TODO: remove w,h,f since we are ignoring them
+ int width, height, format;
+ android_dataspace dataSpace;
if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
@@ -385,6 +386,12 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
mCameraId);
return res;
}
+ if ((res = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
+ reinterpret_cast<int*>(&dataSpace))) != OK) {
+ ALOGE("%s: Camera %d: Failed to query Surface dataSpace", __FUNCTION__,
+ mCameraId);
+ return res;
+ }
// FIXME: remove this override since the default format should be
// IMPLEMENTATION_DEFINED. b/9487482
@@ -397,14 +404,17 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
// Round dimensions to the nearest dimensions available for this format
if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
- format, mDevice->info(), /*out*/&width, /*out*/&height)) {
+ format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
__FUNCTION__, format);
return BAD_VALUE;
}
int streamId = -1;
- res = mDevice->createStream(anw, width, height, format, &streamId);
+ res = mDevice->createStream(anw, width, height, format, dataSpace,
+ static_cast<camera3_stream_rotation_t>
+ (outputConfiguration.getRotation()),
+ &streamId);
if (res == OK) {
mStreamMap.add(bufferProducer->asBinder(), streamId);
@@ -439,10 +449,12 @@ status_t CameraDeviceClient::createStream(int width, int height, int format,
bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
- int32_t format, const CameraMetadata& info,
+ int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
camera_metadata_ro_entry streamConfigs =
+ (dataSpace == HAL_DATASPACE_DEPTH) ?
+ info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
int32_t bestWidth = -1;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 84e46b7..a3dbb90 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -19,6 +19,7 @@
#include <camera/camera2/ICameraDeviceUser.h>
#include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
#include "CameraService.h"
#include "common/FrameProcessorBase.h"
@@ -83,11 +84,7 @@ public:
// Returns -EBUSY if device is not idle
virtual status_t deleteStream(int streamId);
- virtual status_t createStream(
- int width,
- int height,
- int format,
- const sp<IGraphicBufferProducer>& bufferProducer);
+ virtual status_t createStream(const OutputConfiguration &outputConfiguration);
// Create a request object from a template.
virtual status_t createDefaultRequest(int templateId,
@@ -119,7 +116,7 @@ public:
int servicePid);
virtual ~CameraDeviceClient();
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -161,7 +158,8 @@ private:
// a width <= ROUNDING_WIDTH_CAP
static const int32_t ROUNDING_WIDTH_CAP = 1080;
static bool roundBufferDimensionNearest(int32_t width, int32_t height, int32_t format,
- const CameraMetadata& info, /*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
+ android_dataspace dataSpace, const CameraMetadata& info,
+ /*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
// IGraphicsBufferProducer binder -> Stream ID
KeyedVector<sp<IBinder>, int> mStreamMap;
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 2ea460f..8999ee4 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -50,7 +50,7 @@ ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
mExclusiveLock = false;
}
-status_t ProCamera2Client::initialize(camera_module_t *module)
+status_t ProCamera2Client::initialize(CameraModule *module)
{
ATRACE_CALL();
status_t res;
@@ -281,6 +281,7 @@ status_t ProCamera2Client::createStream(int width, int height, int format,
}
return mDevice->createStream(window, width, height, format,
+ HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
streamId);
}
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.h b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
index 9d83122..7f5f6ac 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.h
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
@@ -85,7 +85,7 @@ public:
int servicePid);
virtual ~ProCamera2Client();
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index d6db151..053d6e3 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -78,7 +78,7 @@ status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation)
}
template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
+status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
TClientBase::mCameraId);
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index d198e4e..ca2b74b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
#include "common/CameraDeviceBase.h"
+#include "common/CameraModule.h"
#include "camera/CaptureResult.h"
namespace android {
@@ -55,7 +56,7 @@ public:
int servicePid);
virtual ~Camera2ClientBase();
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t dump(int fd, const Vector<String16>& args);
/**
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index d26e20c..fe55b9e 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -29,6 +29,7 @@
#include "hardware/camera3.h"
#include "camera/CameraMetadata.h"
#include "camera/CaptureResult.h"
+#include "common/CameraModule.h"
namespace android {
@@ -45,7 +46,7 @@ class CameraDeviceBase : public virtual RefBase {
*/
virtual int getId() const = 0;
- virtual status_t initialize(camera_module_t *module) = 0;
+ virtual status_t initialize(CameraModule *module) = 0;
virtual status_t disconnect() = 0;
virtual status_t dump(int fd, const Vector<String16> &args) = 0;
@@ -99,17 +100,14 @@ class CameraDeviceBase : public virtual RefBase {
nsecs_t timeout) = 0;
/**
- * Create an output stream of the requested size and format.
+ * Create an output stream of the requested size, format, rotation and dataspace
*
- * If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device selects
- * an appropriate format; it can be queried with getStreamInfo.
- *
- * If format is HAL_PIXEL_FORMAT_COMPRESSED, the size parameter must be
- * equal to the size in bytes of the buffers to allocate for the stream. For
- * other formats, the size parameter is ignored.
+ * For HAL_PIXEL_FORMAT_BLOB formats, the width and height should be the
+ * logical dimensions of the buffer, not the number of bytes.
*/
virtual status_t createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, int *id) = 0;
+ uint32_t width, uint32_t height, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id) = 0;
/**
* Create an input reprocess stream that uses buffers from an existing
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
new file mode 100644
index 0000000..5f767ad
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "CameraModule"
+//#define LOG_NDEBUG 0
+
+#include "CameraModule.h"
+
+namespace android {
+
+void CameraModule::deriveCameraCharacteristicsKeys(
+ uint32_t deviceVersion, CameraMetadata &chars) {
+ // HAL1 devices should not reach here
+ if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
+ ALOGV("%s: Cannot derive keys for HAL version < 2.0");
+ return;
+ }
+
+ // Keys added in HAL3.3
+ if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+ Vector<uint8_t> controlModes;
+ uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
+ chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
+ data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
+ chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
+ controlModes.push(ANDROID_CONTROL_MODE_OFF);
+ controlModes.push(ANDROID_CONTROL_MODE_AUTO);
+ camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+ if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
+ controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
+ }
+ chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+ }
+ return;
+}
+
+CameraModule::CameraModule(camera_module_t *module) {
+ if (module == NULL) {
+ ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
+ assert(0);
+ }
+
+ mModule = module;
+ for (int i = 0; i < MAX_CAMERAS_PER_MODULE; i++) {
+ mCameraInfoCached[i] = false;
+ }
+}
+
+int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
+ Mutex::Autolock lock(mCameraInfoLock);
+ if (cameraId < 0 || cameraId >= MAX_CAMERAS_PER_MODULE) {
+ ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+ return -EINVAL;
+ }
+
+ // Only override static_camera_characteristics for API2 devices
+ int apiVersion = mModule->common.module_api_version;
+ if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
+ return mModule->get_camera_info(cameraId, info);
+ }
+
+ camera_info &wrappedInfo = mCameraInfo[cameraId];
+ if (!mCameraInfoCached[cameraId]) {
+ camera_info rawInfo;
+ int ret = mModule->get_camera_info(cameraId, &rawInfo);
+ if (ret != 0) {
+ return ret;
+ }
+ CameraMetadata &m = mCameraCharacteristics[cameraId];
+ m = rawInfo.static_camera_characteristics;
+ deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
+ wrappedInfo = rawInfo;
+ wrappedInfo.static_camera_characteristics = m.getAndLock();
+ mCameraInfoCached[cameraId] = true;
+ }
+ *info = wrappedInfo;
+ return 0;
+}
+
+int CameraModule::open(const char* id, struct hw_device_t** device) {
+ return filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
+}
+
+int CameraModule::openLegacy(
+ const char* id, uint32_t halVersion, struct hw_device_t** device) {
+ return mModule->open_legacy(&mModule->common, id, halVersion, device);
+}
+
+const hw_module_t* CameraModule::getRawModule() {
+ return &mModule->common;
+}
+
+int CameraModule::getNumberOfCameras() {
+ return mModule->get_number_of_cameras();
+}
+
+int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
+ return mModule->set_callbacks(callbacks);
+}
+
+bool CameraModule::isVendorTagDefined() {
+ return mModule->get_vendor_tag_ops != NULL;
+}
+
+void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
+ if (mModule->get_vendor_tag_ops) {
+ mModule->get_vendor_tag_ops(ops);
+ }
+}
+
+int CameraModule::setTorchMode(const char* camera_id, bool enable) {
+ return mModule->set_torch_mode(camera_id, enable);
+}
+
+
+status_t CameraModule::filterOpenErrorCode(status_t err) {
+ switch(err) {
+ case NO_ERROR:
+ case -EBUSY:
+ case -EINVAL:
+ case -EUSERS:
+ return err;
+ default:
+ break;
+ }
+ return -ENODEV;
+}
+
+
+}; // namespace android
+
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
new file mode 100644
index 0000000..16207aa
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+#define ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+
+#include <hardware/camera.h>
+#include <camera/CameraMetadata.h>
+#include <utils/Mutex.h>
+
+/* This needs to be increased if we can have more cameras */
+#define MAX_CAMERAS_PER_MODULE 2
+
+
+namespace android {
+/**
+ * A wrapper class for HAL camera module.
+ *
+ * This class wraps camera_module_t returned from HAL to provide a wrapped
+ * get_camera_info implementation which CameraService generates some
+ * camera characteristics keys defined in newer HAL version on an older HAL.
+ */
+class CameraModule {
+public:
+ CameraModule(camera_module_t *module);
+
+ const hw_module_t* getRawModule();
+ int getCameraInfo(int cameraId, struct camera_info *info);
+ int getNumberOfCameras(void);
+ int open(const char* id, struct hw_device_t** device);
+ int openLegacy(const char* id, uint32_t halVersion, struct hw_device_t** device);
+ int setCallbacks(const camera_module_callbacks_t *callbacks);
+ bool isVendorTagDefined();
+ void getVendorTagOps(vendor_tag_ops_t* ops);
+ int setTorchMode(const char* camera_id, bool enable);
+
+private:
+ // Derive camera characteristics keys defined after HAL device version
+ static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars);
+ status_t filterOpenErrorCode(status_t err);
+
+ camera_module_t *mModule;
+ CameraMetadata mCameraCharacteristics[MAX_CAMERAS_PER_MODULE];
+ camera_info mCameraInfo[MAX_CAMERAS_PER_MODULE];
+ bool mCameraInfoCached[MAX_CAMERAS_PER_MODULE];
+ Mutex mCameraInfoLock;
+};
+
+} // namespace android
+
+#endif
+
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 6386838..c79fa59 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -89,24 +89,22 @@ public:
}
}
- status_t initialize(hw_module_t *module)
+ status_t initialize(CameraModule *module)
{
ALOGI("Opening camera %s", mName.string());
- camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
camera_info info;
- status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
+ status_t res = module->getCameraInfo(atoi(mName.string()), &info);
if (res != OK) return res;
int rc = OK;
- if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
+ if (module->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
// Open higher version camera device as HAL1.0 device.
- rc = cameraModule->open_legacy(module, mName.string(),
- CAMERA_DEVICE_API_VERSION_1_0,
- (hw_device_t **)&mDevice);
+ rc = module->openLegacy(mName.string(),
+ CAMERA_DEVICE_API_VERSION_1_0,
+ (hw_device_t **)&mDevice);
} else {
- rc = CameraService::filterOpenErrorCode(module->methods->open(
- module, mName.string(), (hw_device_t **)&mDevice));
+ rc = module->open(mName.string(), (hw_device_t **)&mDevice);
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index d1158d6..878986b 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -53,7 +53,7 @@ int Camera2Device::getId() const {
return mId;
}
-status_t Camera2Device::initialize(camera_module_t *module)
+status_t Camera2Device::initialize(CameraModule *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
@@ -68,8 +68,7 @@ status_t Camera2Device::initialize(camera_module_t *module)
camera2_device_t *device;
- res = CameraService::filterOpenErrorCode(module->common.methods->open(
- &module->common, name, reinterpret_cast<hw_device_t**>(&device)));
+ res = module->open(name, reinterpret_cast<hw_device_t**>(&device));
if (res != OK) {
ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
@@ -87,7 +86,7 @@ status_t Camera2Device::initialize(camera_module_t *module)
}
camera_info info;
- res = module->get_camera_info(mId, &info);
+ res = module->getCameraInfo(mId, &info);
if (res != OK ) return res;
if (info.device_version != device->common.version) {
@@ -242,7 +241,8 @@ status_t Camera2Device::waitUntilRequestReceived(int32_t requestId, nsecs_t time
}
status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, int *id) {
+ uint32_t width, uint32_t height, int format,
+ android_dataspace /*dataSpace*/, camera3_stream_rotation_t rotation, int *id) {
ATRACE_CALL();
status_t res;
ALOGV("%s: E", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 4def8ae..9b32fa6 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -43,7 +43,7 @@ class Camera2Device: public CameraDeviceBase {
* CameraDevice interface
*/
virtual int getId() const;
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t disconnect();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual const CameraMetadata& info() const;
@@ -57,7 +57,8 @@ class Camera2Device: public CameraDeviceBase {
virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
virtual status_t createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, int *id);
+ uint32_t width, uint32_t height, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id);
virtual status_t createReprocessStreamFromStream(int outputId, int *id);
virtual status_t getStreamInfo(int id,
uint32_t *width, uint32_t *height, uint32_t *format);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 53e6fa9..8236788 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -86,7 +86,7 @@ int Camera3Device::getId() const {
* CameraDeviceBase interface
*/
-status_t Camera3Device::initialize(camera_module_t *module)
+status_t Camera3Device::initialize(CameraModule *module)
{
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
@@ -106,9 +106,8 @@ status_t Camera3Device::initialize(camera_module_t *module)
camera3_device_t *device;
ATRACE_BEGIN("camera3->open");
- res = CameraService::filterOpenErrorCode(module->common.methods->open(
- &module->common, deviceName.string(),
- reinterpret_cast<hw_device_t**>(&device)));
+ res = module->open(deviceName.string(),
+ reinterpret_cast<hw_device_t**>(&device));
ATRACE_END();
if (res != OK) {
@@ -127,7 +126,7 @@ status_t Camera3Device::initialize(camera_module_t *module)
}
camera_info info;
- res = CameraService::filterGetInfoErrorCode(module->get_camera_info(
+ res = CameraService::filterGetInfoErrorCode(module->getCameraInfo(
mId, &info));
if (res != OK) return res;
@@ -802,12 +801,13 @@ status_t Camera3Device::createZslStream(
}
status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, int *id) {
+ uint32_t width, uint32_t height, int format, android_dataspace dataSpace,
+ camera3_stream_rotation_t rotation, int *id) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
- ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d",
- mId, mNextStreamId, width, height, format);
+ ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d",
+ mId, mNextStreamId, width, height, format, dataSpace, rotation);
status_t res;
bool wasActive = false;
@@ -847,10 +847,10 @@ status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
}
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, jpegBufferSize, format);
+ width, height, jpegBufferSize, format, dataSpace, rotation);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumer,
- width, height, format);
+ width, height, format, dataSpace, rotation);
}
newStream->setStatusTracker(mStatusTracker);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ec8dc10..a77548d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -73,7 +73,7 @@ class Camera3Device :
virtual int getId() const;
// Transitions to idle state on success.
- virtual status_t initialize(camera_module_t *module);
+ virtual status_t initialize(CameraModule *module);
virtual status_t disconnect();
virtual status_t dump(int fd, const Vector<String16> &args);
virtual const CameraMetadata& info() const;
@@ -95,7 +95,8 @@ class Camera3Device :
// If adding streams while actively capturing, will pause device before adding
// stream, reconfiguring device, and unpausing.
virtual status_t createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, int *id);
+ uint32_t width, uint32_t height, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id);
virtual status_t createInputStream(
uint32_t width, uint32_t height, int format,
int *id);
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 6656b09..01edfff 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -28,7 +28,7 @@ namespace camera3 {
Camera3DummyStream::Camera3DummyStream(int id) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, DUMMY_WIDTH, DUMMY_HEIGHT,
- /*maxSize*/0, DUMMY_FORMAT) {
+ /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE, DUMMY_ROTATION) {
}
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 3e42623..d023c57 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -75,6 +75,8 @@ class Camera3DummyStream :
static const int DUMMY_WIDTH = 320;
static const int DUMMY_HEIGHT = 240;
static const int DUMMY_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
+ static const camera3_stream_rotation_t DUMMY_ROTATION = CAMERA3_STREAM_ROTATION_0;
static const uint32_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
/**
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index cc66459..8696413 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -30,9 +30,10 @@ namespace android {
namespace camera3 {
Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
- uint32_t width, uint32_t height, size_t maxSize, int format) :
+ uint32_t width, uint32_t height, size_t maxSize, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
Camera3Stream(id, type,
- width, height, maxSize, format),
+ width, height, maxSize, format, dataSpace, rotation),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index a35c290..abcf2b1 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -33,7 +33,8 @@ class Camera3IOStreamBase :
public Camera3Stream {
protected:
Camera3IOStreamBase(int id, camera3_stream_type_t type,
- uint32_t width, uint32_t height, size_t maxSize, int format);
+ uint32_t width, uint32_t height, size_t maxSize, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation);
public:
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 319be1d..2f0c8be 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -28,8 +28,8 @@ namespace camera3 {
Camera3InputStream::Camera3InputStream(int id,
uint32_t width, uint32_t height, int format) :
- Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height,
- /*maxSize*/0, format) {
+ Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0,
+ format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0) {
if (format == HAL_PIXEL_FORMAT_BLOB) {
ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 77ad503..96bed0d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -33,9 +33,10 @@ namespace camera3 {
Camera3OutputStream::Camera3OutputStream(int id,
sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format) :
+ uint32_t width, uint32_t height, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
- /*maxSize*/0, format),
+ /*maxSize*/0, format, dataSpace, rotation),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true) {
@@ -48,9 +49,10 @@ Camera3OutputStream::Camera3OutputStream(int id,
Camera3OutputStream::Camera3OutputStream(int id,
sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, size_t maxSize, int format) :
+ uint32_t width, uint32_t height, size_t maxSize, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
- format),
+ format, dataSpace, rotation),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true) {
@@ -69,10 +71,12 @@ Camera3OutputStream::Camera3OutputStream(int id,
Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
uint32_t width, uint32_t height,
- int format) :
+ int format,
+ android_dataspace dataSpace,
+ camera3_stream_rotation_t rotation) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
- format),
+ format, dataSpace, rotation),
mTransform(0) {
// Subclasses expected to initialize mConsumer themselves
@@ -323,6 +327,14 @@ status_t Camera3OutputStream::configureQueueLocked() {
return res;
}
+ res = native_window_set_buffers_data_space(mConsumer.get(),
+ camera3_stream::data_space);
+ if (res != OK) {
+ ALOGE("%s: Unable to configure stream dataspace %#x for stream %d",
+ __FUNCTION__, camera3_stream::data_space, mId);
+ return res;
+ }
+
int maxConsumerBuffers;
res = mConsumer->query(mConsumer.get(),
NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index be278c5..12b2ebb 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -39,14 +39,16 @@ class Camera3OutputStream :
* Set up a stream for formats that have 2 dimensions, such as RAW and YUV.
*/
Camera3OutputStream(int id, sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format);
+ uint32_t width, uint32_t height, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation);
/**
* Set up a stream for formats that have a variable buffer size for the same
* dimensions, such as compressed JPEG.
*/
Camera3OutputStream(int id, sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, size_t maxSize, int format);
+ uint32_t width, uint32_t height, size_t maxSize, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation);
virtual ~Camera3OutputStream();
@@ -64,7 +66,8 @@ class Camera3OutputStream :
protected:
Camera3OutputStream(int id, camera3_stream_type_t type,
- uint32_t width, uint32_t height, int format);
+ uint32_t width, uint32_t height, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation);
/**
* Note that we release the lock briefly in this function
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 3c0e908..4acbce3 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -46,7 +46,8 @@ const Camera3Stream* Camera3Stream::cast(const camera3_stream *stream) {
Camera3Stream::Camera3Stream(int id,
camera3_stream_type type,
- uint32_t width, uint32_t height, size_t maxSize, int format) :
+ uint32_t width, uint32_t height, size_t maxSize, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
camera3_stream(),
mId(id),
mName(String8::format("Camera3Stream[%d]", id)),
@@ -58,6 +59,8 @@ Camera3Stream::Camera3Stream(int id,
camera3_stream::width = width;
camera3_stream::height = height;
camera3_stream::format = format;
+ camera3_stream::data_space = dataSpace;
+ camera3_stream::rotation = rotation;
camera3_stream::usage = 0;
camera3_stream::max_buffers = 0;
camera3_stream::priv = NULL;
@@ -84,6 +87,10 @@ int Camera3Stream::getFormat() const {
return camera3_stream::format;
}
+android_dataspace Camera3Stream::getDataSpace() const {
+ return camera3_stream::data_space;
+}
+
camera3_stream* Camera3Stream::startConfiguration() {
ATRACE_CALL();
Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index d0e1337..aba27fe 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -119,9 +119,10 @@ class Camera3Stream :
/**
* Get the stream's dimensions and format
*/
- uint32_t getWidth() const;
- uint32_t getHeight() const;
- int getFormat() const;
+ uint32_t getWidth() const;
+ uint32_t getHeight() const;
+ int getFormat() const;
+ android_dataspace getDataSpace() const;
/**
* Start the stream configuration process. Returns a handle to the stream's
@@ -264,7 +265,8 @@ class Camera3Stream :
mutable Mutex mLock;
Camera3Stream(int id, camera3_stream_type type,
- uint32_t width, uint32_t height, size_t maxSize, int format);
+ uint32_t width, uint32_t height, size_t maxSize, int format,
+ android_dataspace dataSpace, camera3_stream_rotation_t rotation);
/**
* Interface to be implemented by derived classes
diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
index 81330ea..10d7f2e 100644
--- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
@@ -114,7 +114,8 @@ Camera3ZslStream::Camera3ZslStream(int id, uint32_t width, uint32_t height,
int bufferCount) :
Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL,
width, height,
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0),
mDepth(bufferCount) {
sp<IGraphicBufferProducer> producer;