zoukankan      html  css  js  c++  java
  • <Android Framework 之路> N版本 Framework Camera的一些改动

    前言

    Android N版本最近发布,Nougat是否好吃,不得而知,慢慢看下~
    感谢AndroidXref这个网站,给开发者提供了大量的便捷~以后学习Android就靠它了。


    N版本上Framework关于Camera的一些改动

    CameraServer

    N版本之前,CameraService是运行在MediaServer下的,这样存在一定的问题,因为MediaServer下同时还运行这其他的多媒体内容
    M版本

    /frameworks/av/media/mediaserver/main_mediaserver.cpp

    int main(int argc __unused, char** argv)
    {
        signal(SIGPIPE, SIG_IGN);
        char value[PROPERTY_VALUE_MAX];
        bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
        pid_t childPid;
        // FIXME The advantage of making the process containing media.log service the parent process of
        // the process that contains all the other real services, is that it allows us to collect more
        // detailed information such as signal numbers, stop and continue, resource usage, etc.
        // But it is also more complex.  Consider replacing this by independent processes, and using
        // binder on death notification instead.
        if (doLog && (childPid = fork()) != 0) {
            // media.log service
            //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0);
            // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack
            strcpy(argv[0], "media.log");
            sp<ProcessState> proc(ProcessState::self());
            MediaLogService::instantiate();
            ProcessState::self()->startThreadPool();
            for (;;) {
                siginfo_t info;
                int ret = waitid(P_PID, childPid, &info, WEXITED | WSTOPPED | WCONTINUED);
                if (ret == EINTR) {
                    continue;
                }
                if (ret < 0) {
                    break;
                }
                char buffer[32];
                const char *code;
                switch (info.si_code) {
                case CLD_EXITED:
                    code = "CLD_EXITED";
                    break;
                case CLD_KILLED:
                    code = "CLD_KILLED";
                    break;
                case CLD_DUMPED:
                    code = "CLD_DUMPED";
                    break;
                case CLD_STOPPED:
                    code = "CLD_STOPPED";
                    break;
                case CLD_TRAPPED:
                    code = "CLD_TRAPPED";
                    break;
                case CLD_CONTINUED:
                    code = "CLD_CONTINUED";
                    break;
                default:
                    snprintf(buffer, sizeof(buffer), "unknown (%d)", info.si_code);
                    code = buffer;
                    break;
                }
                struct rusage usage;
                getrusage(RUSAGE_CHILDREN, &usage);
                ALOG(LOG_ERROR, "media.log", "pid %d status %d code %s user %ld.%03lds sys %ld.%03lds",
                        info.si_pid, info.si_status, code,
                        usage.ru_utime.tv_sec, usage.ru_utime.tv_usec / 1000,
                        usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 1000);
                sp<IServiceManager> sm = defaultServiceManager();
                sp<IBinder> binder = sm->getService(String16("media.log"));
                if (binder != 0) {
                    Vector<String16> args;
                    binder->dump(-1, args);
                }
                switch (info.si_code) {
                case CLD_EXITED:
                case CLD_KILLED:
                case CLD_DUMPED: {
                    ALOG(LOG_INFO, "media.log", "exiting");
                    _exit(0);
                    // not reached
                    }
                default:
                    break;
                }
            }
        } else {
            // all other services
            if (doLog) {
                prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me also
                setpgid(0, 0);                      // but if I die first, don't kill my parent
            }
            InitializeIcuOrDie();
            sp<ProcessState> proc(ProcessState::self());
            sp<IServiceManager> sm = defaultServiceManager();
            ALOGI("ServiceManager: %p", sm.get());
            AudioFlinger::instantiate();
            MediaPlayerService::instantiate();
            ResourceManagerService::instantiate();
            CameraService::instantiate();
            AudioPolicyService::instantiate();
            SoundTriggerHwService::instantiate();
            RadioService::instantiate();
            registerExtensions();
            ProcessState::self()->startThreadPool();
            IPCThreadState::self()->joinThreadPool();
        }
    }

    可以看到AudioFlinger,MediaPlayerService, ResourceManagerService,CameraService,AudioPolicyService,SoundTriggerHwService,RadioService等都是运行在这个进程下面的,这样就存在一个问题,假如说其他任何一个服务因为某些原因挂掉了,整个MediaServer将会重启,而这个重启的过程中,倘若相机正在操作,就会出现相机突然挂掉的问题。

    N版本
    /frameworks/av/media/mediaserver/main_mediaserver.cpp

    int main(int argc __unused, char **argv __unused)
    {
        signal(SIGPIPE, SIG_IGN);
    
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm(defaultServiceManager());
        ALOGI("ServiceManager: %p", sm.get());
        InitializeIcuOrDie();
        MediaPlayerService::instantiate();
        ResourceManagerService::instantiate();
        registerExtensions();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }

    有没有觉得少了很多,不仅CameraService被抽离出去了,还有一些内容好像也被抽离出去了。
    在N版本的工程中多出来一个文件夹
    /frameworks/av/camera/cameraserver/
    这里写图片描述
    说明CameraServer是独立于MediaServer的单独的进程,执行PS操作你讲看到独立的Camera进程。

    #define LOG_TAG "cameraserver"
    //#define LOG_NDEBUG 0
    
    // from LOCAL_C_INCLUDES
    #include "CameraService.h"
    
    using namespace android;
    
    int main(int argc __unused, char** argv __unused)
    {
        signal(SIGPIPE, SIG_IGN);
    
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        ALOGI("ServiceManager: %p", sm.get());
        CameraService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }

    初始化的过程并没有变化,只是单纯的将它独立出来而已。
    那么问题来了,CameraService何时启动?
    看到cameraserver.rc文件,

    service cameraserver /system/bin/cameraserver
        class main
        user cameraserver
        group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
        ioprio rt 4
        writepid /dev/cpuset/foreground/tasks

    也就是说只要加载了cameraserver.rc文件,服务就开始启动了,就会往main_cameraserer.cpp的入口函数中执行,因为mk文件中定义了这个模块为cameraserver

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= 
        main_cameraserver.cpp//源文件
    
    LOCAL_SHARED_LIBRARIES := //依赖库
        libcameraservice 
        libcutils 
        libutils 
        libbinder 
        libcamera_client
    
    LOCAL_MODULE:= cameraserver//模块名
    LOCAL_32_BIT_ONLY := true//只支持32位
    
    LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter//一些编译条件,N版本在编译这一块也作出了很大的改动,有机会再研究下
    
    LOCAL_INIT_RC := cameraserver.rc
    
    include $(BUILD_EXECUTABLE)//执行文件

    寻找,谁调用的camearserver.rc ????????????????
    首先我们要看这个文件编译出来之后放在手机的什么位置
    /build/core/base_rules.mk

    # Rule to install the module's companion init.rc.
    my_init_rc := $(LOCAL_INIT_RC_$(my_32_64_bit_suffix))
    my_init_rc_src :=
    my_init_rc_installed :=
    ifndef my_init_rc
    my_init_rc := $(LOCAL_INIT_RC)
    # Make sure we don't define the rule twice in multilib module.
    LOCAL_INIT_RC :=
    endif
    ifdef my_init_rc
    my_init_rc_src := $(LOCAL_PATH)/$(my_init_rc)
    my_init_rc_installed := $(TARGET_OUT$(partition_tag)_ETC)/init/$(notdir $(my_init_rc_src))
    $(my_init_rc_installed) : $(my_init_rc_src) | $(ACP)
        @echo "Install: $@"
        $(copy-file-to-new-target)
    
    $(my_register_name) : $(my_init_rc_installed)

    大致可以看出一些端倪,应该是放在xxx/etc/init目录下,这个xxx根据什么看判断,partition_tag变量

      ifdef LOCAL_IS_HOST_MODULE
        partition_tag :=
      else
      ifeq (true,$(LOCAL_PROPRIETARY_MODULE))
        partition_tag := _VENDOR
      else ifeq (true,$(LOCAL_OEM_MODULE))
        partition_tag := _OEM
      else ifeq (true,$(LOCAL_ODM_MODULE))
        partition_tag := _ODM
      else
        # The definition of should-install-to-system will be different depending
        # on which goal (e.g., sdk or just droid) is being built.
        partition_tag := $(if $(call should-install-to-system,$(my_module_tags)),,_DATA)
      endif

    cameraserver应该是系统所有的,不是oem或者odm特有,存放在system/etc/init目录下。
    接下面看看这个文件
    /system/core/init/readme.txt

    One may specify paths in the mount_all command line to have it import
    .rc files at the specified paths instead of the default ones listed above.
    This is primarily for supporting factory mode and other non-standard boot
    modes.  The three default paths should be used for the normal boot process.
    
    The intention of these directories is as follows
       1) /system/etc/init/ is for core system items such as
          SurfaceFlinger, MediaService, and logcatd.
       2) /vendor/etc/init/ is for SoC vendor items such as actions or
          daemons needed for core SoC functionality.
       3) /odm/etc/init/ is for device manufacturer items such as
          actions or daemons needed for motion sensor or other peripheral
          functionality.

    显然是在执行“mount_all“的时候,CameraServer启动 ~ ,找到启动的位置,这一点和之前的版本是有很大差别的。


    Aidl
    N版本上对于Camera的一些接口采用了Aidl的文件格式
    frameworks/av/camera/aidl/android/hardware/
    这里写图片描述

    其他模块想要访问这些接口,需要include libcamera_client模块才行

    这里写图片描述

    mk文件中有说明。

  • 相关阅读:
    【1】数据库表如何水平拆分和垂直拆分
    【JUC】JDK1.8源码分析之ReentrantReadWriteLock
    【1】【JUC】JDK1.8源码分析之ArrayBlockingQueue,LinkedBlockingQueue
    【JUC】CopyOnWriteArrayList
    <T extends Comparable<? super T>>什么意思
    深拷贝和浅拷贝及实现
    序列化和反序列化的底层实现原理
    willMoveToParentViewController和didMoveToParentViewController
    自定义 ViewController 容器转场
    iOS开发 剖析网易新闻标签栏视图切换(addChildViewController属性介绍)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6467171.html
Copyright © 2011-2022 走看看