android从应用到驱动之—Camera(2)---cameraHAL的实现

来源:互联网 发布:皓月乒乓 淘宝 编辑:程序博客网 时间:2024/04/28 21:55


本来想用这一篇博客把cameraHAL的实现和流程都给写完的.搞了半天,东西实在是太多了.这篇先写cameraHAL的基本实现框架,下一篇在具体写camerahal的流程吧.

cameraHAL的实现:

对于初学者来说,最大的疑问是系统是如何调用hardware的.
这里就以camera来举例说明.
调用hardware的程序是cameraservice,我们就去它里面看看它是如何找到hardware的

先把源码贴上来:

/***** Copyright (C) 2008, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License");** you may not use this file except in compliance with the License.** You may obtain a copy of the License at****     http://www.apache.org/licenses/LICENSE-2.0**** Unless required by applicable law or agreed to in writing, software** distributed under the License is distributed on an "AS IS" BASIS,** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.** See the License for the specific language governing permissions and** limitations under the License.*/#define LOG_TAG "CameraService"//#define LOG_NDEBUG 0#include <stdio.h>#include <sys/types.h>#include <pthread.h>#include <binder/IPCThreadState.h>#include <binder/IServiceManager.h>#include <binder/MemoryBase.h>#include <binder/MemoryHeapBase.h>#include <cutils/atomic.h>#include <cutils/properties.h>#include <gui/SurfaceTextureClient.h>#include <hardware/hardware.h>#include <media/AudioSystem.h>#include <media/mediaplayer.h>#include <surfaceflinger/ISurface.h>#include <utils/Errors.h>#include <utils/Log.h>#include <utils/String16.h>#include "CameraService.h"#include "CameraHardwareInterface.h"namespace android {// ----------------------------------------------------------------------------// Logging support -- this is for debugging only// Use "adb shell dumpsys media.camera -v 1" to change it.static volatile int32_t gLogLevel = 0;#define LOG1(...) LOGD_IF(gLogLevel >= 1, __VA_ARGS__);#define LOG2(...) LOGD_IF(gLogLevel >= 2, __VA_ARGS__);static void setLogLevel(int level) {    android_atomic_write(level, &gLogLevel);}// ----------------------------------------------------------------------------static int getCallingPid() {    return IPCThreadState::self()->getCallingPid();}static int getCallingUid() {    return IPCThreadState::self()->getCallingUid();}// ----------------------------------------------------------------------------// This is ugly and only safe if we never re-create the CameraService, but// should be ok for now.static CameraService *gCameraService;CameraService::CameraService():mSoundRef(0), mModule(0){    LOGI("CameraService started (pid=%d)", getpid());    gCameraService = this;}void CameraService::onFirstRef(){    BnCameraService::onFirstRef();    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,                (const hw_module_t **)&mModule) < 0) {        LOGE("Could not load camera HAL module");        mNumberOfCameras = 0;    }    else {        mNumberOfCameras = mModule->get_number_of_cameras();        if (mNumberOfCameras > MAX_CAMERAS) {            LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",                    mNumberOfCameras, MAX_CAMERAS);            mNumberOfCameras = MAX_CAMERAS;        }        for (int i = 0; i < mNumberOfCameras; i++) {            setCameraFree(i);        }    }    // Read the system property to determine if we have to use the    // AUDIO_STREAM_ENFORCED_AUDIBLE type.    char value[PROPERTY_VALUE_MAX];    property_get("ro.camera.sound.forced", value, "0");    if (strcmp(value, "0") != 0) {        mAudioStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;    } else {        mAudioStreamType = AUDIO_STREAM_MUSIC;    }}CameraService::~CameraService() {    for (int i = 0; i < mNumberOfCameras; i++) {        if (mBusy[i]) {            LOGE("camera %d is still in use in destructor!", i);        }    }    gCameraService = NULL;}int32_t CameraService::getNumberOfCameras() {    return mNumberOfCameras;}status_t CameraService::getCameraInfo(int cameraId,                                      struct CameraInfo* cameraInfo) {    if (!mModule) {        return NO_INIT;    }    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;}sp<ICamera> CameraService::connect(        const sp<ICameraClient>& cameraClient, int cameraId) {    int callingPid = getCallingPid();    sp<CameraHardwareInterface> hardware = NULL;    LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);    if (!mModule) {        LOGE("Camera HAL module not loaded");        return NULL;    }    sp<Client> client;    if (cameraId < 0 || cameraId >= mNumberOfCameras) {        LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",            callingPid, cameraId);        return NULL;    }    char value[PROPERTY_VALUE_MAX];    property_get("sys.secpolicy.camera.disabled", value, "0");    if (strcmp(value, "1") == 0) {        // Camera is disabled by DevicePolicyManager.        LOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);        return NULL;    }    Mutex::Autolock lock(mServiceLock);    if (mClient[cameraId] != 0) {        client = mClient[cameraId].promote();        if (client != 0) {            if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {                LOG1("CameraService::connect X (pid %d) (the same client)",                    callingPid);                return client;            } else {                LOGW("CameraService::connect X (pid %d) rejected (existing client).",                    callingPid);                return NULL;            }        }        mClient[cameraId].clear();    }    if (mBusy[cameraId]) {        LOGW("CameraService::connect X (pid %d) rejected"             " (camera %d is still busy).", callingPid, cameraId);        return NULL;    }    struct camera_info info;    if (mModule->get_camera_info(cameraId, &info) != OK) {        LOGE("Invalid camera id %d", cameraId);        return NULL;    }    char camera_device_name[10];    snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);    hardware = new CameraHardwareInterface(camera_device_name);    if (hardware->initialize(&mModule->common) != OK) {        hardware.clear();        return NULL;    }    client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid);    mClient[cameraId] = client;    LOG1("CameraService::connect X");    return client;}void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {    int callingPid = getCallingPid();    LOG1("CameraService::removeClient E (pid %d)", callingPid);    for (int i = 0; i < mNumberOfCameras; i++) {        // Declare this before the lock to make absolutely sure the        // destructor won't be called with the lock held.        sp<Client> client;        Mutex::Autolock lock(mServiceLock);        // This happens when we have already disconnected (or this is        // just another unused camera).        if (mClient[i] == 0) continue;        // Promote mClient. It can fail if we are called from this path:        // Client::~Client() -> disconnect() -> removeClient().        client = mClient[i].promote();        if (client == 0) {            mClient[i].clear();            continue;        }        if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {            // Found our camera, clear and leave.            LOG1("removeClient: clear camera %d", i);            mClient[i].clear();            break;        }    }    LOG1("CameraService::removeClient X (pid %d)", callingPid);}sp<CameraService::Client> CameraService::getClientById(int cameraId) {    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;    return mClient[cameraId].promote();}status_t CameraService::onTransact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {    // Permission checks    switch (code) {        case BnCameraService::CONNECT:            const int pid = getCallingPid();            const int self_pid = getpid();            if (pid != self_pid) {                // we're called from a different process, do the real check                if (!checkCallingPermission(                        String16("android.permission.CAMERA"))) {                    const int uid = getCallingUid();                    LOGE("Permission Denial: "                         "can't use the camera pid=%d, uid=%d", pid, uid);                    return PERMISSION_DENIED;                }            }            break;    }    return BnCameraService::onTransact(code, data, reply, flags);}// The reason we need this busy bit is a new CameraService::connect() request// may come in while the previous Client's destructor has not been run or is// still running. If the last strong reference of the previous Client is gone// but the destructor has not been finished, we should not allow the new Client// to be created because we need to wait for the previous Client to tear down// the hardware first.void CameraService::setCameraBusy(int cameraId) {    android_atomic_write(1, &mBusy[cameraId]);}void CameraService::setCameraFree(int cameraId) {    android_atomic_write(0, &mBusy[cameraId]);}// We share the media players for shutter and recording sound for all clients.// A reference count is kept to determine when we will actually release the// media players.MediaPlayer* CameraService::newMediaPlayer(const char *file) {    MediaPlayer* mp = new MediaPlayer();    if (mp->setDataSource(file, NULL) == NO_ERROR) {        mp->setAudioStreamType(mAudioStreamType);        mp->prepare();    } else {        LOGE("Failed to load CameraService sounds: %s", file);        return NULL;    }    return mp;}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");}void CameraService::releaseSound() {    Mutex::Autolock lock(mSoundLock);    LOG1("CameraService::releaseSound ref=%d", mSoundRef);    if (--mSoundRef) return;    for (int i = 0; i < NUM_SOUNDS; i++) {        if (mSoundPlayer[i] != 0) {            mSoundPlayer[i]->disconnect();            mSoundPlayer[i].clear();        }    }}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();    }}// ----------------------------------------------------------------------------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);}// tear down the clientCameraService::Client::~Client() {    int callingPid = getCallingPid();    LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);    // set mClientPid to let disconnet() tear down the hardware    mClientPid = callingPid;    disconnect();    mCameraService->releaseSound();    LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);}// ----------------------------------------------------------------------------status_t CameraService::Client::checkPid() const {    int callingPid = getCallingPid();    if (callingPid == mClientPid) return NO_ERROR;    LOGW("attempt to use a locked camera from a different process"         " (old pid %d, new pid %d)", mClientPid, callingPid);    return EBUSY;}status_t CameraService::Client::checkPidAndHardware() const {    status_t result = checkPid();    if (result != NO_ERROR) return result;    if (mHardware == 0) {        LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());        return INVALID_OPERATION;    }    return NO_ERROR;}status_t CameraService::Client::lock() {    int callingPid = getCallingPid();    LOG1("lock (pid %d)", callingPid);    Mutex::Autolock lock(mLock);    // lock camera to this client if the the camera is unlocked    if (mClientPid == 0) {        mClientPid = callingPid;        return NO_ERROR;    }    // returns NO_ERROR if the client already owns the camera, EBUSY otherwise    return checkPid();}status_t CameraService::Client::unlock() {    int callingPid = getCallingPid();    LOG1("unlock (pid %d)", callingPid);    Mutex::Autolock lock(mLock);    // allow anyone to use camera (after they lock the camera)    status_t result = checkPid();    if (result == NO_ERROR) {        if (mHardware->recordingEnabled()) {            LOGE("Not allowed to unlock camera during recording.");            return INVALID_OPERATION;        }        mClientPid = 0;        LOG1("clear mCameraClient (pid %d)", callingPid);        // we need to remove the reference to ICameraClient so that when the app        // goes away, the reference count goes to 0.        mCameraClient.clear();    }    return result;}// connect a new client to the camerastatus_t CameraService::Client::connect(const sp<ICameraClient>& client) {    int callingPid = getCallingPid();    LOG1("connect E (pid %d)", callingPid);    Mutex::Autolock lock(mLock);    if (mClientPid != 0 && checkPid() != NO_ERROR) {        LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",                mClientPid, callingPid);        return EBUSY;    }    if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {        LOG1("Connect to the same client");        return NO_ERROR;    }    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;    mClientPid = callingPid;    mCameraClient = client;    LOG1("connect X (pid %d)", callingPid);    return NO_ERROR;}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) {            LOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),                    result);        }    }}void CameraService::Client::disconnect() {    int callingPid = getCallingPid();    LOG1("disconnect E (pid %d)", callingPid);    Mutex::Autolock lock(mLock);    if (checkPid() != NO_ERROR) {        LOGW("different client - don't disconnect");        return;    }    if (mClientPid <= 0) {        LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);        return;    }    // Make sure disconnect() is done once and once only, whether it is called    // from the user directly, or called by the destructor.    if (mHardware == 0) return;    LOG1("hardware teardown");    // Before destroying mHardware, we must make sure it's in the    // idle state.    // Turn off all messages.    disableMsgType(CAMERA_MSG_ALL_MSGS);    mHardware->stopPreview();    mHardware->cancelPicture();    // Release the hardware resources.    mHardware->release();    // Release the held ANativeWindow resources.    if (mPreviewWindow != 0) {        disconnectWindow(mPreviewWindow);        mPreviewWindow = 0;        mHardware->setPreviewWindow(mPreviewWindow);    }    mHardware.clear();    mCameraService->removeClient(mCameraClient);    mCameraService->setCameraFree(mCameraId);    LOG1("disconnect X (pid %d)", callingPid);}// ----------------------------------------------------------------------------status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,        const sp<ANativeWindow>& window) {    Mutex::Autolock lock(mLock);    status_t result = checkPidAndHardware();    if (result != NO_ERROR) return result;    // return if no change in surface.    if (binder == mSurface) {        return NO_ERROR;    }    if (window != 0) {        result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);        if (result != NO_ERROR) {            LOGE("native_window_api_connect failed: %s (%d)", strerror(-result),                    result);            return result;        }    }    // If preview has been already started, register preview buffers now.    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) {        // Everything has succeeded.  Disconnect the old window and remember the        // new window.        disconnectWindow(mPreviewWindow);        mSurface = binder;        mPreviewWindow = window;    } else {        // Something went wrong after we connected to the new window, so        // disconnect here.        disconnectWindow(window);    }    return result;}// set the Surface that the preview will usestatus_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);    sp<ANativeWindow> window(surface);    return setPreviewWindow(binder, window);}// set the SurfaceTexture that the preview will usestatus_t CameraService::Client::setPreviewTexture(        const sp<ISurfaceTexture>& surfaceTexture) {    LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),            getCallingPid());    sp<IBinder> binder;    sp<ANativeWindow> window;    if (surfaceTexture != 0) {        binder = surfaceTexture->asBinder();        window = new SurfaceTextureClient(surfaceTexture);    }    return setPreviewWindow(binder, window);}// 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);    }}// start preview modestatus_t CameraService::Client::startPreview() {    LOG1("startPreview (pid %d)", getCallingPid());    return startCameraMode(CAMERA_PREVIEW_MODE);}// start recording modestatus_t CameraService::Client::startRecording() {    LOG1("startRecording (pid %d)", getCallingPid());    return startCameraMode(CAMERA_RECORDING_MODE);}// start preview or recordingstatus_t CameraService::Client::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.");                // still able to start preview in this case.            }            return startPreviewMode();        case CAMERA_RECORDING_MODE:            if (mSurface == 0 && mPreviewWindow == 0) {                LOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");                return INVALID_OPERATION;            }            return startRecordingMode();        default:            return UNKNOWN_ERROR;    }}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 (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;}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;}// stop preview modevoid CameraService::Client::stopPreview() {    LOG1("stopPreview (pid %d)", getCallingPid());    Mutex::Autolock lock(mLock);    if (checkPidAndHardware() != NO_ERROR) return;    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);    mHardware->stopPreview();    mPreviewBuffer.clear();}// stop recording modevoid CameraService::Client::stopRecording() {    LOG1("stopRecording (pid %d)", getCallingPid());    Mutex::Autolock lock(mLock);    if (checkPidAndHardware() != NO_ERROR) return;    mCameraService->playSound(SOUND_RECORDING);    disableMsgType(CAMERA_MSG_VIDEO_FRAME);    mHardware->stopRecording();    mPreviewBuffer.clear();}// release a recording framevoid CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {    Mutex::Autolock lock(mLock);    if (checkPidAndHardware() != NO_ERROR) return;    mHardware->releaseRecordingFrame(mem);}status_t CameraService::Client::storeMetaDataInBuffers(bool enabled){    LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");    Mutex::Autolock lock(mLock);    if (checkPidAndHardware() != NO_ERROR) {        return UNKNOWN_ERROR;    }    return mHardware->storeMetaDataInBuffers(enabled);}bool CameraService::Client::previewEnabled() {    LOG1("previewEnabled (pid %d)", getCallingPid());    Mutex::Autolock lock(mLock);    if (checkPidAndHardware() != NO_ERROR) return false;    return mHardware->previewEnabled();}bool CameraService::Client::recordingEnabled() {    LOG1("recordingEnabled (pid %d)", getCallingPid());    Mutex::Autolock lock(mLock);    if (checkPidAndHardware() != NO_ERROR) return false;    return mHardware->recordingEnabled();}status_t CameraService::Client::autoFocus() {    LOG1("autoFocus (pid %d)", getCallingPid());    Mutex::Autolock lock(mLock);    status_t result = checkPidAndHardware();    if (result != NO_ERROR) return result;    return mHardware->autoFocus();}status_t CameraService::Client::cancelAutoFocus() {    LOG1("cancelAutoFocus (pid %d)", getCallingPid());    Mutex::Autolock lock(mLock);    status_t result = checkPidAndHardware();    if (result != NO_ERROR) return result;    return mHardware->cancelAutoFocus();}// take a picture - image is returned in callbackstatus_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();}// set preview/capture parameters - key/value pairsstatus_t CameraService::Client::setParameters(const String8& params) {    LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());    Mutex::Autolock lock(mLock);    status_t result = checkPidAndHardware();    if (result != NO_ERROR) return result;    CameraParameters p(params);    return mHardware->setParameters(p);}// get preview/capture parameters - key/value pairsString8 CameraService::Client::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;}// enable shutter soundstatus_t CameraService::Client::enableShutterSound(bool enable) {    LOG1("enableShutterSound (pid %d)", getCallingPid());    status_t result = checkPidAndHardware();    if (result != NO_ERROR) return result;    if (enable) {        mPlayShutterSound = true;        return OK;    }    // Disabling shutter sound may not be allowed. In that case only    // allow the mediaserver process to disable the sound.    char value[PROPERTY_VALUE_MAX];    property_get("ro.camera.sound.forced", value, "0");    if (strcmp(value, "0") != 0) {        // Disabling shutter sound is not allowed. Deny if the current        // process is not mediaserver.        if (getCallingPid() != getpid()) {            LOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());            return PERMISSION_DENIED;        }    }    mPlayShutterSound = false;    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);    }    return mHardware->sendCommand(cmd, arg1, arg2);}// ----------------------------------------------------------------------------void CameraService::Client::enableMsgType(int32_t msgType) {    android_atomic_or(msgType, &mMsgEnabled);    mHardware->enableMsgType(msgType);}void CameraService::Client::disableMsgType(int32_t msgType) {    android_atomic_and(~msgType, &mMsgEnabled);    mHardware->disableMsgType(msgType);}#define CHECK_MESSAGE_INTERVAL 10 // 10msbool CameraService::Client::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);    }    LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);    return false;}// ----------------------------------------------------------------------------// Converts from a raw pointer to the client to a strong pointer during a// hardware callback. This requires the callbacks only happen when the client// is still alive.sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {    sp<Client> client = gCameraService->getClientById((int) user);    // This could happen if the Client is in the process of shutting down (the    // last strong reference is gone, but the destructor hasn't finished    // stopping the hardware).    if (client == 0) return NULL;    // The checks below are not necessary and are for debugging only.    if (client->mCameraService.get() != gCameraService) {        LOGE("mismatch service!");        return NULL;    }    if (client->mHardware == 0) {        LOGE("mHardware == 0: callback after disconnect()?");        return NULL;    }    return client;}// Callback messages can be dispatched to internal handlers or pass to our// client's callback functions, depending on the message type.//// notifyCallback://      CAMERA_MSG_SHUTTER              handleShutter//      (others)                        c->notifyCallback// dataCallback://      CAMERA_MSG_PREVIEW_FRAME        handlePreviewData//      CAMERA_MSG_POSTVIEW_FRAME       handlePostview//      CAMERA_MSG_RAW_IMAGE            handleRawPicture//      CAMERA_MSG_COMPRESSED_IMAGE     handleCompressedPicture//      (others)                        c->dataCallback// dataCallbackTimestamp//      (others)                        c->dataCallbackTimestamp//// NOTE: the *Callback functions grab mLock of the client before passing// control to handle* functions. So the handle* functions must release the// lock before calling the ICameraClient's callbacks, so those callbacks can// invoke methods in the Client class again (For example, the preview frame// callback may want to releaseRecordingFrame). The handle* functions must// release the lock after all accesses to member variables, so it must be// handled very carefully.void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,        int32_t ext2, void* user) {    LOG2("notifyCallback(%d)", msgType);    sp<Client> client = getClientFromCookie(user);    if (client == 0) return;    if (!client->lockIfMessageWanted(msgType)) return;    switch (msgType) {        case CAMERA_MSG_SHUTTER:            // ext1 is the dimension of the yuv picture.            client->handleShutter();            break;        default:            client->handleGenericNotify(msgType, ext1, ext2);            break;    }}void CameraService::Client::dataCallback(int32_t msgType,        const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {    LOG2("dataCallback(%d)", msgType);    sp<Client> client = getClientFromCookie(user);    if (client == 0) return;    if (!client->lockIfMessageWanted(msgType)) return;    if (dataPtr == 0 && metadata == NULL) {        LOGE("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;    }}void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,        int32_t msgType, const sp<IMemory>& dataPtr, void* user) {    LOG2("dataCallbackTimestamp(%d)", msgType);    sp<Client> client = getClientFromCookie(user);    if (client == 0) return;    if (!client->lockIfMessageWanted(msgType)) return;    if (dataPtr == 0) {        LOGE("Null data returned in data with timestamp callback");        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);        return;    }    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);}// snapshot taken callbackvoid CameraService::Client::handleShutter(void) {    if (mPlayShutterSound) {        mCameraService->playSound(SOUND_SHUTTER);    }    sp<ICameraClient> c = mCameraClient;    if (c != 0) {        mLock.unlock();        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);        if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;    }    disableMsgType(CAMERA_MSG_SHUTTER);    mLock.unlock();}// preview callback - frame buffer updatevoid CameraService::Client::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);    // local copy of the callback flags    int flags = mPreviewCallbackFlag;    // is callback enabled?    if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {        // If the enable bit is off, the copy-out and one-shot bits are ignored        LOG2("frame callback is disabled");        mLock.unlock();        return;    }    // hold a strong pointer to the client    sp<ICameraClient> c = mCameraClient;    // clear callback flags if no client or one-shot mode    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) {        // Is the received frame copied out or not?        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();    }}// picture callback - postview image readyvoid CameraService::Client::handlePostview(const sp<IMemory>& mem) {    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);    sp<ICameraClient> c = mCameraClient;    mLock.unlock();    if (c != 0) {        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);    }}// picture callback - raw image readyvoid CameraService::Client::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 = mCameraClient;    mLock.unlock();    if (c != 0) {        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);    }}// picture callback - compressed picture readyvoid CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {    disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);    sp<ICameraClient> c = mCameraClient;    mLock.unlock();    if (c != 0) {        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);    }}void CameraService::Client::handleGenericNotify(int32_t msgType,    int32_t ext1, int32_t ext2) {    sp<ICameraClient> c = mCameraClient;    mLock.unlock();    if (c != 0) {        c->notifyCallback(msgType, ext1, ext2);    }}void CameraService::Client::handleGenericData(int32_t msgType,    const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {    sp<ICameraClient> c = mCameraClient;    mLock.unlock();    if (c != 0) {        c->dataCallback(msgType, dataPtr, metadata);    }}void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,    int32_t msgType, const sp<IMemory>& dataPtr) {    sp<ICameraClient> c = mCameraClient;    mLock.unlock();    if (c != 0) {        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);    }}void CameraService::Client::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");    // It is necessary to copy out of pmem before sending this to    // the callback. For efficiency, reuse the same MemoryHeapBase    // provided it's big enough. Don't allocate the memory or    // perform the copy if there's no callback.    // hold the preview lock while we grab a reference to the preview buffer    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) {        LOGE("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) {        LOGE("failed to allocate space for frame callback");        mLock.unlock();        return;    }    mLock.unlock();    client->dataCallback(msgType, frame, metadata);}int CameraService::Client::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;        }    }    LOGE("Invalid setDisplayOrientation degrees=%d", degrees);    return -1;}// ----------------------------------------------------------------------------static const int kDumpLockRetries = 50;static const int kDumpLockSleep = 60000;static bool tryLock(Mutex& mutex){    bool locked = false;    for (int i = 0; i < kDumpLockRetries; ++i) {        if (mutex.tryLock() == NO_ERROR) {            locked = true;            break;        }        usleep(kDumpLockSleep);    }    return locked;}status_t CameraService::dump(int fd, const Vector<String16>& args) {    static const char* kDeadlockedString = "CameraService may be deadlocked\n";    const size_t SIZE = 256;    char buffer[SIZE];    String8 result;    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {        snprintf(buffer, SIZE, "Permission Denial: "                "can't dump CameraService from pid=%d, uid=%d\n",                getCallingPid(),                getCallingUid());        result.append(buffer);        write(fd, result.string(), result.size());    } else {        bool locked = tryLock(mServiceLock);        // failed to lock - CameraService is probably deadlocked        if (!locked) {            String8 result(kDeadlockedString);            write(fd, result.string(), result.size());        }        bool hasClient = false;        for (int i = 0; i < mNumberOfCameras; i++) {            sp<Client> client = mClient[i].promote();            if (client == 0) continue;            hasClient = true;            sprintf(buffer, "Client[%d] (%p) PID: %d\n",                    i,                    client->getCameraClient()->asBinder().get(),                    client->mClientPid);            result.append(buffer);            write(fd, result.string(), result.size());            client->mHardware->dump(fd, args);        }        if (!hasClient) {            result.append("No camera client yet.\n");            write(fd, result.string(), result.size());        }        if (locked) mServiceLock.unlock();        // change logging level        int n = args.size();        for (int i = 0; i + 1 < n; i++) {            if (args[i] == String16("-v")) {                String8 levelStr(args[i+1]);                int level = atoi(levelStr.string());                sprintf(buffer, "Set Log Level to %d", level);                result.append(buffer);                setLogLevel(level);            }        }    }    return NO_ERROR;}}; // namespace android

void CameraService::onFirstRef()看这个函数:

void CameraService::onFirstRef(){    BnCameraService::onFirstRef();    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,                (const hw_module_t **)&mModule) < 0) {         LOGE("Could not load camera HAL module");        mNumberOfCameras = 0;     }        else {        mNumberOfCameras = mModule->get_number_of_cameras();//获取camera设备的个数.对应下文中的获取camera个数函数.        if (mNumberOfCameras > MAX_CAMERAS) {            LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",                    mNumberOfCameras, MAX_CAMERAS);            mNumberOfCameras = MAX_CAMERAS;        }            for (int i = 0; i < mNumberOfCameras; i++) {            setCameraFree(i);        }        }        // Read the system property to determine if we have to use the    // AUDIO_STREAM_ENFORCED_AUDIBLE type.    char value[PROPERTY_VALUE_MAX];    property_get("ro.camera.sound.forced", value, "0");    if (strcmp(value, "0") != 0) {         mAudioStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;    } else {        mAudioStreamType = AUDIO_STREAM_MUSIC;    }    }

找了半天也就是它这个函数里边有hw_get_module()这个函数,一看名字就知道是获取hardware的,不找它找谁啊。那么onFirstRef()函数又是何时调用的?
onFirstRef()属于其父类RefBase,该函数在强引用sp新增引用计数时调用,什么意思?就是当 有sp包装的类初始化的时候调用。这里在frameworks/base/services/camera/libcameraservice/CameraService.h 中class CameraService :中有定义

        // these are initialized in the constructor.        sp<CameraService>               mCameraService;  // immutable after constructor        sp<ICameraClient>               mCameraClient;        int                             mCameraId;       // immutable after constructor        int                             mCameraFacing;   // immutable after constructor        pid_t                           mClientPid;        sp<CameraHardwareInterface>     mHardware;       // cleared after disconnect()        int                             mPreviewCallbackFlag;        int                             mOrientation;     // Current display orientation        bool                            mPlayShutterSound;

很明显是这里来初始化的,当然这里不是重点,如果全部都写的话,那基本上就写不完了.
找到了hw_get_module()这个函数,让我们看它的具体实现.
hardware/libhardware/hardware.c
代码如下:

/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <hardware/hardware.h>#include <cutils/properties.h>#include <dlfcn.h>#include <string.h>#include <pthread.h>#include <errno.h>#include <limits.h>#define LOG_TAG "HAL"#include <utils/Log.h>/** Base path of the hal modules */#define HAL_LIBRARY_PATH1 "/system/lib/hw"#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"/** * There are a set of variant filename for modules. The form of the filename * is "<MODULE_ID>.variant.so" so for the led module the Dream variants  * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be: * * led.trout.so * led.msm7k.so * led.ARMV6.so * led.default.so */static const char *variant_keys[] = {    "ro.hardware",  /* This goes first so that it can pick up a different                       file on the emulator. */    "ro.product.board",    "ro.board.platform",    "ro.arch"};static const int HAL_VARIANT_KEYS_COUNT =    (sizeof(variant_keys)/sizeof(variant_keys[0]));/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */static int load(const char *id,        const char *path,        const struct hw_module_t **pHmi){    int status;    void *handle;    struct hw_module_t *hmi;    /*     * load the symbols resolving undefined symbols before     * dlopen returns. Since RTLD_GLOBAL is not or'd in with     * RTLD_NOW the external symbols will not be global     */    handle = dlopen(path, RTLD_NOW);    if (handle == NULL) {        char const *err_str = dlerror();        LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");        status = -EINVAL;        goto done;    }    /* Get the address of the struct hal_module_info. */    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;    hmi = (struct hw_module_t *)dlsym(handle, sym);    if (hmi == NULL) {        LOGE("load: couldn't find symbol %s", sym);        status = -EINVAL;        goto done;    }    /* Check that the id matches */    if (strcmp(id, hmi->id) != 0) {        LOGE("load: id=%s != hmi->id=%s", id, hmi->id);        status = -EINVAL;        goto done;    }    hmi->dso = handle;    /* success */    status = 0;    done:    if (status != 0) {        hmi = NULL;        if (handle != NULL) {            dlclose(handle);            handle = NULL;        }    } else {        LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",                id, path, *pHmi, handle);    }    *pHmi = hmi;    return status;}int hw_get_module_by_class(const char *class_id, const char *inst,                           const struct hw_module_t **module){    int status;    int i;    const struct hw_module_t *hmi = NULL;    char prop[PATH_MAX];    char path[PATH_MAX];    char name[PATH_MAX];    if (inst)        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);    else        strlcpy(name, class_id, PATH_MAX);    /*     * Here we rely on the fact that calling dlopen multiple times on     * the same .so will simply increment a refcount (and not load     * a new copy of the library).     * We also assume that dlopen() is thread-safe.     */    /* Loop through the configuration variants looking for a module */    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {        if (i < HAL_VARIANT_KEYS_COUNT) {            if (property_get(variant_keys[i], prop, NULL) == 0) {                continue;            }            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH2, name, prop);            if (access(path, R_OK) == 0) break;            snprintf(path, sizeof(path), "%s/%s.%s.so",                     HAL_LIBRARY_PATH1, name, prop);            if (access(path, R_OK) == 0) break;        } else {            snprintf(path, sizeof(path), "%s/%s.default.so",                     HAL_LIBRARY_PATH1, name);            if (access(path, R_OK) == 0) break;        }    }    status = -ENOENT;    if (i < HAL_VARIANT_KEYS_COUNT+1) {        /* load the module, if this fails, we're doomed, and we should not try         * to load a different variant. */        status = load(class_id, path, module);    }    return status;}int hw_get_module(const char *id, const struct hw_module_t **module){    return hw_get_module_by_class(id, NULL, module);}

让我们看看它的流程:

int hw_get_module(const char *id, const struct hw_module_t **module)int hw_get_module_by_class(const char *class_id, const char *inst,const struct hw_module_t **module)static int load(const char *id,const char *path,const struct hw_module_t **pHmi)    /* Check that the id matches */if (strcmp(id, hmi->id) != 0) {LOGE("load: id=%s != hmi->id=%s", id, hmi->id);status = -EINVAL;goto done;}...

可以知道,真正来寻找hardware的桥梁是这个ID,在if (strcmp(id, hmi->id) != 0)中,id是frameworks/base/services/camera/libcameraservice/CameraService.cpp中直接赋值的
如下:

    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,                (const hw_module_t **)&mModule) < 0) {        LOGE("Could not load camera HAL module");        mNumberOfCameras = 0;    }

而hmi->id中的这个id很明显是hardware中应该定义的了.
我们看hmi是怎么得来的.

    /* Get the address of the struct hal_module_info. */    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;hmi = (struct hw_module_t *)dlsym(handle, sym);


不用跟踪这个函数就能看出来.hmi一定是从sym中来获取的.所以这里我们也就知道hardware中一定要有这个结构体.这也是实现一个hardware必须要做的事情,这里在hardware.h中也有说明:

/** * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM * and the fields of this data structure must begin with hw_module_t * followed by module specific information. */

即hardware中一定要有这个叫HAL_MODULE_INFO_SYM的结构体.这也是实现一个hardware的第一步:Step-1:实现一个名字为HAL_MODULE_INFO_SYM的结构体,这个结构体必须以hw_module_t开头
好吧,来看一下camera的hardware中是怎么定义的.

看一下common是不是结构体hw_module_t
hardware/libhardware/include/hardware/camera.h

好了,既然hardware要有结构体,那么必须要给他初始化.自定义的函数也得给实现了.
上文注释已经写出来了.这里只是粘贴一下函数的实现.

所以也就自然而然的调用到了实现hardware的第二步,Step-2:
open函数的实现及作用.还是看cameraHAL中对其的实现.

层层包装啊,再看HAL_camera_device_open:
static int HAL_camera_device_open(const struct hw_module_t* module,                                  const char *id,                                  struct hw_device_t** device){    int cameraId = atoi(id);    if (cameraId < 0 || cameraId >= HAL_getNumberOfCameras()) {        return -EINVAL;    }    if (g_cam_device) {//如果系统第二次打开摄像头,则此时g_cam_device已经填充完毕,可以不再填充了.        if (obj(g_cam_device)->getCameraId() == cameraId) {            goto done;        } else {            LOGE("Cannot open camera %d. camera %d is already running!",                    cameraId, obj(g_cam_device)->getCameraId());            return -ENOSYS;        }    }    g_cam_device = (camera_device_t *)malloc(sizeof(camera_device_t));    if (!g_cam_device)        return -ENOMEM;    g_cam_device->common.tag     = HARDWARE_DEVICE_TAG;    g_cam_device->common.version = 1;    g_cam_device->common.module  = const_cast<hw_module_t *>(module);    g_cam_device->common.close   = HAL_camera_device_close;    g_cam_device->ops = &camera_device_ops;    LOGI("%s: open camera %s", __func__, id);    g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device);done:    *device = (hw_device_t *)g_cam_device;    LOGI("%s: opened camera %s (%p)", __func__, id, *device);    return 0;}

这里我们知道.open的作用就是打开指定ID号的摄像头以及填充device结构体,供上层直接调用我们HAL的具体函数比如takePicture(),startPreview()等等.
但是应该怎么去填充这个结构体呢?
还是先看hardware/libhardware/include/hardware/hardware.h怎么说吧.

/** * Every device data structure must begin with hw_device_t * followed by module specific public methods and attributes. */

它说每一个设备都必须以hw_device_t开始,后面跟着methods和attributes.
那我们就在HAL中定义一个static的结构体,按着上边赋值完毕后返回这个指针就成了.看HAL

static camera_device_t *g_cam_device;//定义设备的结构体具体如下.typedef struct camera_device {    hw_device_t common;//以hw_device_t开始    camera_device_ops_t *ops;//紧跟着methods    void *priv;                             //私有数据.} camera_device_t;

看看是怎么填充的:
g_cam_device->common.tag     = HARDWARE_DEVICE_TAG;//hardware.h中定义的.具体设备tag必须这样定义.g_cam_device->common.module  = const_cast<hw_module_t *>(module);//和module模块建立联系g_cam_device->common.close   = HAL_camera_device_close;//设备关闭的函数g_cam_device->ops = &camera_device_ops;// 这个里边包含的就是那些操作摄像头所需要的具体实现.讲HAL的运行流程时细讲.g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device);//真正实现hardware初始化摄像头的函数,讲HAL的运行流程时细讲.

这里先看看camera_device_ops的具体实现,也牵扯到了HAL实现的第三步,Step-3:具体设备的函数实现.
#define SET_METHOD(m) m : HAL_camera_device_##m//相当于m : HAL_camera_device_mstatic camera_device_ops_t camera_device_ops = {        SET_METHOD(set_preview_window),//展开后相当于set_preview_window : HAL_camera_device_set_preview_window,即HAL_camera_device_set_preview_window是set_preview_window的具体实现        SET_METHOD(set_callbacks),//展开后相当于set_callbacks : HAL_camera_device_set_callbacks        SET_METHOD(enable_msg_type),//同上        SET_METHOD(disable_msg_type),        SET_METHOD(msg_type_enabled),        SET_METHOD(start_preview),        SET_METHOD(stop_preview),        SET_METHOD(preview_enabled),        SET_METHOD(store_meta_data_in_buffers),        SET_METHOD(start_recording),        SET_METHOD(stop_recording),        SET_METHOD(recording_enabled),        SET_METHOD(release_recording_frame),        SET_METHOD(auto_focus),        SET_METHOD(cancel_auto_focus),        SET_METHOD(take_picture),        SET_METHOD(cancel_picture),        SET_METHOD(set_parameters),        SET_METHOD(get_parameters),        SET_METHOD(put_parameters),        SET_METHOD(send_command),        SET_METHOD(release),        SET_METHOD(dump),};

先不说HAL中调用函数的具体实现,看看是service怎么调用的.
以start_preview为例.

camera.start_preview()//应用程序public native final void startPreview();       //此处调用JNI frameworks/base/core/java/android/hardware/Camera.javastatic void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)//JNI frameworks/base/core/jni/android_hardware_Camera.cppsp<Camera> camera = get_native_camera(env, thiz, NULL);//获取cameraClientframeworks/base/core/jni/android_hardware_Camera.cppcamera->startPreview();//执行cameraClient的函数frameworks/base/libs/camera/Camera.cpp.status_t CameraService::Client::startPreview();//service中函数的实现frameworks/base/services/camera/libcameraservice/CameraService.cppstatus_t CameraService::Client::startCameraMode(camera_mode mode) //service中的调用frameworks/base/services/camera/libcameraservice/CameraService.cppstatus_t CameraService::Client::startPreviewMode()//service最终调用frameworks/base/services/camera/libcameraservice/CameraService.cpp status_t startPreview()//调用到hardware的接口frameworks/base/services/camera/libcameraservice/CameraHardwareInterface.hmDevice->ops->start_preview(mDevice);//调用到HAL层的start_preview具体实现HAL_camera_device_start_preview.   device/magiclab/common/libcamera/SecCameraHWInterface_zoom.cpp

OK,函数调用到这里也就完成了应用程序调用hardware内具体设备函数的流程.HAL的实现其实也就是实现上面每个函数.使它们协同合作而已.

0 0
原创粉丝点击