前言

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文件中有说明。

<Android Framework 之路> N版本 Framework Camera的一些改动的更多相关文章

  1. Entity Framework 6:专家版本

    随着 Entity Framework 最新主版本 EF6 的推出,Microsoft 对象关系映射 (ORM) 工具达到了新的专业高度,与久负盛名的 .NET ORM 工具相比已不再是门外汉. EF ...

  2. 单点登录跳转失败(原因是 主票据申请子票据失败) asp.net 同站点下不同应用间不同版本Framework问题

    单点登录跳转失败(原因是 主票据申请子票据失败) asp.net 同站点下不同应用间不同版本Framework问题 今天遇到一个问题,在主站点现在配置的应用和主站点登录会话状态不能共享,进入子站点应用 ...

  3. Django rest framework(4)----版本

    目录 Django组件库之(一) APIView源码 Django restframework (1) ----认证 Django rest framework(2)----权限 Django res ...

  4. dotfuscator 在混淆.Net Framework 4.0以上版本的时候报错的解决方法

    dotfuscator 在混淆.Net Framework 4.0以上版本的时候报错的解决方法 在混淆的时候报错了,错误描述大致如下: Could not find a compatible vers ...

  5. Android学习之路——简易版微信为例(一)

    这是“Android学习之路”系列文章的开篇,可能会让大家有些失望——这篇文章中我们不介绍简易版微信的实现(不过不是标题党哦,我会在后续博文中一步步实现这个应用程序的).这里主要是和广大园友们聊聊一个 ...

  6. 基于Entity Framework 6的框架Nido Framework

    随着 Entity Framework 最新主版本 EF6 的推出,Microsoft 对象关系映射 (ORM) 工具达到了新的专业高度,与久负盛名的 .NET ORM 工具相比已不再是门外汉. EF ...

  7. Net Framework 4.0 和.Net Framework 4.0 Client Profile

    Net Framework 4.0 和.Net Framework 4.0 Client Profile区别: .Net Framework 4.0毫无疑问就像是.Net Framework 2.0一 ...

  8. android中如何在低版本(5.0之前)上使用tint(着色)属性

    1. 使用app前缀(app:backgroundTint,app:backgroundTintMode),如果使用android前缀,在低版本上是拿不到值的,因为这些属性是5.0以后才加入的. 2. ...

  9. Android高薪之路-Android程序员面试宝典

    Android高薪之路-Android程序员面试宝典

随机推荐

  1. 并发编程>>概念准备(一)

    工于其善,必先利器 1.并发和并行的区别 并行:同一时间点执行多个任务(CPU多核或多个CPU同时执行多个任务) 并发:同一时间段内行多个任务(单核同时执行多个任务) 2.同步和异步的区别 同步:执行 ...

  2. Django环境搭建之hello world

    当我们想用Python来开发一个web应用时,首先要选择一个优秀的web框架,Django是个非常成熟的web开发框架,网上具有丰富的文档和学习资料,所以选择Django框架来入门web开发是个不错的 ...

  3. 连接Git@OSC操作步骤

    一.准备工作 软件下载 Git:地址 TortoiseGit:地址 二.安装与配置 1.Git安装 Git配置 设置客户端的用户名和email 然后,到Git@OSC 上面注册一个帐号. 这个帐号就是 ...

  4. springboot: mybatis逆向工程

    第一步: pom文件配置 黄线的部分是所要配置的 <?xml version="1.0" encoding="UTF-8"?> <projec ...

  5. sysv-rc-conf介绍

    sysv-rc-conf简介 sysv-rc-conf是一个强大的服务管理程序,Ubuntu运行级别Linux 系统任何时候都运行在一个指定的运行级上,不同的运行级的程序和服务都不同,所要完成的工作和 ...

  6. Tomcat8-启动脚本分析

    1. Tomcat也是一个java程序 最终的入口启动文件:org.apache.catalina.startup.Bootstrap 最后一条命令: start "Tomcat" ...

  7. table中td 内容超长 自动折行 (含字母数字文字)

    <table style="width:100%;table-layout:fixed;"> //列宽由表格宽度和列宽度设定 <thead> <th& ...

  8. C#同步、异步编程

    同步编程public partial class Form1 : Form { public Form1() { InitializeComponent(); } //同步执行 private voi ...

  9. 【12】FtpWebRequest上传下载

    下载文件 /// <summary> /// 下载文件 /// </summary> /// <param name="filename">&l ...

  10. SpringBoot 之Quartz的使用

    对于Quartz的使用,还是想说一句,SpringBoot真的很好用啊! 第一步:当然是引入依赖啦 <parent> <groupId>org.springframework. ...