編輯:關於Android編程
Android N版本最近發布,Nougat是否好吃,不得而知,慢慢看下~
感謝AndroidXref這個網站,給開發者提供了大量的便捷~以後學習Android就靠它了。
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"); spproc(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 sm = defaultServiceManager(); sp binder = sm->getService(String16("media.log")); if (binder != 0) { Vector 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 proc(ProcessState::self()); sp 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); spproc(ProcessState::self()); sp 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); spproc(ProcessState::self()); sp 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模塊才行<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160914/20160914095413502.png" title="" />
mk文件中有說明。
Android應用程序內存洩漏介紹內存洩漏和內存溢出的區別內存溢出(out of memory)是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of mem
vivo x7怎麼截圖?vivo x7手機是剛剛發布出來的新機,可能有用戶還不會截屏,下文介紹vivo x7截屏圖文流程,一起來瞧瞧吧! vivo x7截
1.ViewPager簡單使用ViewPager是android擴展包android.support.v4 裡的一個繼承與ViewGroup組件,通過布局管理器可以實現左
拍照——裁剪,或者是選擇圖片——裁剪,是我們設置頭像或上傳圖片時經常需要的一組操作。上篇講了Camera的使用,這篇講一下