前言

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. Java多线程——对象组合

    我们不希望对每一次的内存访问都进行分析以确保程序是线程安全的,而是希望将一些现有的线程安全组件组合为更大规模的组件或者程序,这里介绍一些组合模式,这些组合模式能够使一个类更容易成为线程安全的,并且在维 ...

  2. 基础概念——令人迷惑的EOF

    EOF概念常常使人迷惑. 首先我们要理解并没有像EOF字符这样的东西. 进一步讲EOF是由内核检测到的一种条件. 应用程序在它接收到由read函数返回的零返回码时,它就会发现EOF条件. 对于磁盘文件 ...

  3. java无符号Byte

    1.无符号byte, 实现了将byte(-128~127) 转换为 (0~255) class UnsignedByte { private short value; private byte raw ...

  4. DB2 命令大全

    check Archiving processing 查看日志归档情况 db2 "SELECT DATE(CAST(START_TIME as TIMESTAMP)) as DATE, co ...

  5. 如何对react进行性能优化

    React本身就非常关注性能,其提供的虚拟DOM搭配上DIff算法,实现对DOM操作最小粒度的改变也是非常高效的,然而其组件的渲染机制,也决定了在对组件更新时还可以进行更细致的优化.  react组件 ...

  6. Android中9-Patch图片之理解

    在android中,不仅可以将扩展名为.png,.jpg,.gif的普通图片作为图片资源,而且可以将扩展名为.9.png的9-Patch图片作为图片资源.扩展名为.png,.jpg,.gif的普通图片 ...

  7. Linux 服务器开发常用命令操作

    1)查看网络端口 netstat -na --ip 2)查看特定应用程序进程 ps -ef | grep vsftp  or ps aux | grep xxx.exe 3)查看系统日志 vi /et ...

  8. 数据库其他注入思路 - 万能密码 - cookie注入 -搜索型注入

    另类登录注入形式: 经常有一类验证(ASP,PHP,JSP均存在),先判断user是否存在,ASP为例子:"select password from admin where user_nam ...

  9. com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote method解决方法

    报错日记: Caused by: com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote method: getUserAuthLeve ...

  10. Maven仓库汇总

    来源:http://tianya23.blog.51cto.com/1081650/386908 1.maven 仓库地址: 共有的仓库http://repo1.maven.org/maven2/ht ...