1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
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#include <vector>
18#include <inttypes.h>
19#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
20#include <android/frameworks/cameraservice/device/2.0/types.h>
21#include <CameraMetadata.h>
22
23#include "ndk_vendor/impl/ACameraDevice.h"
24#include "ACameraCaptureSession.h"
25#include "ACameraMetadata.h"
26#include "ACaptureRequest.h"
27#include "utils.h"
28
29using namespace android;
30
31namespace android {
32namespace acam {
33
34template<class T>
35camera_status_t
36CameraDevice::captureLocked(
37        sp<ACameraCaptureSession> session,
38        /*optional*/T* cbs,
39        int numRequests, ACaptureRequest** requests,
40        /*optional*/int* captureSequenceId) {
41    return submitRequestsLocked(
42            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
43}
44
45template<class T>
46camera_status_t
47CameraDevice::setRepeatingRequestsLocked(
48        sp<ACameraCaptureSession> session,
49        /*optional*/T* cbs,
50        int numRequests, ACaptureRequest** requests,
51        /*optional*/int* captureSequenceId) {
52    return submitRequestsLocked(
53            session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
54}
55
56template<class T>
57camera_status_t CameraDevice::submitRequestsLocked(
58        sp<ACameraCaptureSession> session,
59        /*optional*/T* cbs,
60        int numRequests, ACaptureRequest** requests,
61        /*out*/int* captureSequenceId,
62        bool isRepeating)
63{
64    camera_status_t ret = checkCameraClosedOrErrorLocked();
65    if (ret != ACAMERA_OK) {
66        ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
67        return ret;
68    }
69
70    // Form two vectors of capture request, one for internal tracking
71    std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
72    Vector<sp<CaptureRequest>> requestsV;
73    requestsV.setCapacity(numRequests);
74    for (int i = 0; i < numRequests; i++) {
75        sp<CaptureRequest> req;
76        ret = allocateCaptureRequestLocked(requests[i], req);
77        // We need to call this method since after submitRequestList is called,
78        // the request metadata queue might have removed the capture request
79        // metadata. Therefore we simply add the metadata to its wrapper class,
80        // so that it can be retrieved later.
81        addRequestSettingsMetadata(requests[i], req);
82        if (ret != ACAMERA_OK) {
83            ALOGE("Convert capture request to internal format failure! ret %d", ret);
84            return ret;
85        }
86        if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
87            ALOGE("Capture request without output target cannot be submitted!");
88            return ACAMERA_ERROR_INVALID_PARAMETER;
89        }
90        requestList.push_back(utils::convertToHidl(req.get()));
91        requestsV.push_back(req);
92    }
93    if (isRepeating) {
94        ret = stopRepeatingLocked();
95        if (ret != ACAMERA_OK) {
96            ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
97            return ret;
98        }
99    }
100
101    SubmitInfo info;
102    Status status;
103    auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
104                                                [&status, &info](auto s, auto &submitInfo) {
105                                                    status = s;
106                                                    info = submitInfo;
107                                                });
108    if (!remoteRet.isOk()) {
109        ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
110              remoteRet.description().c_str());
111    }
112    if (status != Status::NO_ERROR) {
113        return utils::convertFromHidl(status);
114    }
115    int32_t sequenceId = info.requestId;
116    int64_t lastFrameNumber = info.lastFrameNumber;
117    if (sequenceId < 0) {
118        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
119        return ACAMERA_ERROR_UNKNOWN;
120    }
121
122    CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
123    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
124    if (isRepeating) {
125        // stopRepeating above should have cleanup repeating sequence id
126        if (mRepeatingSequenceId != REQUEST_ID_NONE) {
127            setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
128            return ACAMERA_ERROR_CAMERA_DEVICE;
129        }
130        mRepeatingSequenceId = sequenceId;
131    } else {
132        mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
133    }
134
135    if (mIdle) {
136        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
137        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
138        msg->setObject(kSessionSpKey, session);
139        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
140        postSessionMsgAndCleanup(msg);
141    }
142    mIdle = false;
143    mBusySession = session;
144
145    if (captureSequenceId) {
146        *captureSequenceId = sequenceId;
147    }
148    return ACAMERA_OK;
149}
150
151} // namespace acam
152} // namespace android
153