blob: bda568ae74d2c7b5357f754b12ec71ea807cc315 [file] [log] [blame]
Igor Murashkine7ee7632013-06-11 18:10:18 -07001/*
Shuzhen Wangc28189a2017-11-27 23:05:10 -08002 * Copyright (C) 2013-2018 The Android Open Source Project
Igor Murashkine7ee7632013-06-11 18:10:18 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "CameraDeviceClient"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
Jianing Weicb0652e2014-03-12 18:29:36 -070019//#define LOG_NDEBUG 0
Igor Murashkine7ee7632013-06-11 18:10:18 -070020
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070021#include <cutils/properties.h>
Igor Murashkine7ee7632013-06-11 18:10:18 -070022#include <utils/Log.h>
23#include <utils/Trace.h>
Igor Murashkine7ee7632013-06-11 18:10:18 -070024#include <gui/Surface.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070025#include <camera/camera2/CaptureRequest.h>
Ruben Brunk5698d442014-06-18 10:39:40 -070026#include <camera/CameraUtils.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070027
28#include "common/CameraDeviceBase.h"
29#include "api2/CameraDeviceClient.h"
30
Emilian Peev00420d22018-02-05 21:33:13 +000031#include <camera_metadata_hidden.h>
32
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080033// Convenience methods for constructing binder::Status objects for error returns
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070034
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080035#define STATUS_ERROR(errorCode, errorString) \
36 binder::Status::fromServiceSpecificError(errorCode, \
Eino-Ville Talvala02bf0322016-02-18 12:41:10 -080037 String8::format("%s:%d: %s", __FUNCTION__, __LINE__, errorString))
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080038
39#define STATUS_ERROR_FMT(errorCode, errorString, ...) \
40 binder::Status::fromServiceSpecificError(errorCode, \
Eino-Ville Talvala02bf0322016-02-18 12:41:10 -080041 String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, \
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080042 __VA_ARGS__))
Igor Murashkine7ee7632013-06-11 18:10:18 -070043
44namespace android {
45using namespace camera2;
46
47CameraDeviceClientBase::CameraDeviceClientBase(
48 const sp<CameraService>& cameraService,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080049 const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
Igor Murashkine7ee7632013-06-11 18:10:18 -070050 const String16& clientPackageName,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080051 const String8& cameraId,
Igor Murashkine7ee7632013-06-11 18:10:18 -070052 int cameraFacing,
53 int clientPid,
54 uid_t clientUid,
55 int servicePid) :
Eino-Ville Talvalae992e752014-11-07 16:17:48 -080056 BasicClient(cameraService,
Marco Nelissenf8880202014-11-14 07:58:25 -080057 IInterface::asBinder(remoteCallback),
Eino-Ville Talvalae992e752014-11-07 16:17:48 -080058 clientPackageName,
59 cameraId,
60 cameraFacing,
61 clientPid,
62 clientUid,
63 servicePid),
Igor Murashkine7ee7632013-06-11 18:10:18 -070064 mRemoteCallback(remoteCallback) {
65}
Igor Murashkine7ee7632013-06-11 18:10:18 -070066
67// Interface used by CameraService
68
69CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080070 const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
71 const String16& clientPackageName,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080072 const String8& cameraId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080073 int cameraFacing,
74 int clientPid,
75 uid_t clientUid,
76 int servicePid) :
Igor Murashkine7ee7632013-06-11 18:10:18 -070077 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
78 cameraId, cameraFacing, clientPid, clientUid, servicePid),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070079 mInputStream(),
Chien-Yu Chene8c535e2016-04-14 12:18:26 -070080 mStreamingRequestId(REQUEST_ID_NONE),
Igor Murashkine7ee7632013-06-11 18:10:18 -070081 mRequestIdCounter(0) {
82
83 ATRACE_CALL();
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080084 ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -070085}
86
Emilian Peevbd8c5032018-02-14 23:05:40 +000087status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
88 const String8& monitorTags) {
89 return initializeImpl(manager, monitorTags);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080090}
91
92template<typename TProviderPtr>
Emilian Peevbd8c5032018-02-14 23:05:40 +000093status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
Igor Murashkine7ee7632013-06-11 18:10:18 -070094 ATRACE_CALL();
95 status_t res;
96
Emilian Peevbd8c5032018-02-14 23:05:40 +000097 res = Camera2ClientBase::initialize(providerPtr, monitorTags);
Igor Murashkine7ee7632013-06-11 18:10:18 -070098 if (res != OK) {
99 return res;
100 }
101
102 String8 threadName;
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -0700103 mFrameProcessor = new FrameProcessorBase(mDevice);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800104 threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700105 mFrameProcessor->run(threadName.string());
106
107 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
108 FRAME_PROCESSOR_LISTENER_MAX_ID,
Eino-Ville Talvala184dfe42013-11-07 15:13:16 -0800109 /*listener*/this,
Zhijun He25a0aef2014-06-25 11:40:02 -0700110 /*sendPartials*/true);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700111
Emilian Peev00420d22018-02-05 21:33:13 +0000112 auto deviceInfo = mDevice->info();
113 camera_metadata_entry_t physicalKeysEntry = deviceInfo.find(
114 ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
115 if (physicalKeysEntry.count > 0) {
116 mSupportedPhysicalRequestKeys.insert(mSupportedPhysicalRequestKeys.begin(),
117 physicalKeysEntry.data.i32,
118 physicalKeysEntry.data.i32 + physicalKeysEntry.count);
119 }
120
Igor Murashkine7ee7632013-06-11 18:10:18 -0700121 return OK;
122}
123
124CameraDeviceClient::~CameraDeviceClient() {
125}
126
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800127binder::Status CameraDeviceClient::submitRequest(
128 const hardware::camera2::CaptureRequest& request,
129 bool streaming,
130 /*out*/
131 hardware::camera2::utils::SubmitInfo *submitInfo) {
132 std::vector<hardware::camera2::CaptureRequest> requestList = { request };
133 return submitRequestList(requestList, streaming, submitInfo);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700134}
135
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800136binder::Status CameraDeviceClient::insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
Emilian Peevf873aa52018-01-26 14:58:28 +0000137 SurfaceMap* outSurfaceMap, Vector<int32_t>* outputStreamIds, int32_t *currentStreamId) {
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800138 int idx = mStreamMap.indexOfKey(IInterface::asBinder(gbp));
139
140 // Trying to submit request with surface that wasn't created
141 if (idx == NAME_NOT_FOUND) {
142 ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
143 " we have not called createStream on",
144 __FUNCTION__, mCameraIdStr.string());
145 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
146 "Request targets Surface that is not part of current capture session");
147 }
148
149 const StreamSurfaceId& streamSurfaceId = mStreamMap.valueAt(idx);
150 if (outSurfaceMap->find(streamSurfaceId.streamId()) == outSurfaceMap->end()) {
151 (*outSurfaceMap)[streamSurfaceId.streamId()] = std::vector<size_t>();
152 outputStreamIds->push_back(streamSurfaceId.streamId());
153 }
154 (*outSurfaceMap)[streamSurfaceId.streamId()].push_back(streamSurfaceId.surfaceId());
155
156 ALOGV("%s: Camera %s: Appending output stream %d surface %d to request",
157 __FUNCTION__, mCameraIdStr.string(), streamSurfaceId.streamId(),
158 streamSurfaceId.surfaceId());
159
Emilian Peevf873aa52018-01-26 14:58:28 +0000160 if (currentStreamId != nullptr) {
161 *currentStreamId = streamSurfaceId.streamId();
162 }
163
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800164 return binder::Status::ok();
165}
166
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800167binder::Status CameraDeviceClient::submitRequestList(
168 const std::vector<hardware::camera2::CaptureRequest>& requests,
169 bool streaming,
170 /*out*/
171 hardware::camera2::utils::SubmitInfo *submitInfo) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700172 ATRACE_CALL();
Mark Salyzyn50468412014-06-18 16:33:43 -0700173 ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700174
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800175 binder::Status res = binder::Status::ok();
176 status_t err;
177 if ( !(res = checkPidStatus(__FUNCTION__) ).isOk()) {
178 return res;
179 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700180
181 Mutex::Autolock icl(mBinderSerializationLock);
182
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800183 if (!mDevice.get()) {
184 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
185 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700186
187 if (requests.empty()) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800188 ALOGE("%s: Camera %s: Sent null request. Rejecting request.",
189 __FUNCTION__, mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800190 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
Jianing Wei90e59c92014-03-12 18:29:36 -0700191 }
192
Emilian Peevaebbe412018-01-15 13:53:24 +0000193 List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700194 std::list<const SurfaceMap> surfaceMapList;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800195 submitInfo->mRequestId = mRequestIdCounter;
Jianing Wei90e59c92014-03-12 18:29:36 -0700196 uint32_t loopCounter = 0;
197
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800198 for (auto&& request: requests) {
199 if (request.mIsReprocess) {
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700200 if (!mInputStream.configured) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800201 ALOGE("%s: Camera %s: no input stream is configured.", __FUNCTION__,
202 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800203 return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800204 "No input configured for camera %s but request is for reprocessing",
205 mCameraIdStr.string());
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700206 } else if (streaming) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800207 ALOGE("%s: Camera %s: streaming reprocess requests not supported.", __FUNCTION__,
208 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800209 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
210 "Repeating reprocess requests not supported");
Emilian Peevaebbe412018-01-15 13:53:24 +0000211 } else if (request.mPhysicalCameraSettings.size() > 1) {
212 ALOGE("%s: Camera %s: reprocess requests not supported for "
213 "multiple physical cameras.", __FUNCTION__,
214 mCameraIdStr.string());
215 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
216 "Reprocess requests not supported for multiple cameras");
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700217 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700218 }
219
Emilian Peevaebbe412018-01-15 13:53:24 +0000220 if (request.mPhysicalCameraSettings.empty()) {
221 ALOGE("%s: Camera %s: request doesn't contain any settings.", __FUNCTION__,
222 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800223 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Emilian Peevaebbe412018-01-15 13:53:24 +0000224 "Request doesn't contain any settings");
225 }
226
227 //The first capture settings should always match the logical camera id
228 String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
229 if (mDevice->getId() != logicalId) {
230 ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
231 mCameraIdStr.string());
232 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
233 "Invalid camera request settings");
234 }
235
Emilian Peevaebbe412018-01-15 13:53:24 +0000236 if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800237 ALOGE("%s: Camera %s: Requests must have at least one surface target. "
238 "Rejecting request.", __FUNCTION__, mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800239 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
240 "Request has no output targets");
Jianing Wei90e59c92014-03-12 18:29:36 -0700241 }
242
Jianing Wei90e59c92014-03-12 18:29:36 -0700243 /**
Shuzhen Wang0129d522016-10-30 22:43:41 -0700244 * Write in the output stream IDs and map from stream ID to surface ID
245 * which we calculate from the capture request's list of surface target
Jianing Wei90e59c92014-03-12 18:29:36 -0700246 */
Shuzhen Wang0129d522016-10-30 22:43:41 -0700247 SurfaceMap surfaceMap;
Jianing Wei90e59c92014-03-12 18:29:36 -0700248 Vector<int32_t> outputStreamIds;
Emilian Peevf873aa52018-01-26 14:58:28 +0000249 std::vector<std::string> requestedPhysicalIds;
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800250 if (request.mSurfaceList.size() > 0) {
251 for (sp<Surface> surface : request.mSurfaceList) {
252 if (surface == 0) continue;
Jianing Wei90e59c92014-03-12 18:29:36 -0700253
Emilian Peevf873aa52018-01-26 14:58:28 +0000254 int32_t streamId;
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800255 sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
Emilian Peevf873aa52018-01-26 14:58:28 +0000256 res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds, &streamId);
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800257 if (!res.isOk()) {
258 return res;
259 }
Emilian Peevf873aa52018-01-26 14:58:28 +0000260
261 ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
262 if (index >= 0) {
263 String8 requestedPhysicalId(
264 mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
265 requestedPhysicalIds.push_back(requestedPhysicalId.string());
266 } else {
267 ALOGW("%s: Output stream Id not found among configured outputs!", __FUNCTION__);
268 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700269 }
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800270 } else {
271 for (size_t i = 0; i < request.mStreamIdxList.size(); i++) {
272 int streamId = request.mStreamIdxList.itemAt(i);
273 int surfaceIdx = request.mSurfaceIdxList.itemAt(i);
Jianing Wei90e59c92014-03-12 18:29:36 -0700274
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800275 ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
276 if (index < 0) {
277 ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
278 " we have not called createStream on: stream %d",
279 __FUNCTION__, mCameraIdStr.string(), streamId);
280 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
281 "Request targets Surface that is not part of current capture session");
282 }
283
284 const auto& gbps = mConfiguredOutputs.valueAt(index).getGraphicBufferProducers();
285 if ((size_t)surfaceIdx >= gbps.size()) {
286 ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
287 " we have not called createStream on: stream %d, surfaceIdx %d",
288 __FUNCTION__, mCameraIdStr.string(), streamId, surfaceIdx);
289 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
290 "Request targets Surface has invalid surface index");
291 }
292
Emilian Peevf873aa52018-01-26 14:58:28 +0000293 res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds, nullptr);
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800294 if (!res.isOk()) {
295 return res;
296 }
Emilian Peevf873aa52018-01-26 14:58:28 +0000297
298 String8 requestedPhysicalId(
299 mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
300 requestedPhysicalIds.push_back(requestedPhysicalId.string());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700301 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700302 }
303
Emilian Peevf873aa52018-01-26 14:58:28 +0000304 CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
305 for (const auto& it : request.mPhysicalCameraSettings) {
Emilian Peev00420d22018-02-05 21:33:13 +0000306 if (it.settings.isEmpty()) {
307 ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
308 __FUNCTION__, mCameraIdStr.string());
309 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
310 "Request settings are empty");
311 }
312
Emilian Peevf873aa52018-01-26 14:58:28 +0000313 String8 physicalId(it.id.c_str());
314 if (physicalId != mDevice->getId()) {
315 auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
316 it.id);
317 if (found == requestedPhysicalIds.end()) {
318 ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
319 __FUNCTION__, mCameraIdStr.string(), physicalId.string());
320 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
321 "Invalid physical camera id");
322 }
Emilian Peev00420d22018-02-05 21:33:13 +0000323
324 if (!mSupportedPhysicalRequestKeys.empty()) {
325 // Filter out any unsupported physical request keys.
326 CameraMetadata filteredParams(mSupportedPhysicalRequestKeys.size());
327 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
328 filteredParams.getAndLock());
329 set_camera_metadata_vendor_id(meta, mDevice->getVendorTagId());
330 filteredParams.unlock(meta);
331
332 for (const auto& keyIt : mSupportedPhysicalRequestKeys) {
333 camera_metadata_ro_entry entry = it.settings.find(keyIt);
334 if (entry.count > 0) {
335 filteredParams.update(entry);
336 }
337 }
338
339 physicalSettingsList.push_back({it.id, filteredParams});
340 }
341 } else {
342 physicalSettingsList.push_back({it.id, it.settings});
Emilian Peevf873aa52018-01-26 14:58:28 +0000343 }
Emilian Peevf873aa52018-01-26 14:58:28 +0000344 }
345
346 if (!enforceRequestPermissions(physicalSettingsList.begin()->metadata)) {
347 // Callee logs
348 return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
349 "Caller does not have permission to change restricted controls");
350 }
351
Emilian Peevaebbe412018-01-15 13:53:24 +0000352 physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
353 &outputStreamIds[0], outputStreamIds.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700354
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800355 if (request.mIsReprocess) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000356 physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_INPUT_STREAMS,
357 &mInputStream.id, 1);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700358 }
359
Emilian Peevaebbe412018-01-15 13:53:24 +0000360 physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_ID,
361 &(submitInfo->mRequestId), /*size*/1);
Jianing Wei90e59c92014-03-12 18:29:36 -0700362 loopCounter++; // loopCounter starts from 1
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800363 ALOGV("%s: Camera %s: Creating request with ID %d (%d of %zu)",
364 __FUNCTION__, mCameraIdStr.string(), submitInfo->mRequestId,
365 loopCounter, requests.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700366
Emilian Peevaebbe412018-01-15 13:53:24 +0000367 metadataRequestList.push_back(physicalSettingsList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700368 surfaceMapList.push_back(surfaceMap);
Jianing Wei90e59c92014-03-12 18:29:36 -0700369 }
370 mRequestIdCounter++;
371
372 if (streaming) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700373 err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
374 &(submitInfo->mLastFrameNumber));
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800375 if (err != OK) {
376 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800377 "Camera %s: Got error %s (%d) after trying to set streaming request",
378 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800379 ALOGE("%s: %s", __FUNCTION__, msg.string());
380 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
381 msg.string());
Jianing Wei90e59c92014-03-12 18:29:36 -0700382 } else {
Shuzhen Wangc9ca6782016-04-26 13:40:31 -0700383 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -0700384 mStreamingRequestId = submitInfo->mRequestId;
Jianing Wei90e59c92014-03-12 18:29:36 -0700385 }
386 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700387 err = mDevice->captureList(metadataRequestList, surfaceMapList,
388 &(submitInfo->mLastFrameNumber));
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800389 if (err != OK) {
390 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800391 "Camera %s: Got error %s (%d) after trying to submit capture request",
392 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800393 ALOGE("%s: %s", __FUNCTION__, msg.string());
394 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
395 msg.string());
Jianing Wei90e59c92014-03-12 18:29:36 -0700396 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800397 ALOGV("%s: requestId = %d ", __FUNCTION__, submitInfo->mRequestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700398 }
399
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800400 ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.string());
Jianing Wei90e59c92014-03-12 18:29:36 -0700401 return res;
402}
403
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800404binder::Status CameraDeviceClient::cancelRequest(
405 int requestId,
406 /*out*/
407 int64_t* lastFrameNumber) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700408 ATRACE_CALL();
409 ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
410
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800411 status_t err;
412 binder::Status res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700413
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800414 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700415
416 Mutex::Autolock icl(mBinderSerializationLock);
417
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800418 if (!mDevice.get()) {
419 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
420 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700421
Shuzhen Wangc9ca6782016-04-26 13:40:31 -0700422 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -0700423 if (mStreamingRequestId != requestId) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800424 String8 msg = String8::format("Camera %s: Canceling request ID %d doesn't match "
425 "current request ID %d", mCameraIdStr.string(), requestId, mStreamingRequestId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800426 ALOGE("%s: %s", __FUNCTION__, msg.string());
427 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700428 }
429
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800430 err = mDevice->clearStreamingRequest(lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700431
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800432 if (err == OK) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800433 ALOGV("%s: Camera %s: Successfully cleared streaming request",
434 __FUNCTION__, mCameraIdStr.string());
Chien-Yu Chene8c535e2016-04-14 12:18:26 -0700435 mStreamingRequestId = REQUEST_ID_NONE;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800436 } else {
437 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800438 "Camera %s: Error clearing streaming request: %s (%d)",
439 mCameraIdStr.string(), strerror(-err), err);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700440 }
441
442 return res;
443}
444
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800445binder::Status CameraDeviceClient::beginConfigure() {
Ruben Brunkb2119af2014-05-09 19:57:56 -0700446 // TODO: Implement this.
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -0700447 ATRACE_CALL();
Zhijun He1fa89992015-06-01 15:44:31 -0700448 ALOGV("%s: Not implemented yet.", __FUNCTION__);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800449 return binder::Status::ok();
Ruben Brunkb2119af2014-05-09 19:57:56 -0700450}
451
Emilian Peev5fbe0ba2017-10-20 15:45:45 +0100452binder::Status CameraDeviceClient::endConfigure(int operatingMode,
453 const hardware::camera2::impl::CameraMetadataNative& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -0700454 ATRACE_CALL();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700455 ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
456 __FUNCTION__, mInputStream.configured ? 1 : 0,
457 mStreamMap.size());
Igor Murashkine2d167e2014-08-19 16:19:59 -0700458
Zhijun He0effd522016-03-04 10:22:27 -0800459 binder::Status res;
460 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
461
462 Mutex::Autolock icl(mBinderSerializationLock);
463
464 if (!mDevice.get()) {
465 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
466 }
467
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800468 if (operatingMode < 0) {
469 String8 msg = String8::format(
470 "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
471 ALOGE("%s: %s", __FUNCTION__, msg.string());
472 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
473 msg.string());
474 }
475
Zhijun He1fa89992015-06-01 15:44:31 -0700476 // Sanitize the high speed session against necessary capability bit.
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800477 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
Zhijun He1fa89992015-06-01 15:44:31 -0700478 if (isConstrainedHighSpeed) {
479 CameraMetadata staticInfo = mDevice->info();
480 camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
481 bool isConstrainedHighSpeedSupported = false;
482 for(size_t i = 0; i < entry.count; ++i) {
483 uint8_t capability = entry.data.u8[i];
484 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
485 isConstrainedHighSpeedSupported = true;
486 break;
487 }
488 }
489 if (!isConstrainedHighSpeedSupported) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800490 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800491 "Camera %s: Try to create a constrained high speed configuration on a device"
492 " that doesn't support it.", mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800493 ALOGE("%s: %s", __FUNCTION__, msg.string());
494 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
495 msg.string());
Zhijun He1fa89992015-06-01 15:44:31 -0700496 }
497 }
498
Emilian Peev5fbe0ba2017-10-20 15:45:45 +0100499 status_t err = mDevice->configureStreams(sessionParams, operatingMode);
Eino-Ville Talvalaace80582016-03-18 13:27:35 -0700500 if (err == BAD_VALUE) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800501 String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
502 mCameraIdStr.string());
Zhijun He5d677d12016-05-29 16:52:39 -0700503 ALOGE("%s: %s", __FUNCTION__, msg.string());
504 res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Eino-Ville Talvalaace80582016-03-18 13:27:35 -0700505 } else if (err != OK) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800506 String8 msg = String8::format("Camera %s: Error configuring streams: %s (%d)",
507 mCameraIdStr.string(), strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -0700508 ALOGE("%s: %s", __FUNCTION__, msg.string());
509 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800510 }
511
512 return res;
Ruben Brunkb2119af2014-05-09 19:57:56 -0700513}
514
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800515binder::Status CameraDeviceClient::deleteStream(int streamId) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700516 ATRACE_CALL();
517 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
518
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800519 binder::Status res;
520 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700521
522 Mutex::Autolock icl(mBinderSerializationLock);
523
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800524 if (!mDevice.get()) {
525 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
526 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700527
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700528 bool isInput = false;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700529 std::vector<sp<IBinder>> surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -0700530 ssize_t dIndex = NAME_NOT_FOUND;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700531
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700532 if (mInputStream.configured && mInputStream.id == streamId) {
533 isInput = true;
534 } else {
535 // Guard against trying to delete non-created streams
536 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700537 if (streamId == mStreamMap.valueAt(i).streamId()) {
538 surfaces.push_back(mStreamMap.keyAt(i));
539 }
540 }
541
542 // See if this stream is one of the deferred streams.
543 for (size_t i = 0; i < mDeferredStreams.size(); ++i) {
544 if (streamId == mDeferredStreams[i]) {
545 dIndex = i;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700546 break;
547 }
548 }
549
Shuzhen Wang0129d522016-10-30 22:43:41 -0700550 if (surfaces.empty() && dIndex == NAME_NOT_FOUND) {
551 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no such"
552 " stream created yet", mCameraIdStr.string(), streamId);
553 ALOGW("%s: %s", __FUNCTION__, msg.string());
554 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700555 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700556 }
557
558 // Also returns BAD_VALUE if stream ID was not valid
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800559 status_t err = mDevice->deleteStream(streamId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700560
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800561 if (err != OK) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800562 String8 msg = String8::format("Camera %s: Unexpected error %s (%d) when deleting stream %d",
563 mCameraIdStr.string(), strerror(-err), err, streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800564 ALOGE("%s: %s", __FUNCTION__, msg.string());
565 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
566 } else {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700567 if (isInput) {
568 mInputStream.configured = false;
Zhijun He5d677d12016-05-29 16:52:39 -0700569 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700570 for (auto& surface : surfaces) {
571 mStreamMap.removeItem(surface);
572 }
573
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800574 mConfiguredOutputs.removeItem(streamId);
575
Shuzhen Wang0129d522016-10-30 22:43:41 -0700576 if (dIndex != NAME_NOT_FOUND) {
577 mDeferredStreams.removeItemsAt(dIndex);
578 }
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700579 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700580 }
581
582 return res;
583}
584
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800585binder::Status CameraDeviceClient::createStream(
586 const hardware::camera2::params::OutputConfiguration &outputConfiguration,
587 /*out*/
588 int32_t* newStreamId) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700589 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700590
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800591 binder::Status res;
592 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700593
594 Mutex::Autolock icl(mBinderSerializationLock);
595
Shuzhen Wang0129d522016-10-30 22:43:41 -0700596 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
597 outputConfiguration.getGraphicBufferProducers();
598 size_t numBufferProducers = bufferProducers.size();
Shuzhen Wang758c2152017-01-10 18:26:18 -0800599 bool deferredConsumer = outputConfiguration.isDeferred();
600 bool isShared = outputConfiguration.isShared();
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800601 String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700602
603 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
604 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
605 __FUNCTION__, bufferProducers.size(), MAX_SURFACES_PER_STREAM);
606 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
607 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800608 bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
Zhijun He5d677d12016-05-29 16:52:39 -0700609 int surfaceType = outputConfiguration.getSurfaceType();
610 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
611 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700612
Zhijun He5d677d12016-05-29 16:52:39 -0700613 if (deferredConsumer && !validSurfaceType) {
614 ALOGE("%s: Target surface is invalid: bufferProducer = %p, surfaceType = %d.",
Shuzhen Wang0129d522016-10-30 22:43:41 -0700615 __FUNCTION__, bufferProducers[0].get(), surfaceType);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800616 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
Yin-Chia Yeh89f14da2014-06-10 16:05:44 -0700617 }
Zhijun He5d677d12016-05-29 16:52:39 -0700618
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800619 if (!mDevice.get()) {
620 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
621 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700622
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800623 if (!checkPhysicalCameraId(physicalCameraId)) {
624 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
625 mCameraIdStr.string(), physicalCameraId.string());
626 ALOGE("%s: %s", __FUNCTION__, msg.string());
627 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
628 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700629 std::vector<sp<Surface>> surfaces;
630 std::vector<sp<IBinder>> binders;
Zhijun He5d677d12016-05-29 16:52:39 -0700631 status_t err;
632
633 // Create stream for deferred surface case.
Shuzhen Wang0129d522016-10-30 22:43:41 -0700634 if (deferredConsumerOnly) {
Shuzhen Wang758c2152017-01-10 18:26:18 -0800635 return createDeferredSurfaceStreamLocked(outputConfiguration, isShared, newStreamId);
Zhijun He5d677d12016-05-29 16:52:39 -0700636 }
637
Shuzhen Wang758c2152017-01-10 18:26:18 -0800638 OutputStreamInfo streamInfo;
639 bool isStreamInfoValid = false;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700640 for (auto& bufferProducer : bufferProducers) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700641 // Don't create multiple streams for the same target surface
Shuzhen Wang0129d522016-10-30 22:43:41 -0700642 sp<IBinder> binder = IInterface::asBinder(bufferProducer);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800643 ssize_t index = mStreamMap.indexOfKey(binder);
644 if (index != NAME_NOT_FOUND) {
645 String8 msg = String8::format("Camera %s: Surface already has a stream created for it "
646 "(ID %zd)", mCameraIdStr.string(), index);
647 ALOGW("%s: %s", __FUNCTION__, msg.string());
648 return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700649 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700650
Shuzhen Wang758c2152017-01-10 18:26:18 -0800651 sp<Surface> surface;
652 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer);
653
654 if (!res.isOk())
655 return res;
656
657 if (!isStreamInfoValid) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800658 // Streaming sharing is only supported for IMPLEMENTATION_DEFINED
659 // formats.
660 if (isShared && streamInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
661 String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
662 "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
663 ALOGW("%s: %s", __FUNCTION__, msg.string());
664 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
665 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800666 isStreamInfoValid = true;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700667 }
668
Shuzhen Wang758c2152017-01-10 18:26:18 -0800669 binders.push_back(IInterface::asBinder(bufferProducer));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700670 surfaces.push_back(surface);
Ruben Brunkbba75572014-11-20 17:29:50 -0800671 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700672
Zhijun He125684a2015-12-26 15:07:30 -0800673 int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
Emilian Peev40ead602017-09-26 15:46:36 +0100674 std::vector<int> surfaceIds;
Shuzhen Wang758c2152017-01-10 18:26:18 -0800675 err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
676 streamInfo.height, streamInfo.format, streamInfo.dataSpace,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800677 static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800678 &streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
679 isShared);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700680
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800681 if (err != OK) {
682 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800683 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
Shuzhen Wang758c2152017-01-10 18:26:18 -0800684 mCameraIdStr.string(), streamInfo.width, streamInfo.height, streamInfo.format,
685 streamInfo.dataSpace, strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800686 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700687 int i = 0;
688 for (auto& binder : binders) {
689 ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d",
690 __FUNCTION__, binder.get(), streamId, i);
Emilian Peev40ead602017-09-26 15:46:36 +0100691 mStreamMap.add(binder, StreamSurfaceId(streamId, surfaceIds[i]));
692 i++;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700693 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800694
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800695 mConfiguredOutputs.add(streamId, outputConfiguration);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800696 mStreamInfoMap[streamId] = streamInfo;
697
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800698 ALOGV("%s: Camera %s: Successfully created a new stream ID %d for output surface"
Shuzhen Wang0129d522016-10-30 22:43:41 -0700699 " (%d x %d) with format 0x%x.",
Shuzhen Wang758c2152017-01-10 18:26:18 -0800700 __FUNCTION__, mCameraIdStr.string(), streamId, streamInfo.width,
701 streamInfo.height, streamInfo.format);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700702
Zhijun He5d677d12016-05-29 16:52:39 -0700703 // Set transform flags to ensure preview to be rotated correctly.
704 res = setStreamTransformLocked(streamId);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700705
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800706 *newStreamId = streamId;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700707 }
708
709 return res;
710}
711
Zhijun He5d677d12016-05-29 16:52:39 -0700712binder::Status CameraDeviceClient::createDeferredSurfaceStreamLocked(
713 const hardware::camera2::params::OutputConfiguration &outputConfiguration,
Shuzhen Wang758c2152017-01-10 18:26:18 -0800714 bool isShared,
Zhijun He5d677d12016-05-29 16:52:39 -0700715 /*out*/
716 int* newStreamId) {
717 int width, height, format, surfaceType;
Emilian Peev050f5dc2017-05-18 14:43:56 +0100718 uint64_t consumerUsage;
Zhijun He5d677d12016-05-29 16:52:39 -0700719 android_dataspace dataSpace;
720 status_t err;
721 binder::Status res;
722
723 if (!mDevice.get()) {
724 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
725 }
726
727 // Infer the surface info for deferred surface stream creation.
728 width = outputConfiguration.getWidth();
729 height = outputConfiguration.getHeight();
730 surfaceType = outputConfiguration.getSurfaceType();
731 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
732 dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
733 // Hardcode consumer usage flags: SurfaceView--0x900, SurfaceTexture--0x100.
734 consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
735 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
736 consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
737 }
738 int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700739 std::vector<sp<Surface>> noSurface;
Emilian Peev40ead602017-09-26 15:46:36 +0100740 std::vector<int> surfaceIds;
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800741 String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700742 err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
743 height, format, dataSpace,
Zhijun He5d677d12016-05-29 16:52:39 -0700744 static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800745 &streamId, physicalCameraId, &surfaceIds,
746 outputConfiguration.getSurfaceSetID(), isShared,
Emilian Peev40ead602017-09-26 15:46:36 +0100747 consumerUsage);
Zhijun He5d677d12016-05-29 16:52:39 -0700748
749 if (err != OK) {
750 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800751 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
752 mCameraIdStr.string(), width, height, format, dataSpace, strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -0700753 } else {
754 // Can not add streamId to mStreamMap here, as the surface is deferred. Add it to
755 // a separate list to track. Once the deferred surface is set, this id will be
756 // relocated to mStreamMap.
757 mDeferredStreams.push_back(streamId);
758
Shuzhen Wang758c2152017-01-10 18:26:18 -0800759 mStreamInfoMap.emplace(std::piecewise_construct, std::forward_as_tuple(streamId),
760 std::forward_as_tuple(width, height, format, dataSpace, consumerUsage));
761
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800762 ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
Zhijun He5d677d12016-05-29 16:52:39 -0700763 " (%d x %d) stream with format 0x%x.",
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800764 __FUNCTION__, mCameraIdStr.string(), streamId, width, height, format);
Zhijun He5d677d12016-05-29 16:52:39 -0700765
766 // Set transform flags to ensure preview to be rotated correctly.
767 res = setStreamTransformLocked(streamId);
768
769 *newStreamId = streamId;
770 }
771 return res;
772}
773
774binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId) {
775 int32_t transform = 0;
776 status_t err;
777 binder::Status res;
778
779 if (!mDevice.get()) {
780 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
781 }
782
783 err = getRotationTransformLocked(&transform);
784 if (err != OK) {
785 // Error logged by getRotationTransformLocked.
786 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
787 "Unable to calculate rotation transform for new stream");
788 }
789
790 err = mDevice->setStreamTransform(streamId, transform);
791 if (err != OK) {
792 String8 msg = String8::format("Failed to set stream transform (stream id %d)",
793 streamId);
794 ALOGE("%s: %s", __FUNCTION__, msg.string());
795 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
796 }
797
798 return res;
799}
Ruben Brunkbba75572014-11-20 17:29:50 -0800800
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800801binder::Status CameraDeviceClient::createInputStream(
802 int width, int height, int format,
803 /*out*/
804 int32_t* newStreamId) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700805
806 ATRACE_CALL();
807 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
808
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800809 binder::Status res;
810 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700811
812 Mutex::Autolock icl(mBinderSerializationLock);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800813
814 if (!mDevice.get()) {
815 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
816 }
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700817
818 if (mInputStream.configured) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800819 String8 msg = String8::format("Camera %s: Already has an input stream "
Yi Kong0f414de2017-12-15 13:48:50 -0800820 "configured (ID %d)", mCameraIdStr.string(), mInputStream.id);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800821 ALOGE("%s: %s", __FUNCTION__, msg.string() );
822 return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700823 }
824
825 int streamId = -1;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800826 status_t err = mDevice->createInputStream(width, height, format, &streamId);
827 if (err == OK) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700828 mInputStream.configured = true;
829 mInputStream.width = width;
830 mInputStream.height = height;
831 mInputStream.format = format;
832 mInputStream.id = streamId;
833
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800834 ALOGV("%s: Camera %s: Successfully created a new input stream ID %d",
835 __FUNCTION__, mCameraIdStr.string(), streamId);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700836
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800837 *newStreamId = streamId;
838 } else {
839 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800840 "Camera %s: Error creating new input stream: %s (%d)", mCameraIdStr.string(),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800841 strerror(-err), err);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700842 }
843
844 return res;
845}
846
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800847binder::Status CameraDeviceClient::getInputSurface(/*out*/ view::Surface *inputSurface) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700848
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800849 binder::Status res;
850 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
851
852 if (inputSurface == NULL) {
853 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Null input surface");
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700854 }
855
856 Mutex::Autolock icl(mBinderSerializationLock);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800857 if (!mDevice.get()) {
858 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
859 }
860 sp<IGraphicBufferProducer> producer;
861 status_t err = mDevice->getInputBufferProducer(&producer);
862 if (err != OK) {
863 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800864 "Camera %s: Error getting input Surface: %s (%d)",
865 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800866 } else {
867 inputSurface->name = String16("CameraInput");
868 inputSurface->graphicBufferProducer = producer;
869 }
870 return res;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700871}
872
Emilian Peev40ead602017-09-26 15:46:36 +0100873binder::Status CameraDeviceClient::updateOutputConfiguration(int streamId,
874 const hardware::camera2::params::OutputConfiguration &outputConfiguration) {
875 ATRACE_CALL();
876
877 binder::Status res;
878 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
879
880 Mutex::Autolock icl(mBinderSerializationLock);
881
882 if (!mDevice.get()) {
883 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
884 }
885
886 const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
887 outputConfiguration.getGraphicBufferProducers();
888 auto producerCount = bufferProducers.size();
889 if (producerCount == 0) {
890 ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
891 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
892 "bufferProducers must not be empty");
893 }
894
895 // The first output is the one associated with the output configuration.
896 // It should always be present, valid and the corresponding stream id should match.
897 sp<IBinder> binder = IInterface::asBinder(bufferProducers[0]);
898 ssize_t index = mStreamMap.indexOfKey(binder);
899 if (index == NAME_NOT_FOUND) {
900 ALOGE("%s: Outputconfiguration is invalid", __FUNCTION__);
901 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
902 "OutputConfiguration is invalid");
903 }
904 if (mStreamMap.valueFor(binder).streamId() != streamId) {
905 ALOGE("%s: Stream Id: %d provided doesn't match the id: %d in the stream map",
906 __FUNCTION__, streamId, mStreamMap.valueFor(binder).streamId());
907 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
908 "Stream id is invalid");
909 }
910
911 std::vector<size_t> removedSurfaceIds;
912 std::vector<sp<IBinder>> removedOutputs;
913 std::vector<sp<Surface>> newOutputs;
914 std::vector<OutputStreamInfo> streamInfos;
915 KeyedVector<sp<IBinder>, sp<IGraphicBufferProducer>> newOutputsMap;
916 for (auto &it : bufferProducers) {
917 newOutputsMap.add(IInterface::asBinder(it), it);
918 }
919
920 for (size_t i = 0; i < mStreamMap.size(); i++) {
921 ssize_t idx = newOutputsMap.indexOfKey(mStreamMap.keyAt(i));
922 if (idx == NAME_NOT_FOUND) {
923 if (mStreamMap[i].streamId() == streamId) {
924 removedSurfaceIds.push_back(mStreamMap[i].surfaceId());
925 removedOutputs.push_back(mStreamMap.keyAt(i));
926 }
927 } else {
928 if (mStreamMap[i].streamId() != streamId) {
929 ALOGE("%s: Output surface already part of a different stream", __FUNCTION__);
930 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
931 "Target Surface is invalid");
932 }
933 newOutputsMap.removeItemsAt(idx);
934 }
935 }
936
937 for (size_t i = 0; i < newOutputsMap.size(); i++) {
938 OutputStreamInfo outInfo;
939 sp<Surface> surface;
940 res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
941 newOutputsMap.valueAt(i));
942 if (!res.isOk())
943 return res;
944
945 // Stream sharing is only supported for IMPLEMENTATION_DEFINED
946 // formats.
947 if (outInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
948 String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
949 "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
950 ALOGW("%s: %s", __FUNCTION__, msg.string());
951 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
952 }
953 streamInfos.push_back(outInfo);
954 newOutputs.push_back(surface);
955 }
956
957 //Trivial case no changes required
958 if (removedSurfaceIds.empty() && newOutputs.empty()) {
959 return binder::Status::ok();
960 }
961
962 KeyedVector<sp<Surface>, size_t> outputMap;
963 auto ret = mDevice->updateStream(streamId, newOutputs, streamInfos, removedSurfaceIds,
964 &outputMap);
965 if (ret != OK) {
966 switch (ret) {
967 case NAME_NOT_FOUND:
968 case BAD_VALUE:
969 case -EBUSY:
970 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
971 "Camera %s: Error updating stream: %s (%d)",
972 mCameraIdStr.string(), strerror(ret), ret);
973 break;
974 default:
975 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
976 "Camera %s: Error updating stream: %s (%d)",
977 mCameraIdStr.string(), strerror(ret), ret);
978 break;
979 }
980 } else {
981 for (const auto &it : removedOutputs) {
982 mStreamMap.removeItem(it);
983 }
984
985 for (size_t i = 0; i < outputMap.size(); i++) {
986 mStreamMap.add(IInterface::asBinder(outputMap.keyAt(i)->getIGraphicBufferProducer()),
987 StreamSurfaceId(streamId, outputMap.valueAt(i)));
988 }
989
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800990 mConfiguredOutputs.replaceValueFor(streamId, outputConfiguration);
991
Emilian Peev40ead602017-09-26 15:46:36 +0100992 ALOGV("%s: Camera %s: Successful stream ID %d update",
993 __FUNCTION__, mCameraIdStr.string(), streamId);
994 }
995
996 return res;
997}
998
Eman Copty6d7af0e2016-06-17 20:46:40 -0700999bool CameraDeviceClient::isPublicFormat(int32_t format)
1000{
1001 switch(format) {
1002 case HAL_PIXEL_FORMAT_RGBA_8888:
1003 case HAL_PIXEL_FORMAT_RGBX_8888:
1004 case HAL_PIXEL_FORMAT_RGB_888:
1005 case HAL_PIXEL_FORMAT_RGB_565:
1006 case HAL_PIXEL_FORMAT_BGRA_8888:
1007 case HAL_PIXEL_FORMAT_YV12:
1008 case HAL_PIXEL_FORMAT_Y8:
1009 case HAL_PIXEL_FORMAT_Y16:
1010 case HAL_PIXEL_FORMAT_RAW16:
1011 case HAL_PIXEL_FORMAT_RAW10:
1012 case HAL_PIXEL_FORMAT_RAW12:
1013 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1014 case HAL_PIXEL_FORMAT_BLOB:
1015 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1016 case HAL_PIXEL_FORMAT_YCbCr_420_888:
1017 case HAL_PIXEL_FORMAT_YCbCr_422_888:
1018 case HAL_PIXEL_FORMAT_YCbCr_444_888:
1019 case HAL_PIXEL_FORMAT_FLEX_RGB_888:
1020 case HAL_PIXEL_FORMAT_FLEX_RGBA_8888:
1021 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
1022 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1023 case HAL_PIXEL_FORMAT_YCbCr_422_I:
1024 return true;
1025 default:
1026 return false;
1027 }
1028}
1029
Shuzhen Wang758c2152017-01-10 18:26:18 -08001030binder::Status CameraDeviceClient::createSurfaceFromGbp(
1031 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
1032 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp) {
1033
1034 // bufferProducer must be non-null
1035 if (gbp == nullptr) {
1036 String8 msg = String8::format("Camera %s: Surface is NULL", mCameraIdStr.string());
1037 ALOGW("%s: %s", __FUNCTION__, msg.string());
1038 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1039 }
1040 // HACK b/10949105
1041 // Query consumer usage bits to set async operation mode for
1042 // GLConsumer using controlledByApp parameter.
1043 bool useAsync = false;
Emilian Peev050f5dc2017-05-18 14:43:56 +01001044 uint64_t consumerUsage = 0;
Shuzhen Wang758c2152017-01-10 18:26:18 -08001045 status_t err;
Emilian Peev050f5dc2017-05-18 14:43:56 +01001046 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
Shuzhen Wang758c2152017-01-10 18:26:18 -08001047 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
1048 mCameraIdStr.string(), strerror(-err), err);
1049 ALOGE("%s: %s", __FUNCTION__, msg.string());
1050 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1051 }
1052 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
Emilian Peev050f5dc2017-05-18 14:43:56 +01001053 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
Shuzhen Wang758c2152017-01-10 18:26:18 -08001054 __FUNCTION__, mCameraIdStr.string(), consumerUsage);
1055 useAsync = true;
1056 }
1057
Emilian Peev050f5dc2017-05-18 14:43:56 +01001058 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
Shuzhen Wang758c2152017-01-10 18:26:18 -08001059 GRALLOC_USAGE_RENDERSCRIPT;
Emilian Peev050f5dc2017-05-18 14:43:56 +01001060 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
Shuzhen Wang758c2152017-01-10 18:26:18 -08001061 GraphicBuffer::USAGE_HW_TEXTURE |
1062 GraphicBuffer::USAGE_HW_COMPOSER;
1063 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
1064 (consumerUsage & allowedFlags) != 0;
1065
1066 surface = new Surface(gbp, useAsync);
1067 ANativeWindow *anw = surface.get();
1068
1069 int width, height, format;
1070 android_dataspace dataSpace;
1071 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
1072 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
1073 mCameraIdStr.string(), strerror(-err), err);
1074 ALOGE("%s: %s", __FUNCTION__, msg.string());
1075 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1076 }
1077 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
1078 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
1079 mCameraIdStr.string(), strerror(-err), err);
1080 ALOGE("%s: %s", __FUNCTION__, msg.string());
1081 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1082 }
1083 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
1084 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
1085 mCameraIdStr.string(), strerror(-err), err);
1086 ALOGE("%s: %s", __FUNCTION__, msg.string());
1087 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1088 }
1089 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
1090 reinterpret_cast<int*>(&dataSpace))) != OK) {
1091 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
1092 mCameraIdStr.string(), strerror(-err), err);
1093 ALOGE("%s: %s", __FUNCTION__, msg.string());
1094 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1095 }
1096
1097 // FIXME: remove this override since the default format should be
1098 // IMPLEMENTATION_DEFINED. b/9487482
1099 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
1100 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
1101 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
1102 __FUNCTION__, mCameraIdStr.string(), format);
1103 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
1104 }
1105 // Round dimensions to the nearest dimensions available for this format
1106 if (flexibleConsumer && isPublicFormat(format) &&
1107 !CameraDeviceClient::roundBufferDimensionNearest(width, height,
1108 format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
1109 String8 msg = String8::format("Camera %s: No supported stream configurations with "
1110 "format %#x defined, failed to create output stream",
1111 mCameraIdStr.string(), format);
1112 ALOGE("%s: %s", __FUNCTION__, msg.string());
1113 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1114 }
1115
1116 if (!isStreamInfoValid) {
1117 streamInfo.width = width;
1118 streamInfo.height = height;
1119 streamInfo.format = format;
1120 streamInfo.dataSpace = dataSpace;
1121 streamInfo.consumerUsage = consumerUsage;
1122 return binder::Status::ok();
1123 }
1124 if (width != streamInfo.width) {
1125 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
1126 mCameraIdStr.string(), width, streamInfo.width);
1127 ALOGE("%s: %s", __FUNCTION__, msg.string());
1128 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1129 }
1130 if (height != streamInfo.height) {
1131 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
1132 mCameraIdStr.string(), height, streamInfo.height);
1133 ALOGE("%s: %s", __FUNCTION__, msg.string());
1134 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1135 }
1136 if (format != streamInfo.format) {
1137 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
1138 mCameraIdStr.string(), format, streamInfo.format);
1139 ALOGE("%s: %s", __FUNCTION__, msg.string());
1140 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1141 }
Shuzhen Wange8ecda92017-02-20 17:10:28 -08001142 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
1143 if (dataSpace != streamInfo.dataSpace) {
1144 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
1145 mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
1146 ALOGE("%s: %s", __FUNCTION__, msg.string());
1147 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1148 }
1149 //At the native side, there isn't a way to check whether 2 surfaces come from the same
1150 //surface class type. Use usage flag to approximate the comparison.
1151 if (consumerUsage != streamInfo.consumerUsage) {
1152 String8 msg = String8::format(
Emilian Peev050f5dc2017-05-18 14:43:56 +01001153 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Shuzhen Wange8ecda92017-02-20 17:10:28 -08001154 mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
1155 ALOGE("%s: %s", __FUNCTION__, msg.string());
1156 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1157 }
Shuzhen Wang758c2152017-01-10 18:26:18 -08001158 }
1159 return binder::Status::ok();
1160}
1161
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001162bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) {
1163 if (0 == physicalCameraId.size()) {
1164 return true;
1165 }
1166
1167 CameraMetadata staticInfo = mDevice->info();
1168 camera_metadata_entry_t entryCap;
1169 bool isLogicalCam = false;
1170
1171 entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
1172 for (size_t i = 0; i < entryCap.count; ++i) {
1173 uint8_t capability = entryCap.data.u8[i];
1174 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
1175 isLogicalCam = true;
1176 }
1177 }
1178 if (!isLogicalCam) {
1179 return false;
1180 }
1181
1182 camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
1183 const uint8_t* ids = entryIds.data.u8;
1184 size_t start = 0;
1185 for (size_t i = 0; i < entryIds.count; ++i) {
1186 if (ids[i] == '\0') {
1187 if (start != i) {
1188 String8 currentId((const char*)ids+start);
1189 if (currentId == physicalCameraId) {
1190 return true;
1191 }
1192 }
1193 start = i+1;
1194 }
1195 }
1196 return false;
1197}
1198
Ruben Brunkbba75572014-11-20 17:29:50 -08001199bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -08001200 int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
Ruben Brunkbba75572014-11-20 17:29:50 -08001201 /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
1202
1203 camera_metadata_ro_entry streamConfigs =
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -08001204 (dataSpace == HAL_DATASPACE_DEPTH) ?
1205 info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
Ruben Brunkbba75572014-11-20 17:29:50 -08001206 info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
1207
1208 int32_t bestWidth = -1;
1209 int32_t bestHeight = -1;
1210
1211 // Iterate through listed stream configurations and find the one with the smallest euclidean
1212 // distance from the given dimensions for the given format.
1213 for (size_t i = 0; i < streamConfigs.count; i += 4) {
1214 int32_t fmt = streamConfigs.data.i32[i];
1215 int32_t w = streamConfigs.data.i32[i + 1];
1216 int32_t h = streamConfigs.data.i32[i + 2];
1217
1218 // Ignore input/output type for now
1219 if (fmt == format) {
1220 if (w == width && h == height) {
1221 bestWidth = width;
1222 bestHeight = height;
1223 break;
1224 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
1225 CameraDeviceClient::euclidDistSquare(w, h, width, height) <
1226 CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) {
1227 bestWidth = w;
1228 bestHeight = h;
1229 }
1230 }
1231 }
1232
1233 if (bestWidth == -1) {
1234 // Return false if no configurations for this format were listed
1235 return false;
1236 }
1237
1238 // Set the outputs to the closet width/height
1239 if (outWidth != NULL) {
1240 *outWidth = bestWidth;
1241 }
1242 if (outHeight != NULL) {
1243 *outHeight = bestHeight;
1244 }
1245
1246 // Return true if at least one configuration for this format was listed
1247 return true;
1248}
1249
1250int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
1251 int64_t d0 = x0 - x1;
1252 int64_t d1 = y0 - y1;
1253 return d0 * d0 + d1 * d1;
1254}
1255
Igor Murashkine7ee7632013-06-11 18:10:18 -07001256// Create a request object from a template.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001257binder::Status CameraDeviceClient::createDefaultRequest(int templateId,
1258 /*out*/
1259 hardware::camera2::impl::CameraMetadataNative* request)
Igor Murashkine7ee7632013-06-11 18:10:18 -07001260{
1261 ATRACE_CALL();
1262 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
1263
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001264 binder::Status res;
1265 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -07001266
1267 Mutex::Autolock icl(mBinderSerializationLock);
1268
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001269 if (!mDevice.get()) {
1270 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1271 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001272
1273 CameraMetadata metadata;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001274 status_t err;
1275 if ( (err = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
Igor Murashkine7ee7632013-06-11 18:10:18 -07001276 request != NULL) {
1277
1278 request->swap(metadata);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001279 } else if (err == BAD_VALUE) {
1280 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001281 "Camera %s: Template ID %d is invalid or not supported: %s (%d)",
1282 mCameraIdStr.string(), templateId, strerror(-err), err);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001283
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001284 } else {
1285 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001286 "Camera %s: Error creating default request for template %d: %s (%d)",
1287 mCameraIdStr.string(), templateId, strerror(-err), err);
Igor Murashkine7ee7632013-06-11 18:10:18 -07001288 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001289 return res;
1290}
1291
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001292binder::Status CameraDeviceClient::getCameraInfo(
1293 /*out*/
1294 hardware::camera2::impl::CameraMetadataNative* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -07001295{
1296 ATRACE_CALL();
1297 ALOGV("%s", __FUNCTION__);
1298
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001299 binder::Status res;
Igor Murashkine7ee7632013-06-11 18:10:18 -07001300
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001301 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -07001302
1303 Mutex::Autolock icl(mBinderSerializationLock);
1304
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001305 if (!mDevice.get()) {
1306 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1307 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001308
Igor Murashkin099b4572013-07-12 17:52:16 -07001309 if (info != NULL) {
1310 *info = mDevice->info(); // static camera metadata
1311 // TODO: merge with device-specific camera metadata
1312 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001313
1314 return res;
1315}
1316
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001317binder::Status CameraDeviceClient::waitUntilIdle()
Zhijun He2ab500c2013-07-23 08:02:53 -07001318{
1319 ATRACE_CALL();
1320 ALOGV("%s", __FUNCTION__);
1321
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001322 binder::Status res;
1323 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Zhijun He2ab500c2013-07-23 08:02:53 -07001324
1325 Mutex::Autolock icl(mBinderSerializationLock);
1326
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001327 if (!mDevice.get()) {
1328 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1329 }
Zhijun He2ab500c2013-07-23 08:02:53 -07001330
1331 // FIXME: Also need check repeating burst.
Shuzhen Wangc9ca6782016-04-26 13:40:31 -07001332 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001333 if (mStreamingRequestId != REQUEST_ID_NONE) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001334 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001335 "Camera %s: Try to waitUntilIdle when there are active streaming requests",
1336 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001337 ALOGE("%s: %s", __FUNCTION__, msg.string());
1338 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
Zhijun He2ab500c2013-07-23 08:02:53 -07001339 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001340 status_t err = mDevice->waitUntilDrained();
1341 if (err != OK) {
1342 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001343 "Camera %s: Error waiting to drain: %s (%d)",
1344 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001345 }
Zhijun He2ab500c2013-07-23 08:02:53 -07001346 ALOGV("%s Done", __FUNCTION__);
Zhijun He2ab500c2013-07-23 08:02:53 -07001347 return res;
1348}
1349
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001350binder::Status CameraDeviceClient::flush(
1351 /*out*/
1352 int64_t* lastFrameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001353 ATRACE_CALL();
1354 ALOGV("%s", __FUNCTION__);
1355
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001356 binder::Status res;
1357 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001358
1359 Mutex::Autolock icl(mBinderSerializationLock);
1360
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001361 if (!mDevice.get()) {
1362 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1363 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001364
Shuzhen Wangc9ca6782016-04-26 13:40:31 -07001365 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001366 mStreamingRequestId = REQUEST_ID_NONE;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001367 status_t err = mDevice->flush(lastFrameNumber);
1368 if (err != OK) {
1369 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001370 "Camera %s: Error flushing device: %s (%d)", mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001371 }
1372 return res;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001373}
1374
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001375binder::Status CameraDeviceClient::prepare(int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001376 ATRACE_CALL();
1377 ALOGV("%s", __FUNCTION__);
1378
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001379 binder::Status res;
1380 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001381
1382 Mutex::Autolock icl(mBinderSerializationLock);
1383
1384 // Guard against trying to prepare non-created streams
1385 ssize_t index = NAME_NOT_FOUND;
1386 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001387 if (streamId == mStreamMap.valueAt(i).streamId()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001388 index = i;
1389 break;
1390 }
1391 }
1392
1393 if (index == NAME_NOT_FOUND) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001394 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
1395 "with that ID exists", mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001396 ALOGW("%s: %s", __FUNCTION__, msg.string());
1397 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001398 }
1399
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07001400 // Also returns BAD_VALUE if stream ID was not valid, or stream already
1401 // has been used
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001402 status_t err = mDevice->prepare(streamId);
1403 if (err == BAD_VALUE) {
1404 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001405 "Camera %s: Stream %d has already been used, and cannot be prepared",
1406 mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001407 } else if (err != OK) {
1408 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001409 "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.string(), streamId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001410 strerror(-err), err);
1411 }
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001412 return res;
1413}
1414
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001415binder::Status CameraDeviceClient::prepare2(int maxCount, int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07001416 ATRACE_CALL();
1417 ALOGV("%s", __FUNCTION__);
1418
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001419 binder::Status res;
1420 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Ruben Brunkc78ac262015-08-13 17:58:46 -07001421
1422 Mutex::Autolock icl(mBinderSerializationLock);
1423
1424 // Guard against trying to prepare non-created streams
1425 ssize_t index = NAME_NOT_FOUND;
1426 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001427 if (streamId == mStreamMap.valueAt(i).streamId()) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07001428 index = i;
1429 break;
1430 }
1431 }
1432
1433 if (index == NAME_NOT_FOUND) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001434 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
1435 "with that ID exists", mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001436 ALOGW("%s: %s", __FUNCTION__, msg.string());
1437 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Ruben Brunkc78ac262015-08-13 17:58:46 -07001438 }
1439
1440 if (maxCount <= 0) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001441 String8 msg = String8::format("Camera %s: maxCount (%d) must be greater than 0",
1442 mCameraIdStr.string(), maxCount);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001443 ALOGE("%s: %s", __FUNCTION__, msg.string());
1444 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Ruben Brunkc78ac262015-08-13 17:58:46 -07001445 }
1446
1447 // Also returns BAD_VALUE if stream ID was not valid, or stream already
1448 // has been used
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001449 status_t err = mDevice->prepare(maxCount, streamId);
1450 if (err == BAD_VALUE) {
1451 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001452 "Camera %s: Stream %d has already been used, and cannot be prepared",
1453 mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001454 } else if (err != OK) {
1455 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001456 "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.string(), streamId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001457 strerror(-err), err);
1458 }
Ruben Brunkc78ac262015-08-13 17:58:46 -07001459
1460 return res;
1461}
1462
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001463binder::Status CameraDeviceClient::tearDown(int streamId) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001464 ATRACE_CALL();
1465 ALOGV("%s", __FUNCTION__);
1466
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001467 binder::Status res;
1468 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001469
1470 Mutex::Autolock icl(mBinderSerializationLock);
1471
1472 // Guard against trying to prepare non-created streams
1473 ssize_t index = NAME_NOT_FOUND;
1474 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001475 if (streamId == mStreamMap.valueAt(i).streamId()) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001476 index = i;
1477 break;
1478 }
1479 }
1480
1481 if (index == NAME_NOT_FOUND) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001482 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
1483 "with that ID exists", mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001484 ALOGW("%s: %s", __FUNCTION__, msg.string());
1485 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001486 }
1487
1488 // Also returns BAD_VALUE if stream ID was not valid or if the stream is in
1489 // use
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001490 status_t err = mDevice->tearDown(streamId);
1491 if (err == BAD_VALUE) {
1492 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001493 "Camera %s: Stream %d is still in use, cannot be torn down",
1494 mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001495 } else if (err != OK) {
1496 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001497 "Camera %s: Error tearing down stream %d: %s (%d)", mCameraIdStr.string(), streamId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001498 strerror(-err), err);
1499 }
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001500
1501 return res;
1502}
1503
Shuzhen Wang758c2152017-01-10 18:26:18 -08001504binder::Status CameraDeviceClient::finalizeOutputConfigurations(int32_t streamId,
Zhijun He5d677d12016-05-29 16:52:39 -07001505 const hardware::camera2::params::OutputConfiguration &outputConfiguration) {
1506 ATRACE_CALL();
1507
1508 binder::Status res;
1509 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
1510
1511 Mutex::Autolock icl(mBinderSerializationLock);
1512
Shuzhen Wang0129d522016-10-30 22:43:41 -07001513 const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
1514 outputConfiguration.getGraphicBufferProducers();
Zhijun He5d677d12016-05-29 16:52:39 -07001515
Shuzhen Wang0129d522016-10-30 22:43:41 -07001516 if (bufferProducers.size() == 0) {
1517 ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
Zhijun He5d677d12016-05-29 16:52:39 -07001518 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
1519 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001520
Shuzhen Wang758c2152017-01-10 18:26:18 -08001521 // streamId should be in mStreamMap if this stream already has a surface attached
1522 // to it. Otherwise, it should be in mDeferredStreams.
1523 bool streamIdConfigured = false;
1524 ssize_t deferredStreamIndex = NAME_NOT_FOUND;
1525 for (size_t i = 0; i < mStreamMap.size(); i++) {
1526 if (mStreamMap.valueAt(i).streamId() == streamId) {
1527 streamIdConfigured = true;
1528 break;
1529 }
Zhijun He5d677d12016-05-29 16:52:39 -07001530 }
Shuzhen Wang758c2152017-01-10 18:26:18 -08001531 for (size_t i = 0; i < mDeferredStreams.size(); i++) {
1532 if (streamId == mDeferredStreams[i]) {
1533 deferredStreamIndex = i;
1534 break;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001535 }
1536
Shuzhen Wang758c2152017-01-10 18:26:18 -08001537 }
1538 if (deferredStreamIndex == NAME_NOT_FOUND && !streamIdConfigured) {
1539 String8 msg = String8::format("Camera %s: deferred surface is set to a unknown stream"
1540 "(ID %d)", mCameraIdStr.string(), streamId);
1541 ALOGW("%s: %s", __FUNCTION__, msg.string());
1542 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Zhijun He5d677d12016-05-29 16:52:39 -07001543 }
1544
Shuzhen Wang88fd0052017-02-09 16:40:07 -08001545 if (mStreamInfoMap[streamId].finalized) {
1546 String8 msg = String8::format("Camera %s: finalizeOutputConfigurations has been called"
1547 " on stream ID %d", mCameraIdStr.string(), streamId);
1548 ALOGW("%s: %s", __FUNCTION__, msg.string());
1549 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1550 }
1551
Zhijun He5d677d12016-05-29 16:52:39 -07001552 if (!mDevice.get()) {
1553 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1554 }
1555
Shuzhen Wang758c2152017-01-10 18:26:18 -08001556 std::vector<sp<Surface>> consumerSurfaces;
Shuzhen Wang758c2152017-01-10 18:26:18 -08001557 for (auto& bufferProducer : bufferProducers) {
1558 // Don't create multiple streams for the same target surface
Zhijun He5d677d12016-05-29 16:52:39 -07001559 ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
1560 if (index != NAME_NOT_FOUND) {
Shuzhen Wang758c2152017-01-10 18:26:18 -08001561 ALOGV("Camera %s: Surface already has a stream created "
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001562 " for it (ID %zd)", mCameraIdStr.string(), index);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001563 continue;
Zhijun He5d677d12016-05-29 16:52:39 -07001564 }
Shuzhen Wang758c2152017-01-10 18:26:18 -08001565
1566 sp<Surface> surface;
1567 res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
1568 surface, bufferProducer);
1569
1570 if (!res.isOk())
1571 return res;
1572
1573 consumerSurfaces.push_back(surface);
Zhijun He5d677d12016-05-29 16:52:39 -07001574 }
1575
Shuzhen Wanga81ce342017-04-13 15:18:36 -07001576 // Gracefully handle case where finalizeOutputConfigurations is called
1577 // without any new surface.
1578 if (consumerSurfaces.size() == 0) {
1579 mStreamInfoMap[streamId].finalized = true;
1580 return res;
1581 }
1582
Zhijun He5d677d12016-05-29 16:52:39 -07001583 // Finish the deferred stream configuration with the surface.
Shuzhen Wang758c2152017-01-10 18:26:18 -08001584 status_t err;
Emilian Peev40ead602017-09-26 15:46:36 +01001585 std::vector<int> consumerSurfaceIds;
1586 err = mDevice->setConsumerSurfaces(streamId, consumerSurfaces, &consumerSurfaceIds);
Zhijun He5d677d12016-05-29 16:52:39 -07001587 if (err == OK) {
Shuzhen Wang758c2152017-01-10 18:26:18 -08001588 for (size_t i = 0; i < consumerSurfaces.size(); i++) {
1589 sp<IBinder> binder = IInterface::asBinder(
1590 consumerSurfaces[i]->getIGraphicBufferProducer());
Emilian Peev40ead602017-09-26 15:46:36 +01001591 ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d", __FUNCTION__,
Shuzhen Wang758c2152017-01-10 18:26:18 -08001592 binder.get(), streamId, consumerSurfaceIds[i]);
1593 mStreamMap.add(binder, StreamSurfaceId(streamId, consumerSurfaceIds[i]));
1594 }
1595 if (deferredStreamIndex != NAME_NOT_FOUND) {
1596 mDeferredStreams.removeItemsAt(deferredStreamIndex);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001597 }
Shuzhen Wang88fd0052017-02-09 16:40:07 -08001598 mStreamInfoMap[streamId].finalized = true;
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -08001599 mConfiguredOutputs.replaceValueFor(streamId, outputConfiguration);
Zhijun He5d677d12016-05-29 16:52:39 -07001600 } else if (err == NO_INIT) {
1601 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001602 "Camera %s: Deferred surface is invalid: %s (%d)",
1603 mCameraIdStr.string(), strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -07001604 } else {
1605 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001606 "Camera %s: Error setting output stream deferred surface: %s (%d)",
1607 mCameraIdStr.string(), strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -07001608 }
1609
1610 return res;
1611}
1612
Igor Murashkine7ee7632013-06-11 18:10:18 -07001613status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
Eino-Ville Talvalac4003962016-01-13 10:07:04 -08001614 return BasicClient::dump(fd, args);
1615}
1616
1617status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001618 dprintf(fd, " CameraDeviceClient[%s] (%p) dump:\n",
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001619 mCameraIdStr.string(),
Eino-Ville Talvalae992e752014-11-07 16:17:48 -08001620 (getRemoteCallback() != NULL ?
Marco Nelissenf8880202014-11-14 07:58:25 -08001621 IInterface::asBinder(getRemoteCallback()).get() : NULL) );
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001622 dprintf(fd, " Current client UID %u\n", mClientUid);
Igor Murashkine7ee7632013-06-11 18:10:18 -07001623
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001624 dprintf(fd, " State:\n");
1625 dprintf(fd, " Request ID counter: %d\n", mRequestIdCounter);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001626 if (mInputStream.configured) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001627 dprintf(fd, " Current input stream ID: %d\n", mInputStream.id);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001628 } else {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001629 dprintf(fd, " No input stream configured.\n");
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001630 }
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001631 if (!mStreamMap.isEmpty()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001632 dprintf(fd, " Current output stream/surface IDs:\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001633 for (size_t i = 0; i < mStreamMap.size(); i++) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001634 dprintf(fd, " Stream %d Surface %d\n",
Shuzhen Wang0129d522016-10-30 22:43:41 -07001635 mStreamMap.valueAt(i).streamId(),
1636 mStreamMap.valueAt(i).surfaceId());
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001637 }
Zhijun He5d677d12016-05-29 16:52:39 -07001638 } else if (!mDeferredStreams.isEmpty()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001639 dprintf(fd, " Current deferred surface output stream IDs:\n");
Zhijun He5d677d12016-05-29 16:52:39 -07001640 for (auto& streamId : mDeferredStreams) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001641 dprintf(fd, " Stream %d\n", streamId);
Zhijun He5d677d12016-05-29 16:52:39 -07001642 }
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001643 } else {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001644 dprintf(fd, " No output streams configured.\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001645 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001646 // TODO: print dynamic/request section from most recent requests
1647 mFrameProcessor->dump(fd, args);
1648
1649 return dumpDevice(fd, args);
1650}
1651
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001652void CameraDeviceClient::notifyError(int32_t errorCode,
Jianing Weicb0652e2014-03-12 18:29:36 -07001653 const CaptureResultExtras& resultExtras) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001654 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001655 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001656
1657 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -07001658 remoteCb->onDeviceError(errorCode, resultExtras);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001659 }
1660}
1661
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001662void CameraDeviceClient::notifyRepeatingRequestError(long lastFrameNumber) {
1663 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
1664
1665 if (remoteCb != 0) {
Yin-Chia Yeh8ca23dc2017-09-05 18:15:56 -07001666 remoteCb->onRepeatingRequestError(lastFrameNumber, mStreamingRequestId);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001667 }
1668
Shuzhen Wangc9ca6782016-04-26 13:40:31 -07001669 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001670 mStreamingRequestId = REQUEST_ID_NONE;
1671}
1672
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001673void CameraDeviceClient::notifyIdle() {
1674 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001675 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001676
1677 if (remoteCb != 0) {
1678 remoteCb->onDeviceIdle();
1679 }
Eino-Ville Talvala412fe562015-08-20 17:08:32 -07001680 Camera2ClientBase::notifyIdle();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001681}
1682
Jianing Weicb0652e2014-03-12 18:29:36 -07001683void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001684 nsecs_t timestamp) {
1685 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001686 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001687 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -07001688 remoteCb->onCaptureStarted(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001689 }
Eino-Ville Talvala412fe562015-08-20 17:08:32 -07001690 Camera2ClientBase::notifyShutter(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001691}
1692
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001693void CameraDeviceClient::notifyPrepared(int streamId) {
1694 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001695 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001696 if (remoteCb != 0) {
1697 remoteCb->onPrepared(streamId);
1698 }
1699}
1700
Shuzhen Wang9d066012016-09-30 11:30:20 -07001701void CameraDeviceClient::notifyRequestQueueEmpty() {
1702 // Thread safe. Don't bother locking.
1703 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
1704 if (remoteCb != 0) {
1705 remoteCb->onRequestQueueEmpty();
1706 }
1707}
1708
Igor Murashkine7ee7632013-06-11 18:10:18 -07001709void CameraDeviceClient::detachDevice() {
1710 if (mDevice == 0) return;
1711
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001712 ALOGV("Camera %s: Stopping processors", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -07001713
1714 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
1715 FRAME_PROCESSOR_LISTENER_MAX_ID,
1716 /*listener*/this);
1717 mFrameProcessor->requestExit();
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001718 ALOGV("Camera %s: Waiting for threads", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -07001719 mFrameProcessor->join();
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001720 ALOGV("Camera %s: Disconnecting device", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -07001721
1722 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
1723 {
1724 mDevice->clearStreamingRequest();
1725
1726 status_t code;
1727 if ((code = mDevice->waitUntilDrained()) != OK) {
1728 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
1729 code);
1730 }
1731 }
1732
1733 Camera2ClientBase::detachDevice();
1734}
1735
1736/** Device-related methods */
Jianing Weicb0652e2014-03-12 18:29:36 -07001737void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
Igor Murashkine7ee7632013-06-11 18:10:18 -07001738 ATRACE_CALL();
1739 ALOGV("%s", __FUNCTION__);
1740
Igor Murashkin4fb55c12013-08-29 17:43:01 -07001741 // Thread-safe. No lock necessary.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001742 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
Igor Murashkin4fb55c12013-08-29 17:43:01 -07001743 if (remoteCb != NULL) {
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001744 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras,
1745 result.mPhysicalMetadatas);
Igor Murashkine7ee7632013-06-11 18:10:18 -07001746 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001747}
1748
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001749binder::Status CameraDeviceClient::checkPidStatus(const char* checkLocation) {
Eino-Ville Talvala6192b892016-04-04 12:31:18 -07001750 if (mDisconnected) {
1751 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED,
1752 "The camera device has been disconnected");
1753 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001754 status_t res = checkPid(checkLocation);
1755 return (res == OK) ? binder::Status::ok() :
1756 STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
1757 "Attempt to use camera from a different process than original client");
1758}
1759
Igor Murashkine7ee7632013-06-11 18:10:18 -07001760// TODO: move to Camera2ClientBase
1761bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
1762
1763 const int pid = IPCThreadState::self()->getCallingPid();
1764 const int selfPid = getpid();
1765 camera_metadata_entry_t entry;
1766
1767 /**
1768 * Mixin default important security values
1769 * - android.led.transmit = defaulted ON
1770 */
1771 CameraMetadata staticInfo = mDevice->info();
1772 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
1773 for(size_t i = 0; i < entry.count; ++i) {
1774 uint8_t led = entry.data.u8[i];
1775
1776 switch(led) {
1777 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
1778 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
1779 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
1780 metadata.update(ANDROID_LED_TRANSMIT,
1781 &transmitDefault, 1);
1782 }
1783 break;
1784 }
1785 }
1786 }
1787
1788 // We can do anything!
1789 if (pid == selfPid) {
1790 return true;
1791 }
1792
1793 /**
1794 * Permission check special fields in the request
1795 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
1796 */
1797 entry = metadata.find(ANDROID_LED_TRANSMIT);
1798 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
1799 String16 permissionString =
1800 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
1801 if (!checkCallingPermission(permissionString)) {
1802 const int uid = IPCThreadState::self()->getCallingUid();
1803 ALOGE("Permission Denial: "
1804 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
1805 return false;
1806 }
1807 }
1808
1809 return true;
1810}
1811
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -07001812status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
1813 ALOGV("%s: begin", __FUNCTION__);
1814
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -07001815 const CameraMetadata& staticInfo = mDevice->info();
Ruben Brunk5698d442014-06-18 10:39:40 -07001816 return CameraUtils::getRotationTransform(staticInfo, transform);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -07001817}
1818
Igor Murashkine7ee7632013-06-11 18:10:18 -07001819} // namespace android