/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "Camera2ClientBase" #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 #include <utils/Log.h> #include <utils/Trace.h> #include <cutils/properties.h> #include <gui/Surface.h> #include <gui/Surface.h> #include "camera2/Parameters.h" #include "Camera2ClientBase.h" #include "camera2/ProFrameProcessor.h" #include "Camera2Device.h" namespace android { using namespace camera2; static int getCallingPid() { return IPCThreadState::self()->getCallingPid(); } // Interface used by CameraService template <typename TClientBase> Camera2ClientBase<TClientBase>::Camera2ClientBase( const sp<CameraService>& cameraService, const sp<TCamCallbacks>& remoteCallback, const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, uid_t clientUid, int servicePid): TClientBase(cameraService, remoteCallback, clientPackageName, cameraId, cameraFacing, clientPid, clientUid, servicePid), mSharedCameraCallbacks(remoteCallback) { ALOGI("Camera %d: Opened", cameraId); mDevice = new Camera2Device(cameraId); } template <typename TClientBase> status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation) const { int callingPid = getCallingPid(); if (callingPid == TClientBase::mClientPid) return NO_ERROR; ALOGE("%s: attempt to use a locked camera from a different process" " (old pid %d, new pid %d)", checkLocation, TClientBase::mClientPid, callingPid); return PERMISSION_DENIED; } template <typename TClientBase> status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) { ATRACE_CALL(); ALOGV("%s: Initializing client for camera %d", __FUNCTION__, TClientBase::mCameraId); status_t res; // Verify ops permissions res = TClientBase::startCameraOps(); if (res != OK) { return res; } if (mDevice == NULL) { ALOGE("%s: Camera %d: No device connected", __FUNCTION__, TClientBase::mCameraId); return NO_INIT; } res = mDevice->initialize(module); if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", __FUNCTION__, TClientBase::mCameraId, strerror(-res), res); return NO_INIT; } res = mDevice->setNotifyCallback(this); return OK; } template <typename TClientBase> Camera2ClientBase<TClientBase>::~Camera2ClientBase() { ATRACE_CALL(); TClientBase::mDestructionStarted = true; TClientBase::finishCameraOps(); disconnect(); ALOGI("Closed Camera %d", TClientBase::mCameraId); } template <typename TClientBase> status_t Camera2ClientBase<TClientBase>::dump(int fd, const Vector<String16>& args) { String8 result; result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n", TClientBase::mCameraId, TClientBase::getRemoteCallback()->asBinder().get(), TClientBase::mClientPid); result.append(" State: "); write(fd, result.string(), result.size()); // TODO: print dynamic/request section from most recent requests return dumpDevice(fd, args); } template <typename TClientBase> status_t Camera2ClientBase<TClientBase>::dumpDevice( int fd, const Vector<String16>& args) { String8 result; result = " Device dump:\n"; write(fd, result.string(), result.size()); if (!mDevice.get()) { result = " *** Device is detached\n"; write(fd, result.string(), result.size()); return NO_ERROR; } status_t res = mDevice->dump(fd, args); if (res != OK) { result = String8::format(" Error dumping device: %s (%d)", strerror(-res), res); write(fd, result.string(), result.size()); } return NO_ERROR; } // ICameraClient2BaseUser interface template <typename TClientBase> void Camera2ClientBase<TClientBase>::disconnect() { ATRACE_CALL(); Mutex::Autolock icl(mBinderSerializationLock); // Allow both client and the media server to disconnect at all times int callingPid = getCallingPid(); if (callingPid != TClientBase::mClientPid && callingPid != TClientBase::mServicePid) return; ALOGV("Camera %d: Shutting down", TClientBase::mCameraId); detachDevice(); CameraService::BasicClient::disconnect(); ALOGV("Camera %d: Shut down complete complete", TClientBase::mCameraId); } template <typename TClientBase> void Camera2ClientBase<TClientBase>::detachDevice() { if (mDevice == 0) return; mDevice->disconnect(); mDevice.clear(); ALOGV("Camera %d: Detach complete", TClientBase::mCameraId); } template <typename TClientBase> status_t Camera2ClientBase<TClientBase>::connect( const sp<TCamCallbacks>& client) { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); Mutex::Autolock icl(mBinderSerializationLock); if (TClientBase::mClientPid != 0 && getCallingPid() != TClientBase::mClientPid) { ALOGE("%s: Camera %d: Connection attempt from pid %d; " "current locked to pid %d", __FUNCTION__, TClientBase::mCameraId, getCallingPid(), TClientBase::mClientPid); return BAD_VALUE; } TClientBase::mClientPid = getCallingPid(); TClientBase::mRemoteCallback = client; mSharedCameraCallbacks = client; return OK; } /** Device-related methods */ template <typename TClientBase> void Camera2ClientBase<TClientBase>::notifyError(int errorCode, int arg1, int arg2) { ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode, arg1, arg2); } template <typename TClientBase> void Camera2ClientBase<TClientBase>::notifyShutter(int frameNumber, nsecs_t timestamp) { (void)frameNumber; (void)timestamp; ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__, frameNumber, timestamp); } template <typename TClientBase> void Camera2ClientBase<TClientBase>::notifyAutoFocus(uint8_t newState, int triggerId) { (void)newState; (void)triggerId; ALOGV("%s: Autofocus state now %d, last trigger %d", __FUNCTION__, newState, triggerId); typename SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); if (l.mRemoteCallback != 0) { l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE, 1, 0); } if (l.mRemoteCallback != 0) { l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, 1, 0); } } template <typename TClientBase> void Camera2ClientBase<TClientBase>::notifyAutoExposure(uint8_t newState, int triggerId) { (void)newState; (void)triggerId; ALOGV("%s: Autoexposure state now %d, last trigger %d", __FUNCTION__, newState, triggerId); } template <typename TClientBase> void Camera2ClientBase<TClientBase>::notifyAutoWhitebalance(uint8_t newState, int triggerId) { (void)newState; (void)triggerId; ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState, triggerId); } template <typename TClientBase> int Camera2ClientBase<TClientBase>::getCameraId() const { return TClientBase::mCameraId; } template <typename TClientBase> const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() { return mDevice; } template <typename TClientBase> const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() { return TClientBase::mCameraService; } template <typename TClientBase> Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::Lock( SharedCameraCallbacks &client) : mRemoteCallback(client.mRemoteCallback), mSharedClient(client) { mSharedClient.mRemoteCallbackLock.lock(); } template <typename TClientBase> Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::~Lock() { mSharedClient.mRemoteCallbackLock.unlock(); } template <typename TClientBase> Camera2ClientBase<TClientBase>::SharedCameraCallbacks::SharedCameraCallbacks( const sp<TCamCallbacks>&client) : mRemoteCallback(client) { } template <typename TClientBase> typename Camera2ClientBase<TClientBase>::SharedCameraCallbacks& Camera2ClientBase<TClientBase>::SharedCameraCallbacks::operator=( const sp<TCamCallbacks>&client) { Mutex::Autolock l(mRemoteCallbackLock); mRemoteCallback = client; return *this; } template <typename TClientBase> void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() { Mutex::Autolock l(mRemoteCallbackLock); mRemoteCallback.clear(); } template class Camera2ClientBase<CameraService::ProClient>; template class Camera2ClientBase<CameraService::Client>; } // namespace android