blob: 4a72de0be58c68205b404b606402dbcedae496e7 [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
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080087status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager) {
88 return initializeImpl(manager);
89}
90
91template<typename TProviderPtr>
92status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr) {
Igor Murashkine7ee7632013-06-11 18:10:18 -070093 ATRACE_CALL();
94 status_t res;
95
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080096 res = Camera2ClientBase::initialize(providerPtr);
Igor Murashkine7ee7632013-06-11 18:10:18 -070097 if (res != OK) {
98 return res;
99 }
100
101 String8 threadName;
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -0700102 mFrameProcessor = new FrameProcessorBase(mDevice);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800103 threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700104 mFrameProcessor->run(threadName.string());
105
106 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
107 FRAME_PROCESSOR_LISTENER_MAX_ID,
Eino-Ville Talvala184dfe42013-11-07 15:13:16 -0800108 /*listener*/this,
Zhijun He25a0aef2014-06-25 11:40:02 -0700109 /*sendPartials*/true);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700110
Emilian Peev00420d22018-02-05 21:33:13 +0000111 auto deviceInfo = mDevice->info();
112 camera_metadata_entry_t physicalKeysEntry = deviceInfo.find(
113 ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
114 if (physicalKeysEntry.count > 0) {
115 mSupportedPhysicalRequestKeys.insert(mSupportedPhysicalRequestKeys.begin(),
116 physicalKeysEntry.data.i32,
117 physicalKeysEntry.data.i32 + physicalKeysEntry.count);
118 }
119
Igor Murashkine7ee7632013-06-11 18:10:18 -0700120 return OK;
121}
122
123CameraDeviceClient::~CameraDeviceClient() {
124}
125
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800126binder::Status CameraDeviceClient::submitRequest(
127 const hardware::camera2::CaptureRequest& request,
128 bool streaming,
129 /*out*/
130 hardware::camera2::utils::SubmitInfo *submitInfo) {
131 std::vector<hardware::camera2::CaptureRequest> requestList = { request };
132 return submitRequestList(requestList, streaming, submitInfo);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700133}
134
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800135binder::Status CameraDeviceClient::insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
Emilian Peevf873aa52018-01-26 14:58:28 +0000136 SurfaceMap* outSurfaceMap, Vector<int32_t>* outputStreamIds, int32_t *currentStreamId) {
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800137 int idx = mStreamMap.indexOfKey(IInterface::asBinder(gbp));
138
139 // Trying to submit request with surface that wasn't created
140 if (idx == NAME_NOT_FOUND) {
141 ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
142 " we have not called createStream on",
143 __FUNCTION__, mCameraIdStr.string());
144 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
145 "Request targets Surface that is not part of current capture session");
146 }
147
148 const StreamSurfaceId& streamSurfaceId = mStreamMap.valueAt(idx);
149 if (outSurfaceMap->find(streamSurfaceId.streamId()) == outSurfaceMap->end()) {
150 (*outSurfaceMap)[streamSurfaceId.streamId()] = std::vector<size_t>();
151 outputStreamIds->push_back(streamSurfaceId.streamId());
152 }
153 (*outSurfaceMap)[streamSurfaceId.streamId()].push_back(streamSurfaceId.surfaceId());
154
155 ALOGV("%s: Camera %s: Appending output stream %d surface %d to request",
156 __FUNCTION__, mCameraIdStr.string(), streamSurfaceId.streamId(),
157 streamSurfaceId.surfaceId());
158
Emilian Peevf873aa52018-01-26 14:58:28 +0000159 if (currentStreamId != nullptr) {
160 *currentStreamId = streamSurfaceId.streamId();
161 }
162
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800163 return binder::Status::ok();
164}
165
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800166binder::Status CameraDeviceClient::submitRequestList(
167 const std::vector<hardware::camera2::CaptureRequest>& requests,
168 bool streaming,
169 /*out*/
170 hardware::camera2::utils::SubmitInfo *submitInfo) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700171 ATRACE_CALL();
Mark Salyzyn50468412014-06-18 16:33:43 -0700172 ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700173
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800174 binder::Status res = binder::Status::ok();
175 status_t err;
176 if ( !(res = checkPidStatus(__FUNCTION__) ).isOk()) {
177 return res;
178 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700179
180 Mutex::Autolock icl(mBinderSerializationLock);
181
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800182 if (!mDevice.get()) {
183 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
184 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700185
186 if (requests.empty()) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800187 ALOGE("%s: Camera %s: Sent null request. Rejecting request.",
188 __FUNCTION__, mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800189 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
Jianing Wei90e59c92014-03-12 18:29:36 -0700190 }
191
Emilian Peevaebbe412018-01-15 13:53:24 +0000192 List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700193 std::list<const SurfaceMap> surfaceMapList;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800194 submitInfo->mRequestId = mRequestIdCounter;
Jianing Wei90e59c92014-03-12 18:29:36 -0700195 uint32_t loopCounter = 0;
196
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800197 for (auto&& request: requests) {
198 if (request.mIsReprocess) {
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700199 if (!mInputStream.configured) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800200 ALOGE("%s: Camera %s: no input stream is configured.", __FUNCTION__,
201 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800202 return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800203 "No input configured for camera %s but request is for reprocessing",
204 mCameraIdStr.string());
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700205 } else if (streaming) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800206 ALOGE("%s: Camera %s: streaming reprocess requests not supported.", __FUNCTION__,
207 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800208 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
209 "Repeating reprocess requests not supported");
Emilian Peevaebbe412018-01-15 13:53:24 +0000210 } else if (request.mPhysicalCameraSettings.size() > 1) {
211 ALOGE("%s: Camera %s: reprocess requests not supported for "
212 "multiple physical cameras.", __FUNCTION__,
213 mCameraIdStr.string());
214 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
215 "Reprocess requests not supported for multiple cameras");
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700216 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700217 }
218
Emilian Peevaebbe412018-01-15 13:53:24 +0000219 if (request.mPhysicalCameraSettings.empty()) {
220 ALOGE("%s: Camera %s: request doesn't contain any settings.", __FUNCTION__,
221 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800222 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
Emilian Peevaebbe412018-01-15 13:53:24 +0000223 "Request doesn't contain any settings");
224 }
225
226 //The first capture settings should always match the logical camera id
227 String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
228 if (mDevice->getId() != logicalId) {
229 ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
230 mCameraIdStr.string());
231 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
232 "Invalid camera request settings");
233 }
234
Emilian Peevaebbe412018-01-15 13:53:24 +0000235 if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800236 ALOGE("%s: Camera %s: Requests must have at least one surface target. "
237 "Rejecting request.", __FUNCTION__, mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800238 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
239 "Request has no output targets");
Jianing Wei90e59c92014-03-12 18:29:36 -0700240 }
241
Jianing Wei90e59c92014-03-12 18:29:36 -0700242 /**
Shuzhen Wang0129d522016-10-30 22:43:41 -0700243 * Write in the output stream IDs and map from stream ID to surface ID
244 * which we calculate from the capture request's list of surface target
Jianing Wei90e59c92014-03-12 18:29:36 -0700245 */
Shuzhen Wang0129d522016-10-30 22:43:41 -0700246 SurfaceMap surfaceMap;
Jianing Wei90e59c92014-03-12 18:29:36 -0700247 Vector<int32_t> outputStreamIds;
Emilian Peevf873aa52018-01-26 14:58:28 +0000248 std::vector<std::string> requestedPhysicalIds;
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800249 if (request.mSurfaceList.size() > 0) {
250 for (sp<Surface> surface : request.mSurfaceList) {
251 if (surface == 0) continue;
Jianing Wei90e59c92014-03-12 18:29:36 -0700252
Emilian Peevf873aa52018-01-26 14:58:28 +0000253 int32_t streamId;
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800254 sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
Emilian Peevf873aa52018-01-26 14:58:28 +0000255 res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds, &streamId);
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800256 if (!res.isOk()) {
257 return res;
258 }
Emilian Peevf873aa52018-01-26 14:58:28 +0000259
260 ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
261 if (index >= 0) {
262 String8 requestedPhysicalId(
263 mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
264 requestedPhysicalIds.push_back(requestedPhysicalId.string());
265 } else {
266 ALOGW("%s: Output stream Id not found among configured outputs!", __FUNCTION__);
267 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700268 }
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800269 } else {
270 for (size_t i = 0; i < request.mStreamIdxList.size(); i++) {
271 int streamId = request.mStreamIdxList.itemAt(i);
272 int surfaceIdx = request.mSurfaceIdxList.itemAt(i);
Jianing Wei90e59c92014-03-12 18:29:36 -0700273
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800274 ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
275 if (index < 0) {
276 ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
277 " we have not called createStream on: stream %d",
278 __FUNCTION__, mCameraIdStr.string(), streamId);
279 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
280 "Request targets Surface that is not part of current capture session");
281 }
282
283 const auto& gbps = mConfiguredOutputs.valueAt(index).getGraphicBufferProducers();
284 if ((size_t)surfaceIdx >= gbps.size()) {
285 ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
286 " we have not called createStream on: stream %d, surfaceIdx %d",
287 __FUNCTION__, mCameraIdStr.string(), streamId, surfaceIdx);
288 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
289 "Request targets Surface has invalid surface index");
290 }
291
Emilian Peevf873aa52018-01-26 14:58:28 +0000292 res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds, nullptr);
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800293 if (!res.isOk()) {
294 return res;
295 }
Emilian Peevf873aa52018-01-26 14:58:28 +0000296
297 String8 requestedPhysicalId(
298 mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
299 requestedPhysicalIds.push_back(requestedPhysicalId.string());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700300 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700301 }
302
Emilian Peevf873aa52018-01-26 14:58:28 +0000303 CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
304 for (const auto& it : request.mPhysicalCameraSettings) {
Emilian Peev00420d22018-02-05 21:33:13 +0000305 if (it.settings.isEmpty()) {
306 ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
307 __FUNCTION__, mCameraIdStr.string());
308 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
309 "Request settings are empty");
310 }
311
Emilian Peevf873aa52018-01-26 14:58:28 +0000312 String8 physicalId(it.id.c_str());
313 if (physicalId != mDevice->getId()) {
314 auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
315 it.id);
316 if (found == requestedPhysicalIds.end()) {
317 ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
318 __FUNCTION__, mCameraIdStr.string(), physicalId.string());
319 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
320 "Invalid physical camera id");
321 }
Emilian Peev00420d22018-02-05 21:33:13 +0000322
323 if (!mSupportedPhysicalRequestKeys.empty()) {
324 // Filter out any unsupported physical request keys.
325 CameraMetadata filteredParams(mSupportedPhysicalRequestKeys.size());
326 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
327 filteredParams.getAndLock());
328 set_camera_metadata_vendor_id(meta, mDevice->getVendorTagId());
329 filteredParams.unlock(meta);
330
331 for (const auto& keyIt : mSupportedPhysicalRequestKeys) {
332 camera_metadata_ro_entry entry = it.settings.find(keyIt);
333 if (entry.count > 0) {
334 filteredParams.update(entry);
335 }
336 }
337
338 physicalSettingsList.push_back({it.id, filteredParams});
339 }
340 } else {
341 physicalSettingsList.push_back({it.id, it.settings});
Emilian Peevf873aa52018-01-26 14:58:28 +0000342 }
Emilian Peevf873aa52018-01-26 14:58:28 +0000343 }
344
345 if (!enforceRequestPermissions(physicalSettingsList.begin()->metadata)) {
346 // Callee logs
347 return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
348 "Caller does not have permission to change restricted controls");
349 }
350
Emilian Peevaebbe412018-01-15 13:53:24 +0000351 physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
352 &outputStreamIds[0], outputStreamIds.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700353
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800354 if (request.mIsReprocess) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000355 physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_INPUT_STREAMS,
356 &mInputStream.id, 1);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700357 }
358
Emilian Peevaebbe412018-01-15 13:53:24 +0000359 physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_ID,
360 &(submitInfo->mRequestId), /*size*/1);
Jianing Wei90e59c92014-03-12 18:29:36 -0700361 loopCounter++; // loopCounter starts from 1
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800362 ALOGV("%s: Camera %s: Creating request with ID %d (%d of %zu)",
363 __FUNCTION__, mCameraIdStr.string(), submitInfo->mRequestId,
364 loopCounter, requests.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700365
Emilian Peevaebbe412018-01-15 13:53:24 +0000366 metadataRequestList.push_back(physicalSettingsList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700367 surfaceMapList.push_back(surfaceMap);
Jianing Wei90e59c92014-03-12 18:29:36 -0700368 }
369 mRequestIdCounter++;
370
371 if (streaming) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700372 err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
373 &(submitInfo->mLastFrameNumber));
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800374 if (err != OK) {
375 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800376 "Camera %s: Got error %s (%d) after trying to set streaming request",
377 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800378 ALOGE("%s: %s", __FUNCTION__, msg.string());
379 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
380 msg.string());
Jianing Wei90e59c92014-03-12 18:29:36 -0700381 } else {
Shuzhen Wangc9ca6782016-04-26 13:40:31 -0700382 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -0700383 mStreamingRequestId = submitInfo->mRequestId;
Jianing Wei90e59c92014-03-12 18:29:36 -0700384 }
385 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700386 err = mDevice->captureList(metadataRequestList, surfaceMapList,
387 &(submitInfo->mLastFrameNumber));
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800388 if (err != OK) {
389 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800390 "Camera %s: Got error %s (%d) after trying to submit capture request",
391 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800392 ALOGE("%s: %s", __FUNCTION__, msg.string());
393 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
394 msg.string());
Jianing Wei90e59c92014-03-12 18:29:36 -0700395 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800396 ALOGV("%s: requestId = %d ", __FUNCTION__, submitInfo->mRequestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700397 }
398
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800399 ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.string());
Jianing Wei90e59c92014-03-12 18:29:36 -0700400 return res;
401}
402
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800403binder::Status CameraDeviceClient::cancelRequest(
404 int requestId,
405 /*out*/
406 int64_t* lastFrameNumber) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700407 ATRACE_CALL();
408 ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
409
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800410 status_t err;
411 binder::Status res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700412
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800413 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700414
415 Mutex::Autolock icl(mBinderSerializationLock);
416
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800417 if (!mDevice.get()) {
418 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
419 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700420
Shuzhen Wangc9ca6782016-04-26 13:40:31 -0700421 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -0700422 if (mStreamingRequestId != requestId) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800423 String8 msg = String8::format("Camera %s: Canceling request ID %d doesn't match "
424 "current request ID %d", mCameraIdStr.string(), requestId, mStreamingRequestId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800425 ALOGE("%s: %s", __FUNCTION__, msg.string());
426 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700427 }
428
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800429 err = mDevice->clearStreamingRequest(lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700430
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800431 if (err == OK) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800432 ALOGV("%s: Camera %s: Successfully cleared streaming request",
433 __FUNCTION__, mCameraIdStr.string());
Chien-Yu Chene8c535e2016-04-14 12:18:26 -0700434 mStreamingRequestId = REQUEST_ID_NONE;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800435 } else {
436 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800437 "Camera %s: Error clearing streaming request: %s (%d)",
438 mCameraIdStr.string(), strerror(-err), err);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700439 }
440
441 return res;
442}
443
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800444binder::Status CameraDeviceClient::beginConfigure() {
Ruben Brunkb2119af2014-05-09 19:57:56 -0700445 // TODO: Implement this.
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -0700446 ATRACE_CALL();
Zhijun He1fa89992015-06-01 15:44:31 -0700447 ALOGV("%s: Not implemented yet.", __FUNCTION__);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800448 return binder::Status::ok();
Ruben Brunkb2119af2014-05-09 19:57:56 -0700449}
450
Emilian Peev5fbe0ba2017-10-20 15:45:45 +0100451binder::Status CameraDeviceClient::endConfigure(int operatingMode,
452 const hardware::camera2::impl::CameraMetadataNative& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -0700453 ATRACE_CALL();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700454 ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
455 __FUNCTION__, mInputStream.configured ? 1 : 0,
456 mStreamMap.size());
Igor Murashkine2d167e2014-08-19 16:19:59 -0700457
Zhijun He0effd522016-03-04 10:22:27 -0800458 binder::Status res;
459 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
460
461 Mutex::Autolock icl(mBinderSerializationLock);
462
463 if (!mDevice.get()) {
464 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
465 }
466
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800467 if (operatingMode < 0) {
468 String8 msg = String8::format(
469 "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
470 ALOGE("%s: %s", __FUNCTION__, msg.string());
471 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
472 msg.string());
473 }
474
Zhijun He1fa89992015-06-01 15:44:31 -0700475 // Sanitize the high speed session against necessary capability bit.
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800476 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
Zhijun He1fa89992015-06-01 15:44:31 -0700477 if (isConstrainedHighSpeed) {
478 CameraMetadata staticInfo = mDevice->info();
479 camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
480 bool isConstrainedHighSpeedSupported = false;
481 for(size_t i = 0; i < entry.count; ++i) {
482 uint8_t capability = entry.data.u8[i];
483 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
484 isConstrainedHighSpeedSupported = true;
485 break;
486 }
487 }
488 if (!isConstrainedHighSpeedSupported) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800489 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800490 "Camera %s: Try to create a constrained high speed configuration on a device"
491 " that doesn't support it.", mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800492 ALOGE("%s: %s", __FUNCTION__, msg.string());
493 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
494 msg.string());
Zhijun He1fa89992015-06-01 15:44:31 -0700495 }
496 }
497
Emilian Peev5fbe0ba2017-10-20 15:45:45 +0100498 status_t err = mDevice->configureStreams(sessionParams, operatingMode);
Eino-Ville Talvalaace80582016-03-18 13:27:35 -0700499 if (err == BAD_VALUE) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800500 String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
501 mCameraIdStr.string());
Zhijun He5d677d12016-05-29 16:52:39 -0700502 ALOGE("%s: %s", __FUNCTION__, msg.string());
503 res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Eino-Ville Talvalaace80582016-03-18 13:27:35 -0700504 } else if (err != OK) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800505 String8 msg = String8::format("Camera %s: Error configuring streams: %s (%d)",
506 mCameraIdStr.string(), strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -0700507 ALOGE("%s: %s", __FUNCTION__, msg.string());
508 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800509 }
510
511 return res;
Ruben Brunkb2119af2014-05-09 19:57:56 -0700512}
513
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800514binder::Status CameraDeviceClient::deleteStream(int streamId) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700515 ATRACE_CALL();
516 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
517
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800518 binder::Status res;
519 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700520
521 Mutex::Autolock icl(mBinderSerializationLock);
522
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800523 if (!mDevice.get()) {
524 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
525 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700526
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700527 bool isInput = false;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700528 std::vector<sp<IBinder>> surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -0700529 ssize_t dIndex = NAME_NOT_FOUND;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700530
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700531 if (mInputStream.configured && mInputStream.id == streamId) {
532 isInput = true;
533 } else {
534 // Guard against trying to delete non-created streams
535 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700536 if (streamId == mStreamMap.valueAt(i).streamId()) {
537 surfaces.push_back(mStreamMap.keyAt(i));
538 }
539 }
540
541 // See if this stream is one of the deferred streams.
542 for (size_t i = 0; i < mDeferredStreams.size(); ++i) {
543 if (streamId == mDeferredStreams[i]) {
544 dIndex = i;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700545 break;
546 }
547 }
548
Shuzhen Wang0129d522016-10-30 22:43:41 -0700549 if (surfaces.empty() && dIndex == NAME_NOT_FOUND) {
550 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no such"
551 " stream created yet", mCameraIdStr.string(), streamId);
552 ALOGW("%s: %s", __FUNCTION__, msg.string());
553 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700554 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700555 }
556
557 // Also returns BAD_VALUE if stream ID was not valid
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800558 status_t err = mDevice->deleteStream(streamId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700559
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800560 if (err != OK) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800561 String8 msg = String8::format("Camera %s: Unexpected error %s (%d) when deleting stream %d",
562 mCameraIdStr.string(), strerror(-err), err, streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800563 ALOGE("%s: %s", __FUNCTION__, msg.string());
564 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
565 } else {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700566 if (isInput) {
567 mInputStream.configured = false;
Zhijun He5d677d12016-05-29 16:52:39 -0700568 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700569 for (auto& surface : surfaces) {
570 mStreamMap.removeItem(surface);
571 }
572
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800573 mConfiguredOutputs.removeItem(streamId);
574
Shuzhen Wang0129d522016-10-30 22:43:41 -0700575 if (dIndex != NAME_NOT_FOUND) {
576 mDeferredStreams.removeItemsAt(dIndex);
577 }
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700578 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700579 }
580
581 return res;
582}
583
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800584binder::Status CameraDeviceClient::createStream(
585 const hardware::camera2::params::OutputConfiguration &outputConfiguration,
586 /*out*/
587 int32_t* newStreamId) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700588 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700589
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800590 binder::Status res;
591 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700592
593 Mutex::Autolock icl(mBinderSerializationLock);
594
Shuzhen Wang0129d522016-10-30 22:43:41 -0700595 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
596 outputConfiguration.getGraphicBufferProducers();
597 size_t numBufferProducers = bufferProducers.size();
Shuzhen Wang758c2152017-01-10 18:26:18 -0800598 bool deferredConsumer = outputConfiguration.isDeferred();
599 bool isShared = outputConfiguration.isShared();
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800600 String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700601
602 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
603 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
604 __FUNCTION__, bufferProducers.size(), MAX_SURFACES_PER_STREAM);
605 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
606 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800607 bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
Zhijun He5d677d12016-05-29 16:52:39 -0700608 int surfaceType = outputConfiguration.getSurfaceType();
609 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
610 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700611
Zhijun He5d677d12016-05-29 16:52:39 -0700612 if (deferredConsumer && !validSurfaceType) {
613 ALOGE("%s: Target surface is invalid: bufferProducer = %p, surfaceType = %d.",
Shuzhen Wang0129d522016-10-30 22:43:41 -0700614 __FUNCTION__, bufferProducers[0].get(), surfaceType);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800615 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
Yin-Chia Yeh89f14da2014-06-10 16:05:44 -0700616 }
Zhijun He5d677d12016-05-29 16:52:39 -0700617
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800618 if (!mDevice.get()) {
619 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
620 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700621
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800622 if (!checkPhysicalCameraId(physicalCameraId)) {
623 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
624 mCameraIdStr.string(), physicalCameraId.string());
625 ALOGE("%s: %s", __FUNCTION__, msg.string());
626 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
627 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700628 std::vector<sp<Surface>> surfaces;
629 std::vector<sp<IBinder>> binders;
Zhijun He5d677d12016-05-29 16:52:39 -0700630 status_t err;
631
632 // Create stream for deferred surface case.
Shuzhen Wang0129d522016-10-30 22:43:41 -0700633 if (deferredConsumerOnly) {
Shuzhen Wang758c2152017-01-10 18:26:18 -0800634 return createDeferredSurfaceStreamLocked(outputConfiguration, isShared, newStreamId);
Zhijun He5d677d12016-05-29 16:52:39 -0700635 }
636
Shuzhen Wang758c2152017-01-10 18:26:18 -0800637 OutputStreamInfo streamInfo;
638 bool isStreamInfoValid = false;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700639 for (auto& bufferProducer : bufferProducers) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700640 // Don't create multiple streams for the same target surface
Shuzhen Wang0129d522016-10-30 22:43:41 -0700641 sp<IBinder> binder = IInterface::asBinder(bufferProducer);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800642 ssize_t index = mStreamMap.indexOfKey(binder);
643 if (index != NAME_NOT_FOUND) {
644 String8 msg = String8::format("Camera %s: Surface already has a stream created for it "
645 "(ID %zd)", mCameraIdStr.string(), index);
646 ALOGW("%s: %s", __FUNCTION__, msg.string());
647 return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700648 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700649
Shuzhen Wang758c2152017-01-10 18:26:18 -0800650 sp<Surface> surface;
651 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer);
652
653 if (!res.isOk())
654 return res;
655
656 if (!isStreamInfoValid) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800657 // Streaming sharing is only supported for IMPLEMENTATION_DEFINED
658 // formats.
659 if (isShared && streamInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
660 String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
661 "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
662 ALOGW("%s: %s", __FUNCTION__, msg.string());
663 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
664 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800665 isStreamInfoValid = true;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700666 }
667
Shuzhen Wang758c2152017-01-10 18:26:18 -0800668 binders.push_back(IInterface::asBinder(bufferProducer));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700669 surfaces.push_back(surface);
Ruben Brunkbba75572014-11-20 17:29:50 -0800670 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700671
Zhijun He125684a2015-12-26 15:07:30 -0800672 int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
Emilian Peev40ead602017-09-26 15:46:36 +0100673 std::vector<int> surfaceIds;
Shuzhen Wang758c2152017-01-10 18:26:18 -0800674 err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
675 streamInfo.height, streamInfo.format, streamInfo.dataSpace,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800676 static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800677 &streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
678 isShared);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700679
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800680 if (err != OK) {
681 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800682 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
Shuzhen Wang758c2152017-01-10 18:26:18 -0800683 mCameraIdStr.string(), streamInfo.width, streamInfo.height, streamInfo.format,
684 streamInfo.dataSpace, strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800685 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700686 int i = 0;
687 for (auto& binder : binders) {
688 ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d",
689 __FUNCTION__, binder.get(), streamId, i);
Emilian Peev40ead602017-09-26 15:46:36 +0100690 mStreamMap.add(binder, StreamSurfaceId(streamId, surfaceIds[i]));
691 i++;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700692 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800693
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800694 mConfiguredOutputs.add(streamId, outputConfiguration);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800695 mStreamInfoMap[streamId] = streamInfo;
696
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800697 ALOGV("%s: Camera %s: Successfully created a new stream ID %d for output surface"
Shuzhen Wang0129d522016-10-30 22:43:41 -0700698 " (%d x %d) with format 0x%x.",
Shuzhen Wang758c2152017-01-10 18:26:18 -0800699 __FUNCTION__, mCameraIdStr.string(), streamId, streamInfo.width,
700 streamInfo.height, streamInfo.format);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700701
Zhijun He5d677d12016-05-29 16:52:39 -0700702 // Set transform flags to ensure preview to be rotated correctly.
703 res = setStreamTransformLocked(streamId);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700704
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800705 *newStreamId = streamId;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700706 }
707
708 return res;
709}
710
Zhijun He5d677d12016-05-29 16:52:39 -0700711binder::Status CameraDeviceClient::createDeferredSurfaceStreamLocked(
712 const hardware::camera2::params::OutputConfiguration &outputConfiguration,
Shuzhen Wang758c2152017-01-10 18:26:18 -0800713 bool isShared,
Zhijun He5d677d12016-05-29 16:52:39 -0700714 /*out*/
715 int* newStreamId) {
716 int width, height, format, surfaceType;
Emilian Peev050f5dc2017-05-18 14:43:56 +0100717 uint64_t consumerUsage;
Zhijun He5d677d12016-05-29 16:52:39 -0700718 android_dataspace dataSpace;
719 status_t err;
720 binder::Status res;
721
722 if (!mDevice.get()) {
723 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
724 }
725
726 // Infer the surface info for deferred surface stream creation.
727 width = outputConfiguration.getWidth();
728 height = outputConfiguration.getHeight();
729 surfaceType = outputConfiguration.getSurfaceType();
730 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
731 dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
732 // Hardcode consumer usage flags: SurfaceView--0x900, SurfaceTexture--0x100.
733 consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
734 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
735 consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
736 }
737 int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700738 std::vector<sp<Surface>> noSurface;
Emilian Peev40ead602017-09-26 15:46:36 +0100739 std::vector<int> surfaceIds;
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800740 String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700741 err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
742 height, format, dataSpace,
Zhijun He5d677d12016-05-29 16:52:39 -0700743 static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
Shuzhen Wangc28189a2017-11-27 23:05:10 -0800744 &streamId, physicalCameraId, &surfaceIds,
745 outputConfiguration.getSurfaceSetID(), isShared,
Emilian Peev40ead602017-09-26 15:46:36 +0100746 consumerUsage);
Zhijun He5d677d12016-05-29 16:52:39 -0700747
748 if (err != OK) {
749 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800750 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
751 mCameraIdStr.string(), width, height, format, dataSpace, strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -0700752 } else {
753 // Can not add streamId to mStreamMap here, as the surface is deferred. Add it to
754 // a separate list to track. Once the deferred surface is set, this id will be
755 // relocated to mStreamMap.
756 mDeferredStreams.push_back(streamId);
757
Shuzhen Wang758c2152017-01-10 18:26:18 -0800758 mStreamInfoMap.emplace(std::piecewise_construct, std::forward_as_tuple(streamId),
759 std::forward_as_tuple(width, height, format, dataSpace, consumerUsage));
760
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800761 ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
Zhijun He5d677d12016-05-29 16:52:39 -0700762 " (%d x %d) stream with format 0x%x.",
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800763 __FUNCTION__, mCameraIdStr.string(), streamId, width, height, format);
Zhijun He5d677d12016-05-29 16:52:39 -0700764
765 // Set transform flags to ensure preview to be rotated correctly.
766 res = setStreamTransformLocked(streamId);
767
768 *newStreamId = streamId;
769 }
770 return res;
771}
772
773binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId) {
774 int32_t transform = 0;
775 status_t err;
776 binder::Status res;
777
778 if (!mDevice.get()) {
779 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
780 }
781
782 err = getRotationTransformLocked(&transform);
783 if (err != OK) {
784 // Error logged by getRotationTransformLocked.
785 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
786 "Unable to calculate rotation transform for new stream");
787 }
788
789 err = mDevice->setStreamTransform(streamId, transform);
790 if (err != OK) {
791 String8 msg = String8::format("Failed to set stream transform (stream id %d)",
792 streamId);
793 ALOGE("%s: %s", __FUNCTION__, msg.string());
794 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
795 }
796
797 return res;
798}
Ruben Brunkbba75572014-11-20 17:29:50 -0800799
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800800binder::Status CameraDeviceClient::createInputStream(
801 int width, int height, int format,
802 /*out*/
803 int32_t* newStreamId) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700804
805 ATRACE_CALL();
806 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
807
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800808 binder::Status res;
809 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700810
811 Mutex::Autolock icl(mBinderSerializationLock);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800812
813 if (!mDevice.get()) {
814 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
815 }
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700816
817 if (mInputStream.configured) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800818 String8 msg = String8::format("Camera %s: Already has an input stream "
Yi Kong0f414de2017-12-15 13:48:50 -0800819 "configured (ID %d)", mCameraIdStr.string(), mInputStream.id);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800820 ALOGE("%s: %s", __FUNCTION__, msg.string() );
821 return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700822 }
823
824 int streamId = -1;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800825 status_t err = mDevice->createInputStream(width, height, format, &streamId);
826 if (err == OK) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700827 mInputStream.configured = true;
828 mInputStream.width = width;
829 mInputStream.height = height;
830 mInputStream.format = format;
831 mInputStream.id = streamId;
832
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800833 ALOGV("%s: Camera %s: Successfully created a new input stream ID %d",
834 __FUNCTION__, mCameraIdStr.string(), streamId);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700835
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800836 *newStreamId = streamId;
837 } else {
838 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800839 "Camera %s: Error creating new input stream: %s (%d)", mCameraIdStr.string(),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800840 strerror(-err), err);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700841 }
842
843 return res;
844}
845
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800846binder::Status CameraDeviceClient::getInputSurface(/*out*/ view::Surface *inputSurface) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700847
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800848 binder::Status res;
849 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
850
851 if (inputSurface == NULL) {
852 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Null input surface");
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700853 }
854
855 Mutex::Autolock icl(mBinderSerializationLock);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800856 if (!mDevice.get()) {
857 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
858 }
859 sp<IGraphicBufferProducer> producer;
860 status_t err = mDevice->getInputBufferProducer(&producer);
861 if (err != OK) {
862 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800863 "Camera %s: Error getting input Surface: %s (%d)",
864 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800865 } else {
866 inputSurface->name = String16("CameraInput");
867 inputSurface->graphicBufferProducer = producer;
868 }
869 return res;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700870}
871
Emilian Peev40ead602017-09-26 15:46:36 +0100872binder::Status CameraDeviceClient::updateOutputConfiguration(int streamId,
873 const hardware::camera2::params::OutputConfiguration &outputConfiguration) {
874 ATRACE_CALL();
875
876 binder::Status res;
877 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
878
879 Mutex::Autolock icl(mBinderSerializationLock);
880
881 if (!mDevice.get()) {
882 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
883 }
884
885 const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
886 outputConfiguration.getGraphicBufferProducers();
887 auto producerCount = bufferProducers.size();
888 if (producerCount == 0) {
889 ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
890 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
891 "bufferProducers must not be empty");
892 }
893
894 // The first output is the one associated with the output configuration.
895 // It should always be present, valid and the corresponding stream id should match.
896 sp<IBinder> binder = IInterface::asBinder(bufferProducers[0]);
897 ssize_t index = mStreamMap.indexOfKey(binder);
898 if (index == NAME_NOT_FOUND) {
899 ALOGE("%s: Outputconfiguration is invalid", __FUNCTION__);
900 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
901 "OutputConfiguration is invalid");
902 }
903 if (mStreamMap.valueFor(binder).streamId() != streamId) {
904 ALOGE("%s: Stream Id: %d provided doesn't match the id: %d in the stream map",
905 __FUNCTION__, streamId, mStreamMap.valueFor(binder).streamId());
906 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
907 "Stream id is invalid");
908 }
909
910 std::vector<size_t> removedSurfaceIds;
911 std::vector<sp<IBinder>> removedOutputs;
912 std::vector<sp<Surface>> newOutputs;
913 std::vector<OutputStreamInfo> streamInfos;
914 KeyedVector<sp<IBinder>, sp<IGraphicBufferProducer>> newOutputsMap;
915 for (auto &it : bufferProducers) {
916 newOutputsMap.add(IInterface::asBinder(it), it);
917 }
918
919 for (size_t i = 0; i < mStreamMap.size(); i++) {
920 ssize_t idx = newOutputsMap.indexOfKey(mStreamMap.keyAt(i));
921 if (idx == NAME_NOT_FOUND) {
922 if (mStreamMap[i].streamId() == streamId) {
923 removedSurfaceIds.push_back(mStreamMap[i].surfaceId());
924 removedOutputs.push_back(mStreamMap.keyAt(i));
925 }
926 } else {
927 if (mStreamMap[i].streamId() != streamId) {
928 ALOGE("%s: Output surface already part of a different stream", __FUNCTION__);
929 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
930 "Target Surface is invalid");
931 }
932 newOutputsMap.removeItemsAt(idx);
933 }
934 }
935
936 for (size_t i = 0; i < newOutputsMap.size(); i++) {
937 OutputStreamInfo outInfo;
938 sp<Surface> surface;
939 res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
940 newOutputsMap.valueAt(i));
941 if (!res.isOk())
942 return res;
943
944 // Stream sharing is only supported for IMPLEMENTATION_DEFINED
945 // formats.
946 if (outInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
947 String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
948 "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
949 ALOGW("%s: %s", __FUNCTION__, msg.string());
950 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
951 }
952 streamInfos.push_back(outInfo);
953 newOutputs.push_back(surface);
954 }
955
956 //Trivial case no changes required
957 if (removedSurfaceIds.empty() && newOutputs.empty()) {
958 return binder::Status::ok();
959 }
960
961 KeyedVector<sp<Surface>, size_t> outputMap;
962 auto ret = mDevice->updateStream(streamId, newOutputs, streamInfos, removedSurfaceIds,
963 &outputMap);
964 if (ret != OK) {
965 switch (ret) {
966 case NAME_NOT_FOUND:
967 case BAD_VALUE:
968 case -EBUSY:
969 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
970 "Camera %s: Error updating stream: %s (%d)",
971 mCameraIdStr.string(), strerror(ret), ret);
972 break;
973 default:
974 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
975 "Camera %s: Error updating stream: %s (%d)",
976 mCameraIdStr.string(), strerror(ret), ret);
977 break;
978 }
979 } else {
980 for (const auto &it : removedOutputs) {
981 mStreamMap.removeItem(it);
982 }
983
984 for (size_t i = 0; i < outputMap.size(); i++) {
985 mStreamMap.add(IInterface::asBinder(outputMap.keyAt(i)->getIGraphicBufferProducer()),
986 StreamSurfaceId(streamId, outputMap.valueAt(i)));
987 }
988
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -0800989 mConfiguredOutputs.replaceValueFor(streamId, outputConfiguration);
990
Emilian Peev40ead602017-09-26 15:46:36 +0100991 ALOGV("%s: Camera %s: Successful stream ID %d update",
992 __FUNCTION__, mCameraIdStr.string(), streamId);
993 }
994
995 return res;
996}
997
Eman Copty6d7af0e2016-06-17 20:46:40 -0700998bool CameraDeviceClient::isPublicFormat(int32_t format)
999{
1000 switch(format) {
1001 case HAL_PIXEL_FORMAT_RGBA_8888:
1002 case HAL_PIXEL_FORMAT_RGBX_8888:
1003 case HAL_PIXEL_FORMAT_RGB_888:
1004 case HAL_PIXEL_FORMAT_RGB_565:
1005 case HAL_PIXEL_FORMAT_BGRA_8888:
1006 case HAL_PIXEL_FORMAT_YV12:
1007 case HAL_PIXEL_FORMAT_Y8:
1008 case HAL_PIXEL_FORMAT_Y16:
1009 case HAL_PIXEL_FORMAT_RAW16:
1010 case HAL_PIXEL_FORMAT_RAW10:
1011 case HAL_PIXEL_FORMAT_RAW12:
1012 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1013 case HAL_PIXEL_FORMAT_BLOB:
1014 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1015 case HAL_PIXEL_FORMAT_YCbCr_420_888:
1016 case HAL_PIXEL_FORMAT_YCbCr_422_888:
1017 case HAL_PIXEL_FORMAT_YCbCr_444_888:
1018 case HAL_PIXEL_FORMAT_FLEX_RGB_888:
1019 case HAL_PIXEL_FORMAT_FLEX_RGBA_8888:
1020 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
1021 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1022 case HAL_PIXEL_FORMAT_YCbCr_422_I:
1023 return true;
1024 default:
1025 return false;
1026 }
1027}
1028
Shuzhen Wang758c2152017-01-10 18:26:18 -08001029binder::Status CameraDeviceClient::createSurfaceFromGbp(
1030 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
1031 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp) {
1032
1033 // bufferProducer must be non-null
1034 if (gbp == nullptr) {
1035 String8 msg = String8::format("Camera %s: Surface is NULL", mCameraIdStr.string());
1036 ALOGW("%s: %s", __FUNCTION__, msg.string());
1037 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1038 }
1039 // HACK b/10949105
1040 // Query consumer usage bits to set async operation mode for
1041 // GLConsumer using controlledByApp parameter.
1042 bool useAsync = false;
Emilian Peev050f5dc2017-05-18 14:43:56 +01001043 uint64_t consumerUsage = 0;
Shuzhen Wang758c2152017-01-10 18:26:18 -08001044 status_t err;
Emilian Peev050f5dc2017-05-18 14:43:56 +01001045 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
Shuzhen Wang758c2152017-01-10 18:26:18 -08001046 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
1047 mCameraIdStr.string(), strerror(-err), err);
1048 ALOGE("%s: %s", __FUNCTION__, msg.string());
1049 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1050 }
1051 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
Emilian Peev050f5dc2017-05-18 14:43:56 +01001052 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
Shuzhen Wang758c2152017-01-10 18:26:18 -08001053 __FUNCTION__, mCameraIdStr.string(), consumerUsage);
1054 useAsync = true;
1055 }
1056
Emilian Peev050f5dc2017-05-18 14:43:56 +01001057 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
Shuzhen Wang758c2152017-01-10 18:26:18 -08001058 GRALLOC_USAGE_RENDERSCRIPT;
Emilian Peev050f5dc2017-05-18 14:43:56 +01001059 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
Shuzhen Wang758c2152017-01-10 18:26:18 -08001060 GraphicBuffer::USAGE_HW_TEXTURE |
1061 GraphicBuffer::USAGE_HW_COMPOSER;
1062 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
1063 (consumerUsage & allowedFlags) != 0;
1064
1065 surface = new Surface(gbp, useAsync);
1066 ANativeWindow *anw = surface.get();
1067
1068 int width, height, format;
1069 android_dataspace dataSpace;
1070 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
1071 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
1072 mCameraIdStr.string(), strerror(-err), err);
1073 ALOGE("%s: %s", __FUNCTION__, msg.string());
1074 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1075 }
1076 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
1077 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
1078 mCameraIdStr.string(), strerror(-err), err);
1079 ALOGE("%s: %s", __FUNCTION__, msg.string());
1080 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1081 }
1082 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
1083 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
1084 mCameraIdStr.string(), strerror(-err), err);
1085 ALOGE("%s: %s", __FUNCTION__, msg.string());
1086 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1087 }
1088 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
1089 reinterpret_cast<int*>(&dataSpace))) != OK) {
1090 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
1091 mCameraIdStr.string(), strerror(-err), err);
1092 ALOGE("%s: %s", __FUNCTION__, msg.string());
1093 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
1094 }
1095
1096 // FIXME: remove this override since the default format should be
1097 // IMPLEMENTATION_DEFINED. b/9487482
1098 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
1099 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
1100 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
1101 __FUNCTION__, mCameraIdStr.string(), format);
1102 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
1103 }
1104 // Round dimensions to the nearest dimensions available for this format
1105 if (flexibleConsumer && isPublicFormat(format) &&
1106 !CameraDeviceClient::roundBufferDimensionNearest(width, height,
1107 format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
1108 String8 msg = String8::format("Camera %s: No supported stream configurations with "
1109 "format %#x defined, failed to create output stream",
1110 mCameraIdStr.string(), format);
1111 ALOGE("%s: %s", __FUNCTION__, msg.string());
1112 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1113 }
1114
1115 if (!isStreamInfoValid) {
1116 streamInfo.width = width;
1117 streamInfo.height = height;
1118 streamInfo.format = format;
1119 streamInfo.dataSpace = dataSpace;
1120 streamInfo.consumerUsage = consumerUsage;
1121 return binder::Status::ok();
1122 }
1123 if (width != streamInfo.width) {
1124 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
1125 mCameraIdStr.string(), width, streamInfo.width);
1126 ALOGE("%s: %s", __FUNCTION__, msg.string());
1127 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1128 }
1129 if (height != streamInfo.height) {
1130 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
1131 mCameraIdStr.string(), height, streamInfo.height);
1132 ALOGE("%s: %s", __FUNCTION__, msg.string());
1133 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1134 }
1135 if (format != streamInfo.format) {
1136 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
1137 mCameraIdStr.string(), format, streamInfo.format);
1138 ALOGE("%s: %s", __FUNCTION__, msg.string());
1139 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1140 }
Shuzhen Wange8ecda92017-02-20 17:10:28 -08001141 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
1142 if (dataSpace != streamInfo.dataSpace) {
1143 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
1144 mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
1145 ALOGE("%s: %s", __FUNCTION__, msg.string());
1146 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1147 }
1148 //At the native side, there isn't a way to check whether 2 surfaces come from the same
1149 //surface class type. Use usage flag to approximate the comparison.
1150 if (consumerUsage != streamInfo.consumerUsage) {
1151 String8 msg = String8::format(
Emilian Peev050f5dc2017-05-18 14:43:56 +01001152 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Shuzhen Wange8ecda92017-02-20 17:10:28 -08001153 mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
1154 ALOGE("%s: %s", __FUNCTION__, msg.string());
1155 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1156 }
Shuzhen Wang758c2152017-01-10 18:26:18 -08001157 }
1158 return binder::Status::ok();
1159}
1160
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001161bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) {
1162 if (0 == physicalCameraId.size()) {
1163 return true;
1164 }
1165
1166 CameraMetadata staticInfo = mDevice->info();
1167 camera_metadata_entry_t entryCap;
1168 bool isLogicalCam = false;
1169
1170 entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
1171 for (size_t i = 0; i < entryCap.count; ++i) {
1172 uint8_t capability = entryCap.data.u8[i];
1173 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
1174 isLogicalCam = true;
1175 }
1176 }
1177 if (!isLogicalCam) {
1178 return false;
1179 }
1180
1181 camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
1182 const uint8_t* ids = entryIds.data.u8;
1183 size_t start = 0;
1184 for (size_t i = 0; i < entryIds.count; ++i) {
1185 if (ids[i] == '\0') {
1186 if (start != i) {
1187 String8 currentId((const char*)ids+start);
1188 if (currentId == physicalCameraId) {
1189 return true;
1190 }
1191 }
1192 start = i+1;
1193 }
1194 }
1195 return false;
1196}
1197
Ruben Brunkbba75572014-11-20 17:29:50 -08001198bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -08001199 int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
Ruben Brunkbba75572014-11-20 17:29:50 -08001200 /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
1201
1202 camera_metadata_ro_entry streamConfigs =
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -08001203 (dataSpace == HAL_DATASPACE_DEPTH) ?
1204 info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
Ruben Brunkbba75572014-11-20 17:29:50 -08001205 info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
1206
1207 int32_t bestWidth = -1;
1208 int32_t bestHeight = -1;
1209
1210 // Iterate through listed stream configurations and find the one with the smallest euclidean
1211 // distance from the given dimensions for the given format.
1212 for (size_t i = 0; i < streamConfigs.count; i += 4) {
1213 int32_t fmt = streamConfigs.data.i32[i];
1214 int32_t w = streamConfigs.data.i32[i + 1];
1215 int32_t h = streamConfigs.data.i32[i + 2];
1216
1217 // Ignore input/output type for now
1218 if (fmt == format) {
1219 if (w == width && h == height) {
1220 bestWidth = width;
1221 bestHeight = height;
1222 break;
1223 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
1224 CameraDeviceClient::euclidDistSquare(w, h, width, height) <
1225 CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) {
1226 bestWidth = w;
1227 bestHeight = h;
1228 }
1229 }
1230 }
1231
1232 if (bestWidth == -1) {
1233 // Return false if no configurations for this format were listed
1234 return false;
1235 }
1236
1237 // Set the outputs to the closet width/height
1238 if (outWidth != NULL) {
1239 *outWidth = bestWidth;
1240 }
1241 if (outHeight != NULL) {
1242 *outHeight = bestHeight;
1243 }
1244
1245 // Return true if at least one configuration for this format was listed
1246 return true;
1247}
1248
1249int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
1250 int64_t d0 = x0 - x1;
1251 int64_t d1 = y0 - y1;
1252 return d0 * d0 + d1 * d1;
1253}
1254
Igor Murashkine7ee7632013-06-11 18:10:18 -07001255// Create a request object from a template.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001256binder::Status CameraDeviceClient::createDefaultRequest(int templateId,
1257 /*out*/
1258 hardware::camera2::impl::CameraMetadataNative* request)
Igor Murashkine7ee7632013-06-11 18:10:18 -07001259{
1260 ATRACE_CALL();
1261 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
1262
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001263 binder::Status res;
1264 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -07001265
1266 Mutex::Autolock icl(mBinderSerializationLock);
1267
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001268 if (!mDevice.get()) {
1269 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1270 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001271
1272 CameraMetadata metadata;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001273 status_t err;
1274 if ( (err = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
Igor Murashkine7ee7632013-06-11 18:10:18 -07001275 request != NULL) {
1276
1277 request->swap(metadata);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001278 } else if (err == BAD_VALUE) {
1279 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001280 "Camera %s: Template ID %d is invalid or not supported: %s (%d)",
1281 mCameraIdStr.string(), templateId, strerror(-err), err);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001282
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001283 } else {
1284 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001285 "Camera %s: Error creating default request for template %d: %s (%d)",
1286 mCameraIdStr.string(), templateId, strerror(-err), err);
Igor Murashkine7ee7632013-06-11 18:10:18 -07001287 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001288 return res;
1289}
1290
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001291binder::Status CameraDeviceClient::getCameraInfo(
1292 /*out*/
1293 hardware::camera2::impl::CameraMetadataNative* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -07001294{
1295 ATRACE_CALL();
1296 ALOGV("%s", __FUNCTION__);
1297
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001298 binder::Status res;
Igor Murashkine7ee7632013-06-11 18:10:18 -07001299
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001300 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -07001301
1302 Mutex::Autolock icl(mBinderSerializationLock);
1303
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001304 if (!mDevice.get()) {
1305 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1306 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001307
Igor Murashkin099b4572013-07-12 17:52:16 -07001308 if (info != NULL) {
1309 *info = mDevice->info(); // static camera metadata
1310 // TODO: merge with device-specific camera metadata
1311 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001312
1313 return res;
1314}
1315
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001316binder::Status CameraDeviceClient::waitUntilIdle()
Zhijun He2ab500c2013-07-23 08:02:53 -07001317{
1318 ATRACE_CALL();
1319 ALOGV("%s", __FUNCTION__);
1320
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001321 binder::Status res;
1322 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Zhijun He2ab500c2013-07-23 08:02:53 -07001323
1324 Mutex::Autolock icl(mBinderSerializationLock);
1325
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001326 if (!mDevice.get()) {
1327 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1328 }
Zhijun He2ab500c2013-07-23 08:02:53 -07001329
1330 // FIXME: Also need check repeating burst.
Shuzhen Wangc9ca6782016-04-26 13:40:31 -07001331 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001332 if (mStreamingRequestId != REQUEST_ID_NONE) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001333 String8 msg = String8::format(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001334 "Camera %s: Try to waitUntilIdle when there are active streaming requests",
1335 mCameraIdStr.string());
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001336 ALOGE("%s: %s", __FUNCTION__, msg.string());
1337 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
Zhijun He2ab500c2013-07-23 08:02:53 -07001338 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001339 status_t err = mDevice->waitUntilDrained();
1340 if (err != OK) {
1341 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001342 "Camera %s: Error waiting to drain: %s (%d)",
1343 mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001344 }
Zhijun He2ab500c2013-07-23 08:02:53 -07001345 ALOGV("%s Done", __FUNCTION__);
Zhijun He2ab500c2013-07-23 08:02:53 -07001346 return res;
1347}
1348
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001349binder::Status CameraDeviceClient::flush(
1350 /*out*/
1351 int64_t* lastFrameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001352 ATRACE_CALL();
1353 ALOGV("%s", __FUNCTION__);
1354
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001355 binder::Status res;
1356 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001357
1358 Mutex::Autolock icl(mBinderSerializationLock);
1359
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001360 if (!mDevice.get()) {
1361 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1362 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001363
Shuzhen Wangc9ca6782016-04-26 13:40:31 -07001364 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001365 mStreamingRequestId = REQUEST_ID_NONE;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001366 status_t err = mDevice->flush(lastFrameNumber);
1367 if (err != OK) {
1368 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001369 "Camera %s: Error flushing device: %s (%d)", mCameraIdStr.string(), strerror(-err), err);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001370 }
1371 return res;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001372}
1373
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001374binder::Status CameraDeviceClient::prepare(int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001375 ATRACE_CALL();
1376 ALOGV("%s", __FUNCTION__);
1377
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001378 binder::Status res;
1379 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001380
1381 Mutex::Autolock icl(mBinderSerializationLock);
1382
1383 // Guard against trying to prepare non-created streams
1384 ssize_t index = NAME_NOT_FOUND;
1385 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001386 if (streamId == mStreamMap.valueAt(i).streamId()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001387 index = i;
1388 break;
1389 }
1390 }
1391
1392 if (index == NAME_NOT_FOUND) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001393 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
1394 "with that ID exists", mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001395 ALOGW("%s: %s", __FUNCTION__, msg.string());
1396 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001397 }
1398
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07001399 // Also returns BAD_VALUE if stream ID was not valid, or stream already
1400 // has been used
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001401 status_t err = mDevice->prepare(streamId);
1402 if (err == BAD_VALUE) {
1403 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001404 "Camera %s: Stream %d has already been used, and cannot be prepared",
1405 mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001406 } else if (err != OK) {
1407 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001408 "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.string(), streamId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001409 strerror(-err), err);
1410 }
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001411 return res;
1412}
1413
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001414binder::Status CameraDeviceClient::prepare2(int maxCount, int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07001415 ATRACE_CALL();
1416 ALOGV("%s", __FUNCTION__);
1417
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001418 binder::Status res;
1419 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Ruben Brunkc78ac262015-08-13 17:58:46 -07001420
1421 Mutex::Autolock icl(mBinderSerializationLock);
1422
1423 // Guard against trying to prepare non-created streams
1424 ssize_t index = NAME_NOT_FOUND;
1425 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001426 if (streamId == mStreamMap.valueAt(i).streamId()) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07001427 index = i;
1428 break;
1429 }
1430 }
1431
1432 if (index == NAME_NOT_FOUND) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001433 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
1434 "with that ID exists", mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001435 ALOGW("%s: %s", __FUNCTION__, msg.string());
1436 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Ruben Brunkc78ac262015-08-13 17:58:46 -07001437 }
1438
1439 if (maxCount <= 0) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001440 String8 msg = String8::format("Camera %s: maxCount (%d) must be greater than 0",
1441 mCameraIdStr.string(), maxCount);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001442 ALOGE("%s: %s", __FUNCTION__, msg.string());
1443 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Ruben Brunkc78ac262015-08-13 17:58:46 -07001444 }
1445
1446 // Also returns BAD_VALUE if stream ID was not valid, or stream already
1447 // has been used
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001448 status_t err = mDevice->prepare(maxCount, streamId);
1449 if (err == BAD_VALUE) {
1450 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001451 "Camera %s: Stream %d has already been used, and cannot be prepared",
1452 mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001453 } else if (err != OK) {
1454 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001455 "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.string(), streamId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001456 strerror(-err), err);
1457 }
Ruben Brunkc78ac262015-08-13 17:58:46 -07001458
1459 return res;
1460}
1461
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001462binder::Status CameraDeviceClient::tearDown(int streamId) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001463 ATRACE_CALL();
1464 ALOGV("%s", __FUNCTION__);
1465
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001466 binder::Status res;
1467 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001468
1469 Mutex::Autolock icl(mBinderSerializationLock);
1470
1471 // Guard against trying to prepare non-created streams
1472 ssize_t index = NAME_NOT_FOUND;
1473 for (size_t i = 0; i < mStreamMap.size(); ++i) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001474 if (streamId == mStreamMap.valueAt(i).streamId()) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001475 index = i;
1476 break;
1477 }
1478 }
1479
1480 if (index == NAME_NOT_FOUND) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001481 String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
1482 "with that ID exists", mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001483 ALOGW("%s: %s", __FUNCTION__, msg.string());
1484 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001485 }
1486
1487 // Also returns BAD_VALUE if stream ID was not valid or if the stream is in
1488 // use
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001489 status_t err = mDevice->tearDown(streamId);
1490 if (err == BAD_VALUE) {
1491 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001492 "Camera %s: Stream %d is still in use, cannot be torn down",
1493 mCameraIdStr.string(), streamId);
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001494 } else if (err != OK) {
1495 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001496 "Camera %s: Error tearing down stream %d: %s (%d)", mCameraIdStr.string(), streamId,
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001497 strerror(-err), err);
1498 }
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001499
1500 return res;
1501}
1502
Shuzhen Wang758c2152017-01-10 18:26:18 -08001503binder::Status CameraDeviceClient::finalizeOutputConfigurations(int32_t streamId,
Zhijun He5d677d12016-05-29 16:52:39 -07001504 const hardware::camera2::params::OutputConfiguration &outputConfiguration) {
1505 ATRACE_CALL();
1506
1507 binder::Status res;
1508 if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
1509
1510 Mutex::Autolock icl(mBinderSerializationLock);
1511
Shuzhen Wang0129d522016-10-30 22:43:41 -07001512 const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
1513 outputConfiguration.getGraphicBufferProducers();
Zhijun He5d677d12016-05-29 16:52:39 -07001514
Shuzhen Wang0129d522016-10-30 22:43:41 -07001515 if (bufferProducers.size() == 0) {
1516 ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
Zhijun He5d677d12016-05-29 16:52:39 -07001517 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
1518 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001519
Shuzhen Wang758c2152017-01-10 18:26:18 -08001520 // streamId should be in mStreamMap if this stream already has a surface attached
1521 // to it. Otherwise, it should be in mDeferredStreams.
1522 bool streamIdConfigured = false;
1523 ssize_t deferredStreamIndex = NAME_NOT_FOUND;
1524 for (size_t i = 0; i < mStreamMap.size(); i++) {
1525 if (mStreamMap.valueAt(i).streamId() == streamId) {
1526 streamIdConfigured = true;
1527 break;
1528 }
Zhijun He5d677d12016-05-29 16:52:39 -07001529 }
Shuzhen Wang758c2152017-01-10 18:26:18 -08001530 for (size_t i = 0; i < mDeferredStreams.size(); i++) {
1531 if (streamId == mDeferredStreams[i]) {
1532 deferredStreamIndex = i;
1533 break;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001534 }
1535
Shuzhen Wang758c2152017-01-10 18:26:18 -08001536 }
1537 if (deferredStreamIndex == NAME_NOT_FOUND && !streamIdConfigured) {
1538 String8 msg = String8::format("Camera %s: deferred surface is set to a unknown stream"
1539 "(ID %d)", mCameraIdStr.string(), streamId);
1540 ALOGW("%s: %s", __FUNCTION__, msg.string());
1541 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
Zhijun He5d677d12016-05-29 16:52:39 -07001542 }
1543
Shuzhen Wang88fd0052017-02-09 16:40:07 -08001544 if (mStreamInfoMap[streamId].finalized) {
1545 String8 msg = String8::format("Camera %s: finalizeOutputConfigurations has been called"
1546 " on stream ID %d", mCameraIdStr.string(), streamId);
1547 ALOGW("%s: %s", __FUNCTION__, msg.string());
1548 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
1549 }
1550
Zhijun He5d677d12016-05-29 16:52:39 -07001551 if (!mDevice.get()) {
1552 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
1553 }
1554
Shuzhen Wang758c2152017-01-10 18:26:18 -08001555 std::vector<sp<Surface>> consumerSurfaces;
Shuzhen Wang758c2152017-01-10 18:26:18 -08001556 for (auto& bufferProducer : bufferProducers) {
1557 // Don't create multiple streams for the same target surface
Zhijun He5d677d12016-05-29 16:52:39 -07001558 ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
1559 if (index != NAME_NOT_FOUND) {
Shuzhen Wang758c2152017-01-10 18:26:18 -08001560 ALOGV("Camera %s: Surface already has a stream created "
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001561 " for it (ID %zd)", mCameraIdStr.string(), index);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001562 continue;
Zhijun He5d677d12016-05-29 16:52:39 -07001563 }
Shuzhen Wang758c2152017-01-10 18:26:18 -08001564
1565 sp<Surface> surface;
1566 res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
1567 surface, bufferProducer);
1568
1569 if (!res.isOk())
1570 return res;
1571
1572 consumerSurfaces.push_back(surface);
Zhijun He5d677d12016-05-29 16:52:39 -07001573 }
1574
Shuzhen Wanga81ce342017-04-13 15:18:36 -07001575 // Gracefully handle case where finalizeOutputConfigurations is called
1576 // without any new surface.
1577 if (consumerSurfaces.size() == 0) {
1578 mStreamInfoMap[streamId].finalized = true;
1579 return res;
1580 }
1581
Zhijun He5d677d12016-05-29 16:52:39 -07001582 // Finish the deferred stream configuration with the surface.
Shuzhen Wang758c2152017-01-10 18:26:18 -08001583 status_t err;
Emilian Peev40ead602017-09-26 15:46:36 +01001584 std::vector<int> consumerSurfaceIds;
1585 err = mDevice->setConsumerSurfaces(streamId, consumerSurfaces, &consumerSurfaceIds);
Zhijun He5d677d12016-05-29 16:52:39 -07001586 if (err == OK) {
Shuzhen Wang758c2152017-01-10 18:26:18 -08001587 for (size_t i = 0; i < consumerSurfaces.size(); i++) {
1588 sp<IBinder> binder = IInterface::asBinder(
1589 consumerSurfaces[i]->getIGraphicBufferProducer());
Emilian Peev40ead602017-09-26 15:46:36 +01001590 ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d", __FUNCTION__,
Shuzhen Wang758c2152017-01-10 18:26:18 -08001591 binder.get(), streamId, consumerSurfaceIds[i]);
1592 mStreamMap.add(binder, StreamSurfaceId(streamId, consumerSurfaceIds[i]));
1593 }
1594 if (deferredStreamIndex != NAME_NOT_FOUND) {
1595 mDeferredStreams.removeItemsAt(deferredStreamIndex);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001596 }
Shuzhen Wang88fd0052017-02-09 16:40:07 -08001597 mStreamInfoMap[streamId].finalized = true;
Yin-Chia Yeh4dfa4cc2017-11-10 20:00:09 -08001598 mConfiguredOutputs.replaceValueFor(streamId, outputConfiguration);
Zhijun He5d677d12016-05-29 16:52:39 -07001599 } else if (err == NO_INIT) {
1600 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001601 "Camera %s: Deferred surface is invalid: %s (%d)",
1602 mCameraIdStr.string(), strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -07001603 } else {
1604 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001605 "Camera %s: Error setting output stream deferred surface: %s (%d)",
1606 mCameraIdStr.string(), strerror(-err), err);
Zhijun He5d677d12016-05-29 16:52:39 -07001607 }
1608
1609 return res;
1610}
1611
Igor Murashkine7ee7632013-06-11 18:10:18 -07001612status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
Eino-Ville Talvalac4003962016-01-13 10:07:04 -08001613 return BasicClient::dump(fd, args);
1614}
1615
1616status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001617 dprintf(fd, " CameraDeviceClient[%s] (%p) dump:\n",
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001618 mCameraIdStr.string(),
Eino-Ville Talvalae992e752014-11-07 16:17:48 -08001619 (getRemoteCallback() != NULL ?
Marco Nelissenf8880202014-11-14 07:58:25 -08001620 IInterface::asBinder(getRemoteCallback()).get() : NULL) );
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001621 dprintf(fd, " Current client UID %u\n", mClientUid);
Igor Murashkine7ee7632013-06-11 18:10:18 -07001622
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001623 dprintf(fd, " State:\n");
1624 dprintf(fd, " Request ID counter: %d\n", mRequestIdCounter);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001625 if (mInputStream.configured) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001626 dprintf(fd, " Current input stream ID: %d\n", mInputStream.id);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001627 } else {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001628 dprintf(fd, " No input stream configured.\n");
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001629 }
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001630 if (!mStreamMap.isEmpty()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001631 dprintf(fd, " Current output stream/surface IDs:\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001632 for (size_t i = 0; i < mStreamMap.size(); i++) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001633 dprintf(fd, " Stream %d Surface %d\n",
Shuzhen Wang0129d522016-10-30 22:43:41 -07001634 mStreamMap.valueAt(i).streamId(),
1635 mStreamMap.valueAt(i).surfaceId());
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001636 }
Zhijun He5d677d12016-05-29 16:52:39 -07001637 } else if (!mDeferredStreams.isEmpty()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001638 dprintf(fd, " Current deferred surface output stream IDs:\n");
Zhijun He5d677d12016-05-29 16:52:39 -07001639 for (auto& streamId : mDeferredStreams) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001640 dprintf(fd, " Stream %d\n", streamId);
Zhijun He5d677d12016-05-29 16:52:39 -07001641 }
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001642 } else {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -08001643 dprintf(fd, " No output streams configured.\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -07001644 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001645 // TODO: print dynamic/request section from most recent requests
1646 mFrameProcessor->dump(fd, args);
1647
1648 return dumpDevice(fd, args);
1649}
1650
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001651void CameraDeviceClient::notifyError(int32_t errorCode,
Jianing Weicb0652e2014-03-12 18:29:36 -07001652 const CaptureResultExtras& resultExtras) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001653 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001654 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001655
1656 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -07001657 remoteCb->onDeviceError(errorCode, resultExtras);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001658 }
1659}
1660
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001661void CameraDeviceClient::notifyRepeatingRequestError(long lastFrameNumber) {
1662 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
1663
1664 if (remoteCb != 0) {
Yin-Chia Yeh8ca23dc2017-09-05 18:15:56 -07001665 remoteCb->onRepeatingRequestError(lastFrameNumber, mStreamingRequestId);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001666 }
1667
Shuzhen Wangc9ca6782016-04-26 13:40:31 -07001668 Mutex::Autolock idLock(mStreamingRequestIdLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07001669 mStreamingRequestId = REQUEST_ID_NONE;
1670}
1671
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001672void CameraDeviceClient::notifyIdle() {
1673 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001674 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001675
1676 if (remoteCb != 0) {
1677 remoteCb->onDeviceIdle();
1678 }
Eino-Ville Talvala412fe562015-08-20 17:08:32 -07001679 Camera2ClientBase::notifyIdle();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001680}
1681
Jianing Weicb0652e2014-03-12 18:29:36 -07001682void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001683 nsecs_t timestamp) {
1684 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001685 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001686 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -07001687 remoteCb->onCaptureStarted(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001688 }
Eino-Ville Talvala412fe562015-08-20 17:08:32 -07001689 Camera2ClientBase::notifyShutter(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001690}
1691
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001692void CameraDeviceClient::notifyPrepared(int streamId) {
1693 // Thread safe. Don't bother locking.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001694 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001695 if (remoteCb != 0) {
1696 remoteCb->onPrepared(streamId);
1697 }
1698}
1699
Shuzhen Wang9d066012016-09-30 11:30:20 -07001700void CameraDeviceClient::notifyRequestQueueEmpty() {
1701 // Thread safe. Don't bother locking.
1702 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
1703 if (remoteCb != 0) {
1704 remoteCb->onRequestQueueEmpty();
1705 }
1706}
1707
Igor Murashkine7ee7632013-06-11 18:10:18 -07001708void CameraDeviceClient::detachDevice() {
1709 if (mDevice == 0) return;
1710
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001711 ALOGV("Camera %s: Stopping processors", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -07001712
1713 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
1714 FRAME_PROCESSOR_LISTENER_MAX_ID,
1715 /*listener*/this);
1716 mFrameProcessor->requestExit();
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001717 ALOGV("Camera %s: Waiting for threads", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -07001718 mFrameProcessor->join();
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -08001719 ALOGV("Camera %s: Disconnecting device", mCameraIdStr.string());
Igor Murashkine7ee7632013-06-11 18:10:18 -07001720
1721 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
1722 {
1723 mDevice->clearStreamingRequest();
1724
1725 status_t code;
1726 if ((code = mDevice->waitUntilDrained()) != OK) {
1727 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
1728 code);
1729 }
1730 }
1731
1732 Camera2ClientBase::detachDevice();
1733}
1734
1735/** Device-related methods */
Jianing Weicb0652e2014-03-12 18:29:36 -07001736void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
Igor Murashkine7ee7632013-06-11 18:10:18 -07001737 ATRACE_CALL();
1738 ALOGV("%s", __FUNCTION__);
1739
Igor Murashkin4fb55c12013-08-29 17:43:01 -07001740 // Thread-safe. No lock necessary.
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001741 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
Igor Murashkin4fb55c12013-08-29 17:43:01 -07001742 if (remoteCb != NULL) {
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001743 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras,
1744 result.mPhysicalMetadatas);
Igor Murashkine7ee7632013-06-11 18:10:18 -07001745 }
Igor Murashkine7ee7632013-06-11 18:10:18 -07001746}
1747
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001748binder::Status CameraDeviceClient::checkPidStatus(const char* checkLocation) {
Eino-Ville Talvala6192b892016-04-04 12:31:18 -07001749 if (mDisconnected) {
1750 return STATUS_ERROR(CameraService::ERROR_DISCONNECTED,
1751 "The camera device has been disconnected");
1752 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08001753 status_t res = checkPid(checkLocation);
1754 return (res == OK) ? binder::Status::ok() :
1755 STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
1756 "Attempt to use camera from a different process than original client");
1757}
1758
Igor Murashkine7ee7632013-06-11 18:10:18 -07001759// TODO: move to Camera2ClientBase
1760bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
1761
1762 const int pid = IPCThreadState::self()->getCallingPid();
1763 const int selfPid = getpid();
1764 camera_metadata_entry_t entry;
1765
1766 /**
1767 * Mixin default important security values
1768 * - android.led.transmit = defaulted ON
1769 */
1770 CameraMetadata staticInfo = mDevice->info();
1771 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
1772 for(size_t i = 0; i < entry.count; ++i) {
1773 uint8_t led = entry.data.u8[i];
1774
1775 switch(led) {
1776 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
1777 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
1778 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
1779 metadata.update(ANDROID_LED_TRANSMIT,
1780 &transmitDefault, 1);
1781 }
1782 break;
1783 }
1784 }
1785 }
1786
1787 // We can do anything!
1788 if (pid == selfPid) {
1789 return true;
1790 }
1791
1792 /**
1793 * Permission check special fields in the request
1794 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
1795 */
1796 entry = metadata.find(ANDROID_LED_TRANSMIT);
1797 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
1798 String16 permissionString =
1799 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
1800 if (!checkCallingPermission(permissionString)) {
1801 const int uid = IPCThreadState::self()->getCallingUid();
1802 ALOGE("Permission Denial: "
1803 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
1804 return false;
1805 }
1806 }
1807
1808 return true;
1809}
1810
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -07001811status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
1812 ALOGV("%s: begin", __FUNCTION__);
1813
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -07001814 const CameraMetadata& staticInfo = mDevice->info();
Ruben Brunk5698d442014-06-18 10:39:40 -07001815 return CameraUtils::getRotationTransform(staticInfo, transform);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -07001816}
1817
Igor Murashkine7ee7632013-06-11 18:10:18 -07001818} // namespace android