1. 程式人生 > >Android 5.0 Camera系統原始碼分析(2):Camera開啟流程

Android 5.0 Camera系統原始碼分析(2):Camera開啟流程

1. 前言

本文將分析android系統原始碼,從frameworks層到hal層,暫不涉及app層和kernel層。由於某些函式比較複雜,在貼出程式碼時會適當對其進行簡化。本文屬於自己對原始碼的總結,僅僅是貫穿程式碼流程,不會深入分析各個細節。歡迎聯絡討論,QQ:1026656828

2. app層

從apk開始,簡單列出各個入口函式

private void initCamera()
{
    Camera mCamera = Camera.open();
    Camera.Parameters mParameters = mCamera.getParameters();
    mParameters.setPictureFormat(PixelFormat.JPEG);
    mCamera.setParameters(mParameters);
    mCamera.setPreviewDisplay(mSurfaceHolder);
    mCamera.startPreview();
    mCamera.takePicture(null, null , mJpegCallback);
}

3. frameworks層

這裡將重點介紹Camera.open函式,其餘函式將在後續博文分析。先來看看Camera.open函式在frameworks層的實現,程式碼路徑為: frameworks/base/core/java/android/hardware/Camera.java
public static Camera open() {
    if (!isPermissionGranted()) {
        return null;
    }    
    int numberOfCameras = getNumberOfCameras();
    CameraInfo cameraInfo = new CameraInfo();
    for (int i = 0; i < numberOfCameras; i++) {
        getCameraInfo(i, cameraInfo);
        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
            return new Camera(i);
        }    
    }    
    return null;
}    
第5行, 通過getNumberOfCameras函式來獲取Camera的個數。從上一篇博文CameraService的啟動流程可以看出,這個資訊儲存在CameraService中。
第10行,需重點關注,構造一個Camera物件,並將它返回給app層。

3.1 getNumberOfCameras函式分析

getNumberOfCameras函式進入到CameraService獲取Camera個數的流程如下:


Camera.java呼叫的getNumberOfCameras函式是一個JNI介面,對應的函式是android_hardware_Camera.cpp裡的android_hardware_Camera_getNumberOfCameras函式

static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz)
{
    return Camera::getNumberOfCameras();
}
這裡只是簡單呼叫了Camera.cpp的getNumberOfCameras函式,Camera繼承了CameraBase,該函式由它實現
template <typename TCam, typename TCamTraits>
int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
    const sp<ICameraService> cs = getCameraService();
    return cs->getNumberOfCameras();
}
第3行, getCameraService函式用來獲取ICameraService的Bp端,程式碼實現如下
const char* kCameraServiceName = "media.camera";

template <typename TCam, typename TCamTraits>
const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
{   
    if (gCameraService.get() == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        binder = sm->getService(String16(kCameraServiceName));       
        gCameraService = interface_cast<ICameraService>(binder);
    }
    return gCameraService;
}

Android的Binder通訊機制

第1行, 獲取的ServiceName為"media.camera",結合上一篇博文CameraService的啟動流程可以看出Bn端的實現在CameraService.cpp

回到之前的getNumberOfCameras函式,在獲取到ICameraService的Bp端後,就可以開始和Bn端通訊了。在第4行,當呼叫cs->getNumberOfCameras函式時,將會進入CameraService.cpp的getNumberOfCameras函式

int32_t CameraService::getNumberOfCameras() {
    return mNumberOfCameras;
}
程式碼很簡單,返回上一篇博文講到的,千辛萬苦從hal層拿到的資料

3.2 Camera建構函式分析

回到最開始的Camera.open函式,在第10行,將會構造一個Camera物件
private int cameraInitVersion(int cameraId, int halVersion) {
    ......
    Looper looper;
    if ((looper = Looper.myLooper()) != null) {
        mEventHandler = new EventHandler(this, looper);
    } else if ((looper = Looper.getMainLooper()) != null) {
        mEventHandler = new EventHandler(this, looper);
    } else {
        mEventHandler = null;
    }

    String packageName = ActivityThread.currentPackageName();

    return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
}

private int cameraInitNormal(int cameraId) {
    return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}

Camera(int cameraId) {
    int err = cameraInitNormal(cameraId);
    ......
}
第14行, native_setup同樣是個JNI介面,對應android_hardware_Camera.cpp裡的android_hardware_Camera_native_setup函式
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
    camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID);

#if 1 // defined(MTK_CAMERA_BSP_SUPPORT)
    sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera);
#else
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
#endif
}
第4行, 呼叫了Camera.cpp的connect函式,同時返回一個Camera物件,儲存在JNICameraContext當中
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
        int clientUid)
{
    return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}

先來看看Camera和CameraBase的類定義

/* ---------- Camera.h ---------- */
template <>
struct CameraTraits<Camera>
{
    ......
    static TCamConnectService fnConnectService;
};

class Camera : public CameraBase<Camera>
{
    ......
}
/* -------- CameraBase.h -------- */
<pre name="code" class="cpp">template <typename TCam>
struct CameraTraits {
};

template <typename TCam, typename TCamTraits = CameraTraits<TCam>>
class CameraBase
{
    ......
    typedef CameraBase<TCam>    CameraBaseT;
}
這裡使用了C++模版,其實就是呼叫CameraBase::connect函式
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService = &ICameraService::connect;

template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
                                               const String16& clientPackageName,
                                               int clientUid)
{
    sp<TCam> c = new TCam(cameraId);
    sp<TCamCallbacks> cl = c;

    const sp<ICameraService>& cs = getCameraService();
    if (cs != 0) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                             /*out*/ c->mCamera);
    }

    return c;
}

第1行, 將CameraTraits::fnConnectService賦為ICameraService::connect

第7行, 構造一個Camera物件

第10行, 獲取ICameraService的Bp端

第13行, 從上面的解釋可以看出,實際就是呼叫CameraService.cpp的connect函式

第17行, 將Camera物件返回給JNI層

status_t CameraService::connectHelperLocked(
        /*out*/
        sp<Client>& client,
        /*in*/
        const sp<ICameraClient>& cameraClient,
        int cameraId,
        const String16& clientPackageName,
        int clientUid,
        int callingPid,
        int halVersion,
        bool legacyMode) {
    ......
    int deviceVersion = getDeviceVersion(cameraId, &facing);

    switch(deviceVersion) {
        case CAMERA_DEVICE_API_VERSION_1_0:
            client = new CameraClient(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid(), legacyMode);
            break;
        case CAMERA_DEVICE_API_VERSION_2_0:
        case CAMERA_DEVICE_API_VERSION_2_1:
        case CAMERA_DEVICE_API_VERSION_3_0:
        case CAMERA_DEVICE_API_VERSION_3_1:
        case CAMERA_DEVICE_API_VERSION_3_2:
            client = new Camera2Client(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid(), legacyMode);
            break;
    }

    status_t status = connectFinishUnsafe(client, client->getRemote());
    mClient[cameraId] = client;
}

status_t CameraService::connect(
        const sp<ICameraClient>& cameraClient,
        int cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<ICamera>& device) {
    ......
    sp<Client> client;
    status = connectHelperLocked(/*out*/client,
                                 cameraClient,
                                 cameraId,
                                 clientPackageName,
                                 clientUid,
                                 callingPid);
    device = client;
    return OK;
}

忽略細節之後connect函式就只是呼叫connectHelperLocked函式

第13行, 獲取api版本資訊,這個函式比較簡單,不細說。這裡的版本為CAMERA_DEVICE_API_VERSION_1_0

第15-30行, 根據不同的api版本選擇構造CameraClient或Camera2Client,這裡是CameraClient

第32行, 呼叫connectFinishUnsafe函式,實現如下
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
                                            const sp<IBinder>& remoteCallback) {
    status_t status = client->initialize(mModule);
}
這裡的client就是上一個函式的CameraClient,mModule就是在上一篇博文CameraService的啟動流程裡提到的hal層的介面
status_t CameraClient::initialize(camera_module_t *module) {
    mHardware = new CameraHardwareInterface(camera_device_name);
    res = mHardware->initialize(&module->common);
    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
            (void *)(uintptr_t)mCameraId);
    return OK;
}
構造一個CameraHardwareInterface物件,並呼叫它的initalize函式,直接看initalize函式
status_t initialize(hw_module_t *module)
{
    module->methods->open(module, mName.string(), (hw_device_t **)&mDevice)
    initHalPreviewWindow();
}
第4行, 從這裡進入到了hal層,hal層主要對Camera硬體進行初始化,並將操作集儲存在mDevice當中

4. hal層-基於MTK平臺

hal層對Camera硬體進行初始化以及返回Device操作集的流程如下


4.1 open函式分析

這裡再看一次module的定義

static
hw_module_methods_t*
get_module_methods()
{
    static
    hw_module_methods_t
    _methods =
    {
        open: open_device
    };

    return  &_methods;
}

static
camera_module
get_camera_module()
{
    camera_module module = {
        common:{
             tag                    : HARDWARE_MODULE_TAG,
             #if (PLATFORM_SDK_VERSION >= 21)
             module_api_version     : CAMERA_MODULE_API_VERSION_2_3,
             #else
             module_api_version     : CAMERA_DEVICE_API_VERSION_1_0,
             #endif
             hal_api_version        : HARDWARE_HAL_API_VERSION,
             id                     : CAMERA_HARDWARE_MODULE_ID,
             name                   : "MediaTek Camera Module",
             author                 : "MediaTek",
             methods                : get_module_methods(),
             dso                    : NULL,
             reserved               : {0},
        },
        get_number_of_cameras       : get_number_of_cameras,
        get_camera_info             : get_camera_info,
        set_callbacks               : set_callbacks,
        get_vendor_tag_ops          : get_vendor_tag_ops,
        #if (PLATFORM_SDK_VERSION >= 21)
        open_legacy                 : open_legacy,
        #endif
        reserved                    : {0},
    };
    return  module;
};

通過module->methods獲取到的函式為open_device,

static
int
open_device(hw_module_t const* module, const char* name, hw_device_t** device)
{
    return  NSCam::getCamDeviceManager()->open(device, module, name);
}
CamDeviceManagerImp 繼承了 CamDeviceManagerBase。這裡直接呼叫了CamDeviceManagerBase的open()
status_t
CamDeviceManagerBase::
openDeviceLocked(
    hw_device_t** device,
    hw_module_t const* module,
    int32_t const i4OpenId,
    uint32_t device_version
)
{
    // [2] get platform
    IPlatform*const pPlatform = getPlatform();
    pDevice = pPlatform->createCam1Device(s8ClientAppMode.string(), i4OpenId);
    *device = const_cast<hw_device_t*>(pDevice->get_hw_device());
}

status_t
CamDeviceManagerBase::
open(
    hw_device_t** device,
    hw_module_t const* module,
    char const* name,
    uint32_t device_version
)
{
    return  openDeviceLocked(device, module, i4OpenId, device_version);
}

第11行, getPlatform函式用來載入libcam_platform.so,並獲取PlatformEntry介面

第12行, 構造一個Cam1Device物件,並呼叫它的init函式

第13行, 獲取camera device的操作集

4.2 getPlatform函式分析

static PlatformEntry g_PlatformEntry;

IPlatform*
getHandleToPlatform()
{
    return &g_PlatformEntry;
}

IPlatform*
CamDeviceManagerBase::
getPlatform()
{
    char const szModulePath[] = "libcam_platform.so";
    char const szEntrySymbol[] = "getHandleToPlatform";
    void* pfnEntry = NULL;
    IPlatform* pIPlatform = NULL;

    mpLibPlatform = ::dlopen(szModulePath, RTLD_NOW);
    pfnEntry = ::dlsym(mpLibPlatform, szEntrySymbol);
    pIPlatform = reinterpret_cast<IPlatform*(*)()>(pfnEntry)();
    gIPlatform = pIPlatform;

    return gIPlatform;
}

第18行, 載入libcam_platform.so

第19 20行, 獲取getHandleToPlatform函式入口,並呼叫,最後返回PlatformEntry介面

4.3 pPlatform->createCam1Device函式分析

NSCam::Cam1Device*
createCam1Device(
    String8 const   s8ClientAppMode,
    int32_t const   i4OpenId
)
{
    NSCam::Cam1Device* pdev = NULL;

    String8 const s8LibPath = String8::format("libcam.device1.so");
    void *handle = ::dlopen(s8LibPath.string(), RTLD_GLOBAL);

    String8 const s8CamDeviceInstFactory = String8::format("createCam1Device_Default");
    void* pCreateInstance = ::dlsym(handle, s8CamDeviceInstFactory.string());
    pdev = reinterpret_cast<NSCam::Cam1Device* (*)(String8 const&, int32_t const)>
                    (pCreateInstance)(s8ClientAppMode, i4OpenId);

    pdev->initialize();
}

ICamDevice*
PlatformEntry::
createCam1Device( 
    char const*         szClientAppMode,
    int32_t const       i4OpenId
)
{
    return  ::createCam1Device(String8(szClientAppMode), i4OpenId);
}

pPlatform->createCam1Device函式呼叫的是Cam1DeviceFactory.cpp裡的createCam1Device函式

第10行, 載入libcam.device1.so

第12-15行, 獲取createCam1Device_Default函式入口並呼叫

第17行, Cam1Device初始化

先來看createCam1Device_Default函式,以及類的繼承關係

class Cam1DeviceBase : public Cam1Device
{
}

class DefaultCam1Device : public Cam1DeviceBase
{
}

NSCam::Cam1Device*
createCam1Device_Default(
    String8 const&          rDevName, 
    int32_t const           i4OpenId
)
{
    return new DefaultCam1Device(rDevName, i4OpenId);
}
接著看DefaultCam1Device的建構函式
Cam1Device::
Cam1Device()
{   
    ::memset(&mDevice, 0, sizeof(mDevice));
    mDevice.priv    = this;
    mDevice.common  = gHwDevice;
    mDevice.ops     = (camera_device_ops*)&mDeviceOps;
    mDeviceOps      = gCameraDevOps;
}  

Cam1DeviceBase::
Cam1DeviceBase(
    String8 const&          rDevName,
    int32_t const           i4OpenId
)
    : Cam1Device()
    , mDevName(rDevName)
    , mi4OpenId(i4OpenId)
{
    MY_LOGD("");
}

DefaultCam1Device::
DefaultCam1Device(
    String8 const&          rDevName,
    int32_t const           i4OpenId
)
    : Cam1DeviceBase(rDevName, i4OpenId)
{
} 
刪除了一些暫不關注的程式碼,DefaultCam1Device的建構函式會不斷呼叫父類的建構函式,需要關注的是它的父類Cam1Device的建構函式。其中的gCameraDevOps結構體很重要,是Camera Device的操作集,預覽、拍照、錄影都是通過它來操作,來看下它的定義
static mtk_camera_device_ops const
gCameraDevOps =
{
    #define OPS(name) name: camera_##name

    {
        OPS(set_preview_window),
        OPS(set_callbacks), 
        OPS(enable_msg_type),
        OPS(disable_msg_type),
        OPS(msg_type_enabled), 
        OPS(start_preview),
        OPS(stop_preview), 
        OPS(preview_enabled), 
        OPS(store_meta_data_in_buffers),
        OPS(start_recording), 
        OPS(stop_recording), 
        OPS(recording_enabled),
        OPS(release_recording_frame),
        OPS(auto_focus), 
        OPS(cancel_auto_focus),
        OPS(take_picture),
        OPS(cancel_picture), 
        OPS(set_parameters), 
        OPS(get_parameters), 
        OPS(put_parameters), 
        OPS(send_command),
        OPS(release),
        OPS(dump)
    },
    OPS(mtk_set_callbacks),

    #undef  OPS
};

回到createCam1Device函式,最後呼叫了pdev->initialize函式,這個函式過程比較複雜,在它的父類Cam1DeviceBase中實現

bool
DefaultCam1Device::
onInit()
{
    //  (1) power on sensor
    if( pthread_create(&mThreadHandle, NULL, doThreadInit, this) != 0 )
    {
        goto lbExit;
    }

    //  (2) Open 3A
    mpHal3a = NS3A::IHal3A::createInstance(
            NS3A::IHal3A::E_Camera_1,
            getOpenId(),
            LOG_TAG);

    //  (3) Init Base.
    if  ( ! Cam1DeviceBase::onInit() )
    {
        goto lbExit;
    }
}

status_t
Cam1DeviceBase::
initialize()
{
    onInit();
    return  OK;  
}
initialize函式只是簡單的回調了onInit函式,如註釋所示,主要做了3件事情。其中(2)和(3)主要是初始化3A和CamClient,這兩個這裡暫時不會關注,所以暫時不進行分析。重點關注(1),也就是doThreadInit函式
bool
DefaultCam1Device::
powerOnSensor()
{
    IHalSensorList* pHalSensorList = IHalSensorList::get();
    mpHalSensor = pHalSensorList->createSensor(USER_NAME, getOpenId());
    sensorIdx = getOpenId();
    if( !mpHalSensor->powerOn(USER_NAME, 1, &sensorIdx) )
    {
        MY_LOGE("sensor power on failed: %d", sensorIdx);
        goto lbExit;
    }
    ......
}

void*   
DefaultCam1Device::
doThreadInit(void* arg)
{
    DefaultCam1Device* pSelf = reinterpret_cast<DefaultCam1Device*>(arg);
    pSelf->mRet = pSelf->powerOnSensor();
    pthread_exit(NULL);
    return NULL;
}
doThreadInit函式只是回撥自身的了powerOnSensor函式,而powerOnSensor函式先呼叫pHalSensorList->createSensor函式建立一個HalSensor例項,然後再呼叫它的PowerOn函式來開始相關的硬體操作,來看powerOn的實現
MBOOL
HalSensor::
powerOn(
    char const* szCallerName,
    MUINT const uCountOfIndex,
    MUINT const*pArrayOfIndex
)
{
    ......
    ret = mpSeninfDrv->init();
    ret = mpSensorDrv->init(sensorDev);
    ret = setTgPhase(sensorDev, pcEn);
    ret = setSensorIODrivingCurrent(sensorDev);
    ret = mpSensorDrv->open(sensorDev);
    ......
}
powerOn函式比較長,這裡暫時只關注SensorDrv的init和open函式
MINT32
ImgSensorDrv::init(MINT32 sensorIdx)
{
    m_fdSensor = ::open("dev/kd_camera_hw", O_RDWR);

    //set driver
    ret = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,sensorDrvInit);

    //init resolution
    pSensorResInfo[0] = &m_SenosrResInfo[0];
    pSensorResInfo[1] = &m_SenosrResInfo[1];
    ret = getResolution(pSensorResInfo);

    if(SENSOR_MAIN & sensorIdx ) {
        sensorDevId = SENSOR_MAIN;

        FeatureParaLen = sizeof(MUINTPTR);
        ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ,  (MUINT8*)&FeaturePara32,(MUINT32*)&FeatureParaLen);

        FeatureParaLen = sizeof(pFeaturePara16);
        ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PERIOD,  (MUINT8*)pFeaturePara16,(MUINT32*)&FeatureParaLen);
    }
    ......
}

MINT32
ImgSensorDrv::open(MINT32 sensorIdx)
{
    MINT32 err = SENSOR_NO_ERROR;

    ......
    err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_CURRENT_SENSOR, &sensorIdx);
    err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_OPEN);

    return err;
}
這兩個函式邏輯比較簡單,就是通過ioctl進入到kernel層來對sensor硬體進行初始化和獲取硬體相關的資訊。kernel層的程式碼暫不分析

4.4 get_hw_device函式分析

回到4.1的openDeviceLocked函式,最後呼叫了pDevice->get_hw_device函式,並將它的返回值賦給*device

class Cam1Device : public ICamDevice
{
    virtual hw_device_t const*      get_hw_device() const { return &mDevice.common; }
}

這個函式很簡單,就是獲取4.3裡面提到的mDevice,這個mDevice最終將被儲存在frameworks層的CameraHardwareInterface.h的mDevice變數當中,以便日後訪問

5. 總結

Camera開啟流程的重點工作在4.3和4.4章節,也就是對Camera硬體進行初始化和將gCameraDevOps操作集返回給frameworks層。

相關推薦

Android 5.0 Camera系統原始碼分析(2)Camera開啟流程

1. 前言 本文將分析android系統原始碼,從frameworks層到hal層,暫不涉及app層和kernel層。由於某些函式比較複雜,在貼出程式碼時會適當對其進行簡化。本文屬於自己對原始碼的總結,僅僅是貫穿程式碼流程,不會深入分析各個細節。歡迎聯絡討論,QQ:1026

Android 5.0 Camera系統原始碼分析(4)Camera預覽流程資料流

1. 前言 上一篇講了怎麼讓Camera進入預覽模式,提到了DisplayClient負責顯示影象資料,而CamAdapter負責提供影象資料,這裡主要記錄了CamAdapter怎麼獲取影象,然後DisplayClient怎麼將影象顯示在螢幕上。 2.

Android 5.0 Camera系統原始碼分析(3)Camera預覽流程控制流

1. 前言 本文分析的是Android系統原始碼,從frameworks層到hal層,記錄了Camera進入預覽模式的重點程式碼,主要為控制流程的程式碼,有關影象buffer的傳遞暫不涉及,硬體平臺基於mt6735。由於某些函式比較複雜,在貼出程式碼時會適當對

Android 5.0 Usb除錯攔截分析及修改

當我們除錯安卓機器時,第一次插上usb線,會彈出一個授權的對話方塊,(前提是打開了usb除錯功能)點選確認,才會允許除錯. 如果我們想機器預設就可以除錯該怎麼做呢? 如果我們想動態攔截,需要使用者輸入帳號密碼,才確認是否可以除錯,該怎麼做呢?或者只是單純的想改變這個不好看

Android應用程式啟動過程原始碼分析(2)

Step 9. ActivityStack.startActivityUncheckedLocked         這個函式定義在frameworks/base/services/java/com/android/server/am/ActivityStack.java檔案中: view plain pu

coreutils4.5.1 expr.c 原始碼分析2

今天又開始讀程式碼。前段時間看演算法分析相關的書,蒐集了不少演算法相關書籍,感覺自己功力太淺,還是讀讀原始碼吧。好在,讀小說,養成了快速讀書的好習慣,再加不求甚解,把快速+不求甚解利用到讀程式碼上,感覺也很有意思。 今天重點翻了翻expr.c,這個原始碼,很有特色,首先啟用debug功能。 文件中有

android 5.0 64bit系統載入庫檔案失敗問題淺析

最近公司的一個專案使用android 5.0 64 bit平臺,相對以前版本,除了android 5.0 有很大變動之外,64 bit系統和32 bit系統也存在很多差異性。 目前碰到的問題就是以前在32位上的so庫檔案,到64 位系統上不能載入的問題。首先來看一下相關lo

Android 7.0 Gallery相簿原始碼分析8

在Android 7.0 Gallery相簿原始碼分析3 - 資料載入及顯示流程一文最後講了AlbumSetSlidingWindow的onContentChanged方法,專輯縮圖和縮圖下面的label的載入就是在此方法中完成的 public

React Native之Android 5.0以下系統WebView訪問https頁面變成空白頁

在我們的React Native專案中,需要開發一個tab頁面專門配置三方h5連結,供使用者瀏覽。自動化測試:Android 5.0以下系統此tab頁面為空白頁面。看效果: 而我們去檢視這個三方的

Android 7.0 Gallery相簿原始碼分析4

上篇文章講了初始化View時會例項化一個SlotView並監聽其事件,至於它是怎麼實現的,用的是Android自帶的GestureDetector。 GestureDetector是Android自帶的用來監聽各種使用者手勢的的一個類,比如監聽單擊、雙擊和

android 5.0以下系統Intent傳遞序列化物件的bug

    專案中使用外掛框架,當外掛在Intent中傳遞Serializable物件時,在android 5.0以下系統上會出現 E/InstrumentationHacker(25176): Parcelable encounteredClassNotFoundExce

Android 5.0核心和原始碼學習(3)——SystemServer啟動了什麼服務?

/**入口 * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); } /**

LAV Filter 原始碼分析 2 LAV Splitter

LAV Filter 中最著名的就是 LAV Splitter,支援Matroska /WebM,MPEG-TS/PS,MP4/MOV,FLV,OGM / OGG,AVI等其他格式,廣泛存在於各種視訊播放器(暴風影音這類的)之中。本文分析一下它的原始碼。在分析之前,先看看它是

Linux-0.11核心原始碼分析系列記憶體管理get_free_page()函式分析

Linux-0.11記憶體管理模組是原始碼中比較難以理解的部分,現在把筆者個人的理解發表 先發Linux-0.11核心記憶體管理get_free_page()函式分析有時間再寫其他函式或者檔案的:) /*  *Author  : DavidLin  *Date    :

SpringMVC原始碼分析2SpringMVC設計理念與DispatcherServlet

轉自:https://my.oschina.net/lichhao/blog SpringMVC簡介 SpringMVC作為Struts2之後異軍突起的一個表現層框架,正越來越流行,相信javaee的開發者們就算沒使用過SpringMVC,也應該對其略有耳聞。我試圖通過對SpringMVC的設計思想和原始碼實

WebRTC原始碼分析視訊處理流程

 文字介紹視訊的處理流程。圖1中顯示了兩路視訊會話視訊訊號流過程。 圖1 視訊流程示意圖 以一路視訊會話為例,主要分為以下幾個執行緒: 1)視訊源產生執行緒:Camera生產視訊畫面,封裝成視訊幀,以一定幀率投遞到下一個模組。; 2)採集執行緒:由Capturer負責採集視訊幀,並對視訊幀進行一定處理,如

Android Camera 系統架構原始碼分析(2)---->Camera的startPreview和setPreviewCallback

Camera startPreview流程 上接第一篇,這個過程的主要任務是,如何讀取資料的,讀取的資料是什麼格式,最好能知道是如何去預覽的 上層APP呼叫的是Camera.java的startPreview();,下面列出startPreview的呼叫流程 //Camera

Android 8.0系統原始碼分析--Binder程序間通訊(一)

 開始我們的沉澱之路,老羅的書中第二章講的是Android HAL層的知識,而且直接自己實現了一個虛擬的freg驅動程式,後面的幾節是分別從native、java層如何訪問這個虛擬的驅動程式介面,我這裡沒有這樣的環境,所以就不分析這節了,第三章的智慧指標我對比8.0系統原

Android 8.0系統原始碼分析--openCamera(HAL)啟動過程原始碼分析

     前面我們詳細分析了從應用層呼叫CameraManager的openCamera的方法來開啟相機的邏輯,上次的分析我們來到了CameraServer程序當中,但是還沒有真正看到open操作裝置節點來實現真正開啟的邏輯,遺留的問題也就是從frameworks\av\se

Android 8.0系統原始碼分析--Activity的視窗Window物件新增過程原始碼分析

     這節我們來看一下Activity的視窗Window物件的建立過程,Activity作為Android提供的四大元件之首,我們之所以能非常簡單的使用它,就是因為它的建立過程中,framework為我們作了大量的初始化工作,包括它的視窗Window、視訊記憶體Surf