1/*
2 * Copyright (C) 2013 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#define LOG_TAG "Camera2ClientBase"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <inttypes.h>
22
23#include <utils/Log.h>
24#include <utils/Trace.h>
25
26#include <cutils/properties.h>
27#include <gui/Surface.h>
28#include <gui/Surface.h>
29
30#include "common/Camera2ClientBase.h"
31
32#include "api2/CameraDeviceClient.h"
33
34#include "device3/Camera3Device.h"
35
36namespace android {
37using namespace camera2;
38
39static int getCallingPid() {
40    return IPCThreadState::self()->getCallingPid();
41}
42
43// Interface used by CameraService
44
45template <typename TClientBase>
46Camera2ClientBase<TClientBase>::Camera2ClientBase(
47        const sp<CameraService>& cameraService,
48        const sp<TCamCallbacks>& remoteCallback,
49        const String16& clientPackageName,
50        const String8& cameraId,
51        int api1CameraId,
52        int cameraFacing,
53        int clientPid,
54        uid_t clientUid,
55        int servicePid):
56        TClientBase(cameraService, remoteCallback, clientPackageName,
57                cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
58        mSharedCameraCallbacks(remoteCallback),
59        mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
60        mDeviceActive(false), mApi1CameraId(api1CameraId)
61{
62    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
63            String8(clientPackageName).string(), clientPid, clientUid);
64
65    mInitialClientPid = clientPid;
66    mDevice = new Camera3Device(cameraId);
67    LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
68}
69
70template <typename TClientBase>
71status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation)
72        const {
73
74    int callingPid = getCallingPid();
75    if (callingPid == TClientBase::mClientPid) return NO_ERROR;
76
77    ALOGE("%s: attempt to use a locked camera from a different process"
78            " (old pid %d, new pid %d)", checkLocation, TClientBase::mClientPid, callingPid);
79    return PERMISSION_DENIED;
80}
81
82template <typename TClientBase>
83status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
84        const String8& monitorTags) {
85    return initializeImpl(manager, monitorTags);
86}
87
88template <typename TClientBase>
89template <typename TProviderPtr>
90status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
91        const String8& monitorTags) {
92    ATRACE_CALL();
93    ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
94          TClientBase::mCameraIdStr.string());
95    status_t res;
96
97    // Verify ops permissions
98    res = TClientBase::startCameraOps();
99    if (res != OK) {
100        return res;
101    }
102
103    if (mDevice == NULL) {
104        ALOGE("%s: Camera %s: No device connected",
105                __FUNCTION__, TClientBase::mCameraIdStr.string());
106        return NO_INIT;
107    }
108
109    res = mDevice->initialize(providerPtr, monitorTags);
110    if (res != OK) {
111        ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
112                __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
113        return res;
114    }
115
116    wp<CameraDeviceBase::NotificationListener> weakThis(this);
117    res = mDevice->setNotifyCallback(weakThis);
118
119    return OK;
120}
121
122template <typename TClientBase>
123Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
124    ATRACE_CALL();
125
126    TClientBase::mDestructionStarted = true;
127
128    disconnect();
129
130    ALOGI("Closed Camera %s. Client was: %s (PID %d, UID %u)",
131            TClientBase::mCameraIdStr.string(),
132            String8(TClientBase::mClientPackageName).string(),
133            mInitialClientPid, TClientBase::mClientUid);
134}
135
136template <typename TClientBase>
137status_t Camera2ClientBase<TClientBase>::dumpClient(int fd,
138                                              const Vector<String16>& args) {
139    String8 result;
140    result.appendFormat("Camera2ClientBase[%s] (%p) PID: %d, dump:\n",
141            TClientBase::mCameraIdStr.string(),
142            (TClientBase::getRemoteCallback() != NULL ?
143                    IInterface::asBinder(TClientBase::getRemoteCallback()).get() : NULL),
144            TClientBase::mClientPid);
145    result.append("  State: ");
146
147    write(fd, result.string(), result.size());
148    // TODO: print dynamic/request section from most recent requests
149
150    return dumpDevice(fd, args);
151}
152
153template <typename TClientBase>
154status_t Camera2ClientBase<TClientBase>::dumpDevice(
155                                                int fd,
156                                                const Vector<String16>& args) {
157    String8 result;
158
159    result = "  Device dump:\n";
160    write(fd, result.string(), result.size());
161
162    sp<CameraDeviceBase> device = mDevice;
163    if (!device.get()) {
164        result = "  *** Device is detached\n";
165        write(fd, result.string(), result.size());
166        return NO_ERROR;
167    }
168
169    status_t res = device->dump(fd, args);
170    if (res != OK) {
171        result = String8::format("   Error dumping device: %s (%d)",
172                strerror(-res), res);
173        write(fd, result.string(), result.size());
174    }
175
176    return NO_ERROR;
177}
178
179// ICameraClient2BaseUser interface
180
181
182template <typename TClientBase>
183binder::Status Camera2ClientBase<TClientBase>::disconnect() {
184    ATRACE_CALL();
185    Mutex::Autolock icl(mBinderSerializationLock);
186
187    binder::Status res = binder::Status::ok();
188    // Allow both client and the media server to disconnect at all times
189    int callingPid = getCallingPid();
190    if (callingPid != TClientBase::mClientPid &&
191        callingPid != TClientBase::mServicePid) return res;
192
193    ALOGV("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
194
195    detachDevice();
196
197    CameraService::BasicClient::disconnect();
198
199    ALOGV("Camera %s: Shut down complete complete", TClientBase::mCameraIdStr.string());
200
201    return res;
202}
203
204template <typename TClientBase>
205void Camera2ClientBase<TClientBase>::detachDevice() {
206    if (mDevice == 0) return;
207    mDevice->disconnect();
208
209    mDevice.clear();
210
211    ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.string());
212}
213
214template <typename TClientBase>
215status_t Camera2ClientBase<TClientBase>::connect(
216        const sp<TCamCallbacks>& client) {
217    ATRACE_CALL();
218    ALOGV("%s: E", __FUNCTION__);
219    Mutex::Autolock icl(mBinderSerializationLock);
220
221    if (TClientBase::mClientPid != 0 &&
222        getCallingPid() != TClientBase::mClientPid) {
223
224        ALOGE("%s: Camera %s: Connection attempt from pid %d; "
225                "current locked to pid %d",
226                __FUNCTION__,
227                TClientBase::mCameraIdStr.string(),
228                getCallingPid(),
229                TClientBase::mClientPid);
230        return BAD_VALUE;
231    }
232
233    TClientBase::mClientPid = getCallingPid();
234
235    TClientBase::mRemoteCallback = client;
236    mSharedCameraCallbacks = client;
237
238    return OK;
239}
240
241/** Device-related methods */
242
243template <typename TClientBase>
244void Camera2ClientBase<TClientBase>::notifyError(
245        int32_t errorCode,
246        const CaptureResultExtras& resultExtras) {
247    ALOGE("Error condition %d reported by HAL, requestId %" PRId32, errorCode,
248          resultExtras.requestId);
249}
250
251template <typename TClientBase>
252void Camera2ClientBase<TClientBase>::notifyIdle() {
253    if (mDeviceActive) {
254        getCameraService()->updateProxyDeviceState(
255            hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, TClientBase::mCameraIdStr,
256            TClientBase::mCameraFacing, TClientBase::mClientPackageName,
257            ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 :
258             hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1));
259    }
260    mDeviceActive = false;
261
262    ALOGV("Camera device is now idle");
263}
264
265template <typename TClientBase>
266void Camera2ClientBase<TClientBase>::notifyShutter(const CaptureResultExtras& resultExtras,
267                                                   nsecs_t timestamp) {
268    (void)resultExtras;
269    (void)timestamp;
270
271    if (!mDeviceActive) {
272        getCameraService()->updateProxyDeviceState(
273            hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE, TClientBase::mCameraIdStr,
274            TClientBase::mCameraFacing, TClientBase::mClientPackageName,
275            ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 :
276             hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1));
277    }
278    mDeviceActive = true;
279
280    ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
281            __FUNCTION__, resultExtras.requestId, timestamp);
282}
283
284template <typename TClientBase>
285void Camera2ClientBase<TClientBase>::notifyAutoFocus(uint8_t newState,
286                                                     int triggerId) {
287    (void)newState;
288    (void)triggerId;
289
290    ALOGV("%s: Autofocus state now %d, last trigger %d",
291          __FUNCTION__, newState, triggerId);
292
293}
294
295template <typename TClientBase>
296void Camera2ClientBase<TClientBase>::notifyAutoExposure(uint8_t newState,
297                                                        int triggerId) {
298    (void)newState;
299    (void)triggerId;
300
301    ALOGV("%s: Autoexposure state now %d, last trigger %d",
302            __FUNCTION__, newState, triggerId);
303}
304
305template <typename TClientBase>
306void Camera2ClientBase<TClientBase>::notifyAutoWhitebalance(uint8_t newState,
307                                                            int triggerId) {
308    (void)newState;
309    (void)triggerId;
310
311    ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
312            __FUNCTION__, newState, triggerId);
313}
314
315template <typename TClientBase>
316void Camera2ClientBase<TClientBase>::notifyPrepared(int streamId) {
317    (void)streamId;
318
319    ALOGV("%s: Stream %d now prepared",
320            __FUNCTION__, streamId);
321}
322
323template <typename TClientBase>
324void Camera2ClientBase<TClientBase>::notifyRequestQueueEmpty() {
325
326    ALOGV("%s: Request queue now empty", __FUNCTION__);
327}
328
329template <typename TClientBase>
330void Camera2ClientBase<TClientBase>::notifyRepeatingRequestError(long lastFrameNumber) {
331    (void)lastFrameNumber;
332
333    ALOGV("%s: Repeating request was stopped. Last frame number is %ld",
334            __FUNCTION__, lastFrameNumber);
335}
336
337template <typename TClientBase>
338int Camera2ClientBase<TClientBase>::getCameraId() const {
339    return mApi1CameraId;
340}
341
342template <typename TClientBase>
343int Camera2ClientBase<TClientBase>::getCameraDeviceVersion() const {
344    return mDeviceVersion;
345}
346
347template <typename TClientBase>
348const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() {
349    return mDevice;
350}
351
352template <typename TClientBase>
353const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() {
354    return TClientBase::sCameraService;
355}
356
357template <typename TClientBase>
358Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::Lock(
359        SharedCameraCallbacks &client) :
360
361        mRemoteCallback(client.mRemoteCallback),
362        mSharedClient(client) {
363
364    mSharedClient.mRemoteCallbackLock.lock();
365}
366
367template <typename TClientBase>
368Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::~Lock() {
369    mSharedClient.mRemoteCallbackLock.unlock();
370}
371
372template <typename TClientBase>
373Camera2ClientBase<TClientBase>::SharedCameraCallbacks::SharedCameraCallbacks(
374        const sp<TCamCallbacks>&client) :
375
376        mRemoteCallback(client) {
377}
378
379template <typename TClientBase>
380typename Camera2ClientBase<TClientBase>::SharedCameraCallbacks&
381Camera2ClientBase<TClientBase>::SharedCameraCallbacks::operator=(
382        const sp<TCamCallbacks>&client) {
383
384    Mutex::Autolock l(mRemoteCallbackLock);
385    mRemoteCallback = client;
386    return *this;
387}
388
389template <typename TClientBase>
390void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() {
391    Mutex::Autolock l(mRemoteCallbackLock);
392    mRemoteCallback.clear();
393}
394
395template class Camera2ClientBase<CameraService::Client>;
396template class Camera2ClientBase<CameraDeviceClientBase>;
397
398} // namespace android
399