<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文件中有说明。
<Android Framework 之路> N版本 Framework Camera的一些改动的更多相关文章
- Entity Framework 6:专家版本
随着 Entity Framework 最新主版本 EF6 的推出,Microsoft 对象关系映射 (ORM) 工具达到了新的专业高度,与久负盛名的 .NET ORM 工具相比已不再是门外汉. EF ...
- 单点登录跳转失败(原因是 主票据申请子票据失败) asp.net 同站点下不同应用间不同版本Framework问题
单点登录跳转失败(原因是 主票据申请子票据失败) asp.net 同站点下不同应用间不同版本Framework问题 今天遇到一个问题,在主站点现在配置的应用和主站点登录会话状态不能共享,进入子站点应用 ...
- Django rest framework(4)----版本
目录 Django组件库之(一) APIView源码 Django restframework (1) ----认证 Django rest framework(2)----权限 Django res ...
- dotfuscator 在混淆.Net Framework 4.0以上版本的时候报错的解决方法
dotfuscator 在混淆.Net Framework 4.0以上版本的时候报错的解决方法 在混淆的时候报错了,错误描述大致如下: Could not find a compatible vers ...
- Android学习之路——简易版微信为例(一)
这是“Android学习之路”系列文章的开篇,可能会让大家有些失望——这篇文章中我们不介绍简易版微信的实现(不过不是标题党哦,我会在后续博文中一步步实现这个应用程序的).这里主要是和广大园友们聊聊一个 ...
- 基于Entity Framework 6的框架Nido Framework
随着 Entity Framework 最新主版本 EF6 的推出,Microsoft 对象关系映射 (ORM) 工具达到了新的专业高度,与久负盛名的 .NET ORM 工具相比已不再是门外汉. EF ...
- 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一 ...
- android中如何在低版本(5.0之前)上使用tint(着色)属性
1. 使用app前缀(app:backgroundTint,app:backgroundTintMode),如果使用android前缀,在低版本上是拿不到值的,因为这些属性是5.0以后才加入的. 2. ...
- Android高薪之路-Android程序员面试宝典
Android高薪之路-Android程序员面试宝典
随机推荐
- python实现数据库增删改查
column_dic = {"id": 0, "name": 1, "age": 2, "phone": 3, &quo ...
- 2018沈阳网络赛 - Ka Chang KD树暴力
题意:给你一棵树,n个点q次操作,操作1查询x子树深度为d的节点权值和,操作2查询子树x权值和 把每个点按(dfn,depth)的二维关系构造kd树,剩下的只需维护lazy标记即可 #include& ...
- 【ORACLE】oracle 日志文件管理
修改Oracle重做日志文件大小 创建新的日志组1 删除旧的日志组0(旧的日志组状态需要是INACTIVE) 创建新的日志组2,组名为旧的日志组0的组名 删除日志组1 ---------------- ...
- Compile android source and kernel for emulator in Debian
1.download the android source code Reference from http://source.android.com/source/downloading.html ...
- Java中的语法树结构
1.JCTypeParameter class B<T extends CA&IA&IB> { ...} 截图如下: 接口继承了StatementTree接口,而实现类实现 ...
- WPF获取程序版本号(Version)的方法
1.第一种:通过System来获取 public static Version GetEdition() { return System.Reflection.Assembly.GetExecutin ...
- JS中深拷贝数组、对象、对象数组方法
我们在JS程序中需要进行频繁的变量赋值运算,对于字符串.布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组.对象.对象数组的拷贝,我们需要理解更多的内容. 首先,我们需要了解JS的浅拷贝与深拷贝 ...
- Visual Studio、.net framework、CLR与JDK、JRE、JVM、Eclipse
.net平台 java平台 开发工具 Visual Studio ...
- vs2015 点击cshtml 后提示 "无效指针" 的解决办法
1. 关闭vs 2. 删除 %LocalAppData%\Microsoft\VisualStudio\14.0\ComponentModelCache 3. 打开vs OK 解决
- Sumblime Text 2/3 插件安装方法
使用Package Control组件安装 按Ctrl+`调出console(注:安装有QQ输入法的这个快捷键会有冲突的,输入法属性设置-输入法管理-取消热键切换至QQ拼音): 如果是sublime ...