Commit message: None
CVE: CVE-2016-0826
CWE: CWE-264
Vulnerability description: libcameraservice in mediaserver in Android 4.x before 4.4.4, 5.x before 5.1.1 LMY49H, and 6.x before 2016-03-01 does not require use of the ICameraService::dump method for a camera service dump, which allows attackers to gain privileges via a crafted application that directly dumps, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 26265403.

Project: Android

CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
 const sp<IBinder>& remoteCallback,
 const String16& clientPackageName,
 int cameraId, int cameraFacing,
 int clientPid, uid_t clientUid,
 int servicePid):
        mClientPackageName(clientPackageName)
{
    mCameraService = cameraService;
    mRemoteBinder = remoteCallback;
    mCameraId = cameraId;
    mCameraFacing = cameraFacing;
    mClientPid = clientPid;
    mClientUid = clientUid;
    mServicePid = servicePid;
    mOpsActive = false;
    mDestructionStarted = false;
}

Project: Android

CameraService::CameraService()
 :mSoundRef(0), mModule(0)
{
    ALOGI("CameraService started (pid=%d)", getpid());
    gCameraService = this;

 for (size_t i = 0; i < MAX_CAMERAS; ++i) {
        mStatusList[i] = ICameraServiceListener::STATUS_PRESENT;
 }

 this->camera_device_status_change = android::camera_device_status_change;
}

Project: Android

CameraService::Client::Client(const sp<CameraService>& cameraService,
 const sp<ICameraClient>& cameraClient,
 const String16& clientPackageName,
 int cameraId, int cameraFacing,
 int clientPid, uid_t clientUid,
 int servicePid) :
 CameraService::BasicClient(cameraService, cameraClient->asBinder(),
                clientPackageName,
                cameraId, cameraFacing,
                clientPid, clientUid,
                servicePid)
{
 int callingPid = getCallingPid();
    LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);

    mRemoteCallback = cameraClient;

    cameraService->setCameraBusy(cameraId);
    cameraService->loadSound();

    LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
}

Project: Android

CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client):
        mClient(client) {
}

Project: Android

CameraService::ProClient::ProClient(const sp<CameraService>& cameraService,
 const sp<IProCameraCallbacks>& remoteCallback,
 const String16& clientPackageName,
 int cameraId,
 int cameraFacing,
 int clientPid,
 uid_t clientUid,
 int servicePid)
 : CameraService::BasicClient(cameraService, remoteCallback->asBinder(),
                clientPackageName, cameraId, cameraFacing,
                clientPid,  clientUid, servicePid)
{
    mRemoteCallback = remoteCallback;
}

Project: Android

status_t CameraService::addListener(
 const sp<ICameraServiceListener>& listener) {
    ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());

 if (listener == 0) {
        ALOGE("%s: Listener must not be null", __FUNCTION__);
 return BAD_VALUE;
 }

 Mutex::Autolock lock(mServiceLock);

 Vector<sp<ICameraServiceListener> >::iterator it, end;
 for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
 if ((*it)->asBinder() == listener->asBinder()) {
            ALOGW("%s: Tried to add listener %p which was already subscribed",
                  __FUNCTION__, listener.get());
 return ALREADY_EXISTS;
 }
 }

    mListenerList.push_back(listener);

 /* Immediately signal current status to this listener only */
 {
 Mutex::Autolock m(mStatusMutex) ;
 int numCams = getNumberOfCameras();
 for (int i = 0; i < numCams; ++i) {
            listener->onStatusChanged(mStatusList[i], i);
 }
 }

 return OK;
}

Project: Android

static void camera_device_status_change(
 const struct camera_module_callbacks* callbacks,
 int camera_id,
 int new_status) {
    sp<CameraService> cs = const_cast<CameraService*>(
 static_cast<const CameraService*>(callbacks));

    cs->onDeviceStatusChanged(
        camera_id,
        new_status);
}

Project: Android

bool CameraService::canConnectUnsafe(int cameraId,
 const String16& clientPackageName,
 const sp<IBinder>& remoteCallback,
                                     sp<BasicClient> &client) {
 String8 clientName8(clientPackageName);
 int callingPid = getCallingPid();

 if (mClient[cameraId] != 0) {
        client = mClient[cameraId].promote();
 if (client != 0) {
 if (remoteCallback == client->getRemote()) {
                LOG1("CameraService::connect X (pid %d) (the same client)",
                     callingPid);
 return true;
 } else {
                ALOGW("CameraService::connect X (pid %d) rejected"
 " (existing client).", callingPid);
 return false;
 }
 }
        mClient[cameraId].clear();
 }

 /*
    mBusy is set to false as the last step of the Client destructor,
    after which it is guaranteed that the Client destructor has finished (
    including any inherited destructors)

    We only need this for a Client subclasses since we don't allow
    multiple Clents to be opened concurrently, but multiple BasicClient
    would be fine
    */
 if (mBusy[cameraId]) {
        ALOGW("CameraService::connect X (pid %d, \"%s\") rejected"
 " (camera %d is still busy).", callingPid,
                clientName8.string(), cameraId);
 return false;
 }

 return true;
}

Project: Android

status_t CameraService::connect(
 const sp<ICameraClient>& cameraClient,
 int cameraId,
 const String16& clientPackageName,
 int clientUid,
 /*out*/
        sp<ICamera>& device) {

 String8 clientName8(clientPackageName);
 int callingPid = getCallingPid();

    LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
            clientName8.string(), cameraId);

 status_t status = validateConnect(cameraId, /*inout*/clientUid);
 if (status != OK) {
 return status;
 }


    sp<Client> client;
 {
 Mutex::Autolock lock(mServiceLock);
        sp<BasicClient> clientTmp;
 if (!canConnectUnsafe(cameraId, clientPackageName,
                              cameraClient->asBinder(),
 /*out*/clientTmp)) {
 return -EBUSY;
 } else if (client.get() != NULL) {
            device = static_cast<Client*>(clientTmp.get());
 return OK;
 }

 int facing = -1;
 int deviceVersion = getDeviceVersion(cameraId, &facing);

 if (isValidCameraId(cameraId)) {
            updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
                         cameraId);
 }

 switch(deviceVersion) {
 case CAMERA_DEVICE_API_VERSION_1_0:
            client = new CameraClient(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid());
 break;
 case CAMERA_DEVICE_API_VERSION_2_0:
 case CAMERA_DEVICE_API_VERSION_2_1:
 case CAMERA_DEVICE_API_VERSION_3_0:
            client = new Camera2Client(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid(),
                    deviceVersion);
 break;
 case -1:
            ALOGE("Invalid camera id %d", cameraId);
 return BAD_VALUE;
 default:
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
 return INVALID_OPERATION;
 }

 status_t status = connectFinishUnsafe(client, client->getRemote());
 if (status != OK) {
            updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
 return status;
 }

        mClient[cameraId] = client;
        LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
             getpid());
 }

    device = client;
 return OK;
}

Project: Android

status_t CameraService::connectDevice(
 const sp<ICameraDeviceCallbacks>& cameraCb,
 int cameraId,
 const String16& clientPackageName,
 int clientUid,
 /*out*/
        sp<ICameraDeviceUser>& device)
{

 String8 clientName8(clientPackageName);
 int callingPid = getCallingPid();

    LOG1("CameraService::connectDevice E (pid %d \"%s\", id %d)", callingPid,
            clientName8.string(), cameraId);

 status_t status = validateConnect(cameraId, /*inout*/clientUid);
 if (status != OK) {
 return status;
 }

    sp<CameraDeviceClient> client;
 {
 Mutex::Autolock lock(mServiceLock);
 {
            sp<BasicClient> client;
 if (!canConnectUnsafe(cameraId, clientPackageName,
                                  cameraCb->asBinder(),
 /*out*/client)) {
 return -EBUSY;
 }
 }

 int facing = -1;
 int deviceVersion = getDeviceVersion(cameraId, &facing);

 if (isValidCameraId(cameraId)) {
            updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
                         cameraId);
 }

 switch(deviceVersion) {
 case CAMERA_DEVICE_API_VERSION_1_0:
            ALOGW("Camera using old HAL version: %d", deviceVersion);
 return -EOPNOTSUPP;
 case CAMERA_DEVICE_API_VERSION_2_0:
 case CAMERA_DEVICE_API_VERSION_2_1:
 case CAMERA_DEVICE_API_VERSION_3_0:
            client = new CameraDeviceClient(this, cameraCb, clientPackageName,
                    cameraId, facing, callingPid, clientUid, getpid());
 break;
 case -1:
            ALOGE("Invalid camera id %d", cameraId);
 return BAD_VALUE;
 default:
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
 return INVALID_OPERATION;
 }

 status_t status = connectFinishUnsafe(client, client->getRemote());
 if (status != OK) {
            updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
 return status;
 }

        LOG1("CameraService::connectDevice X (id %d, this pid is %d)", cameraId,
                getpid());

        mClient[cameraId] = client;
 }

    device = client;
 return OK;
}

Project: Android

status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
 const sp<IBinder>& remoteCallback) {
 status_t status = client->initialize(mModule);
 if (status != OK) {
 return status;
 }

    remoteCallback->linkToDeath(this);

 return OK;
}

Project: Android

status_t CameraService::connectPro(
 const sp<IProCameraCallbacks>& cameraCb,
 int cameraId,
 const String16& clientPackageName,
 int clientUid,
 /*out*/
                                        sp<IProCameraUser>& device)
{
 String8 clientName8(clientPackageName);
 int callingPid = getCallingPid();

    LOG1("CameraService::connectPro E (pid %d \"%s\", id %d)", callingPid,
            clientName8.string(), cameraId);
 status_t status = validateConnect(cameraId, /*inout*/clientUid);
 if (status != OK) {
 return status;
 }

    sp<ProClient> client;
 {
 Mutex::Autolock lock(mServiceLock);
 {
            sp<BasicClient> client;
 if (!canConnectUnsafe(cameraId, clientPackageName,
                                  cameraCb->asBinder(),
 /*out*/client)) {
 return -EBUSY;
 }
 }

 int facing = -1;
 int deviceVersion = getDeviceVersion(cameraId, &facing);

 switch(deviceVersion) {
 case CAMERA_DEVICE_API_VERSION_1_0:
            ALOGE("Camera id %d uses HALv1, doesn't support ProCamera",
                  cameraId);
 return -EOPNOTSUPP;
 break;
 case CAMERA_DEVICE_API_VERSION_2_0:
 case CAMERA_DEVICE_API_VERSION_2_1:
 case CAMERA_DEVICE_API_VERSION_3_0:
            client = new ProCamera2Client(this, cameraCb, clientPackageName,
                    cameraId, facing, callingPid, clientUid, getpid());
 break;
 case -1:
            ALOGE("Invalid camera id %d", cameraId);
 return BAD_VALUE;
 default:
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
 return INVALID_OPERATION;
 }

 status_t status = connectFinishUnsafe(client, client->getRemote());
 if (status != OK) {
 return status;
 }

        mProClientList[cameraId].push(client);

        LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId,
                getpid());
 }
    device = client;
 return OK;
}

Project: Android

void CameraService::Client::disconnect() {
    ALOGV("Client::disconnect");
 BasicClient::disconnect();
    mCameraService->setCameraFree(mCameraId);

 StatusVector rejectSourceStates;
    rejectSourceStates.push_back(ICameraServiceListener::STATUS_NOT_PRESENT);
    rejectSourceStates.push_back(ICameraServiceListener::STATUS_ENUMERATING);

    mCameraService->updateStatus(ICameraServiceListener::STATUS_PRESENT,
                                 mCameraId,
 &rejectSourceStates);
}

Project: Android

sp<CameraService::BasicClient> CameraService::findClientUnsafe(
 const wp<IBinder>& cameraClient, int& outIndex) {
    sp<BasicClient> client;

 for (int i = 0; i < mNumberOfCameras; i++) {

 if (mClient[i] == 0) continue;

        client = mClient[i].promote();

 if (client == NULL) {
            mClient[i].clear();
 continue;
 }

 if (cameraClient == client->getRemote()) {
            outIndex = i;
 return client;
 }
 }

    outIndex = -1;
 return NULL;
}

Project: Android

sp<CameraService::ProClient> CameraService::findProClientUnsafe(
 const wp<IBinder>& cameraCallbacksRemote)
{
    sp<ProClient> clientPro;

 for (int i = 0; i < mNumberOfCameras; ++i) {
 Vector<size_t> removeIdx;

 for (size_t j = 0; j < mProClientList[i].size(); ++j) {
            wp<ProClient> cl = mProClientList[i][j];

            sp<ProClient> clStrong = cl.promote();
 if (clStrong != NULL && clStrong->getRemote() == cameraCallbacksRemote) {
                clientPro = clStrong;
 break;
 } else if (clStrong == NULL) {
                removeIdx.push(j);
 }
 }

 for (ssize_t j = (ssize_t)removeIdx.size() - 1; j >= 0; --j) {
            mProClientList[i].removeAt(removeIdx[j]);
 }

 }

 return clientPro;
}

Project: Android

status_t CameraService::BasicClient::finishCameraOps() {
 if (mOpsActive) {
        mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
                mClientPackageName);
        mOpsActive = false;
 }
    mAppOpsManager.stopWatchingMode(mOpsCallback);
    mOpsCallback.clear();

 return OK;
}

Project: Android

static int getCallingUid() {
 return IPCThreadState::self()->getCallingUid();
}

Project: Android

status_t CameraService::getCameraInfo(int cameraId,
 struct CameraInfo* cameraInfo) {
 if (!mModule) {
 return -ENODEV;
 }

 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
 return BAD_VALUE;
 }

 struct camera_info info;
 status_t rc = mModule->get_camera_info(cameraId, &info);
    cameraInfo->facing = info.facing;
    cameraInfo->orientation = info.orientation;
 return rc;
}

Project: Android

CameraService::BasicClient* CameraService::getClientByIdUnsafe(int cameraId) {
 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
 return mClient[cameraId].unsafe_get();
}

Project: Android

sp<CameraService::BasicClient> CameraService::getClientByRemote(
 const wp<IBinder>& cameraClient) {

    sp<BasicClient> client;

 Mutex::Autolock lock(mServiceLock);

 int outIndex;
    client = findClientUnsafe(cameraClient, outIndex);

 return client;
}

Project: Android

CameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
 BasicClient *basicClient = gCameraService->getClientByIdUnsafe((int) user);
 Client* client = static_cast<Client*>(basicClient);

 if (client == NULL) return NULL;

 if (client->mDestructionStarted) return NULL;

 return client;
}

Project: Android

Mutex* CameraService::getClientLockById(int cameraId) {
 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
 return &mClientLock[cameraId];
}

Project: Android

Mutex* CameraService::Client::getClientLockFromCookie(void* user) {
 return gCameraService->getClientLockById((int) user);
}

Project: Android

int CameraService::getDeviceVersion(int cameraId, int* facing) {
 struct camera_info info;
 if (mModule->get_camera_info(cameraId, &info) != OK) {
 return -1;
 }

 int deviceVersion;
 if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
        deviceVersion = info.device_version;
 } else {
        deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
 }

 if (facing) {
 *facing = info.facing;
 }

 return deviceVersion;
}

Project: Android

int32_t CameraService::getNumberOfCameras() {
 return mNumberOfCameras;
}

Project: Android

ICameraServiceListener::Status CameraService::getStatus(int cameraId) const {
 if (cameraId < 0 || cameraId >= MAX_CAMERAS) {
        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
 return ICameraServiceListener::STATUS_UNKNOWN;
 }

 Mutex::Autolock al(mStatusMutex);
 return mStatusList[cameraId];
}

Project: Android

bool CameraService::isValidCameraId(int cameraId) {
 int facing;
 int deviceVersion = getDeviceVersion(cameraId, &facing);

 switch(deviceVersion) {
 case CAMERA_DEVICE_API_VERSION_1_0:
 case CAMERA_DEVICE_API_VERSION_2_0:
 case CAMERA_DEVICE_API_VERSION_2_1:
 case CAMERA_DEVICE_API_VERSION_3_0:
 return true;
 default:
 return false;
 }

 return false;
}

Project: Android

void CameraService::loadSound() {
 Mutex::Autolock lock(mSoundLock);
    LOG1("CameraService::loadSound ref=%d", mSoundRef);
 if (mSoundRef++) return;

    mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
    mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
}

Project: Android

MediaPlayer* CameraService::newMediaPlayer(const char *file) {
 MediaPlayer* mp = new MediaPlayer();
 if (mp->setDataSource(file, NULL) == NO_ERROR) {
        mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
        mp->prepare();
 } else {
        ALOGE("Failed to load CameraService sounds: %s", file);
 return NULL;
 }
 return mp;
}

Project: Android

void CameraService::Client::notifyError() {
    mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
}

Project: Android

void CameraService::ProClient::notifyError() {
    mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
}

Project: Android

void CameraService::onFirstRef()
{
    LOG1("CameraService::onFirstRef");

 BnCameraService::onFirstRef();

 if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
 (const hw_module_t **)&mModule) < 0) {
        ALOGE("Could not load camera HAL module");
        mNumberOfCameras = 0;
 }
 else {
        ALOGI("Loaded \"%s\" camera module", mModule->common.name);
        mNumberOfCameras = mModule->get_number_of_cameras();
 if (mNumberOfCameras > MAX_CAMERAS) {
            ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
                    mNumberOfCameras, MAX_CAMERAS);
            mNumberOfCameras = MAX_CAMERAS;
 }
 for (int i = 0; i < mNumberOfCameras; i++) {
            setCameraFree(i);
 }

 if (mModule->common.module_api_version >=
                CAMERA_MODULE_API_VERSION_2_1) {
            mModule->set_callbacks(this);
 }

 CameraDeviceFactory::registerService(this);
 }
}

Project: Android

status_t CameraService::onTransact(
 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
 switch (code) {
 case BnCameraService::CONNECT:
 case BnCameraService::CONNECT_PRO:
 case BnCameraService::CONNECT_DEVICE:
 const int pid = getCallingPid();
 const int self_pid = getpid();
 if (pid != self_pid) {
 if (!checkCallingPermission(
 String16("android.permission.CAMERA"))) {
 const int uid = getCallingUid();
                    ALOGE("Permission Denial: "
 "can't use the camera pid=%d, uid=%d", pid, uid);
 return PERMISSION_DENIED;
 }
 }
 break;
 }

 return BnCameraService::onTransact(code, data, reply, flags);
}

Project: Android

void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
 String8 name(packageName);
 String8 myName(mClientPackageName);

 if (op != AppOpsManager::OP_CAMERA) {
        ALOGW("Unexpected app ops notification received: %d", op);
 return;
 }

 int32_t res;
    res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA,
            mClientUid, mClientPackageName);
    ALOGV("checkOp returns: %d, %s ", res,
            res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
            res == AppOpsManager::MODE_IGNORED ? "IGNORED" :
            res == AppOpsManager::MODE_ERRORED ? "ERRORED" :
 "UNKNOWN");

 if (res != AppOpsManager::MODE_ALLOWED) {
        ALOGI("Camera %d: Access for \"%s\" revoked", mCameraId,
                myName.string());
        mClientPid = getCallingPid();
        notifyError();
        disconnect();
 }
}

Project: Android

void CameraService::Client::OpsCallback::opChanged(int32_t op,
 const String16& packageName) {
    sp<BasicClient> client = mClient.promote();
 if (client != NULL) {
        client->opChanged(op, packageName);
 }
}

Project: Android

void CameraService::playSound(sound_kind kind) {
    LOG1("playSound(%d)", kind);
 Mutex::Autolock lock(mSoundLock);
    sp<MediaPlayer> player = mSoundPlayer[kind];
 if (player != 0) {
        player->seekTo(0);
        player->start();
 }
}

Project: Android

void CameraService::removeClientByRemote(const wp<IBinder>& remoteBinder) {
 int callingPid = getCallingPid();
    LOG1("CameraService::removeClientByRemote E (pid %d)", callingPid);

 Mutex::Autolock lock(mServiceLock);

 int outIndex;
    sp<BasicClient> client = findClientUnsafe(remoteBinder, outIndex);

 if (client != 0) {
        LOG1("removeClient: clear camera %d", outIndex);
        mClient[outIndex].clear();

        client->getRemote()->unlinkToDeath(this);
 } else {

        sp<ProClient> clientPro = findProClientUnsafe(remoteBinder);

 if (clientPro != NULL) {
            LOG1("removeClient: clear pro %p", clientPro.get());

            clientPro->getRemoteCallback()->asBinder()->unlinkToDeath(this);
 }
 }

    LOG1("CameraService::removeClientByRemote X (pid %d)", callingPid);
}

Project: Android

status_t CameraService::removeListener(
 const sp<ICameraServiceListener>& listener) {
    ALOGV("%s: Remove listener %p", __FUNCTION__, listener.get());

 if (listener == 0) {
        ALOGE("%s: Listener must not be null", __FUNCTION__);
 return BAD_VALUE;
 }

 Mutex::Autolock lock(mServiceLock);

 Vector<sp<ICameraServiceListener> >::iterator it;
 for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
 if ((*it)->asBinder() == listener->asBinder()) {
            mListenerList.erase(it);
 return OK;
 }
 }

    ALOGW("%s: Tried to remove a listener %p which was not subscribed",
          __FUNCTION__, listener.get());

 return BAD_VALUE;
}

Project: Android

void CameraService::setCameraBusy(int cameraId) {
    android_atomic_write(1, &mBusy[cameraId]);

    ALOGV("setCameraBusy cameraId=%d", cameraId);
}

Project: Android

void CameraService::setCameraFree(int cameraId) {
    android_atomic_write(0, &mBusy[cameraId]);

    ALOGV("setCameraFree cameraId=%d", cameraId);
}

Project: Android

static void setLogLevel(int level) {
    android_atomic_write(level, &gLogLevel);
}

Project: Android

 status_t CameraService::BasicClient::startCameraOps() {
     int32_t res;
 
    mOpsCallback = new OpsCallback(this);

 {
        ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
              __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
 }

    mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
            mClientPackageName, mOpsCallback);
    res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA,
            mClientUid, mClientPackageName);

 if (res != AppOpsManager::MODE_ALLOWED) {
        ALOGI("Camera %d: Access for \"%s\" has been revoked",
                mCameraId, String8(mClientPackageName).string());
 return PERMISSION_DENIED;
 }
    mOpsActive = true;
 return OK;
}

Project: Android

void CameraService::updateStatus(ICameraServiceListener::Status status,
 int32_t cameraId,
 const StatusVector *rejectSourceStates) {
 Mutex::Autolock lock(mStatusMutex);

 ICameraServiceListener::Status oldStatus = mStatusList[cameraId];

    mStatusList[cameraId] = status;

 if (oldStatus != status) {
        ALOGV("%s: Status has changed for camera ID %d from 0x%x to 0x%x",
              __FUNCTION__, cameraId, (uint32_t)oldStatus, (uint32_t)status);

 if (oldStatus == ICameraServiceListener::STATUS_NOT_PRESENT &&
 (status != ICameraServiceListener::STATUS_PRESENT &&
             status != ICameraServiceListener::STATUS_ENUMERATING)) {

            ALOGW("%s: From NOT_PRESENT can only transition into PRESENT"
 " or ENUMERATING", __FUNCTION__);
            mStatusList[cameraId] = oldStatus;
 return;
 }

 if (rejectSourceStates != NULL) {
 const StatusVector &rejectList = *rejectSourceStates;
 StatusVector::const_iterator it = rejectList.begin();

 /**
             * Sometimes we want to conditionally do a transition.
             * For example if a client disconnects, we want to go to PRESENT
             * only if we weren't already in NOT_PRESENT or ENUMERATING.
             */
 for (; it != rejectList.end(); ++it) {
 if (oldStatus == *it) {
                    ALOGV("%s: Rejecting status transition for Camera ID %d, "
 " since the source state was was in one of the bad "
 " states.", __FUNCTION__, cameraId);
                    mStatusList[cameraId] = oldStatus;
 return;
 }
 }
 }

 /**
          * ProClients lose their exclusive lock.
          * - Done before the CameraClient can initialize the HAL device,
          *   since we want to be able to close it before they get to initialize
          */
 if (status == ICameraServiceListener::STATUS_NOT_AVAILABLE) {
 Vector<wp<ProClient> > proClients(mProClientList[cameraId]);
 Vector<wp<ProClient> >::const_iterator it;

 for (it = proClients.begin(); it != proClients.end(); ++it) {
                sp<ProClient> proCl = it->promote();
 if (proCl.get() != NULL) {
                    proCl->onExclusiveLockStolen();
 }
 }
 }

 Vector<sp<ICameraServiceListener> >::const_iterator it;
 for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
 (*it)->onStatusChanged(status, cameraId);
 }
 }
}

Project: Android

status_t CameraService::validateConnect(int cameraId,
 /*inout*/
 int& clientUid) const {

 int callingPid = getCallingPid();

 if (clientUid == USE_CALLING_UID) {
        clientUid = getCallingUid();
 } else {
 if (callingPid != getpid()) {
            ALOGE("CameraService::connect X (pid %d) rejected (don't trust clientUid)",
                    callingPid);
 return PERMISSION_DENIED;
 }
 }

 if (!mModule) {
        ALOGE("Camera HAL module not loaded");
 return -ENODEV;
 }

 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
        ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
            callingPid, cameraId);
 return -ENODEV;
 }

 char value[PROPERTY_VALUE_MAX];
    property_get("sys.secpolicy.camera.disabled", value, "0");
 if (strcmp(value, "1") == 0) {
        ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
 return -EACCES;
 }

 ICameraServiceListener::Status currentStatus = getStatus(cameraId);
 if (currentStatus == ICameraServiceListener::STATUS_NOT_PRESENT) {
        ALOGI("Camera is not plugged in,"
 " connect X (pid %d) rejected", callingPid);
 return -ENODEV;
 } else if (currentStatus == ICameraServiceListener::STATUS_ENUMERATING) {
        ALOGI("Camera is enumerating,"
 " connect X (pid %d) rejected", callingPid);
 return -EBUSY;
 }

 return OK;
}

Project: Android

CameraService::BasicClient::~BasicClient() {
    ALOGV("~BasicClient");
    mDestructionStarted = true;
}

Project: Android

CameraService::Client::~Client() {
    ALOGV("~Client");
    mDestructionStarted = true;

    mCameraService->releaseSound();
 Client::disconnect();
}

Project: Android

CameraService::ProClient::~ProClient() {
}

Project: Android

Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
 const sp<ICameraClient>& cameraClient,
 const String16& clientPackageName,
 int cameraId,
 int cameraFacing,
 int clientPid,
 uid_t clientUid,
 int servicePid,
 int deviceVersion):
 Camera2ClientBase(cameraService, cameraClient, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
        mParameters(cameraId, cameraFacing),
        mDeviceVersion(deviceVersion)
{
    ATRACE_CALL();

 SharedParameters::Lock l(mParameters);
    l.mParameters.state = Parameters::DISCONNECTED;
}

Project: Android

status_t Camera2Client::autoFocus() {
    ATRACE_CALL();
 Mutex::Autolock icl(mBinderSerializationLock);
    ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 int triggerId;
 bool notifyImmediately = false;
 bool notifySuccess = false;
 {
 SharedParameters::Lock l(mParameters);
 if (l.mParameters.state < Parameters::PREVIEW) {
 return INVALID_OPERATION;
 }

 /**
          * If the camera does not support auto-focus, it is a no-op and
          * onAutoFocus(boolean, Camera) callback will be called immediately
          * with a fake value of success set to true.
          *
          * Similarly, if focus mode is set to INFINITY, there's no reason to
          * bother the HAL.
          */
 if (l.mParameters.focusMode == Parameters::FOCUS_MODE_FIXED ||
                l.mParameters.focusMode == Parameters::FOCUS_MODE_INFINITY) {
            notifyImmediately = true;
            notifySuccess = true;
 }
 /**
         * If we're in CAF mode, and AF has already been locked, just fire back
         * the callback right away; the HAL would not send a notification since
         * no state change would happen on a AF trigger.
         */
 if ( (l.mParameters.focusMode == Parameters::FOCUS_MODE_CONTINUOUS_PICTURE ||
                l.mParameters.focusMode == Parameters::FOCUS_MODE_CONTINUOUS_VIDEO) &&
                l.mParameters.focusState == ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED ) {
            notifyImmediately = true;
            notifySuccess = true;
 }
 /**
         * Send immediate notification back to client
         */
 if (notifyImmediately) {
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
 if (l.mRemoteCallback != 0) {
                l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
                        notifySuccess ? 1 : 0, 0);
 }
 return OK;
 }
 /**
         * Handle quirk mode for AF in scene modes
         */
 if (l.mParameters.quirks.triggerAfWithAuto &&
                l.mParameters.sceneMode != ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED &&
                l.mParameters.focusMode != Parameters::FOCUS_MODE_AUTO &&
 !l.mParameters.focusingAreas[0].isEmpty()) {
            ALOGV("%s: Quirk: Switching from focusMode %d to AUTO",
                    __FUNCTION__, l.mParameters.focusMode);
            l.mParameters.shadowFocusMode = l.mParameters.focusMode;
            l.mParameters.focusMode = Parameters::FOCUS_MODE_AUTO;
            updateRequests(l.mParameters);
 }

        l.mParameters.currentAfTriggerId = ++l.mParameters.afTriggerCounter;
        triggerId = l.mParameters.currentAfTriggerId;
 }
    ATRACE_ASYNC_BEGIN(kAutofocusLabel, triggerId);

    syncWithDevice();

    mDevice->triggerAutofocus(triggerId);

 return OK;
}

Project: Android

size_t Camera2Client::calculateBufferSize(int width, int height,
 int format, int stride) {
 switch (format) {
 case HAL_PIXEL_FORMAT_YCbCr_422_SP: // NV16
 return width * height * 2;
 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
 return width * height * 3 / 2;
 case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUY2
 return width * height * 2;
 case HAL_PIXEL_FORMAT_YV12: { // YV12
 size_t ySize = stride * height;
 size_t uvStride = (stride / 2 + 0xF) & ~0xF;
 size_t uvSize = uvStride * height / 2;
 return ySize + uvSize * 2;
 }
 case HAL_PIXEL_FORMAT_RGB_565:
 return width * height * 2;
 case HAL_PIXEL_FORMAT_RGBA_8888:
 return width * height * 4;
 case HAL_PIXEL_FORMAT_RAW_SENSOR:
 return width * height * 2;
 default:
            ALOGE("%s: Unknown preview format: %x",
                    __FUNCTION__,  format);
 return 0;
 }
}

Project: Android

status_t Camera2Client::cancelAutoFocus() {
    ATRACE_CALL();
 Mutex::Autolock icl(mBinderSerializationLock);
    ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 int triggerId;
 {
 SharedParameters::Lock l(mParameters);
 if (l.mParameters.focusMode == Parameters::FOCUS_MODE_FIXED ||
                l.mParameters.focusMode == Parameters::FOCUS_MODE_INFINITY) {
 return OK;
 }

 if (l.mParameters.afTriggerCounter == l.mParameters.currentAfTriggerId) {
            ATRACE_ASYNC_END(kAutofocusLabel, l.mParameters.currentAfTriggerId);
 }

        triggerId = ++l.mParameters.afTriggerCounter;

 if (l.mParameters.shadowFocusMode != Parameters::FOCUS_MODE_INVALID) {
            ALOGV("%s: Quirk: Restoring focus mode to %d", __FUNCTION__,
                    l.mParameters.shadowFocusMode);
            l.mParameters.focusMode = l.mParameters.shadowFocusMode;
            l.mParameters.shadowFocusMode = Parameters::FOCUS_MODE_INVALID;
            updateRequests(l.mParameters);

 return OK;
 }
 }
    syncWithDevice();

    mDevice->triggerCancelAutofocus(triggerId);

 return OK;
}

Project: Android

status_t Camera2Client::commandEnableFocusMoveMsgL(bool enable) {
 SharedParameters::Lock l(mParameters);
    l.mParameters.enableFocusMoveMessages = enable;

 return OK;
}

Project: Android

status_t Camera2Client::commandEnableShutterSoundL(bool enable) {
 SharedParameters::Lock l(mParameters);
 if (enable) {
        l.mParameters.playShutterSound = true;
 return OK;
 }

 char value[PROPERTY_VALUE_MAX];
    property_get("ro.camera.sound.forced", value, "0");
 if (strncmp(value, "0", 2) != 0) {
 if (getCallingPid() != getpid()) {
            ALOGE("Failed to disable shutter sound. Permission denied (pid %d)",
                    getCallingPid());
 return PERMISSION_DENIED;
 }
 }

    l.mParameters.playShutterSound = false;
 return OK;
}

Project: Android

status_t Camera2Client::commandPingL() {
 SharedParameters::Lock l(mParameters);
 if (l.mParameters.state != Parameters::DISCONNECTED) {
 return OK;
 } else {
 return NO_INIT;
 }
}

Project: Android

status_t Camera2Client::commandPlayRecordingSoundL() {
    mCameraService->playSound(CameraService::SOUND_RECORDING);
 return OK;
}

Project: Android

status_t Camera2Client::commandSetVideoBufferCountL(size_t count) {
 if (recordingEnabledL()) {
        ALOGE("%s: Camera %d: Error setting video buffer count after "
 "recording was started", __FUNCTION__, mCameraId);
 return INVALID_OPERATION;
 }

 return mStreamingProcessor->setRecordingBufferCount(count);
}

Project: Android

status_t Camera2Client::commandStartFaceDetectionL(int /*type*/) {
    ALOGV("%s: Camera %d: Starting face detection",
          __FUNCTION__, mCameraId);
 status_t res;
 SharedParameters::Lock l(mParameters);
 switch (l.mParameters.state) {
 case Parameters::DISCONNECTED:
 case Parameters::STOPPED:
 case Parameters::WAITING_FOR_PREVIEW_WINDOW:
 case Parameters::STILL_CAPTURE:
            ALOGE("%s: Camera %d: Cannot start face detection without preview active",
                    __FUNCTION__, mCameraId);
 return INVALID_OPERATION;
 case Parameters::PREVIEW:
 case Parameters::RECORD:
 case Parameters::VIDEO_SNAPSHOT:
 break;
 }
 if (l.mParameters.fastInfo.bestFaceDetectMode ==
            ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) {
        ALOGE("%s: Camera %d: Face detection not supported",
                __FUNCTION__, mCameraId);
 return BAD_VALUE;
 }
 if (l.mParameters.enableFaceDetect) return OK;

    l.mParameters.enableFaceDetect = true;

    res = updateRequests(l.mParameters);

 return res;
}

Project: Android

status_t Camera2Client::commandStartSmoothZoomL() {
    ALOGE("%s: Unimplemented!", __FUNCTION__);
 return OK;
}

Project: Android

status_t Camera2Client::commandStopSmoothZoomL() {
    ALOGE("%s: Unimplemented!", __FUNCTION__);
 return OK;
}

Project: Android

void Camera2Client::disconnect() {
    ATRACE_CALL();
 Mutex::Autolock icl(mBinderSerializationLock);

 int callingPid = getCallingPid();
 if (callingPid != mClientPid && callingPid != mServicePid) return;

 if (mDevice == 0) return;

    ALOGV("Camera %d: Shutting down", mCameraId);

 /**
     * disconnect() cannot call any methods that might need to promote a
     * wp<Camera2Client>, since disconnect can be called from the destructor, at
     * which point all such promotions will fail.
     */

    stopPreviewL();

 {
 SharedParameters::Lock l(mParameters);
 if (l.mParameters.state == Parameters::DISCONNECTED) return;
        l.mParameters.state = Parameters::DISCONNECTED;
 }

    mStreamingProcessor->requestExit();
    mFrameProcessor->requestExit();
    mCaptureSequencer->requestExit();
    mJpegProcessor->requestExit();
    mZslProcessorThread->requestExit();
    mCallbackProcessor->requestExit();

    ALOGV("Camera %d: Waiting for threads", mCameraId);

    mStreamingProcessor->join();
    mFrameProcessor->join();
    mCaptureSequencer->join();
    mJpegProcessor->join();
    mZslProcessorThread->join();
    mCallbackProcessor->join();

    ALOGV("Camera %d: Deleting streams", mCameraId);

    mStreamingProcessor->deletePreviewStream();
    mStreamingProcessor->deleteRecordingStream();
    mJpegProcessor->deleteStream();
    mCallbackProcessor->deleteStream();
    mZslProcessor->deleteStream();

    ALOGV("Camera %d: Disconnecting device", mCameraId);

    mDevice->disconnect();

    mDevice.clear();

 CameraService::Client::disconnect();
}

Project: Android

int Camera2Client::getCaptureStreamId() const {
 return mJpegProcessor->getStreamId();
}

Project: Android

camera2::SharedParameters& Camera2Client::getParameters() {
 return mParameters;
}

Project: Android

int Camera2Client::getPreviewStreamId() const {
 return mStreamingProcessor->getPreviewStreamId();
}

Project: Android

int Camera2Client::getRecordingStreamId() const {
 return mStreamingProcessor->getRecordingStreamId();
}

Project: Android

int Camera2Client::getZslStreamId() const {
 return mZslProcessor->getStreamId();
}

Project: Android

status_t Camera2Client::initialize(camera_module_t *module)
{
    ATRACE_CALL();
    ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
 status_t res;

    res = Camera2ClientBase::initialize(module);
 if (res != OK) {
 return res;
 }

 {
 SharedParameters::Lock l(mParameters);

        res = l.mParameters.initialize(&(mDevice->info()));
 if (res != OK) {
            ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return NO_INIT;
 }
 }

 String8 threadName;

    mStreamingProcessor = new StreamingProcessor(this);
    threadName = String8::format("C2-%d-StreamProc",
            mCameraId);
    mStreamingProcessor->run(threadName.string());

    mFrameProcessor = new FrameProcessor(mDevice, this);
    threadName = String8::format("C2-%d-FrameProc",
            mCameraId);
    mFrameProcessor->run(threadName.string());

    mCaptureSequencer = new CaptureSequencer(this);
    threadName = String8::format("C2-%d-CaptureSeq",
            mCameraId);
    mCaptureSequencer->run(threadName.string());

    mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);
    threadName = String8::format("C2-%d-JpegProc",
            mCameraId);
    mJpegProcessor->run(threadName.string());

 switch (mDeviceVersion) {
 case CAMERA_DEVICE_API_VERSION_2_0: {
            sp<ZslProcessor> zslProc =
 new ZslProcessor(this, mCaptureSequencer);
            mZslProcessor = zslProc;
            mZslProcessorThread = zslProc;
 break;
 }
 case CAMERA_DEVICE_API_VERSION_3_0:{
            sp<ZslProcessor3> zslProc =
 new ZslProcessor3(this, mCaptureSequencer);
            mZslProcessor = zslProc;
            mZslProcessorThread = zslProc;
 break;
 }
 default:
 break;
 }
    threadName = String8::format("C2-%d-ZslProc",
            mCameraId);
    mZslProcessorThread->run(threadName.string());

    mCallbackProcessor = new CallbackProcessor(this);
    threadName = String8::format("C2-%d-CallbkProc",
            mCameraId);
    mCallbackProcessor->run(threadName.string());

 if (gLogLevel >= 1) {
 SharedParameters::Lock l(mParameters);
        ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
              mCameraId);
        ALOGD("%s", l.mParameters.paramsFlattened.string());
 }

 return OK;
}

Project: Android

status_t Camera2Client::lock() {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
    ALOGV("%s: Camera %d: Lock call from pid %d; current client pid %d",
            __FUNCTION__, mCameraId, getCallingPid(), mClientPid);

 if (mClientPid == 0) {
        mClientPid = getCallingPid();
 return OK;
 }

 if (mClientPid != getCallingPid()) {
        ALOGE("%s: Camera %d: Lock call from pid %d; currently locked to pid %d",
                __FUNCTION__, mCameraId, getCallingPid(), mClientPid);
 return EBUSY;
 }

 return OK;
}

Project: Android

void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
    ALOGV("%s: Autoexposure state now %d, last trigger %d",
            __FUNCTION__, newState, triggerId);
    mCaptureSequencer->notifyAutoExposure(newState, triggerId);
}

Project: Android

void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
    ALOGV("%s: Autofocus state now %d, last trigger %d",
            __FUNCTION__, newState, triggerId);
 bool sendCompletedMessage = false;
 bool sendMovingMessage = false;

 bool success = false;
 bool afInMotion = false;
 {
 SharedParameters::Lock l(mParameters);
 char tmp[32];
 if (l.mParameters.afStateCounter > 0) {
            camera_metadata_enum_snprint(
                ANDROID_CONTROL_AF_STATE, l.mParameters.focusState, tmp, sizeof(tmp));
            ATRACE_ASYNC_END(tmp, l.mParameters.afStateCounter);
 }

        l.mParameters.focusState = newState;
        l.mParameters.afStateCounter++;


        camera_metadata_enum_snprint(
            ANDROID_CONTROL_AF_STATE, l.mParameters.focusState, tmp, sizeof(tmp));
        ATRACE_ASYNC_BEGIN(tmp, l.mParameters.afStateCounter);

 switch (l.mParameters.focusMode) {
 case Parameters::FOCUS_MODE_AUTO:
 case Parameters::FOCUS_MODE_MACRO:
 if (triggerId != l.mParameters.currentAfTriggerId) break;
 switch (newState) {
 case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
                        success = true;
 case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
                        sendCompletedMessage = true;
                        l.mParameters.currentAfTriggerId = -1;
 break;
 case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
 break;
 case ANDROID_CONTROL_AF_STATE_INACTIVE:
 case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
 case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
 case ANDROID_CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
 default:
                        ALOGE("%s: Unexpected AF state transition in AUTO/MACRO mode: %d",
                                __FUNCTION__, newState);
 break;
 }
 break;
 case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO:
 case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE:
 switch (newState) {
 case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
                        success = true;
 case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
 if (triggerId != l.mParameters.currentAfTriggerId) break;
                        sendCompletedMessage = true;
                        afInMotion = false;
 if (l.mParameters.enableFocusMoveMessages &&
                                l.mParameters.afInMotion) {
                            sendMovingMessage = true;
 }
                        l.mParameters.currentAfTriggerId = -1;
 break;
 case ANDROID_CONTROL_AF_STATE_INACTIVE:
                        afInMotion = false;
 if (l.mParameters.enableFocusMoveMessages &&
                                l.mParameters.afInMotion) {
                            sendMovingMessage = true;
 }
 break;
 case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
                        afInMotion = true;
 case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
 case ANDROID_CONTROL_AF_STATE_PASSIVE_UNFOCUSED:
 if (l.mParameters.enableFocusMoveMessages) {
                            sendMovingMessage = true;
 }
 break;
 }
                l.mParameters.afInMotion = afInMotion;
 break;
 case Parameters::FOCUS_MODE_EDOF:
 case Parameters::FOCUS_MODE_INFINITY:
 case Parameters::FOCUS_MODE_FIXED:
 default:
 if (newState != ANDROID_CONTROL_AF_STATE_INACTIVE) {
                    ALOGE("%s: Unexpected AF state change %d "
 "(ID %d) in focus mode %d",
                          __FUNCTION__, newState, triggerId,
                            l.mParameters.focusMode);
 }
 }
 }
 if (sendMovingMessage) {
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
 if (l.mRemoteCallback != 0) {
            l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
                    afInMotion ? 1 : 0, 0);
 }
 }
 if (sendCompletedMessage) {
        ATRACE_ASYNC_END(kAutofocusLabel, triggerId);
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
 if (l.mRemoteCallback != 0) {
            l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
                    success ? 1 : 0, 0);
 }
 }
}

Project: Android

bool Camera2Client::previewEnabled() {
    ATRACE_CALL();
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return false;

 SharedParameters::Lock l(mParameters);
 return l.mParameters.state == Parameters::PREVIEW;
}

Project: Android

bool Camera2Client::recordingEnabledL() {
    ATRACE_CALL();
 SharedParameters::Lock l(mParameters);

 return (l.mParameters.state == Parameters::RECORD
 || l.mParameters.state == Parameters::VIDEO_SNAPSHOT);
}

Project: Android

void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
    ATRACE_CALL();
 Mutex::Autolock icl(mBinderSerializationLock);
 if ( checkPid(__FUNCTION__) != OK) return;

    mStreamingProcessor->releaseRecordingFrame(mem);
}

Project: Android

status_t Camera2Client::removeFrameListener(int32_t minId, int32_t maxId,
        wp<camera2::FrameProcessor::FilteredListener> listener) {
 return mFrameProcessor->removeListener(minId, maxId, listener);
}

Project: Android

status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
    ATRACE_CALL();
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    ALOGV("%s: Camera %d: Command %d (%d, %d)", __FUNCTION__, mCameraId,
            cmd, arg1, arg2);

 switch (cmd) {
 case CAMERA_CMD_START_SMOOTH_ZOOM:
 return commandStartSmoothZoomL();
 case CAMERA_CMD_STOP_SMOOTH_ZOOM:
 return commandStopSmoothZoomL();
 case CAMERA_CMD_SET_DISPLAY_ORIENTATION:
 return commandSetDisplayOrientationL(arg1);
 case CAMERA_CMD_ENABLE_SHUTTER_SOUND:
 return commandEnableShutterSoundL(arg1 == 1);
 case CAMERA_CMD_PLAY_RECORDING_SOUND:
 return commandPlayRecordingSoundL();
 case CAMERA_CMD_START_FACE_DETECTION:
 return commandStartFaceDetectionL(arg1);
 case CAMERA_CMD_STOP_FACE_DETECTION: {
 SharedParameters::Lock l(mParameters);
 return commandStopFaceDetectionL(l.mParameters);
 }
 case CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG:
 return commandEnableFocusMoveMsgL(arg1 == 1);
 case CAMERA_CMD_PING:
 return commandPingL();
 case CAMERA_CMD_SET_VIDEO_BUFFER_COUNT:
 return commandSetVideoBufferCountL(arg1);
 default:
            ALOGE("%s: Unknown command %d (arguments %d, %d)",
                    __FUNCTION__, cmd, arg1, arg2);
 return BAD_VALUE;
 }
}

Project: Android

status_t Camera2Client::setParameters(const String8& params) {
    ATRACE_CALL();
    ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 SharedParameters::Lock l(mParameters);

    res = l.mParameters.set(params);
 if (res != OK) return res;

    res = updateRequests(l.mParameters);

 return res;
}

Project: Android

void Camera2Client::setPreviewCallbackFlagL(Parameters &params, int flag) {
 status_t res = OK;

 switch(params.state) {
 case Parameters::STOPPED:
 case Parameters::WAITING_FOR_PREVIEW_WINDOW:
 case Parameters::PREVIEW:
 case Parameters::STILL_CAPTURE:
 break;
 default:
 if (flag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
                ALOGE("%s: Camera %d: Can't use preview callbacks "
 "in state %d", __FUNCTION__, mCameraId, params.state);
 return;
 }
 }

 if (flag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
        ALOGV("%s: setting oneshot", __FUNCTION__);
        params.previewCallbackOneShot = true;
 }
 if (params.previewCallbackFlags != (uint32_t)flag) {

 if (params.previewCallbackSurface && flag != CAMERA_FRAME_CALLBACK_FLAG_NOOP) {
            res = mCallbackProcessor->setCallbackWindow(NULL);
 if (res != OK) {
                ALOGE("%s: Camera %d: Unable to clear preview callback surface:"
 " %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
 return;
 }
            params.previewCallbackSurface = false;
 }

        params.previewCallbackFlags = flag;

 if (params.state == Parameters::PREVIEW) {
            res = startPreviewL(params, true);
 if (res != OK) {
                ALOGE("%s: Camera %d: Unable to refresh request in state %s",
                        __FUNCTION__, mCameraId,
 Parameters::getStateName(params.state));
 }
 }
 }
}

Project: Android

status_t Camera2Client::setPreviewCallbackTarget(
 const sp<IGraphicBufferProducer>& callbackProducer) {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    sp<ANativeWindow> window;
 if (callbackProducer != 0) {
        window = new Surface(callbackProducer);
 }

    res = mCallbackProcessor->setCallbackWindow(window);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to set preview callback surface: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

 SharedParameters::Lock l(mParameters);

 if (window != NULL) {
        l.mParameters.previewCallbackFlags = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
        l.mParameters.previewCallbackOneShot = false;
        l.mParameters.previewCallbackSurface = true;
 } else {
        l.mParameters.previewCallbackSurface = false;
 }

 switch(l.mParameters.state) {
 case Parameters::PREVIEW:
            res = startPreviewL(l.mParameters, true);
 break;
 case Parameters::RECORD:
 case Parameters::VIDEO_SNAPSHOT:
            res = startRecordingL(l.mParameters, true);
 break;
 default:
 break;
 }
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to refresh request in state %s",
                __FUNCTION__, mCameraId,
 Parameters::getStateName(l.mParameters.state));
 }

 return OK;
}

Project: Android

status_t Camera2Client::setPreviewTarget(
 const sp<IGraphicBufferProducer>& bufferProducer) {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    sp<IBinder> binder;
    sp<ANativeWindow> window;
 if (bufferProducer != 0) {
        binder = bufferProducer->asBinder();
        window = new Surface(bufferProducer, /*controlledByApp*/ true);
 }
 return setPreviewWindowL(binder, window);
}

Project: Android

status_t Camera2Client::setPreviewWindowL(const sp<IBinder>& binder,
        sp<ANativeWindow> window) {
    ATRACE_CALL();
 status_t res;

 if (binder == mPreviewSurface) {
        ALOGV("%s: Camera %d: New window is same as old window",
                __FUNCTION__, mCameraId);
 return NO_ERROR;
 }

 Parameters::State state;
 {
 SharedParameters::Lock l(mParameters);
        state = l.mParameters.state;
 }
 switch (state) {
 case Parameters::DISCONNECTED:
 case Parameters::RECORD:
 case Parameters::STILL_CAPTURE:
 case Parameters::VIDEO_SNAPSHOT:
            ALOGE("%s: Camera %d: Cannot set preview display while in state %s",
                    __FUNCTION__, mCameraId,
 Parameters::getStateName(state));
 return INVALID_OPERATION;
 case Parameters::STOPPED:
 case Parameters::WAITING_FOR_PREVIEW_WINDOW:
 break;
 case Parameters::PREVIEW:
            res = stopStream();
 if (res != OK) {
                ALOGE("%s: Unable to stop preview to swap windows: %s (%d)",
                        __FUNCTION__, strerror(-res), res);
 return res;
 }
            state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
 break;
 }

    mPreviewSurface = binder;
    res = mStreamingProcessor->setPreviewWindow(window);
 if (res != OK) {
        ALOGE("%s: Unable to set new preview window: %s (%d)",
                __FUNCTION__, strerror(-res), res);
 return res;
 }

 if (state == Parameters::WAITING_FOR_PREVIEW_WINDOW) {
 SharedParameters::Lock l(mParameters);
        l.mParameters.state = state;
 return startPreviewL(l.mParameters, false);
 }

 return OK;
}

Project: Android

status_t Camera2Client::startPreview() {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
 SharedParameters::Lock l(mParameters);
 return startPreviewL(l.mParameters, false);
}

Project: Android

status_t Camera2Client::startPreviewL(Parameters &params, bool restart) {
    ATRACE_CALL();
 status_t res;

    ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);

 if ( (params.state == Parameters::PREVIEW ||
                    params.state == Parameters::RECORD ||
                    params.state == Parameters::VIDEO_SNAPSHOT)
 && !restart) {
        ALOGI("%s: Camera %d: Preview already active, ignoring restart",
                __FUNCTION__, mCameraId);
 return OK;
 }
 if (params.state > Parameters::PREVIEW && !restart) {
        ALOGE("%s: Can't start preview in state %s",
                __FUNCTION__,
 Parameters::getStateName(params.state));
 return INVALID_OPERATION;
 }

 if (!mStreamingProcessor->haveValidPreviewWindow()) {
        params.state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
 return OK;
 }
    params.state = Parameters::STOPPED;
 int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();

    res = mStreamingProcessor->updatePreviewStream(params);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to update preview stream: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

 bool previewStreamChanged = mStreamingProcessor->getPreviewStreamId() != lastPreviewStreamId;

    res = updateProcessorStream(mJpegProcessor, params);
 if (res != OK) {
        ALOGE("%s: Camera %d: Can't pre-configure still image "
 "stream: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

 Vector<int32_t> outputStreams;
 bool callbacksEnabled = (params.previewCallbackFlags &
            CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) ||
            params.previewCallbackSurface;

 if (callbacksEnabled) {
 if (mStreamingProcessor->getRecordingStreamId() != NO_STREAM) {
            ALOGV("%s: Camera %d: Clearing out recording stream before "
 "creating callback stream", __FUNCTION__, mCameraId);
            res = mStreamingProcessor->stopStream();
 if (res != OK) {
                ALOGE("%s: Camera %d: Can't stop streaming to delete "
 "recording stream", __FUNCTION__, mCameraId);
 return res;
 }
            res = mStreamingProcessor->deleteRecordingStream();
 if (res != OK) {
                ALOGE("%s: Camera %d: Unable to delete recording stream before "
 "enabling callbacks: %s (%d)", __FUNCTION__, mCameraId,
                        strerror(-res), res);
 return res;
 }
 }

        res = mCallbackProcessor->updateStream(params);
 if (res != OK) {
            ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
        outputStreams.push(getCallbackStreamId());
 } else if (previewStreamChanged && mCallbackProcessor->getStreamId() != NO_STREAM) {
 /**
         * Delete the unused callback stream when preview stream is changed and
         * preview is not enabled. Don't need stop preview stream as preview is in
         * STOPPED state now.
         */
        ALOGV("%s: Camera %d: Delete unused preview callback stream.",  __FUNCTION__, mCameraId);
        res = mCallbackProcessor->deleteStream();
 if (res != OK) {
            ALOGE("%s: Camera %d: Unable to delete callback stream %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
 }
 if (params.zslMode && !params.recordingHint) {
        res = updateProcessorStream(mZslProcessor, params);
 if (res != OK) {
            ALOGE("%s: Camera %d: Unable to update ZSL stream: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
        outputStreams.push(getZslStreamId());
 }

    outputStreams.push(getPreviewStreamId());

 if (!params.recordingHint) {
 if (!restart) {
            res = mStreamingProcessor->updatePreviewRequest(params);
 if (res != OK) {
                ALOGE("%s: Camera %d: Can't set up preview request: "
 "%s (%d)", __FUNCTION__, mCameraId,
                        strerror(-res), res);
 return res;
 }
 }
        res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,
                outputStreams);
 } else {
 if (!restart) {
            res = mStreamingProcessor->updateRecordingRequest(params);
 if (res != OK) {
                ALOGE("%s: Camera %d: Can't set up preview request with "
 "record hint: %s (%d)", __FUNCTION__, mCameraId,
                        strerror(-res), res);
 return res;
 }
 }
        res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,
                outputStreams);
 }
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to start streaming preview: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

    params.state = Parameters::PREVIEW;
 return OK;
}

Project: Android

status_t Camera2Client::startRecording() {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
 SharedParameters::Lock l(mParameters);

 return startRecordingL(l.mParameters, false);
}

Project: Android

status_t Camera2Client::startRecordingL(Parameters &params, bool restart) {
 status_t res;

    ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);

 switch (params.state) {
 case Parameters::STOPPED:
            res = startPreviewL(params, false);
 if (res != OK) return res;
 break;
 case Parameters::PREVIEW:
 break;
 case Parameters::RECORD:
 case Parameters::VIDEO_SNAPSHOT:
 if (!restart) return OK;
 break;
 default:
            ALOGE("%s: Camera %d: Can't start recording in state %s",
                    __FUNCTION__, mCameraId,
 Parameters::getStateName(params.state));
 return INVALID_OPERATION;
 };

 if (!params.storeMetadataInBuffers) {
        ALOGE("%s: Camera %d: Recording only supported in metadata mode, but "
 "non-metadata recording mode requested!", __FUNCTION__,
                mCameraId);
 return INVALID_OPERATION;
 }

 if (!restart) {
        mCameraService->playSound(CameraService::SOUND_RECORDING);
        mStreamingProcessor->updateRecordingRequest(params);
 if (res != OK) {
            ALOGE("%s: Camera %d: Unable to update recording request: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
 }

 if (mCallbackProcessor->getStreamId() != NO_STREAM) {
        ALOGV("%s: Camera %d: Clearing out callback stream before "
 "creating recording stream", __FUNCTION__, mCameraId);
        res = mStreamingProcessor->stopStream();
 if (res != OK) {
            ALOGE("%s: Camera %d: Can't stop streaming to delete callback stream",
                    __FUNCTION__, mCameraId);
 return res;
 }
        res = mCallbackProcessor->deleteStream();
 if (res != OK) {
            ALOGE("%s: Camera %d: Unable to delete callback stream before "
 "record: %s (%d)", __FUNCTION__, mCameraId,
                    strerror(-res), res);
 return res;
 }
 }
    params.previewCallbackFlags = 0;

    res = updateProcessorStream<
 StreamingProcessor,
 &StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
                                                        params);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to update recording stream: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

 Vector<int32_t> outputStreams;
    outputStreams.push(getPreviewStreamId());
    outputStreams.push(getRecordingStreamId());

    res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,
            outputStreams);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to start recording stream: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

 if (params.state < Parameters::RECORD) {
        params.state = Parameters::RECORD;
 }

 return OK;
}

Project: Android

void Camera2Client::stopPreview() {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return;
    stopPreviewL();
}

Project: Android

void Camera2Client::stopRecording() {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
 SharedParameters::Lock l(mParameters);

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return;

 switch (l.mParameters.state) {
 case Parameters::RECORD:
 break;
 case Parameters::STOPPED:
 case Parameters::PREVIEW:
 case Parameters::STILL_CAPTURE:
 case Parameters::VIDEO_SNAPSHOT:
 default:
            ALOGE("%s: Camera %d: Can't stop recording in state %s",
                    __FUNCTION__, mCameraId,
 Parameters::getStateName(l.mParameters.state));
 return;
 };

    mCameraService->playSound(CameraService::SOUND_RECORDING);

    res = startPreviewL(l.mParameters, true);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to return to preview",
                __FUNCTION__, mCameraId);
 }
}

Project: Android

status_t Camera2Client::stopStream() {
 return mStreamingProcessor->stopStream();
}

Project: Android

status_t Camera2Client::syncWithDevice() {
    ATRACE_CALL();
 const nsecs_t kMaxSyncTimeout = 500000000; // 500 ms
 status_t res;

 int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
 if (activeRequestId == 0) return OK;

    res = mDevice->waitUntilRequestReceived(activeRequestId, kMaxSyncTimeout);
 if (res == TIMED_OUT) {
        ALOGE("%s: Camera %d: Timed out waiting sync with HAL",
                __FUNCTION__, mCameraId);
 } else if (res != OK) {
        ALOGE("%s: Camera %d: Error while waiting to sync with HAL",
                __FUNCTION__, mCameraId);
 }
 return res;
}

Project: Android

status_t Camera2Client::unlock() {
    ATRACE_CALL();
    ALOGV("%s: E", __FUNCTION__);
 Mutex::Autolock icl(mBinderSerializationLock);
    ALOGV("%s: Camera %d: Unlock call from pid %d; current client pid %d",
            __FUNCTION__, mCameraId, getCallingPid(), mClientPid);

 if (mClientPid == getCallingPid()) {
 SharedParameters::Lock l(mParameters);
 if (l.mParameters.state == Parameters::RECORD ||
                l.mParameters.state == Parameters::VIDEO_SNAPSHOT) {
            ALOGD("Not allowed to unlock camera during recording.");
 return INVALID_OPERATION;
 }
        mClientPid = 0;
        mRemoteCallback.clear();
        mSharedCameraCallbacks.clear();
 return OK;
 }

    ALOGE("%s: Camera %d: Unlock call from pid %d; currently locked to pid %d",
            __FUNCTION__, mCameraId, getCallingPid(), mClientPid);
 return EBUSY;
}

Project: Android

status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,
                                              camera2::Parameters params) {
 return updateProcessorStream<ProcessorT, &ProcessorT::updateStream>(
            processor, params);
}

Project: Android

status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,
 Parameters params) {
 status_t res;

 ProcessorT *processorPtr = processor.get();
    res = (processorPtr->*updateStreamF)(params);

 /**
     * Can't update the stream if it's busy?
     *
     * Then we need to stop the device (by temporarily clearing the request
     * queue) and then try again. Resume streaming once we're done.
     */
 if (res == -EBUSY) {
        ALOGV("%s: Camera %d: Pausing to update stream", __FUNCTION__,
                mCameraId);
        res = mStreamingProcessor->togglePauseStream(/*pause*/true);
 if (res != OK) {
            ALOGE("%s: Camera %d: Can't pause streaming: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 }

        res = mDevice->waitUntilDrained();
 if (res != OK) {
            ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 }

        res = (processorPtr->*updateStreamF)(params);
 if (res != OK) {
            ALOGE("%s: Camera %d: Failed to update processing stream "
 " despite having halted streaming first: %s (%d)",
                  __FUNCTION__, mCameraId, strerror(-res), res);
 }

        res = mStreamingProcessor->togglePauseStream(/*pause*/false);
 if (res != OK) {
            ALOGE("%s: Camera %d: Can't unpause streaming: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 }
 }

 return res;
}

Project: Android

status_t Camera2Client::updateRequests(Parameters &params) {
 status_t res;

    ALOGV("%s: Camera %d: state = %d", __FUNCTION__, getCameraId(), params.state);

    res = mStreamingProcessor->incrementStreamingIds();
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to increment request IDs: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

    res = mStreamingProcessor->updatePreviewRequest(params);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
    res = mStreamingProcessor->updateRecordingRequest(params);
 if (res != OK) {
        ALOGE("%s: Camera %d: Unable to update recording request: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }

 if (params.state == Parameters::PREVIEW) {
        res = startPreviewL(params, true);
 if (res != OK) {
            ALOGE("%s: Camera %d: Error streaming new preview request: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
 } else if (params.state == Parameters::RECORD ||
            params.state == Parameters::VIDEO_SNAPSHOT) {
        res = startRecordingL(params, true);
 if (res != OK) {
            ALOGE("%s: Camera %d: Error streaming new record request: %s (%d)",
                    __FUNCTION__, mCameraId, strerror(-res), res);
 return res;
 }
 }
 return res;
}

Project: Android

Camera2Client::~Camera2Client() {
    ATRACE_CALL();
    ALOGV("~Camera2Client");

    mDestructionStarted = true;

    disconnect();

    ALOGI("Camera %d: Closed", mCameraId);

 }

Project: Android

CameraClient::CameraClient(const sp<CameraService>& cameraService,
 const sp<ICameraClient>& cameraClient,
 const String16& clientPackageName,
 int cameraId, int cameraFacing,
 int clientPid, int clientUid,
 int servicePid):
 Client(cameraService, cameraClient, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
 int callingPid = getCallingPid();
    LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);

    mHardware = NULL;
    mMsgEnabled = 0;
    mSurface = 0;
    mPreviewWindow = 0;
    mDestructionStarted = false;

    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
    mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
    mPlayShutterSound = true;
    LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}

Project: Android

status_t CameraClient::autoFocus() {
    LOG1("autoFocus (pid %d)", getCallingPid());

 Mutex::Autolock lock(mLock);
 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 return mHardware->autoFocus();
}

Project: Android

status_t CameraClient::cancelAutoFocus() {
    LOG1("cancelAutoFocus (pid %d)", getCallingPid());

 Mutex::Autolock lock(mLock);
 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 return mHardware->cancelAutoFocus();
}

Project: Android

status_t CameraClient::checkPidAndHardware() const {
 status_t result = checkPid();
 if (result != NO_ERROR) return result;
 if (mHardware == 0) {
        ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
 return INVALID_OPERATION;
 }
 return NO_ERROR;
}

Project: Android

status_t CameraClient::connect(const sp<ICameraClient>& client) {
 int callingPid = getCallingPid();
    LOG1("connect E (pid %d)", callingPid);
 Mutex::Autolock lock(mLock);

 if (mClientPid != 0 && checkPid() != NO_ERROR) {
        ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
                mClientPid, callingPid);
 return EBUSY;
 }

 if (mRemoteCallback != 0 &&
 (client->asBinder() == mRemoteCallback->asBinder())) {
        LOG1("Connect to the same client");
 return NO_ERROR;
 }

    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
    mClientPid = callingPid;
    mRemoteCallback = client;

    LOG1("connect X (pid %d)", callingPid);
 return NO_ERROR;
}

Project: Android

void CameraClient::copyFrameAndPostCopiedFrame(
 int32_t msgType, const sp<ICameraClient>& client,
 const sp<IMemoryHeap>& heap, size_t offset, size_t size,
 camera_frame_metadata_t *metadata) {
    LOG2("copyFrameAndPostCopiedFrame");
    sp<MemoryHeapBase> previewBuffer;

 if (mPreviewBuffer == 0) {
        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
 } else if (size > mPreviewBuffer->virtualSize()) {
        mPreviewBuffer.clear();
        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
 }
 if (mPreviewBuffer == 0) {
        ALOGE("failed to allocate space for preview buffer");
        mLock.unlock();
 return;
 }
    previewBuffer = mPreviewBuffer;

    memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);

    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
 if (frame == 0) {
        ALOGE("failed to allocate space for frame callback");
        mLock.unlock();
 return;
 }

    mLock.unlock();
    client->dataCallback(msgType, frame, metadata);
}

Project: Android

void CameraClient::dataCallback(int32_t msgType,
 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
    LOG2("dataCallback(%d)", msgType);

 Mutex* lock = getClientLockFromCookie(user);
 if (lock == NULL) return;
 Mutex::Autolock alock(*lock);

 CameraClient* client =
 static_cast<CameraClient*>(getClientFromCookie(user));
 if (client == NULL) return;

 if (!client->lockIfMessageWanted(msgType)) return;
 if (dataPtr == 0 && metadata == NULL) {
        ALOGE("Null data returned in data callback");
        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
 return;
 }

 switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
 case CAMERA_MSG_PREVIEW_FRAME:
            client->handlePreviewData(msgType, dataPtr, metadata);
 break;
 case CAMERA_MSG_POSTVIEW_FRAME:
            client->handlePostview(dataPtr);
 break;
 case CAMERA_MSG_RAW_IMAGE:
            client->handleRawPicture(dataPtr);
 break;
 case CAMERA_MSG_COMPRESSED_IMAGE:
            client->handleCompressedPicture(dataPtr);
 break;
 default:
            client->handleGenericData(msgType, dataPtr, metadata);
 break;
 }
}

Project: Android

void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
    LOG2("dataCallbackTimestamp(%d)", msgType);

 Mutex* lock = getClientLockFromCookie(user);
 if (lock == NULL) return;
 Mutex::Autolock alock(*lock);

 CameraClient* client =
 static_cast<CameraClient*>(getClientFromCookie(user));
 if (client == NULL) return;

 if (!client->lockIfMessageWanted(msgType)) return;

 if (dataPtr == 0) {
        ALOGE("Null data returned in data with timestamp callback");
        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
 return;
 }

    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
}

Project: Android

void CameraClient::disableMsgType(int32_t msgType) {
    android_atomic_and(~msgType, &mMsgEnabled);
    mHardware->disableMsgType(msgType);
}

Project: Android

static void disconnectWindow(const sp<ANativeWindow>& window) {
 if (window != 0) {
 status_t result = native_window_api_disconnect(window.get(),
                NATIVE_WINDOW_API_CAMERA);
 if (result != NO_ERROR) {
            ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
                    result);
 }
 }
}

Project: Android

status_t CameraClient::enableShutterSound(bool enable) {
    LOG1("enableShutterSound (pid %d)", getCallingPid());

 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 if (enable) {
        mPlayShutterSound = true;
 return OK;
 }

 char value[PROPERTY_VALUE_MAX];
    property_get("ro.camera.sound.forced", value, "0");
 if (strcmp(value, "0") != 0) {
 if (getCallingPid() != getpid()) {
            ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
 return PERMISSION_DENIED;
 }
 }

    mPlayShutterSound = false;
 return OK;
}

Project: Android

int CameraClient::getOrientation(int degrees, bool mirror) {
 if (!mirror) {
 if (degrees == 0) return 0;
 else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
 else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
 else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
 } else { // Do mirror (horizontal flip)
 if (degrees == 0) { // FLIP_H and ROT_0
 return HAL_TRANSFORM_FLIP_H;
 } else if (degrees == 90) { // FLIP_H and ROT_90
 return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
 } else if (degrees == 180) { // FLIP_H and ROT_180
 return HAL_TRANSFORM_FLIP_V;
 } else if (degrees == 270) { // FLIP_H and ROT_270
 return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
 }
 }
    ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
 return -1;
}

Project: Android

String8 CameraClient::getParameters() const {
 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return String8();

 String8 params(mHardware->getParameters().flatten());
    LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
 return params;
}

Project: Android

void CameraClient::handleGenericData(int32_t msgType,
 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
    sp<ICameraClient> c = mRemoteCallback;
    mLock.unlock();
 if (c != 0) {
        c->dataCallback(msgType, dataPtr, metadata);
 }
}

Project: Android

void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
 int32_t msgType, const sp<IMemory>& dataPtr) {
    sp<ICameraClient> c = mRemoteCallback;
    mLock.unlock();
 if (c != 0) {
        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
 }
}

Project: Android

void CameraClient::handleGenericNotify(int32_t msgType,
 int32_t ext1, int32_t ext2) {
    sp<ICameraClient> c = mRemoteCallback;
    mLock.unlock();
 if (c != 0) {
        c->notifyCallback(msgType, ext1, ext2);
 }
}

Project: Android

void CameraClient::handlePostview(const sp<IMemory>& mem) {
    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);

    sp<ICameraClient> c = mRemoteCallback;
    mLock.unlock();
 if (c != 0) {
        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
 }
}

Project: Android

void CameraClient::handlePreviewData(int32_t msgType,
 const sp<IMemory>& mem,
 camera_frame_metadata_t *metadata) {
 ssize_t offset;
 size_t size;
    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);

 int flags = mPreviewCallbackFlag;

 if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
        LOG2("frame callback is disabled");
        mLock.unlock();
 return;
 }

    sp<ICameraClient> c = mRemoteCallback;

 if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
        LOG2("Disable preview callback");
        mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
                                  CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
                                  CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
 }

 if (c != 0) {
 if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
            LOG2("frame is copied");
            copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
 } else {
            LOG2("frame is forwarded");
            mLock.unlock();
            c->dataCallback(msgType, mem, metadata);
 }
 } else {
        mLock.unlock();
 }
}

Project: Android

void CameraClient::handleRawPicture(const sp<IMemory>& mem) {
    disableMsgType(CAMERA_MSG_RAW_IMAGE);

 ssize_t offset;
 size_t size;
    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);

    sp<ICameraClient> c = mRemoteCallback;
    mLock.unlock();
 if (c != 0) {
        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
 }
}

Project: Android

void CameraClient::handleShutter(void) {
 if (mPlayShutterSound) {
        mCameraService->playSound(CameraService::SOUND_SHUTTER);
 }

    sp<ICameraClient> c = mRemoteCallback;
 if (c != 0) {
        mLock.unlock();
        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
 }
    disableMsgType(CAMERA_MSG_SHUTTER);

    mLock.unlock();
}

Project: Android

status_t CameraClient::initialize(camera_module_t *module) {
 int callingPid = getCallingPid();
 status_t res;

    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

    res = startCameraOps();
 if (res != OK) {
 return res;
 }

 char camera_device_name[10];
    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

    mHardware = new CameraHardwareInterface(camera_device_name);
    res = mHardware->initialize(&module->common);
 if (res != OK) {
        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mHardware.clear();
 return NO_INIT;
 }

    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
 (void *)mCameraId);

    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);

    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
 return OK;
}

Project: Android

status_t CameraClient::lock() {
 int callingPid = getCallingPid();
    LOG1("lock (pid %d)", callingPid);
 Mutex::Autolock lock(mLock);

 if (mClientPid == 0) {
        mClientPid = callingPid;
 return NO_ERROR;
 }

 return checkPid();
}

Project: Android

bool CameraClient::lockIfMessageWanted(int32_t msgType) {
 int sleepCount = 0;
 while (mMsgEnabled & msgType) {
 if (mLock.tryLock() == NO_ERROR) {
 if (sleepCount > 0) {
                LOG1("lockIfMessageWanted(%d): waited for %d ms",
                    msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
 }
 return true;
 }
 if (sleepCount++ == 0) {
            LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
 }
        usleep(CHECK_MESSAGE_INTERVAL * 1000);
 }
    ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
 return false;
}

Project: Android

void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
 int32_t ext2, void* user) {
    LOG2("notifyCallback(%d)", msgType);

 Mutex* lock = getClientLockFromCookie(user);
 if (lock == NULL) return;
 Mutex::Autolock alock(*lock);

 CameraClient* client =
 static_cast<CameraClient*>(getClientFromCookie(user));
 if (client == NULL) return;

 if (!client->lockIfMessageWanted(msgType)) return;

 switch (msgType) {
 case CAMERA_MSG_SHUTTER:
            client->handleShutter();
 break;
 default:
            client->handleGenericNotify(msgType, ext1, ext2);
 break;
 }
}

Project: Android

bool CameraClient::previewEnabled() {
    LOG1("previewEnabled (pid %d)", getCallingPid());

 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return false;
 return mHardware->previewEnabled();
}

Project: Android

bool CameraClient::recordingEnabled() {
    LOG1("recordingEnabled (pid %d)", getCallingPid());

 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return false;
 return mHardware->recordingEnabled();
}

Project: Android

void CameraClient::releaseRecordingFrame(const sp<IMemory>& mem) {
 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return;
    mHardware->releaseRecordingFrame(mem);
}

Project: Android

status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
    LOG1("sendCommand (pid %d)", getCallingPid());
 int orientation;
 Mutex::Autolock lock(mLock);
 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
        orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
 if (orientation == -1) return BAD_VALUE;

 if (mOrientation != orientation) {
            mOrientation = orientation;
 if (mPreviewWindow != 0) {
                native_window_set_buffers_transform(mPreviewWindow.get(),
                        mOrientation);
 }
 }
 return OK;
 } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
 switch (arg1) {
 case 0:
 return enableShutterSound(false);
 case 1:
 return enableShutterSound(true);
 default:
 return BAD_VALUE;
 }
 return OK;
 } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
        mCameraService->playSound(CameraService::SOUND_RECORDING);
 } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) {
 return INVALID_OPERATION;
 } else if (cmd == CAMERA_CMD_PING) {
 return OK;
 }

 return mHardware->sendCommand(cmd, arg1, arg2);
}

Project: Android

void CameraClient::setPreviewCallbackFlag(int callback_flag) {
    LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return;

    mPreviewCallbackFlag = callback_flag;
 if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
        enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
 } else {
        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
 }
}

Project: Android

status_t CameraClient::setPreviewCallbackTarget(
 const sp<IGraphicBufferProducer>& callbackProducer) {
 (void)callbackProducer;
    ALOGE("%s: Unimplemented!", __FUNCTION__);
 return INVALID_OPERATION;
}

Project: Android

status_t CameraClient::setPreviewTarget(
 const sp<IGraphicBufferProducer>& bufferProducer) {
    LOG1("setPreviewTarget(%p) (pid %d)", bufferProducer.get(),
            getCallingPid());

    sp<IBinder> binder;
    sp<ANativeWindow> window;
 if (bufferProducer != 0) {
        binder = bufferProducer->asBinder();
        window = new Surface(bufferProducer, /*controlledByApp*/ true);
 }
 return setPreviewWindow(binder, window);
}

Project: Android

status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
 const sp<ANativeWindow>& window) {
 Mutex::Autolock lock(mLock);
 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 if (binder == mSurface) {
 return NO_ERROR;
 }

 if (window != 0) {
        result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
 if (result != NO_ERROR) {
            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
                    result);
 return result;
 }
 }

 if (mHardware->previewEnabled()) {
 if (window != 0) {
            native_window_set_scaling_mode(window.get(),
                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
            native_window_set_buffers_transform(window.get(), mOrientation);
            result = mHardware->setPreviewWindow(window);
 }
 }

 if (result == NO_ERROR) {
        disconnectWindow(mPreviewWindow);
        mSurface = binder;
        mPreviewWindow = window;
 } else {
        disconnectWindow(window);
 }

 return result;
}

Project: Android

status_t CameraClient::startCameraMode(camera_mode mode) {
    LOG1("startCameraMode(%d)", mode);
 Mutex::Autolock lock(mLock);
 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 switch(mode) {
 case CAMERA_PREVIEW_MODE:
 if (mSurface == 0 && mPreviewWindow == 0) {
                LOG1("mSurface is not set yet.");
 }
 return startPreviewMode();
 case CAMERA_RECORDING_MODE:
 if (mSurface == 0 && mPreviewWindow == 0) {
                ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
 return INVALID_OPERATION;
 }
 return startRecordingMode();
 default:
 return UNKNOWN_ERROR;
 }
}

Project: Android

status_t CameraClient::startPreviewMode() {
    LOG1("startPreviewMode");
 status_t result = NO_ERROR;

 if (mHardware->previewEnabled()) {
 return NO_ERROR;
 }

 if (mPreviewWindow != 0) {
        native_window_set_scaling_mode(mPreviewWindow.get(),
                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
        native_window_set_buffers_transform(mPreviewWindow.get(),
                mOrientation);
 }
    mHardware->setPreviewWindow(mPreviewWindow);
    result = mHardware->startPreview();

 return result;
}

Project: Android

status_t CameraClient::startRecordingMode() {
    LOG1("startRecordingMode");
 status_t result = NO_ERROR;

 if (mHardware->recordingEnabled()) {
 return NO_ERROR;
 }

 if (!mHardware->previewEnabled()) {
        result = startPreviewMode();
 if (result != NO_ERROR) {
 return result;
 }
 }

    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
    mCameraService->playSound(CameraService::SOUND_RECORDING);
    result = mHardware->startRecording();
 if (result != NO_ERROR) {
        ALOGE("mHardware->startRecording() failed with status %d", result);
 }
 return result;
}

Project: Android

void CameraClient::stopPreview() {
    LOG1("stopPreview (pid %d)", getCallingPid());
 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return;


    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
    mHardware->stopPreview();

    mPreviewBuffer.clear();
}

Project: Android

void CameraClient::stopRecording() {
    LOG1("stopRecording (pid %d)", getCallingPid());
 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) return;

    disableMsgType(CAMERA_MSG_VIDEO_FRAME);
    mHardware->stopRecording();
    mCameraService->playSound(CameraService::SOUND_RECORDING);

    mPreviewBuffer.clear();
}

Project: Android

status_t CameraClient::storeMetaDataInBuffers(bool enabled)
{
    LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
 Mutex::Autolock lock(mLock);
 if (checkPidAndHardware() != NO_ERROR) {
 return UNKNOWN_ERROR;
 }
 return mHardware->storeMetaDataInBuffers(enabled);
}

Project: Android

status_t CameraClient::takePicture(int msgType) {
    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);

 Mutex::Autolock lock(mLock);
 status_t result = checkPidAndHardware();
 if (result != NO_ERROR) return result;

 if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
 (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
        ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
 " cannot be both enabled");
 return BAD_VALUE;
 }

 int picMsgType = msgType
 & (CAMERA_MSG_SHUTTER |
                           CAMERA_MSG_POSTVIEW_FRAME |
                           CAMERA_MSG_RAW_IMAGE |
                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
                           CAMERA_MSG_COMPRESSED_IMAGE);

    enableMsgType(picMsgType);

 return mHardware->takePicture();
}

Project: Android

CameraClient::~CameraClient() {
 Mutex* lock = mCameraService->getClientLockById(mCameraId);
    lock->lock();
    mDestructionStarted = true;
    lock->unlock();
 int callingPid = getCallingPid();
    LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this);

    disconnect();
    LOG1("CameraClient::~CameraClient X (pid %d, this %p)", callingPid, this);

 }

Project: Android

CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
 const sp<ICameraDeviceCallbacks>& remoteCallback,
 const String16& clientPackageName,
 int cameraId,
 int cameraFacing,
 int clientPid,
 uid_t clientUid,
 int servicePid) :
 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
    mRequestIdCounter(0) {

    ATRACE_CALL();
    ALOGI("CameraDeviceClient %d: Opened", cameraId);
}

Project: Android

CameraDeviceClientBase::CameraDeviceClientBase(
 const sp<CameraService>& cameraService,
 const sp<ICameraDeviceCallbacks>& remoteCallback,
 const String16& clientPackageName,
 int cameraId,
 int cameraFacing,
 int clientPid,
 uid_t clientUid,
 int servicePid) :
 BasicClient(cameraService, remoteCallback->asBinder(), clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
    mRemoteCallback(remoteCallback) {
}

Project: Android

status_t CameraDeviceClient::createDefaultRequest(int templateId,
 /*out*/
 CameraMetadata* request)
{
    ATRACE_CALL();
    ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 CameraMetadata metadata;
 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
        request != NULL) {

        request->swap(metadata);
 }

 return res;
}

Project: Android

status_t CameraDeviceClient::createStream(int width, int height, int format,
 const sp<IGraphicBufferProducer>& bufferProducer)
{
    ATRACE_CALL();
    ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 {
 ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder());
 if (index != NAME_NOT_FOUND) {
            ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
 "(ID %d)",
                  __FUNCTION__, mCameraId, index);
 return ALREADY_EXISTS;
 }
 }

 bool useAsync = false;
 int32_t consumerUsage;
 if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
 &consumerUsage)) != OK) {
        ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__,
              mCameraId);
 return res;
 }
 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
        ALOGW("%s: Camera %d: Forcing asynchronous mode for stream",
                __FUNCTION__, mCameraId);
        useAsync = true;
 }

    sp<IBinder> binder;
    sp<ANativeWindow> anw;
 if (bufferProducer != 0) {
        binder = bufferProducer->asBinder();
        anw = new Surface(bufferProducer, useAsync);
 }


 if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
        ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
              mCameraId);
 return res;
 }
 if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
        ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__,
              mCameraId);
 return res;
 }
 if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
        ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__,
              mCameraId);
 return res;
 }

 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
        format <= HAL_PIXEL_FORMAT_BGRA_8888) {
        ALOGW("%s: Camera %d: Overriding format 0x%x to IMPLEMENTATION_DEFINED",
              __FUNCTION__, mCameraId, format);
        format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
 }


 int streamId = -1;
 if (format == HAL_PIXEL_FORMAT_BLOB) {
 CameraMetadata staticInfo = mDevice->info();
 camera_metadata_entry_t entry = staticInfo.find(ANDROID_JPEG_MAX_SIZE);
 if (entry.count == 0) {
            ALOGE("%s: Camera %d: Can't find maximum JPEG size in "
 "static metadata!", __FUNCTION__, mCameraId);
 return INVALID_OPERATION;
 }
 int32_t maxJpegSize = entry.data.i32[0];
        res = mDevice->createStream(anw, width, height, format, maxJpegSize,
 &streamId);
 } else {
        res = mDevice->createStream(anw, width, height, format, /*size*/0,
 &streamId);
 }

 if (res == OK) {
        mStreamMap.add(bufferProducer->asBinder(), streamId);

        ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
              __FUNCTION__, mCameraId, streamId);

 /**
         * Set the stream transform flags to automatically
         * rotate the camera stream for preview use cases.
         */
 int32_t transform = 0;
        res = getRotationTransformLocked(&transform);

 if (res != OK) {
 return res;
 }

        res = mDevice->setStreamTransform(streamId, transform);
 if (res != OK) {
            ALOGE("%s: Failed to set stream transform (stream id %d)",
                  __FUNCTION__, streamId);
 return res;
 }

 return streamId;
 }

 return res;
}

Project: Android

status_t CameraDeviceClient::deleteStream(int streamId) {
    ATRACE_CALL();
    ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 ssize_t index = NAME_NOT_FOUND;
 for (size_t i = 0; i < mStreamMap.size(); ++i) {
 if (streamId == mStreamMap.valueAt(i)) {
            index = i;
 break;
 }
 }

 if (index == NAME_NOT_FOUND) {
        ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
 "created yet", __FUNCTION__, mCameraId, streamId);
 return BAD_VALUE;
 }

    res = mDevice->deleteStream(streamId);

 if (res == BAD_VALUE) {
        ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we"
 " already checked and the stream ID (%d) should be valid.",
              __FUNCTION__, mCameraId, streamId);
 } else if (res == OK) {
        mStreamMap.removeItemsAt(index);

        ALOGV("%s: Camera %d: Successfully deleted stream ID (%d)",
              __FUNCTION__, mCameraId, streamId);
 }

 return res;
}

Project: Android

void CameraDeviceClient::detachDevice() {
 if (mDevice == 0) return;

    ALOGV("Camera %d: Stopping processors", mCameraId);

    mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                    FRAME_PROCESSOR_LISTENER_MAX_ID,
 /*listener*/this);
    mFrameProcessor->requestExit();
    ALOGV("Camera %d: Waiting for threads", mCameraId);
    mFrameProcessor->join();
    ALOGV("Camera %d: Disconnecting device", mCameraId);

 {
        mDevice->clearStreamingRequest();

 status_t code;
 if ((code = mDevice->waitUntilDrained()) != OK) {
            ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
                  code);
 }
 }

 Camera2ClientBase::detachDevice();
}

Project: Android

status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info)
{
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 status_t res = OK;

 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 if (info != NULL) {
 *info = mDevice->info(); // static camera metadata
 }

 return res;
}

Project: Android

status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
    ALOGV("%s: begin", __FUNCTION__);

 if (transform == NULL) {
        ALOGW("%s: null transform", __FUNCTION__);
 return BAD_VALUE;
 }

 *transform = 0;

 const CameraMetadata& staticInfo = mDevice->info();
 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_SENSOR_ORIENTATION);
 if (entry.count == 0) {
        ALOGE("%s: Camera %d: Can't find android.sensor.orientation in "
 "static metadata!", __FUNCTION__, mCameraId);
 return INVALID_OPERATION;
 }

 int32_t& flags = *transform;

 int orientation = entry.data.i32[0];
 switch (orientation) {
 case 0:
            flags = 0;
 break;
 case 90:
            flags = NATIVE_WINDOW_TRANSFORM_ROT_90;
 break;
 case 180:
            flags = NATIVE_WINDOW_TRANSFORM_ROT_180;
 break;
 case 270:
            flags = NATIVE_WINDOW_TRANSFORM_ROT_270;
 break;
 default:
            ALOGE("%s: Invalid HAL android.sensor.orientation value: %d",
                  __FUNCTION__, orientation);
 return INVALID_OPERATION;
 }

 /**
     * This magic flag makes surfaceflinger un-rotate the buffers
     * to counter the extra global device UI rotation whenever the user
     * physically rotates the device.
     *
     * By doing this, the camera buffer always ends up aligned
     * with the physical camera for a "see through" effect.
     *
     * In essence, the buffer only gets rotated during preview use-cases.
     * The user is still responsible to re-create streams of the proper
     * aspect ratio, or the preview will end up looking non-uniformly
     * stretched.
     */
    flags |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;

    ALOGV("%s: final transform = 0x%x", __FUNCTION__, flags);

 return OK;
}

Project: Android

status_t CameraDeviceClient::initialize(camera_module_t *module)
{
    ATRACE_CALL();
 status_t res;

    res = Camera2ClientBase::initialize(module);
 if (res != OK) {
 return res;
 }

 String8 threadName;
    mFrameProcessor = new FrameProcessorBase(mDevice);
    threadName = String8::format("CDU-%d-FrameProc", mCameraId);
    mFrameProcessor->run(threadName.string());

    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
 /*listener*/this,
 /*quirkSendPartials*/true);

 return OK;
}

Project: Android

void CameraDeviceClient::notifyError() {
    sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();

 if (remoteCb != 0) {
        remoteCb->onDeviceError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE);
 }
}

Project: Android

void CameraDeviceClient::notifyShutter(int requestId,
 nsecs_t timestamp) {
    sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
 if (remoteCb != 0) {
        remoteCb->onCaptureStarted(requestId, timestamp);
 }
}

Project: Android

void CameraDeviceClient::onFrameAvailable(int32_t requestId,
 const CameraMetadata& frame) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

    sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
 if (remoteCb != NULL) {
        ALOGV("%s: frame = %p ", __FUNCTION__, &frame);
        remoteCb->onResultReceived(requestId, frame);
 }
}

Project: Android

status_t CameraDeviceClient::waitUntilIdle()
{
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 status_t res = OK;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 if (!mStreamingRequestList.isEmpty()) {
        ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests",
              __FUNCTION__, mCameraId);
 return INVALID_OPERATION;
 }
    res = mDevice->waitUntilDrained();
    ALOGV("%s Done", __FUNCTION__);

 return res;
}

Project: Android

ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
 const sp<IProCameraCallbacks>& remoteCallback,
 const String16& clientPackageName,
 int cameraId,
 int cameraFacing,
 int clientPid,
 uid_t clientUid,
 int servicePid) :
 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
    ATRACE_CALL();
    ALOGI("ProCamera %d: Opened", cameraId);

    mExclusiveLock = false;
}

Project: Android

status_t ProCamera2Client::cancelRequest(int requestId) {
 (void)requestId;
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 if (!mExclusiveLock) {
 return PERMISSION_DENIED;
 }

    ALOGE("%s: not fully implemented yet", __FUNCTION__);
 return INVALID_OPERATION;
}

Project: Android

status_t ProCamera2Client::createDefaultRequest(int templateId,
 /*out*/
                              camera_metadata** request)
{
    ATRACE_CALL();
    ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);

 if (request) {
 *request = NULL;
 }

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 CameraMetadata metadata;
 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
 *request = metadata.release();
 }

 return res;
}

Project: Android

status_t ProCamera2Client::createStream(int width, int height, int format,
 const sp<IGraphicBufferProducer>& bufferProducer,
 /*out*/
 int* streamId)
{
 if (streamId) {
 *streamId = -1;
 }

    ATRACE_CALL();
    ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

    sp<IBinder> binder;
    sp<ANativeWindow> window;
 if (bufferProducer != 0) {
        binder = bufferProducer->asBinder();
        window = new Surface(bufferProducer);
 }

 return mDevice->createStream(window, width, height, format, /*size*/1,
                                 streamId);
}

Project: Android

status_t ProCamera2Client::deleteStream(int streamId) {
    ATRACE_CALL();
    ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);

 status_t res;
 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;
    mDevice->clearStreamingRequest();

 status_t code;
 if ((code = mDevice->waitUntilDrained()) != OK) {
        ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, code);
 }

 return mDevice->deleteStream(streamId);
}

Project: Android

void ProCamera2Client::detachDevice() {
 if (mDevice == 0) return;

    ALOGV("Camera %d: Stopping processors", mCameraId);

    mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                    FRAME_PROCESSOR_LISTENER_MAX_ID,
 /*listener*/this);
    mFrameProcessor->requestExit();
    ALOGV("Camera %d: Waiting for threads", mCameraId);
    mFrameProcessor->join();
    ALOGV("Camera %d: Disconnecting device", mCameraId);

 {
        mDevice->clearStreamingRequest();

 status_t code;
 if ((code = mDevice->waitUntilDrained()) != OK) {
            ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
                  code);
 }
 }

 Camera2ClientBase::detachDevice();
}

Project: Android

bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {

 const int pid = IPCThreadState::self()->getCallingPid();
 const int selfPid = getpid();
 camera_metadata_entry_t entry;

 /**
     * Mixin default important security values
     * - android.led.transmit = defaulted ON
     */
 CameraMetadata staticInfo = mDevice->info();
    entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
 for(size_t i = 0; i < entry.count; ++i) {
 uint8_t led = entry.data.u8[i];

 switch(led) {
 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
                    metadata.update(ANDROID_LED_TRANSMIT,
 &transmitDefault, 1);
 }
 break;
 }
 }
 }

 if (pid == selfPid) {
 return true;
 }

 /**
     * Permission check special fields in the request
     * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
     */
    entry = metadata.find(ANDROID_LED_TRANSMIT);
 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
 String16 permissionString =
 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
 if (!checkCallingPermission(permissionString)) {
 const int uid = IPCThreadState::self()->getCallingUid();
            ALOGE("Permission Denial: "
 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
 return false;
 }
 }

 return true;
}

Project: Android

status_t ProCamera2Client::exclusiveLock() {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 Mutex::Autolock icl(mBinderSerializationLock);
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

 if (!mDevice.get()) return PERMISSION_DENIED;

 /**
     * TODO: this should asynchronously 'wait' until the lock becomes available
     * if another client already has an exclusive lock.
     *
     * once we have proper sharing support this will need to do
     * more than just return immediately
     */
 if (!mExclusiveLock) {
        mExclusiveLock = true;

 if (mRemoteCallback != NULL) {
            mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
 }

        ALOGV("%s: exclusive lock acquired", __FUNCTION__);

 return OK;
 }

    ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
 , __FUNCTION__);
 return ALREADY_EXISTS;
}

Project: Android

status_t ProCamera2Client::exclusiveTryLock() {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 Mutex::Autolock icl(mBinderSerializationLock);
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

 if (!mDevice.get()) return PERMISSION_DENIED;

 if (!mExclusiveLock) {
        mExclusiveLock = true;

 if (mRemoteCallback != NULL) {
            mRemoteCallback->onLockStatusChanged(
 IProCameraCallbacks::LOCK_ACQUIRED);
 }

        ALOGV("%s: exclusive lock acquired", __FUNCTION__);

 return OK;
 }


    ALOGW("%s: exclusive lock already exists - recursive locking is not"
 "allowed", __FUNCTION__);

 return ALREADY_EXISTS;
}

Project: Android

status_t ProCamera2Client::getCameraInfo(int cameraId,
 /*out*/
                                         camera_metadata** info)
{
 if (cameraId != mCameraId) {
 return INVALID_OPERATION;
 }

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 CameraMetadata deviceInfo = mDevice->info();
 *info = deviceInfo.release();

 return OK;

 }

Project: Android

bool ProCamera2Client::hasExclusiveLock() {
 Mutex::Autolock icl(mBinderSerializationLock);
 return mExclusiveLock;
}

Project: Android

status_t ProCamera2Client::initialize(camera_module_t *module)
{
    ATRACE_CALL();
 status_t res;

    res = Camera2ClientBase::initialize(module);
 if (res != OK) {
 return res;
 }

 String8 threadName;
    mFrameProcessor = new FrameProcessorBase(mDevice);
    threadName = String8::format("PC2-%d-FrameProc", mCameraId);
    mFrameProcessor->run(threadName.string());

    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
 /*listener*/this);

 return OK;
}

Project: Android

void ProCamera2Client::onExclusiveLockStolen() {
    ALOGV("%s: ProClient lost exclusivity (id %d)",
          __FUNCTION__, mCameraId);

 Mutex::Autolock icl(mBinderSerializationLock);
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

 if (mExclusiveLock && mRemoteCallback.get() != NULL) {
        mRemoteCallback->onLockStatusChanged(
 IProCameraCallbacks::LOCK_STOLEN);
 }

    mExclusiveLock = false;

    detachDevice();
}

Project: Android

void ProCamera2Client::onFrameAvailable(int32_t requestId,
 const CameraMetadata& frame) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 Mutex::Autolock icl(mBinderSerializationLock);
 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);

 if (mRemoteCallback != NULL) {
 CameraMetadata tmp(frame);
 camera_metadata_t* meta = tmp.release();
        ALOGV("%s: meta = %p ", __FUNCTION__, meta);
        mRemoteCallback->onResultReceived(requestId, meta);
        tmp.acquire(meta);
 }

}

Project: Android

status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
 bool streaming) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);

 Mutex::Autolock icl(mBinderSerializationLock);

 if (!mDevice.get()) return DEAD_OBJECT;

 if (!mExclusiveLock) {
 return PERMISSION_DENIED;
 }

 CameraMetadata metadata(request);

 if (!enforceRequestPermissions(metadata)) {
 return PERMISSION_DENIED;
 }

 if (streaming) {
 return mDevice->setStreamingRequest(metadata);
 } else {
 return mDevice->capture(metadata);
 }

 return OK;
}

Project: Android

ProCamera2Client::~ProCamera2Client() {
}