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) {
        // Mirror the preview if the camera is front-facing.
        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) {
        // Silently ignore this command
        return INVALID_OPERATION;
    } else if (cmd == CAMERA_CMD_PING) {
        // If mHardware is 0, checkPidAndHardware will return error.
        return OK;
#ifdef QCOM_HARDWARE
    } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) {
        enableMsgType(CAMERA_MSG_STATS_DATA);
    } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) {
        disableMsgType(CAMERA_MSG_STATS_DATA);
    } else if (cmd == CAMERA_CMD_METADATA_ON) {
        enableMsgType(CAMERA_MSG_META_DATA);
    } else if (cmd == CAMERA_CMD_METADATA_OFF) {
        disableMsgType(CAMERA_MSG_META_DATA);
    } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) {
        mLongshotEnabled = true;
    } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) {
        mLongshotEnabled = false;
        disableMsgType(CAMERA_MSG_SHUTTER);
        disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
#endif
    }

    return mHardware->sendCommand(cmd, arg1, arg2);
}
status_t CameraClient::initialize(camera_module_t *module) {
    int callingPid = getCallingPid();
    status_t res;

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

    // Verify ops permissions
    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 res;
    }

    // mtk callback
    mHardware->setMtkCallbacks(
            mtkMetadataCallback,
            (void *)(uintptr_t)mCameraId
            );

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



    // Enable zoom, error, focus, and metadata messages by default
    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);

//!++
#if 1
    // Enable MTK-extended messages by default
    enableMsgType(MTK_CAMERA_MSG_EXT_NOTIFY | MTK_CAMERA_MSG_EXT_DATA);
#endif
//!--

    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    return OK;
}
status_t CameraService::Client::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) {
        // Mirror the preview if the camera is front-facing.
        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:
                enableShutterSound(false);
                break;
            case 1:
                enableShutterSound(true);
                break;
            default:
                return BAD_VALUE;
        }
        return OK;
    } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
        mCameraService->playSound(SOUND_RECORDING);
    }
    else if (cmd == CAMERA_CMD_HISTOGRAM_ON ) {
        enableMsgType(CAMERA_MSG_STATS_DATA);
    }
    else if (cmd ==  CAMERA_CMD_HISTOGRAM_OFF) {
        disableMsgType(CAMERA_MSG_STATS_DATA);
    } else if (cmd ==   CAMERA_CMD_START_FACE_DETECTION) {
      mFaceDetection = true;
      enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
    } else if (cmd ==   CAMERA_CMD_STOP_FACE_DETECTION) {
      mFaceDetection = false;
      disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
    }


    return mHardware->sendCommand(cmd, arg1, arg2);
}
// take a picture - image is returned in callback
status_t CameraService::Client::takePicture(int msgType) {
    char prop[PROPERTY_VALUE_MAX];
    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);

    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;
	//zxj ++
	mstopPreview = true;
	//zxj --
    if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
        (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
        LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
                " cannot be both enabled");
        return BAD_VALUE;
    }

    // We only accept picture related message types
    // and ignore other types of messages for takePicture().
    int picMsgType = msgType
                        & (CAMERA_MSG_SHUTTER |
                           CAMERA_MSG_POSTVIEW_FRAME |
                           CAMERA_MSG_RAW_IMAGE |
                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
                           CAMERA_MSG_COMPRESSED_IMAGE);
    disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
    enableMsgType(picMsgType);
    mburstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter");
    if(mburstCnt <= 0) mburstCnt = 1;
    LOG1("mburstCnt = %d", mburstCnt);
    return mHardware->takePicture();
}
		status_t CameraService::Client::startPreviewMode() {
			LOG1("startPreviewMode");
			status_t result = NO_ERROR;
			
			// if preview has been enabled, nothing needs to be done
			if (mHardware->previewEnabled()) {
				return NO_ERROR;
			}
			
			if (mUseOverlay) {
				// If preview display has been set, set overlay now.
				if (mSurface != 0) {
					result = setOverlay();
				}
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
				result = mHardware->startPreview();
#endif
				if (result != NO_ERROR) return result;
#ifndef USE_OVERLAY_FORMAT_YCbCr_420_SP
				result = mHardware->startPreview();
#endif
			} else {
				enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
				result = mHardware->startPreview();
				if (result != NO_ERROR) return result;
				// If preview display has been set, register preview buffers now.
				if (mSurface != 0) {
					// Unregister here because the surface may be previously registered
					// with the raw (snapshot) heap.
					mSurface->unregisterBuffers();
					result = registerPreviewBuffers();
				}
			}
			return result;
		}
// start preview mode
status_t CameraClient::startPreview() {
#ifdef CAMERA_MSG_MGMT
    enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
#endif
    LOG1("startPreview (pid %d)", getCallingPid());
    return startCameraMode(CAMERA_PREVIEW_MODE);
}
// take a picture - image is returned in callback
status_t CameraService::Client::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)) {
        LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
                " cannot be both enabled");
        return BAD_VALUE;
    }

    // We only accept picture related message types
    // and ignore other types of messages for takePicture().
    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();
}
// start preview mode
status_t CameraClient::startPreview() {
    LOG1("startPreview (pid %d)", getCallingPid());
#ifdef QCOM_HARDWARE
    enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
#endif
    return startCameraMode(CAMERA_PREVIEW_MODE);
}
status_t CameraService::Client::startRecordingMode() {
    LOG1("startRecordingMode");
    status_t result = NO_ERROR;

    // if recording has been enabled, nothing needs to be done
    if (mHardware->recordingEnabled()) {
        return NO_ERROR;
    }

    // if preview has not been started, start preview first
    if (!mHardware->previewEnabled()) {
        result = startPreviewMode();
        if (result != NO_ERROR) {
            return result;
        }
    }

    // start recording mode
    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
    mCameraService->playSound(SOUND_RECORDING);
    result = mHardware->startRecording();
    if (result != NO_ERROR) {
        LOGE("mHardware->startRecording() failed with status %d", result);
    }
    return result;
}
CameraService::Client::Client(const sp<CameraService>& cameraService,
        const sp<ICameraClient>& cameraClient,
        const sp<CameraHardwareInterface>& hardware,
        int cameraId, int cameraFacing, int clientPid) {
    int callingPid = getCallingPid();
    LOG1("Client::Client E (pid %d)", callingPid);

    mCameraService = cameraService;
    mCameraClient = cameraClient;
    mHardware = hardware;
    mCameraId = cameraId;
    mCameraFacing = cameraFacing;
    mClientPid = clientPid;
    mMsgEnabled = 0;
    mSurface = 0;
    mPreviewWindow = 0;
    mHardware->setCallbacks(notifyCallback,
                            dataCallback,
                            dataCallbackTimestamp,
                            (void *)cameraId);

    // Enable zoom, error, focus, and metadata messages by default
    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
                  CAMERA_MSG_PREVIEW_METADATA);

    // Callback is disabled by default
    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
    mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
    mPlayShutterSound = true;
    cameraService->setCameraBusy(cameraId);
    cameraService->loadSound();
    LOG1("Client::Client X (pid %d)", callingPid);
}
// start preview mode
status_t CameraService::Client::startPreview() {
    LOG1("startPreview (pid %d)", getCallingPid());
	//zxj ++
	mstopPreview = false;
	//zxj --
    if (mFaceDetection) {
      enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
    }
    return startCameraMode(CAMERA_PREVIEW_MODE);
}
// set the preview callback flag to affect how the received frames from
// preview are handled.
void CameraService::Client::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);
    }
}
// take a picture - image is returned in callback
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;
    }

    // We only accept picture related message types
    // and ignore other types of messages for takePicture().
    int picMsgType = msgType
                        & (CAMERA_MSG_SHUTTER |
                           CAMERA_MSG_POSTVIEW_FRAME |
                           CAMERA_MSG_RAW_IMAGE |
                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
                           CAMERA_MSG_RAW_BURST |
#endif
                           CAMERA_MSG_COMPRESSED_IMAGE);

#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
    picMsgType |= CAMERA_MSG_COMPRESSED_BURST_IMAGE;
#endif
#ifdef CAMERA_MSG_MGMT
    disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
#endif
    enableMsgType(picMsgType);
#ifdef QCOM_HARDWARE
    mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter");
    if(mBurstCnt <= 0)
        mBurstCnt = 1;

    LOG1("mBurstCnt = %d", mBurstCnt);

    // HTC HDR mode requires that we snap multiple times, but only get one jpeg
    int numJpegs = mHardware->getParameters().getInt("num-jpegs-per-shutter");
    if (numJpegs == 1 && mBurstCnt > 1) {
        while (mBurstCnt > 1) {
            result = mHardware->takePicture();
            mBurstCnt--;
        }
    }
#endif

    return mHardware->takePicture();
}
Exemple #14
0
/******************************************************************************
 *  Burst Shutter Callback Handler
 *       ext2: count-down shutter number; 0: the last one shutter.
 ******************************************************************************/
void
CameraClient::
handleMtkExtBurstShutter(int32_t /*ext1*/, int32_t ext2)
{
    handleShutter();
    if  (0 < ext2) {
        //  not the last one burst shutter.
        enableMsgType(CAMERA_MSG_SHUTTER);
        ALOGD("[handleMtkExtBurstShutter] count-down burst shutter number:%d - enableMsgType(CAMERA_MSG_SHUTTER) \r\n", ext2);
    }
    else {
        ALOGD("[handleMtkExtBurstShutter] the last one burst shutter \r\n");
    }
}
		// take a picture - image is returned in callback
		status_t CameraService::Client::takePicture() {
			LOG1("takePicture (pid %d)", getCallingPid());
			
			Mutex::Autolock lock(mLock);
			status_t result = checkPidAndHardware();
			if (result != NO_ERROR) return result;
			
			enableMsgType(CAMERA_MSG_SHUTTER |
						  CAMERA_MSG_POSTVIEW_FRAME |
						  CAMERA_MSG_RAW_IMAGE |
						  CAMERA_MSG_COMPRESSED_IMAGE);
			
			return mHardware->takePicture();
		}
// picture callback - compressed picture ready
void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
    if (mburstCnt) mburstCnt--;

    if (!mburstCnt) {
        LOG1("mburstCnt = %d", mburstCnt);
        disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
        if (mFaceDetection) {
          enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
        }
    }
    sp<ICameraClient> c = mCameraClient;
    mLock.unlock();
    if (c != 0) {
        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
    }
}
status_t CameraClient::initialize(camera_module_t *module) {
    int callingPid = getCallingPid();
    status_t res;

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

    // Verify ops permissions
    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);

    // Enable zoom, error, focus, and metadata messages by default
    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS
#ifndef QCOM_HARDWARE
                  | CAMERA_MSG_PREVIEW_METADATA 
#endif
#ifndef OMAP_ICS_CAMERA
                  | CAMERA_MSG_FOCUS_MOVE
#endif
                 );

    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    return OK;
}
	CameraService::Client::Client(const sp<CameraService>& cameraService,
								  const sp<ICameraClient>& cameraClient,
								  const sp<CameraHardwareInterface>& hardware,
								  int cameraId, int cameraFacing, int clientPid) {
		int callingPid = getCallingPid();
		LOG1("Client::Client E (pid %d)", callingPid);
		
		mCameraService = cameraService;
		mCameraClient = cameraClient;
		mHardware = hardware;
		mCameraId = cameraId;
		mCameraFacing = cameraFacing;
		mClientPid = clientPid;
		mMsgEnabled = 0;
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
		if (mHardware != NULL) {
#endif
			mUseOverlay = mHardware->useOverlay();
			
			mHardware->setCallbacks(notifyCallback,
									dataCallback,
									dataCallbackTimestamp,
									(void *)cameraId);
			
			// Enable zoom, error, and focus messages by default
			enableMsgType(CAMERA_MSG_ERROR |
						  CAMERA_MSG_ZOOM |
						  CAMERA_MSG_FOCUS);
			mOverlayW = 0;
			mOverlayH = 0;
			
			// Callback is disabled by default
			mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
			mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
			mOrientationChanged = false;
			cameraService->setCameraBusy(cameraId);
			cameraService->loadSound();
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
		}
#endif
		LOG1("Client::Client X (pid %d)", callingPid);
	}
	// set the ISurface that the preview will use
	status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
		LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
		Mutex::Autolock lock(mLock);
		status_t result = checkPidAndHardware();
		if (result != NO_ERROR) return result;
		
		result = NO_ERROR;
		
		// return if no change in surface.
		// asBinder() is safe on NULL (returns NULL)
		if (surface->asBinder() == mSurface->asBinder()) {
			return result;
		}
		
		if (mSurface != 0) {
			LOG1("clearing old preview surface %p", mSurface.get());
			if (mUseOverlay) {
				// Force the destruction of any previous overlay
				sp<Overlay> dummy;
				mHardware->setOverlay(dummy);
				mOverlayRef = 0;
			} else {
				mSurface->unregisterBuffers();
			}
		}
		mSurface = surface;
		mOverlayRef = 0;
		// If preview has been already started, set overlay or register preview
		// buffers now.
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
		if (mHardware->previewEnabled() || mUseOverlay) {
#else
			if (mHardware->previewEnabled()) {
#endif
				if (mUseOverlay) {
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
					if (mSurface != NULL) {
#endif
						result = setOverlay();
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
					}
#endif
				} else if (mSurface != 0) {
					result = registerPreviewBuffers();
				}
			}
			
			return result;
		}
		
		status_t CameraService::Client::registerPreviewBuffers() {
			int w, h;
			CameraParameters params(mHardware->getParameters());
			params.getPreviewSize(&w, &h);
			
			//for 720p recording , preview can be 800X448
			if(w ==  preview_sizes[0].width && h== preview_sizes[0].height){
				LOGD("registerpreviewbufs :changing dimensions to 768X432 for 720p recording.");
				w = preview_sizes[1].width;
				h = preview_sizes[1].height;
			}
			
			// FIXME: don't use a hardcoded format here.
			ISurface::BufferHeap buffers(w, h, w, h,
										 HAL_PIXEL_FORMAT_YCrCb_420_SP,
										 mOrientation,
										 0,
										 mHardware->getPreviewHeap());
			
			status_t result = mSurface->registerBuffers(buffers);
			if (result != NO_ERROR) {
				LOGE("registerBuffers failed with status %d", result);
			}
			return result;
		}
		
		status_t CameraService::Client::setOverlay() {
			int w, h;
			CameraParameters params(mHardware->getParameters());
			params.getPreviewSize(&w, &h);
			
			//for 720p recording , preview can be 800X448
			if(w == preview_sizes[0].width && h==preview_sizes[0].height){
				LOGD("Changing overlay dimensions to 768X432 for 720p recording.");
				w = preview_sizes[1].width;
				h = preview_sizes[1].height;
			}
			
			if (w != mOverlayW || h != mOverlayH || mOrientationChanged) {
				// Force the destruction of any previous overlay
				sp<Overlay> dummy;
				mHardware->setOverlay(dummy);
				mOverlayRef = 0;
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
				if (mOverlay != NULL) {
					mOverlay->destroy();
				}
#endif
				mOrientationChanged = false;
			}
			
			status_t result = NO_ERROR;
			if (mSurface == 0) {
				result = mHardware->setOverlay(NULL);
			} else {
				if (mOverlayRef == 0) {
					// FIXME:
					// Surfaceflinger may hold onto the previous overlay reference for some
					// time after we try to destroy it. retry a few times. In the future, we
					// should make the destroy call block, or possibly specify that we can
					// wait in the createOverlay call if the previous overlay is in the
					// process of being destroyed.
					for (int retry = 0; retry < 50; ++retry) {
						mOverlayRef = mSurface->createOverlay(w, h,
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
															  HAL_PIXEL_FORMAT_YCbCr_420_SP,
#else
															  OVERLAY_FORMAT_DEFAULT,
#endif
															  mOrientation);
						if (mOverlayRef != 0) break;
						LOGW("Overlay create failed - retrying");
						usleep(20000);
					}
					if (mOverlayRef == 0) {
						LOGE("Overlay Creation Failed!");
						return -EINVAL;
					}
#ifdef USE_OVERLAY_FORMAT_YCbCr_420_SP
					mOverlay = new Overlay(mOverlayRef);
					result = mHardware->setOverlay(mOverlay);
#else
					result = mHardware->setOverlay(new Overlay(mOverlayRef));
#endif
				}
			}
			if (result != NO_ERROR) {
				LOGE("mHardware->setOverlay() failed with status %d\n", result);
				return result;
			}
			
			mOverlayW = w;
			mOverlayH = h;
			
			return result;
		}
		
		// set the preview callback flag to affect how the received frames from
		// preview are handled.
		void CameraService::Client::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 we don't use overlay, we always need the preview frame for display.
			// If we do use overlay, we only need the preview frame if the user
			// wants the data.
			if (mUseOverlay) {
				if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
					enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
				} else {
					disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
				}
			}
		}