summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
Diffstat (limited to 'camera')
-rw-r--r--camera/Android.mk5
-rw-r--r--camera/Camera.cpp3
-rw-r--r--camera/CameraBase.cpp2
-rw-r--r--camera/CameraMetadata.cpp15
-rw-r--r--camera/CameraParameters.cpp6
-rw-r--r--camera/ICameraService.cpp129
-rw-r--r--camera/ICameraServiceListener.cpp37
-rw-r--r--camera/ICameraServiceProxy.cpp55
-rw-r--r--camera/IProCameraCallbacks.cpp125
-rw-r--r--camera/IProCameraUser.cpp324
-rw-r--r--camera/ProCamera.cpp436
-rw-r--r--camera/camera2/CaptureRequest.cpp9
-rw-r--r--camera/camera2/ICameraDeviceCallbacks.cpp22
-rw-r--r--camera/camera2/ICameraDeviceUser.cpp171
-rw-r--r--camera/camera2/OutputConfiguration.cpp84
-rw-r--r--camera/tests/Android.mk4
-rw-r--r--camera/tests/CameraBinderTests.cpp484
-rw-r--r--camera/tests/ProCameraTests.cpp1278
-rw-r--r--camera/tests/VendorTagDescriptorTests.cpp9
19 files changed, 928 insertions, 2270 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
index da5ac59..471cb0d 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -28,14 +28,13 @@ LOCAL_SRC_FILES:= \
ICameraClient.cpp \
ICameraService.cpp \
ICameraServiceListener.cpp \
+ ICameraServiceProxy.cpp \
ICameraRecordingProxy.cpp \
ICameraRecordingProxyListener.cpp \
- IProCameraUser.cpp \
- IProCameraCallbacks.cpp \
camera2/ICameraDeviceUser.cpp \
camera2/ICameraDeviceCallbacks.cpp \
camera2/CaptureRequest.cpp \
- ProCamera.cpp \
+ camera2/OutputConfiguration.cpp \
CameraBase.cpp \
CameraUtils.cpp \
VendorTagDescriptor.cpp
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 3a9fb4c..9bf3134 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -97,7 +97,8 @@ status_t Camera::connectLegacy(int cameraId, int halVersion,
c->mStatus = NO_ERROR;
camera = c;
} else {
- ALOGW("An error occurred while connecting to camera: %d", cameraId);
+ ALOGW("An error occurred while connecting to camera %d: %d (%s)",
+ cameraId, status, strerror(-status));
c.clear();
}
return status;
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 65a1a47..5d50aa8 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -29,7 +29,6 @@
#include <camera/ICameraService.h>
// needed to instantiate
-#include <camera/ProCamera.h>
#include <camera/Camera.h>
#include <system/camera_metadata.h>
@@ -217,7 +216,6 @@ status_t CameraBase<TCam, TCamTraits>::removeServiceListener(
return cs->removeListener(listener);
}
-template class CameraBase<ProCamera>;
template class CameraBase<Camera>;
} // namespace android
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 043437f..46bcc1d 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -74,7 +74,7 @@ CameraMetadata::~CameraMetadata() {
clear();
}
-const camera_metadata_t* CameraMetadata::getAndLock() {
+const camera_metadata_t* CameraMetadata::getAndLock() const {
mLocked = true;
return mBuffer;
}
@@ -289,6 +289,17 @@ status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
return BAD_VALUE;
}
+ // Safety check - ensure that data isn't pointing to this metadata, since
+ // that would get invalidated if a resize is needed
+ size_t bufferSize = get_camera_metadata_size(mBuffer);
+ uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
+ uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
+ if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
+ ALOGE("%s: Update attempted with data from the same metadata buffer!",
+ __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
size_t data_size = calculate_camera_metadata_entry_data_size(type,
data_count);
@@ -583,7 +594,7 @@ status_t CameraMetadata::writeToParcel(Parcel& data,
*/
WritableBlob blob;
do {
- res = data.writeBlob(blobSize, &blob);
+ res = data.writeBlob(blobSize, false, &blob);
if (res != OK) {
break;
}
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index e5e4e90..68969cf 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -526,8 +526,12 @@ 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;
}
+bool CameraParameters::isEmpty() const {
+ return mMap.isEmpty();
+}
+
}; // namespace android
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index fc3e437..7c9720f 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -2,16 +2,16 @@
**
** Copyright 2008, 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
+** 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
+** 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
+** 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.
*/
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <utils/String16.h>
+#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
@@ -29,8 +30,6 @@
#include <camera/ICameraService.h>
#include <camera/ICameraServiceListener.h>
-#include <camera/IProCameraUser.h>
-#include <camera/IProCameraCallbacks.h>
#include <camera/ICamera.h>
#include <camera/ICameraClient.h>
#include <camera/camera2/ICameraDeviceUser.h>
@@ -176,10 +175,13 @@ public:
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
- remote()->transact(BnCameraService::CONNECT, data, &reply);
+
+ status_t status;
+ status = remote()->transact(BnCameraService::CONNECT, data, &reply);
+ if (status != OK) return status;
if (readExceptionCode(reply)) return -EPROTO;
- status_t status = reply.readInt32();
+ status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast<ICamera>(reply.readStrongBinder());
}
@@ -199,36 +201,31 @@ public:
data.writeInt32(halVersion);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
- remote()->transact(BnCameraService::CONNECT_LEGACY, data, &reply);
+
+ status_t status;
+ status = remote()->transact(BnCameraService::CONNECT_LEGACY, data, &reply);
+ if (status != OK) return status;
if (readExceptionCode(reply)) return -EPROTO;
- status_t status = reply.readInt32();
+ status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast<ICamera>(reply.readStrongBinder());
}
return status;
}
- // connect to camera service (pro client)
- virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb, int cameraId,
- const String16 &clientPackageName, int clientUid,
- /*out*/
- sp<IProCameraUser>& device)
+ virtual status_t setTorchMode(const String16& cameraId, bool enabled,
+ const sp<IBinder>& clientBinder)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(cameraCb));
- data.writeInt32(cameraId);
- data.writeString16(clientPackageName);
- data.writeInt32(clientUid);
- remote()->transact(BnCameraService::CONNECT_PRO, data, &reply);
+ data.writeString16(cameraId);
+ data.writeInt32(enabled ? 1 : 0);
+ data.writeStrongBinder(clientBinder);
+ remote()->transact(BnCameraService::SET_TORCH_MODE, data, &reply);
if (readExceptionCode(reply)) return -EPROTO;
- status_t status = reply.readInt32();
- if (reply.readInt32() != 0) {
- device = interface_cast<IProCameraUser>(reply.readStrongBinder());
- }
- return status;
+ return reply.readInt32();
}
// connect to camera service (android.hardware.camera2.CameraDevice)
@@ -246,10 +243,13 @@ public:
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
- remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply);
+
+ status_t status;
+ status = remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply);
+ if (status != OK) return status;
if (readExceptionCode(reply)) return -EPROTO;
- status_t status = reply.readInt32();
+ status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast<ICameraDeviceUser>(reply.readStrongBinder());
}
@@ -285,6 +285,7 @@ public:
}
Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeInt32(cameraId);
remote()->transact(BnCameraService::GET_LEGACY_PARAMETERS, data, &reply);
@@ -304,6 +305,7 @@ public:
virtual status_t supportsCameraApi(int cameraId, int apiVersion) {
Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeInt32(cameraId);
data.writeInt32(apiVersion);
remote()->transact(BnCameraService::SUPPORTS_CAMERA_API, data, &reply);
@@ -312,6 +314,16 @@ public:
status_t res = data.readInt32();
return res;
}
+
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+ data.writeInt32(eventId);
+ data.writeInt32Array(len, args);
+ remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
+
};
IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
@@ -390,26 +402,6 @@ status_t BnCameraService::onTransact(
}
return NO_ERROR;
} break;
- case CONNECT_PRO: {
- CHECK_INTERFACE(ICameraService, data, reply);
- sp<IProCameraCallbacks> cameraClient =
- interface_cast<IProCameraCallbacks>(data.readStrongBinder());
- int32_t cameraId = data.readInt32();
- const String16 clientName = data.readString16();
- int32_t clientUid = data.readInt32();
- sp<IProCameraUser> camera;
- status_t status = connectPro(cameraClient, cameraId,
- clientName, clientUid, /*out*/camera);
- reply->writeNoException();
- reply->writeInt32(status);
- if (camera != NULL) {
- reply->writeInt32(1);
- reply->writeStrongBinder(IInterface::asBinder(camera));
- } else {
- reply->writeInt32(0);
- }
- return NO_ERROR;
- } break;
case CONNECT_DEVICE: {
CHECK_INTERFACE(ICameraService, data, reply);
sp<ICameraDeviceCallbacks> cameraClient =
@@ -490,6 +482,41 @@ 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;
+ case NOTIFY_SYSTEM_EVENT: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ int32_t eventId = data.readInt32();
+ int32_t len = data.readInt32();
+ if (len < 0) {
+ ALOGE("%s: Received poorly formatted length in binder request: notifySystemEvent.",
+ __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+ if (len > 512) {
+ ALOGE("%s: Length %" PRIi32 " too long in binder request: notifySystemEvent.",
+ __FUNCTION__, len);
+ return FAILED_TRANSACTION;
+ }
+ int32_t events[len];
+ memset(events, 0, sizeof(int32_t) * len);
+ status_t status = data.read(events, sizeof(int32_t) * len);
+ if (status != NO_ERROR) {
+ ALOGE("%s: Received poorly formatted binder request: notifySystemEvent.",
+ __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+ notifySystemEvent(eventId, events, len);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
index b2f1729..0010325 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
@@ -44,8 +45,7 @@ public:
virtual void onStatusChanged(Status status, int32_t cameraId)
{
Parcel data, reply;
- data.writeInterfaceToken(
- ICameraServiceListener::getInterfaceDescriptor());
+ data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
data.writeInt32(static_cast<int32_t>(status));
data.writeInt32(cameraId);
@@ -54,19 +54,29 @@ public:
data,
&reply,
IBinder::FLAG_ONEWAY);
+ }
+
+ virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
- reply.readExceptionCode();
+ data.writeInt32(static_cast<int32_t>(status));
+ data.writeString16(cameraId);
+
+ remote()->transact(TORCH_STATUS_CHANGED,
+ data,
+ &reply,
+ IBinder::FLAG_ONEWAY);
}
};
-IMPLEMENT_META_INTERFACE(CameraServiceListener,
- "android.hardware.ICameraServiceListener");
+IMPLEMENT_META_INTERFACE(CameraServiceListener, "android.hardware.ICameraServiceListener");
// ----------------------------------------------------------------------
-status_t BnCameraServiceListener::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
+status_t BnCameraServiceListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
switch(code) {
case STATUS_CHANGED: {
CHECK_INTERFACE(ICameraServiceListener, data, reply);
@@ -75,7 +85,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/ICameraServiceProxy.cpp b/camera/ICameraServiceProxy.cpp
new file mode 100644
index 0000000..06a5afb
--- /dev/null
+++ b/camera/ICameraServiceProxy.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 "BpCameraServiceProxy"
+
+#include <stdint.h>
+
+#include <binder/Parcel.h>
+
+#include <camera/ICameraServiceProxy.h>
+
+namespace android {
+
+class BpCameraServiceProxy: public BpInterface<ICameraServiceProxy> {
+public:
+ BpCameraServiceProxy(const sp<IBinder>& impl) : BpInterface<ICameraServiceProxy>(impl) {}
+
+ virtual void pingForUserUpdate() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraServiceProxy::getInterfaceDescriptor());
+ remote()->transact(BnCameraServiceProxy::PING_FOR_USER_UPDATE, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
+};
+
+
+IMPLEMENT_META_INTERFACE(CameraServiceProxy, "android.hardware.ICameraServiceProxy");
+
+status_t BnCameraServiceProxy::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ switch(code) {
+ case PING_FOR_USER_UPDATE: {
+ CHECK_INTERFACE(ICameraServiceProxy, data, reply);
+ pingForUserUpdate();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+}; // namespace android
+
diff --git a/camera/IProCameraCallbacks.cpp b/camera/IProCameraCallbacks.cpp
deleted file mode 100644
index bd3d420..0000000
--- a/camera/IProCameraCallbacks.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-**
-** Copyright 2013, 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_NDEBUG 0
-#define LOG_TAG "IProCameraCallbacks"
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include <utils/Mutex.h>
-
-#include <camera/IProCameraCallbacks.h>
-
-#include "camera/CameraMetadata.h"
-
-namespace android {
-
-enum {
- NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
- LOCK_STATUS_CHANGED,
- RESULT_RECEIVED,
-};
-
-class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks>
-{
-public:
- BpProCameraCallbacks(const sp<IBinder>& impl)
- : BpInterface<IProCameraCallbacks>(impl)
- {
- }
-
- // generic callback from camera service to app
- void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
- {
- ALOGV("notifyCallback");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(msgType);
- data.writeInt32(ext1);
- data.writeInt32(ext2);
- remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- void onLockStatusChanged(LockStatus newLockStatus) {
- ALOGV("onLockStatusChanged");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(newLockStatus);
- remote()->transact(LOCK_STATUS_CHANGED, data, &reply,
- IBinder::FLAG_ONEWAY);
- }
-
- void onResultReceived(int32_t requestId, camera_metadata* result) {
- ALOGV("onResultReceived");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(requestId);
- CameraMetadata::writeToParcel(data, result);
- remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(ProCameraCallbacks,
- "android.hardware.IProCameraCallbacks");
-
-// ----------------------------------------------------------------------
-
-status_t BnProCameraCallbacks::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- ALOGV("onTransact - code = %d", code);
- switch(code) {
- case NOTIFY_CALLBACK: {
- ALOGV("NOTIFY_CALLBACK");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- int32_t msgType = data.readInt32();
- int32_t ext1 = data.readInt32();
- int32_t ext2 = data.readInt32();
- notifyCallback(msgType, ext1, ext2);
- return NO_ERROR;
- } break;
- case LOCK_STATUS_CHANGED: {
- ALOGV("LOCK_STATUS_CHANGED");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- LockStatus newLockStatus
- = static_cast<LockStatus>(data.readInt32());
- onLockStatusChanged(newLockStatus);
- return NO_ERROR;
- } break;
- case RESULT_RECEIVED: {
- ALOGV("RESULT_RECEIVED");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- int32_t requestId = data.readInt32();
- camera_metadata_t *result = NULL;
- CameraMetadata::readFromParcel(data, &result);
- onResultReceived(requestId, result);
- return NO_ERROR;
- break;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp
deleted file mode 100644
index 9bd7597..0000000
--- a/camera/IProCameraUser.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-**
-** Copyright 2013, 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_NDEBUG 0
-#define LOG_TAG "IProCameraUser"
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <camera/IProCameraUser.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-#include "camera/CameraMetadata.h"
-
-namespace android {
-
-enum {
- DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
- CONNECT,
- EXCLUSIVE_TRY_LOCK,
- EXCLUSIVE_LOCK,
- EXCLUSIVE_UNLOCK,
- HAS_EXCLUSIVE_LOCK,
- SUBMIT_REQUEST,
- CANCEL_REQUEST,
- DELETE_STREAM,
- CREATE_STREAM,
- CREATE_DEFAULT_REQUEST,
- GET_CAMERA_INFO,
-};
-
-class BpProCameraUser: public BpInterface<IProCameraUser>
-{
-public:
- BpProCameraUser(const sp<IBinder>& impl)
- : BpInterface<IProCameraUser>(impl)
- {
- }
-
- // disconnect from camera service
- void disconnect()
- {
- ALOGV("disconnect");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(DISCONNECT, data, &reply);
- reply.readExceptionCode();
- }
-
- virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(cameraClient));
- remote()->transact(CONNECT, data, &reply);
- return reply.readInt32();
- }
-
- /* Shared ProCameraUser */
-
- virtual status_t exclusiveTryLock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
- return reply.readInt32();
- }
- virtual status_t exclusiveLock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(EXCLUSIVE_LOCK, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t exclusiveUnlock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
- return reply.readInt32();
- }
-
- virtual bool hasExclusiveLock()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
- return !!reply.readInt32();
- }
-
- virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
- {
-
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
-
- // arg0+arg1
- CameraMetadata::writeToParcel(data, metadata);
-
- // arg2 = streaming (bool)
- data.writeInt32(streaming);
-
- remote()->transact(SUBMIT_REQUEST, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t cancelRequest(int requestId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(requestId);
-
- remote()->transact(CANCEL_REQUEST, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t deleteStream(int streamId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(streamId);
-
- remote()->transact(DELETE_STREAM, data, &reply);
- return reply.readInt32();
- }
-
- virtual status_t createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(width);
- data.writeInt32(height);
- data.writeInt32(format);
-
- sp<IBinder> b(IInterface::asBinder(bufferProducer));
- data.writeStrongBinder(b);
-
- remote()->transact(CREATE_STREAM, data, &reply);
-
- int sId = reply.readInt32();
- if (streamId) {
- *streamId = sId;
- }
- return reply.readInt32();
- }
-
- // Create a request object from a template.
- virtual status_t createDefaultRequest(int templateId,
- /*out*/
- camera_metadata** request)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(templateId);
- remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
- CameraMetadata::readFromParcel(reply, /*out*/request);
- return reply.readInt32();
- }
-
-
- virtual status_t getCameraInfo(int cameraId, camera_metadata** info)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(cameraId);
- remote()->transact(GET_CAMERA_INFO, data, &reply);
- CameraMetadata::readFromParcel(reply, /*out*/info);
- return reply.readInt32();
- }
-
-
-private:
-
-
-};
-
-IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
-
-// ----------------------------------------------------------------------
-
-status_t BnProCameraUser::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case DISCONNECT: {
- ALOGV("DISCONNECT");
- CHECK_INTERFACE(IProCameraUser, data, reply);
- disconnect();
- reply->writeNoException();
- return NO_ERROR;
- } break;
- case CONNECT: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- sp<IProCameraCallbacks> cameraClient =
- interface_cast<IProCameraCallbacks>(data.readStrongBinder());
- reply->writeInt32(connect(cameraClient));
- return NO_ERROR;
- } break;
-
- /* Shared ProCameraUser */
- case EXCLUSIVE_TRY_LOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(exclusiveTryLock());
- return NO_ERROR;
- } break;
- case EXCLUSIVE_LOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(exclusiveLock());
- return NO_ERROR;
- } break;
- case EXCLUSIVE_UNLOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(exclusiveUnlock());
- return NO_ERROR;
- } break;
- case HAS_EXCLUSIVE_LOCK: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- reply->writeInt32(hasExclusiveLock());
- return NO_ERROR;
- } break;
- case SUBMIT_REQUEST: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- camera_metadata_t* metadata;
- CameraMetadata::readFromParcel(data, /*out*/&metadata);
-
- // arg2 = streaming (bool)
- bool streaming = data.readInt32();
-
- // return code: requestId (int32)
- reply->writeInt32(submitRequest(metadata, streaming));
-
- return NO_ERROR;
- } break;
- case CANCEL_REQUEST: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int requestId = data.readInt32();
- reply->writeInt32(cancelRequest(requestId));
- return NO_ERROR;
- } break;
- case DELETE_STREAM: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int streamId = data.readInt32();
- reply->writeInt32(deleteStream(streamId));
- return NO_ERROR;
- } break;
- case CREATE_STREAM: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int width, height, format;
-
- width = data.readInt32();
- height = data.readInt32();
- format = data.readInt32();
-
- sp<IGraphicBufferProducer> bp =
- interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
-
- int streamId = -1;
- status_t ret;
- ret = createStream(width, height, format, bp, &streamId);
-
- reply->writeInt32(streamId);
- reply->writeInt32(ret);
-
- return NO_ERROR;
- } break;
-
- case CREATE_DEFAULT_REQUEST: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
-
- int templateId = data.readInt32();
-
- camera_metadata_t* request = NULL;
- status_t ret;
- ret = createDefaultRequest(templateId, &request);
-
- CameraMetadata::writeToParcel(*reply, request);
- reply->writeInt32(ret);
-
- free_camera_metadata(request);
-
- return NO_ERROR;
- } break;
- case GET_CAMERA_INFO: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
-
- int cameraId = data.readInt32();
-
- camera_metadata_t* info = NULL;
- status_t ret;
- ret = getCameraInfo(cameraId, &info);
-
- CameraMetadata::writeToParcel(*reply, info);
- reply->writeInt32(ret);
-
- free_camera_metadata(info);
-
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
deleted file mode 100644
index 48f8e8e..0000000
--- a/camera/ProCamera.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
-**
-** Copyright (C) 2013, 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_NDEBUG 0
-#define LOG_TAG "ProCamera"
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/Mutex.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/IMemory.h>
-
-#include <camera/ProCamera.h>
-#include <camera/IProCameraUser.h>
-#include <camera/IProCameraCallbacks.h>
-
-#include <gui/IGraphicBufferProducer.h>
-
-#include <system/camera_metadata.h>
-
-namespace android {
-
-sp<ProCamera> ProCamera::connect(int cameraId)
-{
- return CameraBaseT::connect(cameraId, String16(),
- ICameraService::USE_CALLING_UID);
-}
-
-ProCamera::ProCamera(int cameraId)
- : CameraBase(cameraId)
-{
-}
-
-CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService =
- &ICameraService::connectPro;
-
-ProCamera::~ProCamera()
-{
-
-}
-
-/* IProCameraUser's implementation */
-
-// callback from camera service
-void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
-{
- return CameraBaseT::notifyCallback(msgType, ext1, ext2);
-}
-
-void ProCamera::onLockStatusChanged(
- IProCameraCallbacks::LockStatus newLockStatus)
-{
- ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
-
- sp<ProCameraListener> listener;
- {
- Mutex::Autolock _l(mLock);
- listener = mListener;
- }
- if (listener != NULL) {
- switch (newLockStatus) {
- case IProCameraCallbacks::LOCK_ACQUIRED:
- listener->onLockAcquired();
- break;
- case IProCameraCallbacks::LOCK_RELEASED:
- listener->onLockReleased();
- break;
- case IProCameraCallbacks::LOCK_STOLEN:
- listener->onLockStolen();
- break;
- default:
- ALOGE("%s: Unknown lock status: %d",
- __FUNCTION__, newLockStatus);
- }
- }
-}
-
-void ProCamera::onResultReceived(int32_t requestId, camera_metadata* result) {
- ALOGV("%s: requestId = %d, result = %p", __FUNCTION__, requestId, result);
-
- sp<ProCameraListener> listener;
- {
- Mutex::Autolock _l(mLock);
- listener = mListener;
- }
-
- CameraMetadata tmp(result);
-
- // Unblock waitForFrame(id) callers
- {
- Mutex::Autolock al(mWaitMutex);
- mMetadataReady = true;
- mLatestMetadata = tmp; // make copy
- mWaitCondition.broadcast();
- }
-
- result = tmp.release();
-
- if (listener != NULL) {
- listener->onResultReceived(requestId, result);
- } else {
- free_camera_metadata(result);
- }
-
-}
-
-status_t ProCamera::exclusiveTryLock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->exclusiveTryLock();
-}
-status_t ProCamera::exclusiveLock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->exclusiveLock();
-}
-status_t ProCamera::exclusiveUnlock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->exclusiveUnlock();
-}
-bool ProCamera::hasExclusiveLock()
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->hasExclusiveLock();
-}
-
-// Note that the callee gets a copy of the metadata.
-int ProCamera::submitRequest(const struct camera_metadata* metadata,
- bool streaming)
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
- streaming);
-}
-
-status_t ProCamera::cancelRequest(int requestId)
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->cancelRequest(requestId);
-}
-
-status_t ProCamera::deleteStream(int streamId)
-{
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- status_t s = c->deleteStream(streamId);
-
- mStreams.removeItem(streamId);
-
- return s;
-}
-
-status_t ProCamera::createStream(int width, int height, int format,
- const sp<Surface>& surface,
- /*out*/
- int* streamId)
-{
- *streamId = -1;
-
- ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
- format);
-
- if (surface == 0) {
- return BAD_VALUE;
- }
-
- return createStream(width, height, format,
- surface->getIGraphicBufferProducer(),
- streamId);
-}
-
-status_t ProCamera::createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId) {
- *streamId = -1;
-
- ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
- format);
-
- if (bufferProducer == 0) {
- return BAD_VALUE;
- }
-
- sp <IProCameraUser> c = mCamera;
- status_t stat = c->createStream(width, height, format, bufferProducer,
- streamId);
-
- if (stat == OK) {
- StreamInfo s(*streamId);
-
- mStreams.add(*streamId, s);
- }
-
- return stat;
-}
-
-status_t ProCamera::createStreamCpu(int width, int height, int format,
- int heapCount,
- /*out*/
- sp<CpuConsumer>* cpuConsumer,
- int* streamId) {
- return createStreamCpu(width, height, format, heapCount,
- /*synchronousMode*/true,
- cpuConsumer, streamId);
-}
-
-status_t ProCamera::createStreamCpu(int width, int height, int format,
- int heapCount,
- bool synchronousMode,
- /*out*/
- sp<CpuConsumer>* cpuConsumer,
- int* streamId)
-{
- ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
- format);
-
- *cpuConsumer = NULL;
-
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- sp<CpuConsumer> cc = new CpuConsumer(consumer, heapCount
- /*, synchronousMode*/);
- cc->setName(String8("ProCamera::mCpuConsumer"));
-
- sp<Surface> stc = new Surface(producer);
-
- status_t s = createStream(width, height, format,
- stc->getIGraphicBufferProducer(),
- streamId);
-
- if (s != OK) {
- ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
- width, height, format);
- return s;
- }
-
- sp<ProFrameListener> frameAvailableListener =
- new ProFrameListener(this, *streamId);
-
- getStreamInfo(*streamId).cpuStream = true;
- getStreamInfo(*streamId).cpuConsumer = cc;
- getStreamInfo(*streamId).synchronousMode = synchronousMode;
- getStreamInfo(*streamId).stc = stc;
- // for lifetime management
- getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
-
- cc->setFrameAvailableListener(frameAvailableListener);
-
- *cpuConsumer = cc;
-
- return s;
-}
-
-camera_metadata* ProCamera::getCameraInfo(int cameraId) {
- ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
-
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NULL;
-
- camera_metadata* ptr = NULL;
- status_t status = c->getCameraInfo(cameraId, &ptr);
-
- if (status != OK) {
- ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
- }
-
- return ptr;
-}
-
-status_t ProCamera::createDefaultRequest(int templateId,
- camera_metadata** request) const {
- ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
-
- sp <IProCameraUser> c = mCamera;
- if (c == 0) return NO_INIT;
-
- return c->createDefaultRequest(templateId, request);
-}
-
-void ProCamera::onFrameAvailable(int streamId) {
- ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
-
- sp<ProCameraListener> listener = mListener;
- StreamInfo& stream = getStreamInfo(streamId);
-
- if (listener.get() != NULL) {
- listener->onFrameAvailable(streamId, stream.cpuConsumer);
- }
-
- // Unblock waitForFrame(id) callers
- {
- Mutex::Autolock al(mWaitMutex);
- getStreamInfo(streamId).frameReady++;
- mWaitCondition.broadcast();
- }
-}
-
-int ProCamera::waitForFrameBuffer(int streamId) {
- status_t stat = BAD_VALUE;
- Mutex::Autolock al(mWaitMutex);
-
- StreamInfo& si = getStreamInfo(streamId);
-
- if (si.frameReady > 0) {
- int numFrames = si.frameReady;
- si.frameReady = 0;
- return numFrames;
- } else {
- while (true) {
- stat = mWaitCondition.waitRelative(mWaitMutex,
- mWaitTimeout);
- if (stat != OK) {
- ALOGE("%s: Error while waiting for frame buffer: %d",
- __FUNCTION__, stat);
- return stat;
- }
-
- if (si.frameReady > 0) {
- int numFrames = si.frameReady;
- si.frameReady = 0;
- return numFrames;
- }
- // else it was some other stream that got unblocked
- }
- }
-
- return stat;
-}
-
-int ProCamera::dropFrameBuffer(int streamId, int count) {
- StreamInfo& si = getStreamInfo(streamId);
-
- if (!si.cpuStream) {
- return BAD_VALUE;
- } else if (count < 0) {
- return BAD_VALUE;
- }
-
- if (!si.synchronousMode) {
- ALOGW("%s: No need to drop frames on asynchronous streams,"
- " as asynchronous mode only keeps 1 latest frame around.",
- __FUNCTION__);
- return BAD_VALUE;
- }
-
- int numDropped = 0;
- for (int i = 0; i < count; ++i) {
- CpuConsumer::LockedBuffer buffer;
- if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
- break;
- }
-
- si.cpuConsumer->unlockBuffer(buffer);
- numDropped++;
- }
-
- return numDropped;
-}
-
-status_t ProCamera::waitForFrameMetadata() {
- status_t stat = BAD_VALUE;
- Mutex::Autolock al(mWaitMutex);
-
- if (mMetadataReady) {
- return OK;
- } else {
- while (true) {
- stat = mWaitCondition.waitRelative(mWaitMutex,
- mWaitTimeout);
-
- if (stat != OK) {
- ALOGE("%s: Error while waiting for metadata: %d",
- __FUNCTION__, stat);
- return stat;
- }
-
- if (mMetadataReady) {
- mMetadataReady = false;
- return OK;
- }
- // else it was some other stream or metadata
- }
- }
-
- return stat;
-}
-
-CameraMetadata ProCamera::consumeFrameMetadata() {
- Mutex::Autolock al(mWaitMutex);
-
- // Destructive: Subsequent calls return empty metadatas
- CameraMetadata tmp = mLatestMetadata;
- mLatestMetadata.clear();
-
- return tmp;
-}
-
-ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
- return mStreams.editValueFor(streamId);
-}
-
-}; // namespace android
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index 66d6913..4217bc6 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -81,6 +81,13 @@ status_t CaptureRequest::readFromParcel(Parcel* parcel) {
mSurfaceList.push_back(surface);
}
+ int isReprocess = 0;
+ if ((err = parcel->readInt32(&isReprocess)) != OK) {
+ ALOGE("%s: Failed to read reprocessing from parcel", __FUNCTION__);
+ return err;
+ }
+ mIsReprocess = (isReprocess != 0);
+
return OK;
}
@@ -118,6 +125,8 @@ status_t CaptureRequest::writeToParcel(Parcel* parcel) const {
parcel->writeStrongBinder(binder);
}
+ parcel->writeInt32(mIsReprocess ? 1 : 0);
+
return OK;
}
diff --git a/camera/camera2/ICameraDeviceCallbacks.cpp b/camera/camera2/ICameraDeviceCallbacks.cpp
index 4cc7b5d..f599879 100644
--- a/camera/camera2/ICameraDeviceCallbacks.cpp
+++ b/camera/camera2/ICameraDeviceCallbacks.cpp
@@ -37,6 +37,7 @@ enum {
CAMERA_IDLE,
CAPTURE_STARTED,
RESULT_RECEIVED,
+ PREPARED
};
class BpCameraDeviceCallbacks: public BpInterface<ICameraDeviceCallbacks>
@@ -80,7 +81,6 @@ public:
data.writeNoException();
}
-
void onResultReceived(const CameraMetadata& metadata,
const CaptureResultExtras& resultExtras) {
ALOGV("onResultReceived");
@@ -93,6 +93,17 @@ public:
remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
data.writeNoException();
}
+
+ void onPrepared(int streamId)
+ {
+ ALOGV("onPrepared");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
+ data.writeInt32(streamId);
+ remote()->transact(PREPARED, data, &reply, IBinder::FLAG_ONEWAY);
+ data.writeNoException();
+ }
+
};
IMPLEMENT_META_INTERFACE(CameraDeviceCallbacks,
@@ -160,6 +171,15 @@ status_t BnCameraDeviceCallbacks::onTransact(
data.readExceptionCode();
return NO_ERROR;
} break;
+ case PREPARED: {
+ ALOGV("onPrepared");
+ CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
+ CaptureResultExtras result;
+ int streamId = data.readInt32();
+ onPrepared(streamId);
+ data.readExceptionCode();
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index 277b5db..d2dc200 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 {
@@ -41,10 +42,14 @@ enum {
END_CONFIGURE,
DELETE_STREAM,
CREATE_STREAM,
+ CREATE_INPUT_STREAM,
+ GET_INPUT_SURFACE,
CREATE_DEFAULT_REQUEST,
GET_CAMERA_INFO,
WAIT_UNTIL_IDLE,
- FLUSH
+ FLUSH,
+ PREPARE,
+ TEAR_DOWN
};
namespace {
@@ -78,7 +83,7 @@ public:
reply.readExceptionCode();
}
- virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating,
+ virtual int submitRequest(sp<CaptureRequest> request, bool repeating,
int64_t *lastFrameNumber)
{
Parcel data, reply;
@@ -107,13 +112,13 @@ public:
}
}
- if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if (res < 0 || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
}
- virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
+ virtual int submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
int64_t *lastFrameNumber)
{
Parcel data, reply;
@@ -147,7 +152,7 @@ public:
resFrameNumber = reply.readInt64(lastFrameNumber);
}
}
- if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+ if (res < 0 || (resFrameNumber != NO_ERROR)) {
res = FAILED_TRANSACTION;
}
return res;
@@ -186,11 +191,13 @@ public:
return reply.readInt32();
}
- virtual status_t endConfigure()
+ virtual status_t endConfigure(bool isConstrainedHighSpeed)
{
ALOGV("endConfigure");
Parcel data, reply;
data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+ data.writeInt32(isConstrainedHighSpeed);
+
remote()->transact(END_CONFIGURE, data, &reply);
reply.readExceptionCode();
return reply.readInt32();
@@ -208,8 +215,23 @@ 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());
+ 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();
+ return reply.readInt32();
+ }
+
+ virtual status_t createInputStream(int width, int height, int format)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
@@ -217,17 +239,42 @@ public:
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(IInterface::asBinder(bufferProducer));
- data.writeStrongBinder(b);
-
- remote()->transact(CREATE_STREAM, data, &reply);
+ remote()->transact(CREATE_INPUT_STREAM, data, &reply);
reply.readExceptionCode();
return reply.readInt32();
}
+ // get the buffer producer of the input stream
+ virtual status_t getInputBufferProducer(
+ sp<IGraphicBufferProducer> *producer) {
+ if (producer == NULL) {
+ return BAD_VALUE;
+ }
+
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+
+ remote()->transact(GET_INPUT_SURFACE, data, &reply);
+
+ reply.readExceptionCode();
+ status_t result = reply.readInt32() ;
+ if (result != OK) {
+ return result;
+ }
+
+ sp<IGraphicBufferProducer> bp = NULL;
+ if (reply.readInt32() != 0) {
+ String16 name = readMaybeEmptyString16(reply);
+ bp = interface_cast<IGraphicBufferProducer>(
+ reply.readStrongBinder());
+ }
+
+ *producer = bp;
+
+ return *producer == NULL ? INVALID_OPERATION : OK;
+ }
+
// Create a request object from a template.
virtual status_t createDefaultRequest(int templateId,
/*out*/
@@ -305,6 +352,34 @@ public:
return res;
}
+ virtual status_t prepare(int streamId)
+ {
+ ALOGV("prepare");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+ data.writeInt32(streamId);
+
+ remote()->transact(PREPARE, data, &reply);
+
+ reply.readExceptionCode();
+ return reply.readInt32();
+ }
+
+ virtual status_t tearDown(int streamId)
+ {
+ ALOGV("tearDown");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+ data.writeInt32(streamId);
+
+ remote()->transact(TEAR_DOWN, data, &reply);
+
+ reply.readExceptionCode();
+ return reply.readInt32();
+ }
+
private:
@@ -396,39 +471,51 @@ status_t BnCameraDeviceUser::onTransact(
} break;
case CREATE_STREAM: {
CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+
+ status_t ret = BAD_VALUE;
+ if (data.readInt32() != 0) {
+ OutputConfiguration outputConfiguration(data);
+ ret = createStream(outputConfiguration);
+ } else {
+ ALOGE("%s: cannot take an empty OutputConfiguration", __FUNCTION__);
+ }
+
+ reply->writeNoException();
+ ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
+ reply->writeInt32(ret);
+ ALOGV("%s: CREATE_STREAM: write ret = %d", __FUNCTION__, ret);
+
+ return NO_ERROR;
+ } break;
+ case CREATE_INPUT_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);
+ status_t ret = createInputStream(width, height, format);
- sp<IGraphicBufferProducer> bp;
- if (data.readInt32() != 0) {
- String16 name = readMaybeEmptyString16(data);
- bp = interface_cast<IGraphicBufferProducer>(
- data.readStrongBinder());
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
- ALOGV("%s: CREATE_STREAM: bp = %p, name = %s", __FUNCTION__,
- bp.get(), String8(name).string());
- } else {
- ALOGV("%s: CREATE_STREAM: bp = unset, name = unset",
- __FUNCTION__);
- }
+ } break;
+ case GET_INPUT_SURFACE: {
+ CHECK_INTERFACE(ICameraDeviceUser, data, reply);
- status_t ret;
- ret = createStream(width, height, format, bp);
+ sp<IGraphicBufferProducer> bp;
+ status_t ret = getInputBufferProducer(&bp);
+ sp<IBinder> b(IInterface::asBinder(ret == OK ? bp : NULL));
reply->writeNoException();
- ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
reply->writeInt32(ret);
- ALOGV("%s: CREATE_STREAM: write ret = %d", __FUNCTION__, ret);
+ reply->writeInt32(1);
+ reply->writeString16(String16("camera input")); // name of surface
+ reply->writeStrongBinder(b);
return NO_ERROR;
} break;
-
case CREATE_DEFAULT_REQUEST: {
CHECK_INTERFACE(ICameraDeviceUser, data, reply);
@@ -486,10 +573,26 @@ status_t BnCameraDeviceUser::onTransact(
} break;
case END_CONFIGURE: {
CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+ bool isConstrainedHighSpeed = data.readInt32();
reply->writeNoException();
- reply->writeInt32(endConfigure());
+ reply->writeInt32(endConfigure(isConstrainedHighSpeed));
return NO_ERROR;
} break;
+ case PREPARE: {
+ CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+ int streamId = data.readInt32();
+ reply->writeNoException();
+ reply->writeInt32(prepare(streamId));
+ return NO_ERROR;
+ } break;
+ case TEAR_DOWN: {
+ CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+ int streamId = data.readInt32();
+ reply->writeNoException();
+ reply->writeInt32(tearDown(streamId));
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
new file mode 100644
index 0000000..20a23e0
--- /dev/null
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -0,0 +1,84 @@
+/*
+**
+** 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());
+}
+
+OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation) {
+ mGbp = gbp;
+ mRotation = rotation;
+}
+
+status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
+
+ parcel.writeInt32(mRotation);
+ parcel.writeString16(String16("unknown_name")); // name of surface
+ sp<IBinder> b(IInterface::asBinder(mGbp));
+ parcel.writeStrongBinder(b);
+
+ return OK;
+}
+
+}; // namespace android
+
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index 2db4c14..3777d94 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -17,8 +17,8 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES:= \
- ProCameraTests.cpp \
- VendorTagDescriptorTests.cpp
+ VendorTagDescriptorTests.cpp \
+ CameraBinderTests.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
new file mode 100644
index 0000000..572fb72
--- /dev/null
+++ b/camera/tests/CameraBinderTests.cpp
@@ -0,0 +1,484 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "CameraBinderTests"
+
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <system/graphics.h>
+#include <hardware/gralloc.h>
+
+#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/ICameraServiceListener.h>
+#include <camera/camera2/CaptureRequest.h>
+#include <camera/camera2/ICameraDeviceUser.h>
+#include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
+
+#include <gui/BufferItemConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <utility>
+#include <vector>
+#include <map>
+#include <algorithm>
+
+using namespace android;
+
+#define ASSERT_NOT_NULL(x) \
+ ASSERT_TRUE((x) != nullptr)
+
+#define SETUP_TIMEOUT 2000000000 // ns
+#define IDLE_TIMEOUT 2000000000 // ns
+
+// Stub listener implementation
+class TestCameraServiceListener : public BnCameraServiceListener {
+ std::map<String16, TorchStatus> mCameraTorchStatuses;
+ std::map<int32_t, Status> mCameraStatuses;
+ mutable Mutex mLock;
+ mutable Condition mCondition;
+ mutable Condition mTorchCondition;
+public:
+ virtual ~TestCameraServiceListener() {};
+
+ virtual void onStatusChanged(Status status, int32_t cameraId) {
+ Mutex::Autolock l(mLock);
+ mCameraStatuses[cameraId] = status;
+ mCondition.broadcast();
+ };
+
+ virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
+ Mutex::Autolock l(mLock);
+ mCameraTorchStatuses[cameraId] = status;
+ mTorchCondition.broadcast();
+ };
+
+ bool waitForNumCameras(size_t num) const {
+ Mutex::Autolock l(mLock);
+
+ if (mCameraStatuses.size() == num) {
+ return true;
+ }
+
+ while (mCameraStatuses.size() < num) {
+ if (mCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ bool waitForTorchState(TorchStatus status, int32_t cameraId) const {
+ Mutex::Autolock l(mLock);
+
+ const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+ if (iter != mCameraTorchStatuses.end() && iter->second == status) {
+ return true;
+ }
+
+ bool foundStatus = false;
+ while (!foundStatus) {
+ if (mTorchCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
+ return false;
+ }
+ const auto& iter =
+ mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+ foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status);
+ }
+ return true;
+ };
+
+ TorchStatus getTorchStatus(int32_t cameraId) const {
+ Mutex::Autolock l(mLock);
+ const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+ if (iter == mCameraTorchStatuses.end()) {
+ return ICameraServiceListener::TORCH_STATUS_UNKNOWN;
+ }
+ return iter->second;
+ };
+
+ Status getStatus(int32_t cameraId) const {
+ Mutex::Autolock l(mLock);
+ const auto& iter = mCameraStatuses.find(cameraId);
+ if (iter == mCameraStatuses.end()) {
+ return ICameraServiceListener::STATUS_UNKNOWN;
+ }
+ return iter->second;
+ };
+};
+
+// Callback implementation
+class TestCameraDeviceCallbacks : public BnCameraDeviceCallbacks {
+public:
+ enum Status {
+ IDLE,
+ ERROR,
+ PREPARED,
+ RUNNING,
+ SENT_RESULT,
+ UNINITIALIZED
+ };
+
+protected:
+ bool mError;
+ Status mLastStatus;
+ mutable std::vector<Status> mStatusesHit;
+ mutable Mutex mLock;
+ mutable Condition mStatusCondition;
+public:
+ TestCameraDeviceCallbacks() : mError(false), mLastStatus(UNINITIALIZED) {}
+
+ virtual ~TestCameraDeviceCallbacks() {}
+
+ virtual void onDeviceError(CameraErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
+ ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode));
+ Mutex::Autolock l(mLock);
+ mError = true;
+ mLastStatus = ERROR;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ virtual void onDeviceIdle() {
+ Mutex::Autolock l(mLock);
+ mLastStatus = IDLE;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ virtual void onCaptureStarted(const CaptureResultExtras& resultExtras,
+ int64_t timestamp) {
+ Mutex::Autolock l(mLock);
+ mLastStatus = RUNNING;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+
+ virtual void onResultReceived(const CameraMetadata& metadata,
+ const CaptureResultExtras& resultExtras) {
+ Mutex::Autolock l(mLock);
+ mLastStatus = SENT_RESULT;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ virtual void onPrepared(int streamId) {
+ Mutex::Autolock l(mLock);
+ mLastStatus = PREPARED;
+ mStatusesHit.push_back(mLastStatus);
+ mStatusCondition.broadcast();
+ }
+
+ // Test helper functions:
+
+ bool hadError() const {
+ Mutex::Autolock l(mLock);
+ return mError;
+ }
+
+ bool waitForStatus(Status status) const {
+ Mutex::Autolock l(mLock);
+ if (mLastStatus == status) {
+ return true;
+ }
+
+ while (std::find(mStatusesHit.begin(), mStatusesHit.end(), status)
+ == mStatusesHit.end()) {
+
+ if (mStatusCondition.waitRelative(mLock, IDLE_TIMEOUT) != OK) {
+ mStatusesHit.clear();
+ return false;
+ }
+ }
+ mStatusesHit.clear();
+
+ return true;
+
+ }
+
+ void clearStatus() const {
+ Mutex::Autolock l(mLock);
+ mStatusesHit.clear();
+ }
+
+ bool waitForIdle() const {
+ return waitForStatus(IDLE);
+ }
+
+};
+
+// Exercise basic binder calls for the camera service
+TEST(CameraServiceBinderTest, CheckBinderCameraService) {
+ ProcessState::self()->startThreadPool();
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.camera"));
+ ASSERT_NOT_NULL(binder);
+ sp<ICameraService> service = interface_cast<ICameraService>(binder);
+
+
+ int32_t numCameras = service->getNumberOfCameras();
+ EXPECT_LE(0, numCameras);
+
+ // Check listener binder calls
+ sp<TestCameraServiceListener> listener(new TestCameraServiceListener());
+ EXPECT_EQ(OK, service->addListener(listener));
+
+ EXPECT_TRUE(listener->waitForNumCameras(numCameras));
+
+ for (int32_t i = 0; i < numCameras; i++) {
+ // We only care about binder calls for the Camera2 API. Camera1 is deprecated.
+ status_t camera2Support = service->supportsCameraApi(i, ICameraService::API_VERSION_2);
+ if (camera2Support != OK) {
+ EXPECT_EQ(-EOPNOTSUPP, camera2Support);
+ continue;
+ }
+
+ // Check metadata binder call
+ CameraMetadata metadata;
+ EXPECT_EQ(OK, service->getCameraCharacteristics(i, &metadata));
+ EXPECT_FALSE(metadata.isEmpty());
+
+ // Make sure we're available, or skip device tests otherwise
+ ICameraServiceListener::Status s = listener->getStatus(i);
+ EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
+ if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+ continue;
+ }
+
+ // Check connect binder calls
+ sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
+ sp<ICameraDeviceUser> device;
+ EXPECT_EQ(OK, service->connectDevice(callbacks, i, String16("meeeeeeeee!"),
+ ICameraService::USE_CALLING_UID, /*out*/device));
+ ASSERT_NE(nullptr, device.get());
+ device->disconnect();
+ EXPECT_FALSE(callbacks->hadError());
+
+ ICameraServiceListener::TorchStatus torchStatus = listener->getTorchStatus(i);
+ if (torchStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
+ // Check torch calls
+ EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
+ /*enabled*/true, callbacks));
+ EXPECT_TRUE(listener->waitForTorchState(
+ ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
+ EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
+ /*enabled*/false, callbacks));
+ EXPECT_TRUE(listener->waitForTorchState(
+ ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
+ }
+ }
+
+ EXPECT_EQ(OK, service->removeListener(listener));
+}
+
+// Test fixture for client focused binder tests
+class CameraClientBinderTest : public testing::Test {
+protected:
+ sp<ICameraService> service;
+ int32_t numCameras;
+ std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>> openDeviceList;
+ sp<TestCameraServiceListener> serviceListener;
+
+ std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>> openNewDevice(int deviceId) {
+
+ sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
+ sp<ICameraDeviceUser> device;
+ {
+ SCOPED_TRACE("openNewDevice");
+ EXPECT_EQ(OK, service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
+ ICameraService::USE_CALLING_UID, /*out*/device));
+ }
+ auto p = std::make_pair(callbacks, device);
+ openDeviceList.push_back(p);
+ return p;
+ }
+
+ void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>& p) {
+ if (p.second.get() != nullptr) {
+ p.second->disconnect();
+ {
+ SCOPED_TRACE("closeDevice");
+ EXPECT_FALSE(p.first->hadError());
+ }
+ }
+ auto iter = std::find(openDeviceList.begin(), openDeviceList.end(), p);
+ if (iter != openDeviceList.end()) {
+ openDeviceList.erase(iter);
+ }
+ }
+
+ virtual void SetUp() {
+ ProcessState::self()->startThreadPool();
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.camera"));
+ service = interface_cast<ICameraService>(binder);
+ serviceListener = new TestCameraServiceListener();
+ service->addListener(serviceListener);
+ numCameras = service->getNumberOfCameras();
+ }
+
+ virtual void TearDown() {
+ service = nullptr;
+ numCameras = 0;
+ for (auto& p : openDeviceList) {
+ closeDevice(p);
+ }
+ }
+
+};
+
+TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
+ ASSERT_NOT_NULL(service);
+
+ EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
+ for (int32_t i = 0; i < numCameras; i++) {
+ // Make sure we're available, or skip device tests otherwise
+ ICameraServiceListener::Status s = serviceListener->getStatus(i);
+ EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
+ if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+ continue;
+ }
+
+ auto p = openNewDevice(i);
+ sp<TestCameraDeviceCallbacks> callbacks = p.first;
+ sp<ICameraDeviceUser> device = p.second;
+
+ // Setup a buffer queue; I'm just using the vendor opaque format here as that is
+ // guaranteed to be present
+ sp<IGraphicBufferProducer> gbProducer;
+ sp<IGraphicBufferConsumer> gbConsumer;
+ BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
+ sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer,
+ GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/2, /*controlledByApp*/true);
+ EXPECT_TRUE(opaqueConsumer.get() != nullptr);
+ opaqueConsumer->setName(String8("nom nom nom"));
+
+ // Set to VGA dimens for default, as that is guaranteed to be present
+ EXPECT_EQ(OK, gbConsumer->setDefaultBufferSize(640, 480));
+ EXPECT_EQ(OK, gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED));
+
+ sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
+
+ OutputConfiguration output(gbProducer, /*rotation*/0);
+
+ // Can we configure?
+ EXPECT_EQ(OK, device->beginConfigure());
+ status_t streamId = device->createStream(output);
+ EXPECT_LE(0, streamId);
+ EXPECT_EQ(OK, device->endConfigure());
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we make requests?
+ CameraMetadata requestTemplate;
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate));
+ sp<CaptureRequest> request(new CaptureRequest());
+ request->mMetadata = requestTemplate;
+ request->mSurfaceList.add(surface);
+ request->mIsReprocess = false;
+ int64_t lastFrameNumber = 0;
+ int64_t lastFrameNumberPrev = 0;
+ callbacks->clearStatus();
+ int requestId = device->submitRequest(request, /*streaming*/true, /*out*/&lastFrameNumber);
+ EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+ EXPECT_LE(0, requestId);
+
+ // Can we stop requests?
+ EXPECT_EQ(OK, device->cancelRequest(requestId, /*out*/&lastFrameNumber));
+ EXPECT_TRUE(callbacks->waitForIdle());
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we do it again?
+ lastFrameNumberPrev = lastFrameNumber;
+ lastFrameNumber = 0;
+ requestTemplate.clear();
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate));
+ sp<CaptureRequest> request2(new CaptureRequest());
+ request2->mMetadata = requestTemplate;
+ request2->mSurfaceList.add(surface);
+ request2->mIsReprocess = false;
+ callbacks->clearStatus();
+ int requestId2 = device->submitRequest(request2, /*streaming*/true,
+ /*out*/&lastFrameNumber);
+ EXPECT_EQ(-1, lastFrameNumber);
+ lastFrameNumber = 0;
+ EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+ EXPECT_LE(0, requestId2);
+ EXPECT_EQ(OK, device->cancelRequest(requestId2, /*out*/&lastFrameNumber));
+ EXPECT_TRUE(callbacks->waitForIdle());
+ EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+ sleep(/*second*/1); // allow some time for errors to show up, if any
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we do it with a request list?
+ lastFrameNumberPrev = lastFrameNumber;
+ lastFrameNumber = 0;
+ requestTemplate.clear();
+ CameraMetadata requestTemplate2;
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate));
+ EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+ /*out*/&requestTemplate2));
+ sp<CaptureRequest> request3(new CaptureRequest());
+ sp<CaptureRequest> request4(new CaptureRequest());
+ request3->mMetadata = requestTemplate;
+ request3->mSurfaceList.add(surface);
+ request3->mIsReprocess = false;
+ request4->mMetadata = requestTemplate2;
+ request4->mSurfaceList.add(surface);
+ request4->mIsReprocess = false;
+ List<sp<CaptureRequest>> requestList;
+ requestList.push_back(request3);
+ requestList.push_back(request4);
+
+ callbacks->clearStatus();
+ int requestId3 = device->submitRequestList(requestList, /*streaming*/false,
+ /*out*/&lastFrameNumber);
+ EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+ EXPECT_TRUE(callbacks->waitForIdle());
+ EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+ sleep(/*second*/1); // allow some time for errors to show up, if any
+ EXPECT_FALSE(callbacks->hadError());
+
+ // Can we unconfigure?
+ EXPECT_EQ(OK, device->beginConfigure());
+ EXPECT_EQ(OK, device->deleteStream(streamId));
+ EXPECT_EQ(OK, device->endConfigure());
+ sleep(/*second*/1); // allow some time for errors to show up, if any
+ EXPECT_FALSE(callbacks->hadError());
+
+ closeDevice(p);
+ }
+
+};
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
deleted file mode 100644
index 1f5867a..0000000
--- a/camera/tests/ProCameraTests.cpp
+++ /dev/null
@@ -1,1278 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include <gtest/gtest.h>
-#include <iostream>
-
-#include <binder/IPCThreadState.h>
-#include <utils/Thread.h>
-
-#include "Camera.h"
-#include "ProCamera.h"
-#include <utils/Vector.h>
-#include <utils/Mutex.h>
-#include <utils/Condition.h>
-
-#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
-
-#include <system/camera_metadata.h>
-#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only
-#include <camera/CameraMetadata.h>
-
-#include <camera/ICameraServiceListener.h>
-
-namespace android {
-namespace camera2 {
-namespace tests {
-namespace client {
-
-#define CAMERA_ID 0
-#define TEST_DEBUGGING 0
-
-#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout
-#define TEST_FORMAT HAL_PIXEL_FORMAT_Y16 //TODO: YUY2 instead
-
-#define TEST_FORMAT_MAIN HAL_PIXEL_FORMAT_Y8
-#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16
-
-// defaults for display "test"
-#define TEST_DISPLAY_FORMAT HAL_PIXEL_FORMAT_Y8
-#define TEST_DISPLAY_WIDTH 320
-#define TEST_DISPLAY_HEIGHT 240
-
-#define TEST_CPU_FRAME_COUNT 2
-#define TEST_CPU_HEAP_COUNT 5
-
-#define TEST_FRAME_PROCESSING_DELAY_US 200000 // 200 ms
-
-#if TEST_DEBUGGING
-#define dout std::cerr
-#else
-#define dout if (0) std::cerr
-#endif
-
-#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
-#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
-
-class ProCameraTest;
-
-struct ServiceListener : public BnCameraServiceListener {
-
- ServiceListener() :
- mLatestStatus(STATUS_UNKNOWN),
- mPrevStatus(STATUS_UNKNOWN)
- {
- }
-
- void onStatusChanged(Status status, int32_t cameraId) {
- dout << "On status changed: 0x" << std::hex
- << (unsigned int) status << " cameraId " << cameraId
- << std::endl;
-
- Mutex::Autolock al(mMutex);
-
- mLatestStatus = status;
- mCondition.broadcast();
- }
-
- status_t waitForStatusChange(Status& newStatus) {
- Mutex::Autolock al(mMutex);
-
- if (mLatestStatus != mPrevStatus) {
- newStatus = mLatestStatus;
- mPrevStatus = mLatestStatus;
- return OK;
- }
-
- status_t stat = mCondition.waitRelative(mMutex,
- TEST_LISTENER_TIMEOUT);
-
- if (stat == OK) {
- newStatus = mLatestStatus;
- mPrevStatus = mLatestStatus;
- }
-
- return stat;
- }
-
- Condition mCondition;
- Mutex mMutex;
-
- Status mLatestStatus;
- Status mPrevStatus;
-};
-
-enum ProEvent {
- UNKNOWN,
- ACQUIRED,
- RELEASED,
- STOLEN,
- FRAME_RECEIVED,
- RESULT_RECEIVED,
-};
-
-inline int ProEvent_Mask(ProEvent e) {
- return (1 << static_cast<int>(e));
-}
-
-typedef Vector<ProEvent> EventList;
-
-class ProCameraTestThread : public Thread
-{
-public:
- ProCameraTestThread() {
- }
-
- virtual bool threadLoop() {
- mProc = ProcessState::self();
- mProc->startThreadPool();
-
- IPCThreadState *ptr = IPCThreadState::self();
-
- ptr->joinThreadPool();
-
- return false;
- }
-
- sp<ProcessState> mProc;
-};
-
-class ProCameraTestListener : public ProCameraListener {
-
-public:
- static const int EVENT_MASK_ALL = 0xFFFFFFFF;
-
- ProCameraTestListener() {
- mEventMask = EVENT_MASK_ALL;
- mDropFrames = false;
- }
-
- status_t WaitForEvent() {
- Mutex::Autolock cal(mConditionMutex);
-
- {
- Mutex::Autolock al(mListenerMutex);
-
- if (mProEventList.size() > 0) {
- return OK;
- }
- }
-
- return mListenerCondition.waitRelative(mConditionMutex,
- TEST_LISTENER_TIMEOUT);
- }
-
- /* Read events into out. Existing queue is flushed */
- void ReadEvents(EventList& out) {
- Mutex::Autolock al(mListenerMutex);
-
- for (size_t i = 0; i < mProEventList.size(); ++i) {
- out.push(mProEventList[i]);
- }
-
- mProEventList.clear();
- }
-
- /**
- * Dequeue 1 event from the event queue.
- * Returns UNKNOWN if queue is empty
- */
- ProEvent ReadEvent() {
- Mutex::Autolock al(mListenerMutex);
-
- if (mProEventList.size() == 0) {
- return UNKNOWN;
- }
-
- ProEvent ev = mProEventList[0];
- mProEventList.removeAt(0);
-
- return ev;
- }
-
- void SetEventMask(int eventMask) {
- Mutex::Autolock al(mListenerMutex);
- mEventMask = eventMask;
- }
-
- // Automatically acquire/release frames as they are available
- void SetDropFrames(bool dropFrames) {
- Mutex::Autolock al(mListenerMutex);
- mDropFrames = dropFrames;
- }
-
-private:
- void QueueEvent(ProEvent ev) {
- bool eventAdded = false;
- {
- Mutex::Autolock al(mListenerMutex);
-
- // Drop events not part of mask
- if (ProEvent_Mask(ev) & mEventMask) {
- mProEventList.push(ev);
- eventAdded = true;
- }
- }
-
- if (eventAdded) {
- mListenerCondition.broadcast();
- }
- }
-
-protected:
-
- //////////////////////////////////////////////////
- ///////// ProCameraListener //////////////////////
- //////////////////////////////////////////////////
-
-
- // Lock has been acquired. Write operations now available.
- virtual void onLockAcquired() {
- QueueEvent(ACQUIRED);
- }
- // Lock has been released with exclusiveUnlock
- virtual void onLockReleased() {
- QueueEvent(RELEASED);
- }
-
- // Lock has been stolen by another client.
- virtual void onLockStolen() {
- QueueEvent(STOLEN);
- }
-
- // Lock free.
- virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) {
-
- dout << "Trigger notify: " << ext1 << " " << ext2
- << " " << ext3 << std::endl;
- }
-
- virtual void onFrameAvailable(int streamId,
- const sp<CpuConsumer>& consumer) {
-
- QueueEvent(FRAME_RECEIVED);
-
- Mutex::Autolock al(mListenerMutex);
- if (mDropFrames) {
- CpuConsumer::LockedBuffer buf;
- status_t ret;
-
- if (OK == (ret = consumer->lockNextBuffer(&buf))) {
-
- dout << "Frame received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
- } else {
- dout << "Frame received on streamId = " << streamId << std::endl;
- }
- }
-
- virtual void onResultReceived(int32_t requestId,
- camera_metadata* request) {
- dout << "Result received requestId = " << requestId
- << ", requestPtr = " << (void*)request << std::endl;
- QueueEvent(RESULT_RECEIVED);
- free_camera_metadata(request);
- }
-
- virtual void notify(int32_t msg, int32_t ext1, int32_t ext2) {
- dout << "Notify received: msg " << std::hex << msg
- << ", ext1: " << std::hex << ext1 << ", ext2: " << std::hex << ext2
- << std::endl;
- }
-
- Vector<ProEvent> mProEventList;
- Mutex mListenerMutex;
- Mutex mConditionMutex;
- Condition mListenerCondition;
- int mEventMask;
- bool mDropFrames;
-};
-
-class ProCameraTest : public ::testing::Test {
-
-public:
- ProCameraTest() {
- char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
- if (displaySecsEnv != NULL) {
- mDisplaySecs = atoi(displaySecsEnv);
- if (mDisplaySecs < 0) {
- mDisplaySecs = 0;
- }
- } else {
- mDisplaySecs = 0;
- }
-
- char* displayFmtEnv = getenv("TEST_DISPLAY_FORMAT");
- if (displayFmtEnv != NULL) {
- mDisplayFmt = FormatFromString(displayFmtEnv);
- } else {
- mDisplayFmt = TEST_DISPLAY_FORMAT;
- }
-
- char* displayWidthEnv = getenv("TEST_DISPLAY_WIDTH");
- if (displayWidthEnv != NULL) {
- mDisplayW = atoi(displayWidthEnv);
- if (mDisplayW < 0) {
- mDisplayW = 0;
- }
- } else {
- mDisplayW = TEST_DISPLAY_WIDTH;
- }
-
- char* displayHeightEnv = getenv("TEST_DISPLAY_HEIGHT");
- if (displayHeightEnv != NULL) {
- mDisplayH = atoi(displayHeightEnv);
- if (mDisplayH < 0) {
- mDisplayH = 0;
- }
- } else {
- mDisplayH = TEST_DISPLAY_HEIGHT;
- }
- }
-
- static void SetUpTestCase() {
- // Binder Thread Pool Initialization
- mTestThread = new ProCameraTestThread();
- mTestThread->run("ProCameraTestThread");
- }
-
- virtual void SetUp() {
- mCamera = ProCamera::connect(CAMERA_ID);
- ASSERT_NE((void*)NULL, mCamera.get());
-
- mListener = new ProCameraTestListener();
- mCamera->setListener(mListener);
- }
-
- virtual void TearDown() {
- ASSERT_NE((void*)NULL, mCamera.get());
- mCamera->disconnect();
- }
-
-protected:
- sp<ProCamera> mCamera;
- sp<ProCameraTestListener> mListener;
-
- static sp<Thread> mTestThread;
-
- int mDisplaySecs;
- int mDisplayFmt;
- int mDisplayW;
- int mDisplayH;
-
- sp<SurfaceComposerClient> mComposerClient;
- sp<SurfaceControl> mSurfaceControl;
-
- sp<SurfaceComposerClient> mDepthComposerClient;
- sp<SurfaceControl> mDepthSurfaceControl;
-
- int getSurfaceWidth() {
- return 512;
- }
- int getSurfaceHeight() {
- return 512;
- }
-
- void createOnScreenSurface(sp<Surface>& surface) {
- mComposerClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
-
- mSurfaceControl = mComposerClient->createSurface(
- String8("ProCameraTest StreamingImage Surface"),
- getSurfaceWidth(), getSurfaceHeight(),
- PIXEL_FORMAT_RGB_888, 0);
-
- mSurfaceControl->setPosition(0, 0);
-
- ASSERT_TRUE(mSurfaceControl != NULL);
- ASSERT_TRUE(mSurfaceControl->isValid());
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
- ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
-
- sp<ANativeWindow> window = mSurfaceControl->getSurface();
- surface = mSurfaceControl->getSurface();
-
- ASSERT_NE((void*)NULL, surface.get());
- }
-
- void createDepthOnScreenSurface(sp<Surface>& surface) {
- mDepthComposerClient = new SurfaceComposerClient;
- ASSERT_EQ(NO_ERROR, mDepthComposerClient->initCheck());
-
- mDepthSurfaceControl = mDepthComposerClient->createSurface(
- String8("ProCameraTest StreamingImage Surface"),
- getSurfaceWidth(), getSurfaceHeight(),
- PIXEL_FORMAT_RGB_888, 0);
-
- mDepthSurfaceControl->setPosition(640, 0);
-
- ASSERT_TRUE(mDepthSurfaceControl != NULL);
- ASSERT_TRUE(mDepthSurfaceControl->isValid());
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->setLayer(0x7FFFFFFF));
- ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
-
- sp<ANativeWindow> window = mDepthSurfaceControl->getSurface();
- surface = mDepthSurfaceControl->getSurface();
-
- ASSERT_NE((void*)NULL, surface.get());
- }
-
- template <typename T>
- static bool ExistsItem(T needle, T* array, size_t count) {
- if (!array) {
- return false;
- }
-
- for (size_t i = 0; i < count; ++i) {
- if (array[i] == needle) {
- return true;
- }
- }
- return false;
- }
-
-
- static int FormatFromString(const char* str) {
- std::string s(str);
-
-#define CMP_STR(x, y) \
- if (s == #x) return HAL_PIXEL_FORMAT_ ## y;
-#define CMP_STR_SAME(x) CMP_STR(x, x)
-
- CMP_STR_SAME( Y16);
- CMP_STR_SAME( Y8);
- CMP_STR_SAME( YV12);
- 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(RGBA, RGBA_8888);
-
- std::cerr << "Unknown format string " << str << std::endl;
- return -1;
-
- }
-
- /**
- * Creating a streaming request for these output streams from a template,
- * and submit it
- */
- void createSubmitRequestForStreams(int32_t* streamIds, size_t count, int requestCount=-1) {
-
- ASSERT_NE((void*)NULL, streamIds);
- ASSERT_LT(0u, count);
-
- camera_metadata_t *requestTmp = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&requestTmp));
- ASSERT_NE((void*)NULL, requestTmp);
- CameraMetadata request(requestTmp);
-
- // set the output streams. default is empty
-
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- request.update(tag, streamIds, count);
-
- requestTmp = request.release();
-
- if (requestCount < 0) {
- EXPECT_OK(mCamera->submitRequest(requestTmp, /*streaming*/true));
- } else {
- for (int i = 0; i < requestCount; ++i) {
- EXPECT_OK(mCamera->submitRequest(requestTmp,
- /*streaming*/false));
- }
- }
- request.acquire(requestTmp);
- }
-};
-
-sp<Thread> ProCameraTest::mTestThread;
-
-TEST_F(ProCameraTest, AvailableFormats) {
- if (HasFatalFailure()) {
- return;
- }
-
- CameraMetadata staticInfo = mCamera->getCameraInfo(CAMERA_ID);
- ASSERT_FALSE(staticInfo.isEmpty());
-
- uint32_t tag = static_cast<uint32_t>(ANDROID_SCALER_AVAILABLE_FORMATS);
- EXPECT_TRUE(staticInfo.exists(tag));
- camera_metadata_entry_t entry = staticInfo.find(tag);
-
- EXPECT_TRUE(ExistsItem<int32_t>(HAL_PIXEL_FORMAT_YV12,
- entry.data.i32, entry.count));
- EXPECT_TRUE(ExistsItem<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP,
- entry.data.i32, entry.count));
-}
-
-// test around exclusiveTryLock (immediate locking)
-TEST_F(ProCameraTest, LockingImmediate) {
-
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
- ProEvent_Mask(STOLEN) |
- ProEvent_Mask(RELEASED));
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveTryLock());
- // at this point we definitely have the lock
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
-
- EXPECT_TRUE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveUnlock());
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(RELEASED, mListener->ReadEvent());
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
-}
-
-// test around exclusiveLock (locking at some future point in time)
-TEST_F(ProCameraTest, LockingAsynchronous) {
-
- if (HasFatalFailure()) {
- return;
- }
-
-
- mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
- ProEvent_Mask(STOLEN) |
- ProEvent_Mask(RELEASED));
-
- // TODO: Add another procamera that has a lock here.
- // then we can be test that the lock wont immediately be acquired
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveTryLock());
- // at this point we definitely have the lock
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
-
- EXPECT_TRUE(mCamera->hasExclusiveLock());
- EXPECT_EQ(OK, mCamera->exclusiveUnlock());
-
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(RELEASED, mListener->ReadEvent());
-
- EXPECT_FALSE(mCamera->hasExclusiveLock());
-}
-
-// Stream directly to the screen.
-TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
- if (HasFatalFailure()) {
- return;
- }
-
- sp<Surface> surface;
- if (mDisplaySecs > 0) {
- createOnScreenSurface(/*out*/surface);
- }
- else {
- dout << "Skipping, will not render to screen" << std::endl;
- return;
- }
-
- int depthStreamId = -1;
-
- sp<ServiceListener> listener = new ServiceListener();
- EXPECT_OK(ProCamera::addServiceListener(listener));
-
- ServiceListener::Status currentStatus;
-
- // when subscribing a new listener,
- // we immediately get a callback to the current status
- while (listener->waitForStatusChange(/*out*/currentStatus) != OK);
- EXPECT_EQ(ServiceListener::STATUS_PRESENT, currentStatus);
-
- dout << "Will now stream and resume infinitely..." << std::endl;
- while (true) {
-
- if (currentStatus == ServiceListener::STATUS_PRESENT) {
-
- ASSERT_OK(mCamera->createStream(mDisplayW, mDisplayH, mDisplayFmt,
- surface,
- &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { depthStreamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(
- streams,
- /*count*/1));
- }
-
- ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
-
- // TODO: maybe check for getch every once in a while?
- while (listener->waitForStatusChange(/*out*/stat) != OK);
-
- if (currentStatus != stat) {
- if (stat == ServiceListener::STATUS_PRESENT) {
- dout << "Reconnecting to camera" << std::endl;
- mCamera = ProCamera::connect(CAMERA_ID);
- } else if (stat == ServiceListener::STATUS_NOT_AVAILABLE) {
- dout << "Disconnecting from camera" << std::endl;
- mCamera->disconnect();
- } else if (stat == ServiceListener::STATUS_NOT_PRESENT) {
- dout << "Camera unplugged" << std::endl;
- mCamera = NULL;
- } else {
- dout << "Unknown status change "
- << std::hex << stat << std::endl;
- }
-
- currentStatus = stat;
- }
- }
-
- EXPECT_OK(ProCamera::removeServiceListener(listener));
- EXPECT_OK(mCamera->deleteStream(depthStreamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-// Stream directly to the screen.
-TEST_F(ProCameraTest, DISABLED_StreamingImageDual) {
- if (HasFatalFailure()) {
- return;
- }
- sp<Surface> surface;
- sp<Surface> depthSurface;
- if (mDisplaySecs > 0) {
- createOnScreenSurface(/*out*/surface);
- createDepthOnScreenSurface(/*out*/depthSurface);
- }
-
- int streamId = -1;
- EXPECT_OK(mCamera->createStream(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, surface, &streamId));
- EXPECT_NE(-1, streamId);
-
- int depthStreamId = -1;
- EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- /*
- */
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- // it would probably be better to use CameraMetadata from camera service.
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- /*FIXME: dont need this later, at which point the above should become an
- ASSERT_NE*/
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- // wow what a verbose API.
- int32_t allStreams[] = { streamId, depthStreamId };
- // IMPORTANT. bad things will happen if its not a uint8.
- size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/streamCount, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- dout << "will sleep now for " << mDisplaySecs << std::endl;
- sleep(mDisplaySecs);
-
- free_camera_metadata(request);
-
- for (size_t i = 0; i < streamCount; ++i) {
- EXPECT_OK(mCamera->deleteStream(allStreams[i]));
- }
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, CpuConsumerSingle) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
- ProEvent_Mask(STOLEN) |
- ProEvent_Mask(RELEASED) |
- ProEvent_Mask(FRAME_RECEIVED));
- mListener->SetDropFrames(true);
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- // it would probably be better to use CameraMetadata from camera service.
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- /*FIXME: dont need this later, at which point the above should become an
- ASSERT_NE*/
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- int32_t allStreams[] = { streamId };
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/1) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/1));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/1, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- // Consume a couple of frames
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
- }
-
- // Done: clean up
- free_camera_metadata(request);
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, CpuConsumerDual) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(FRAME_RECEIVED));
- mListener->SetDropFrames(true);
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- int depthStreamId = -1;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &consumer, &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- /*
- */
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- // it would probably be better to use CameraMetadata from camera service.
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- // wow what a verbose API.
- int32_t allStreams[] = { streamId, depthStreamId };
- size_t streamCount = 2;
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/streamCount, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- // Consume a couple of frames
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- // stream id 1
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
-
- // stream id 2
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
-
- //TODO: events should be a struct with some data like the stream id
- }
-
- // Done: clean up
- free_camera_metadata(request);
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, ResultReceiver) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
- mListener->SetDropFrames(true);
- //FIXME: if this is run right after the previous test we get FRAME_RECEIVED
- // need to filter out events at read time
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
- /*
- */
- /* iterate in a loop submitting requests every frame.
- * what kind of requests doesnt really matter, just whatever.
- */
-
- camera_metadata_t *request = NULL;
- EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
- /*out*/&request));
- EXPECT_NE((void*)NULL, request);
-
- /*FIXME*/
- if(request == NULL) request = allocate_camera_metadata(10, 100);
-
- // set the output streams to just this stream ID
-
- int32_t allStreams[] = { streamId };
- size_t streamCount = 1;
- camera_metadata_entry_t entry;
- uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
- int find = find_camera_metadata_entry(request, tag, &entry);
- if (find == -ENOENT) {
- if (add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount) != OK) {
- camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
- ASSERT_OK(append_camera_metadata(tmp, request));
- free_camera_metadata(request);
- request = tmp;
-
- ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
- /*data_count*/streamCount));
- }
- } else {
- ASSERT_OK(update_camera_metadata_entry(request, entry.index,
- &allStreams, /*data_count*/streamCount, &entry));
- }
-
- EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
-
- // Consume a couple of results
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(RESULT_RECEIVED, mListener->ReadEvent());
- }
-
- // Done: clean up
- free_camera_metadata(request);
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-// FIXME: This is racy and sometimes fails on waitForFrameMetadata
-TEST_F(ProCameraTest, DISABLED_WaitForResult) {
- if (HasFatalFailure()) {
- return;
- }
-
- mListener->SetDropFrames(true);
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1));
-
- // Consume a couple of results
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_OK(mCamera->waitForFrameMetadata());
- CameraMetadata meta = mCamera->consumeFrameMetadata();
- EXPECT_FALSE(meta.isEmpty());
- }
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, WaitForSingleStreamBuffer) {
- if (HasFatalFailure()) {
- return;
- }
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
- /*requests*/TEST_CPU_FRAME_COUNT));
-
- // Consume a couple of results
- for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
- EXPECT_EQ(1, mCamera->waitForFrameBuffer(streamId));
-
- CpuConsumer::LockedBuffer buf;
- EXPECT_OK(consumer->lockNextBuffer(&buf));
-
- dout << "Buffer synchronously received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-// FIXME: This is racy and sometimes fails on waitForFrameMetadata
-TEST_F(ProCameraTest, DISABLED_WaitForDualStreamBuffer) {
- if (HasFatalFailure()) {
- return;
- }
-
- const int REQUEST_COUNT = TEST_CPU_FRAME_COUNT * 10;
-
- // 15 fps
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- // 30 fps
- int depthStreamId = -1;
- sp<CpuConsumer> depthConsumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
- TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &depthConsumer, &depthStreamId));
- EXPECT_NE(-1, depthStreamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId, depthStreamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/2,
- /*requests*/REQUEST_COUNT));
-
- int depthFrames = 0;
- int greyFrames = 0;
-
- // Consume two frames simultaneously. Unsynchronized by timestamps.
- for (int i = 0; i < REQUEST_COUNT; ++i) {
-
- // Exhaust event queue so it doesn't keep growing
- while (mListener->ReadEvent() != UNKNOWN);
-
- // Get the metadata
- EXPECT_OK(mCamera->waitForFrameMetadata());
- CameraMetadata meta = mCamera->consumeFrameMetadata();
- EXPECT_FALSE(meta.isEmpty());
-
- // Get the buffers
-
- EXPECT_EQ(1, mCamera->waitForFrameBuffer(depthStreamId));
-
- /**
- * Guaranteed to be able to consume the depth frame,
- * since we waited on it.
- */
- CpuConsumer::LockedBuffer depthBuffer;
- EXPECT_OK(depthConsumer->lockNextBuffer(&depthBuffer));
-
- dout << "Depth Buffer synchronously received on streamId = " <<
- streamId <<
- ", dataPtr = " << (void*)depthBuffer.data <<
- ", timestamp = " << depthBuffer.timestamp << std::endl;
-
- EXPECT_OK(depthConsumer->unlockBuffer(depthBuffer));
-
- depthFrames++;
-
-
- /** Consume Greyscale frames if there are any.
- * There may not be since it runs at half FPS */
- CpuConsumer::LockedBuffer greyBuffer;
- while (consumer->lockNextBuffer(&greyBuffer) == OK) {
-
- dout << "GRAY Buffer synchronously received on streamId = " <<
- streamId <<
- ", dataPtr = " << (void*)greyBuffer.data <<
- ", timestamp = " << greyBuffer.timestamp << std::endl;
-
- EXPECT_OK(consumer->unlockBuffer(greyBuffer));
-
- greyFrames++;
- }
- }
-
- dout << "Done, summary: depth frames " << std::dec << depthFrames
- << ", grey frames " << std::dec << greyFrames << std::endl;
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesSync) {
- if (HasFatalFailure()) {
- return;
- }
-
- const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
- /*synchronousMode*/true, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
- /*requests*/NUM_REQUESTS));
-
- // Consume a couple of results
- for (int i = 0; i < NUM_REQUESTS; ++i) {
- int numFrames;
- EXPECT_TRUE((numFrames = mCamera->waitForFrameBuffer(streamId)) > 0);
-
- // Drop all but the newest framebuffer
- EXPECT_EQ(numFrames-1, mCamera->dropFrameBuffer(streamId, numFrames-1));
-
- dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;
-
- // Skip the counter ahead, don't try to consume these frames again
- i += numFrames-1;
-
- // "Consume" the buffer
- CpuConsumer::LockedBuffer buf;
- EXPECT_OK(consumer->lockNextBuffer(&buf));
-
- dout << "Buffer synchronously received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
-
- // Process at 10fps, stream is at 15fps.
- // This means we will definitely fill up the buffer queue with
- // extra buffers and need to drop them.
- usleep(TEST_FRAME_PROCESSING_DELAY_US);
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesAsync) {
- if (HasFatalFailure()) {
- return;
- }
-
- const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;
-
- int streamId = -1;
- sp<CpuConsumer> consumer;
- EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
- TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
- /*synchronousMode*/false, &consumer, &streamId));
- EXPECT_NE(-1, streamId);
-
- EXPECT_OK(mCamera->exclusiveTryLock());
-
- int32_t streams[] = { streamId };
- ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
- /*requests*/NUM_REQUESTS));
-
- uint64_t lastFrameNumber = 0;
- int numFrames;
-
- // Consume a couple of results
- int i;
- for (i = 0; i < NUM_REQUESTS && lastFrameNumber < NUM_REQUESTS; ++i) {
- EXPECT_LT(0, (numFrames = mCamera->waitForFrameBuffer(streamId)));
-
- dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;
-
- // Skip the counter ahead, don't try to consume these frames again
- i += numFrames-1;
-
- // "Consume" the buffer
- CpuConsumer::LockedBuffer buf;
-
- EXPECT_EQ(OK, consumer->lockNextBuffer(&buf));
-
- lastFrameNumber = buf.frameNumber;
-
- dout << "Buffer asynchronously received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp <<
- ", framenumber = " << buf.frameNumber << std::endl;
-
- // Process at 10fps, stream is at 15fps.
- // This means we will definitely fill up the buffer queue with
- // extra buffers and need to drop them.
- usleep(TEST_FRAME_PROCESSING_DELAY_US);
-
- EXPECT_OK(consumer->unlockBuffer(buf));
- }
-
- dout << "Done after " << i << " iterations " << std::endl;
-
- // Done: clean up
- EXPECT_OK(mCamera->deleteStream(streamId));
- EXPECT_OK(mCamera->exclusiveUnlock());
-}
-
-
-
-//TODO: refactor into separate file
-TEST_F(ProCameraTest, ServiceListenersSubscribe) {
-
- ASSERT_EQ(4u, sizeof(ServiceListener::Status));
-
- sp<ServiceListener> listener = new ServiceListener();
-
- EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
- EXPECT_OK(ProCamera::addServiceListener(listener));
-
- EXPECT_EQ(ALREADY_EXISTS, ProCamera::addServiceListener(listener));
- EXPECT_OK(ProCamera::removeServiceListener(listener));
-
- EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
-}
-
-//TODO: refactor into separate file
-TEST_F(ProCameraTest, ServiceListenersFunctional) {
-
- sp<ServiceListener> listener = new ServiceListener();
-
- EXPECT_OK(ProCamera::addServiceListener(listener));
-
- sp<Camera> cam = Camera::connect(CAMERA_ID,
- /*clientPackageName*/String16(),
- -1);
- EXPECT_NE((void*)NULL, cam.get());
-
- ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
- EXPECT_OK(listener->waitForStatusChange(/*out*/stat));
-
- EXPECT_EQ(ServiceListener::STATUS_NOT_AVAILABLE, stat);
-
- if (cam.get()) {
- cam->disconnect();
- }
-
- EXPECT_OK(listener->waitForStatusChange(/*out*/stat));
- EXPECT_EQ(ServiceListener::STATUS_PRESENT, stat);
-
- EXPECT_OK(ProCamera::removeServiceListener(listener));
-}
-
-
-
-}
-}
-}
-}
diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp
index 6624e79..9082dbf 100644
--- a/camera/tests/VendorTagDescriptorTests.cpp
+++ b/camera/tests/VendorTagDescriptorTests.cpp
@@ -53,6 +53,10 @@ static bool ContainsTag(uint32_t* tagArray, size_t size, uint32_t tag) {
extern "C" {
+static int zero_get_tag_count(const vendor_tag_ops_t* vOps) {
+ return 0;
+}
+
static int default_get_tag_count(const vendor_tag_ops_t* vOps) {
return VENDOR_TAG_COUNT_ERR;
}
@@ -173,10 +177,13 @@ TEST(VendorTagDescriptorTest, ErrorConditions) {
vendor_tag_ops_t vOps;
FillWithDefaults(&vOps);
+ // Make empty tag count
+ vOps.get_tag_count = zero_get_tag_count;
+
// Ensure create fails when using null vOps
EXPECT_EQ(BAD_VALUE, VendorTagDescriptor::createDescriptorFromOps(/*vOps*/NULL, vDesc));
- // Ensure create works when there are no vtags defined in a well-formed vOps
+ // Ensure creat succeeds for empty vendor tag ops
ASSERT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(&vOps, vDesc));
// Ensure defaults are returned when no vtags are defined, or tag is unknown