Zygote家的大儿子-SystemServer

本文基于 Android 9.0 , 代码仓库地址 : android_9.0.0_r45文中源码链接: SystemServer.java SystemServiceManager.java SystemService.java 首先来回顾一下上篇文章 Java 世界的盘古和女娲 —— Zygote ,主要介绍了 Android 世界中的第一个 Java 进程 Zygote,它的主要工作流程如下: registerServerSocketFromEnv(), 注册服务端 socket,用于和客户端进程通信preload(),预加载一系列资源,提高应用启动速度forkSystemServer(),创建 system_server 进程功成身退,调用 runSelectLoop() 等待响应客户端请求,创建应用进程本篇文章的主角 system_server 进程是 Zygote 进程 fork 出的第一个进程,它负责管理和启动整个 Framework 层。 再来看看 Gityuan 的这张图片,找一下 System Server 的位置,它承载了各类系统服务的创建和启动。关于 system_server 进程的创建流程,上篇文章中已经做了详细介绍,这里再简单看一下流程图: 最终会调用到 SystemServer.main() 方法。下面就以此为起点,来具体分析 SystemServer 都做了些什么。 SystemServer 启动流程public static void main(String[] args) { new SystemServer().run();}接着看 run() 方法。 private void run() { try { ...... // 如果设备时间早于 1970 年,很多 API 处理负数时会 crash。所以直接设置为 1970 年 1 月 1 日 if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } // 未设置时区的话默认设为 GMT String timezoneProperty = SystemProperties.get("persist.sys.timezone"); if (timezoneProperty == null || timezoneProperty.isEmpty()) { Slog.w(TAG, "Timezone not set; setting to GMT."); SystemProperties.set("persist.sys.timezone", "GMT"); } // 语言地区设置 if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag(); SystemProperties.set("persist.sys.locale", languageTag); SystemProperties.set("persist.sys.language", ""); SystemProperties.set("persist.sys.country", ""); SystemProperties.set("persist.sys.localevar", ""); } // The system server should never make non-oneway calls Binder.setWarnOnBlocking(true); // The system server should always load safe labels PackageItemInfo.setForceSafeLabels(true); // Default to FULL within the system server. SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL; // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized SQLiteCompatibilityWalFlags.init(null); // Here we go! Slog.i(TAG, "Entered the Android system server!"); int uptimeMillis = (int) SystemClock.elapsedRealtime(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis); if (!mRuntimeRestart) { MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis); } // 设置虚拟机运行库路径 SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); // Mmmmmm... more memory! // 清除虚拟机内存增长限制,允许应用申请更多内存 VMRuntime.getRuntime().clearGrowthLimit(); // 设置堆内存的有效利用率为 0.8,(可能被忽略) VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // 确保指纹信息已经定义 Build.ensureFingerprintProperty(); // Within the system server, it is an error to access Environment paths without // explicitly specifying a user. Environment.setUserRequired(true); // Within the system server, any incoming Bundles should be defused // to avoid throwing BadParcelableException. BaseBundle.setShouldDefuse(true); // Within the system server, when parceling exceptions, include the stack trace Parcel.setStackTraceParceling(true); // 确保系统的 Binder 调用总是运行在前台优先级 BinderInternal.disableBackgroundScheduling(true); // Increase the number of binder threads in system_server BinderInternal.setMaxThreads(sMaxBinderThreads); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); // 1. 创建主线程 Looper Looper.prepareMainLooper(); Looper.getMainLooper().setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); // 初始化 native 服务,加载 libandroid_servers.so System.loadLibrary("android_servers"); // 检查上次关机是否失败,可能不会有返回值 performPendingShutdown(); // 2. 初始化系统上下文 createSystemContext(); // 3. 创建系统服务管理 SystemServiceManager // 并将 mSystemServiceManager 注册到 sLocalServiceObjects 中 mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Prepare the thread pool for init tasks that can be parallelized SystemServerInitThreadPool.get(); } finally { traceEnd(); // InitBeforeStartServices } // Start services. try { traceBeginAndSlog("StartServices"); startBootstrapServices(); // 4. 启动系统引导服务 startCoreServices(); // 5. 启动系统核心服务 startOtherServices(); // 6. 启动其他服务 SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } finally { traceEnd(); } StrictMode.initVmDefaults(null); if (!mRuntimeRestart && !isFirstBootOrUpgrade()) { int uptimeMillis = (int) SystemClock.elapsedRealtime(); MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis); final int MAX_UPTIME_MILLIS = 60 * 1000; if (uptimeMillis > MAX_UPTIME_MILLIS) { Slog.wtf(SYSTEM_SERVER_TIMING_TAG, "SystemServer init took too long. uptimeMillis=" + uptimeMillis); } } // 7. Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}代码虽然比较长,但是逻辑很清晰。我在注释里标记了比较重要的 7 个步骤,逐一分析。 ...

October 14, 2019 · 9 min · jiezi

Android Studio 导入 AOSP 源码

有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具。问题来了,如何将 AOSP 源码导入 Android Studio?安装 Java虚拟机新装的 Ubutun 一开始是没有 Java 的,需要先安装,输入命令java,报以下错误:<!–more–>Command ‘java’ not found, but can be installed with:sudo apt install default-jresudo apt install openjdk-11-jre-headlesssudo apt install openjdk-8-jre-headless输入以上命令进行安装,然后整编(关于整编和单编下节细讲)代码又报错:Your version is: openjdk version “10.0.1” 2018-04-17 OpenJDK Runtime Environment (build 10.0.1+10-Ubuntu-3ubuntu1) OpenJDK 64-Bit Server VM (build 10.0.1+10-Ubuntu-3ubuntu1, mixed mode).The required version is: “1.8.x"提示 Java 版本只能是 1.8.x,需要指定 Java 版本:sudo update-alternatives –config java输出:有 2 个候选项可用于替换 java (提供 /usr/bin/java)。选择 路径 优先级 状态————————————————————* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1101 自动模式1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1101 手动模式2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 手动模式要维持当前值[*]请按<回车键>,或者键入选择的编号:2拓展JDK 也有门派之分的,那就是 Open JDK 和 Oacle JDK,其实我刚开编译时,用的是 Oracle JDK,整编报错:You asked for an OpenJDK based build but your version isjava version “1.8.0_181” Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode).idegen.jar在 Ubuntu 系统下,进入源码根目录,运行如下命令:source build/envsetup.shmmm development/tools/idegen/报错:Command ‘make’ not found, but can be installed with:sudo apt install makesudo apt install make-guile命令安装 make 成功后,再次运行mmm development/tools/idegen/,会在源码目录下的 out/host/linux-x86/framework目录下生成了 idegen.jar 文件。如果命令 mmm development/tools/idegen/ 一直报错,可以尝试一下命令 make idegen 依赖编译下。android.iml 和 android.ipr在源码目录下继续执行如下命令:development/tools/idegen/idegen.sh会在根目录下生成android.iml 和 android.ipr 这两个文件,这两个文件是 Android Studio 的工程配置文件,这时候其实已经可以直接导入 Android Studio,但会导入所有的源码模块,会很慢,可以进行过滤,除了 frameworks 模块和 packages 模块,其他都给过滤掉,不导入 Android Studio,打开 android.iml 文件,搜下excludeFolder,在后面加入如下代码:<excludeFolder url=“file://$MODULE_DIR$/art” /><excludeFolder url=“file://$MODULE_DIR$/bionic” /><excludeFolder url=“file://$MODULE_DIR$/bootable” /><excludeFolder url=“file://$MODULE_DIR$/build” /><excludeFolder url=“file://$MODULE_DIR$/cts” /><excludeFolder url=“file://$MODULE_DIR$/dalvik” /><excludeFolder url=“file://$MODULE_DIR$/developers” /><excludeFolder url=“file://$MODULE_DIR$/development” /><excludeFolder url=“file://$MODULE_DIR$/device” /><excludeFolder url=“file://$MODULE_DIR$/docs” /><excludeFolder url=“file://$MODULE_DIR$/external” /><excludeFolder url=“file://$MODULE_DIR$/hardware” /><excludeFolder url=“file://$MODULE_DIR$/kernel” /><excludeFolder url=“file://$MODULE_DIR$/libcore” /><excludeFolder url=“file://$MODULE_DIR$/libnativehelper” /><excludeFolder url=“file://$MODULE_DIR$/out” /><excludeFolder url=“file://$MODULE_DIR$/pdk” /><excludeFolder url=“file://$MODULE_DIR$/platform_testing” /><excludeFolder url=“file://$MODULE_DIR$/prebuilts” /><excludeFolder url=“file://$MODULE_DIR$/sdk” /><excludeFolder url=“file://$MODULE_DIR$/system” /><excludeFolder url=“file://$MODULE_DIR$/test” /><excludeFolder url=“file://$MODULE_DIR$/toolchain” /><excludeFolder url=“file://$MODULE_DIR$/tools” /><excludeFolder url=“file://$MODULE_DIR$/.repo” />导入 Android Studio我把 Android 源码拷到我的 Mac 上,打开 Android Studio,选择 Open an existing Android Studio project,找到源码目录,点击 Android.ipr,Open,大约等 6 分钟,导入完毕,Enjoy coding。问题发现 Android Studio 不停 scanning files to index,我的强迫症又犯了,解决:1 invalidate and restart 不起作用;2 右击项目 –> Open module setting –> Modules –> 找到 gen 文件夹 –> 右键选择 Resources,终于告别烦人的 scanning files to index。系列博客VirtualBox 安装 UbuntuAOSP 源码下载AOSP 源码整编单编参考https://blog.csdn.net/HQZ8208…https://www.jianshu.com/p/fb1...https://blog.csdn.net/shisanm…公众号我的公众号:吴小龙同学,欢迎关注交流~ ...

February 26, 2019 · 2 min · jiezi

AOSP 源码下载

网上关于这块大部分教程都是无效的,因为墙的缘故,无法使用官方提供的下载链接,我这里使用了清华大学的镜像,是能够顺利将 AOSP 下载下来。如果你还没有安装 Ubuntu,请看《VirtualBox 安装 Ubuntu》。下载 repoRepo 是一款工具,可让您在 Android 环境中更轻松地使用 Git,首先需要安装 Git:sudo apt-get install git创建 bin,并加入 path:mkdir /binPATH=/bin:$PATH下载 repo:curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo错误:Command ‘curl’ not found, but can be installed with:sudo apt install curl需要安装 curl,执行命令sudo apt-get install curl进行安装。注意:命令 apt 在低版本 Ubuntu 不行,本教程统一使用命令 apt-get。权限设置:chmod a+x /bin/repo如何验证 repo 安装成功输入命令repo,提示:/usr/bin/env: “python”: 没有那个文件或目录需要安装 python,执行命令sudo apt-get install python安装,再次输入命令repo,提示如下即 repo 安装成功:error: repo is not installed. Use “repo init” to install it here.下载源码初始化仓库建立工作目录 AOSP,命令:mkdir AOSPcd AOSP初始化仓库:repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest错误错误1error.GitError: manifests var: *** 请告诉我你是谁。运行 git config –global user.email “you@example.com” git config –global user.name “Your Name"来设置您账号的缺省身份标识。如果仅在本仓库设置身份标识,则省略 –global 参数。没有设置身份,要使用 Gerrit 代码审核工具,您需要一个与已注册的 Google 帐号关联的电子邮件地址:git config –global user.email “wuxiaolong.me@gmail.com"git config –global user.name “WuXiaolong"其他邮箱应该也是可以的。错误2fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundlefatal: error [Errno 101] Network is unreachable因为 repo 运行过程中会尝试访问官方的 git 源更新自己,如果想使用 tuna 的镜像源进行更新,将如下内容复制到你的/.bashrc里,然后重启终端模拟器。export REPO_URL=‘https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'错误3:curl: (22) The requested URL returned error: 404 Not FoundServer does not provide clone.bundle; ignoring.为什么会出现此种 log ?在通过 Git 的 HTTP 协议下载最新数据之前,Repo 尝试下载预先打包的捆绑文件以引导每个 git。原文:Repo attempts to download a prepackaged bundle file to bootstrap each git prior to downloading the most recent data via Git’s HTTP protocol.如果捆绑文件不可用(如本例所示),Repo 将忽略它并继续进行,换句话说,不要注意这一点。原文:If a bundle file isn’t available (like in this case), Repo will ignore it and proceed anyway. In other words, don’t pay any attention to this.最后,如何取消 download clone.bundle ?只需要 在repo 添加一个参数 –no-clone-bundle,如下:可通过 repo <cmd> -h 获得参数 –no-clone-bundle 的说明repo init –no-clone-bundlerepo sync –no-clone-bundle指定某个 Android 版本如果需要某个特定的 Android 版本(列表):repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.0.0_r1提示以下,即 init 成功:Your identity is: WuXiaolong <wuxiaolong.me@gmail.com>If you want to change this, please re-run ‘repo init’ with –config-namerepo has been initialized in /media/disk/Project/AOSP疑问如果没有指定版本,如何知道下载好的 AOSP 是什么版本?找到build/make/core/version_defaults.mk文件打开,搜索PLATFORM_SDK_VERSION,找到了 PLATFORM_SDK_VERSION := 28,从 SDK 版本可以知道 AOSP 版本是 9.0,我下载的就是最新的。同步代码同步源码树(以后只需执行这条命令来同步):repo sync然后等待下载完毕:正在检出文件: 100% (1709/1709), 完成.正在检出文件: 100% (9492/9492), 完成.在检出文件: 2% (251/9492) 正在检出文件: 100% (617/617), 完成.正在检出文件: 17% (106/617) 正在检出文件: 100% (15779/15779), 完成.检出文件: 7% (1251/15779) 正在检出文件: 100% (29/29), 完成. 正在检出文件: 27% (8/29) Syncing work tree: 100% (568/568), done. 最后整个源码大小 27.2 G。参考https://source.android.google…公众号我的公众号:吴小龙同学,欢迎交流~ ...

January 5, 2019 · 2 min · jiezi

AOSP 源码整编单编

《AOSP 源码下载》完成后,就可以开编了。整编整编,顾名思义就是编译整个 Android 源码,最终 out 目录会生成几个重要的镜像文件,其中有 system.img、userdata.img、ramdisk.img 等,这些是可以刷机的。初始化编译环境项目目录,打开终端,输入命令:source build/envsetup.sh选择编译目标命令:lunch输出:You’re building on LinuxLunch menu… pick a combo: 1. aosp_arm-eng 2. aosp_arm64-eng 3. aosp_blueline-userdebug 4. aosp_car_arm-userdebug 5. aosp_car_arm64-userdebug 6. aosp_car_x86-userdebug 7. aosp_car_x86_64-userdebug 8. aosp_cf_x86_64_auto-userdebug 9. aosp_cf_x86_64_phone-userdebug 10. aosp_cf_x86_64_tablet-userdebug 11. aosp_cf_x86_64_tablet_3g-userdebug 12. aosp_cf_x86_64_tv-userdebug 13. aosp_cf_x86_64_wear-userdebug 14. aosp_cf_x86_auto-userdebug 15. aosp_cf_x86_phone-userdebug 16. aosp_cf_x86_tablet-userdebug 17. aosp_cf_x86_tablet_3g-userdebug 18. aosp_cf_x86_tv-userdebug 19. aosp_cf_x86_wear-userdebug 20. aosp_crosshatch-userdebug 21. aosp_marlin-userdebug 22. aosp_sailfish-userdebug 23. aosp_taimen-userdebug 24. aosp_walleye-userdebug 25. aosp_walleye_test-userdebug 26. aosp_x86-eng 27. aosp_x86_64-eng 28. beagle_x15-userdebug 29. hikey-userdebug 30. hikey64_only-userdebug 31. hikey960-userdebug 32. hikey960_tv-userdebug 33. hikey_tv-userdebug 34. m_e_arm-userdebug 35. mini_emulator_arm64-userdebug 36. mini_emulator_x86-userdebug 37. mini_emulator_x86_64-userdebug 38. poplar-eng 39. poplar-user 40. poplar-userdebug 41. uml-userdebugWhich would you like? [aosp_arm-eng] 26编译目标格式说明编译目标的格式:BUILD-BUILDTYPE,比如上面的 poplar-eng 的 BUILD 是 poplar,BUILDTYPE 是 eng.什么是 BUILDBUILD 指的是特定功能的组合的特定名称,即表示编译出的镜像可以运行在什么环境。其中 aosp(Android Open Source Project)代表 Android 开源项目;arm 表示系统是运行在 arm 架构的处理器上,arm64 则是指 64 位 arm 架构处理器,x86 则表示 x86 架构的处理器,更多设备代码和编译目标参考官方文档。什么是 BUILDTYPEBUILDTYPE 则指的是编译类型,通常有三种:user:用来正式发布到市场的版本,权限受限,如没有 root 权限,不能 dedug 等。userdebug:在user版本的基础上开放了 root 权限和 debug 权限。eng:代表 engineer,开发工程师的版本,拥有最大的权限(root等),具有额外调试工具的开发配置。如果没有谷歌手机设备,可以选择 arm 或者 x86,我选择了 aosp_x86-eng,编译完后运行模拟器看看,因此这里选择序号 26。开始编译通过 make 指令进行代码编译:make -j8其中 -jN 参数表示处理并行任务,通常使用的任务数 N 介于编译时所用计算机上硬件线程数的 1-2 倍之间。查看计算机上的核心数:cat /proc/cpuinfo | grep processorprocessor : 0processor : 1processor : 2processor : 3可看到创建的虚拟机 CPU 核心共有 4 个,那么要实现最快的编译速度,可以使用介于 make -j4 到 make -j8 之间的命令。不出意外,当看到:#### build completed successfully (03:55:24 (hh:mm:ss)) ####就整编成功了。运行模拟器整编完,网上很多都是说直接运行命令:emulator,但是我报以下错误了:emulator: WARNING: Couldn’t find crash service executable /media/ubuntu/disk/Project/AOSP9/prebuilts/android-emulator/linux-x86_64/emulator64-crash-serviceemulator: WARNING: system partition size adjusted to match image file (1080 MB > 800 MB)queryCoreProfileSupport: swap interval not foundfailed to create drawablefailed to create drawablefailed to create drawablefailed to create drawablefailed to create drawablefailed to create drawablefailed to create drawablefailed to create drawablegetGLES2ExtensionString: Could not make GLES 2.x context current!第一个警告不管,第二个警告可以 emulator 加参数 -partition-size 2048解决,也可以不管,最后一个折腾了很久,可以加参数-gpu off,完整运行模拟器的命令:emulator -gpu off -partition-size 2048,这时应该又会报:emulator: WARNING: Couldn’t find crash service executable /media/ubuntu/disk/Project/AOSP9/prebuilts/android-emulator/linux-x86_64/emulator64-crash-serviceemulator: WARNING: system partition size adjusted to match image file (1338 MB > 800 MB)emulator: ERROR: Running multiple emulators with the same AVD is an experimental feature.Please use -read-only flag to enable this feature.只能重启一下才能解决。如果编译完成后启动模拟器时卡在黑屏,可以尝试编译其他的!emulator 还有很多参数,可以用 emulator -help 查看,参数如下:-sysdir <dir> 为模拟器在<dir>目录中搜索系统硬盘镜像-system <file> 为模拟器从<file>文件中读取初始化系统镜像-datadir <dir> 设置用户数据写入的目录-kernel <file> 为模拟器设置使用指定的模拟器内核-ramdisk <file> 设置内存RAM 镜像文件(默认为<system>/ramdisk.img)-image <file> 废弃,使用-system <file> 替代-init-data <file> 设置初始化数据镜像(默认为<system>/userdata.img)-initdata <file> 和"-init-data <file>“使用方法一致-data <file> 设置数据镜像(默认为<datadir>/userdata-qemu.img)-partition-size <size> system/data 分区容量大小(MB)-cache <file> 设置模拟器缓存分区镜像(默认为零时文件)-no-cache 禁用缓存分区-nocache 与”-no-cache"使用方法相同-sdcard <file> 指定模拟器SDCard 镜像文件(默认为<system>/sdcard.img)-wipe-data 清除并重置用户数据镜像(从initdata 拷贝)-avd <name> 指定模拟器使用Android 虚拟设备-skindir <dir> 设置模拟器皮肤在<dir>目录中搜索皮肤(默认为<system>/skins 目录)-skin <name> 选择使用给定的皮肤-no-skin 不适用任何模拟器皮肤-noskin 使用方法与"-no-skin"相同-memory <size> 物理RAM 内存大小(MB)-netspeed <speed> 设置最大网络下载、上传速度-netdelay <delay> 网络时延模拟-netfast 禁用网络形态-tarce <name> 代码配置可用-show-kernel 显示内核信息-shell 在当前终端中使用根Shell 命令-no-jni Dalvik 运行时禁用JNI 检测-nojni 使用方法与"-no-jni"相同-logcat <tag> 输出给定tag 的Logcat 信息-no-audio 禁用音频支持-noaudio 与"-no-audio"用法相同-audio <backend> 使用指定的音频backend-audio-in <backend> 使用指定的输入音频backend-audoi-out <backend> 使用指定的输出音频backend-raw-keys 禁用Unicode 键盘翻转图-radio 重定向无线模式接口到个性化设备-port <port> 设置控制台使用的TCP 端口-ports <consoleport>,<adbport> 设置控制台使用的TCP 端口和ADB 调试桥使用的TCP 端口-onion <image> 在屏幕上层使用覆盖PNG 图片-onion-alpha <%age> 指定上层皮肤半透明度-onion-rotation 0|1|2|3 指定上层皮肤旋转-scale <scale> 调节模拟器窗口尺寸(三种:1.0-3.0、dpi、auto)-dpi-device <dpi> 设置设备的resolution (dpi 单位) (默认165)-http-proxy <proxy> 通过一个HTTP 或HTTPS 代理来创建TCP 连接-timezone <timezone> 使用给定的时区,而不是主机默认的-dns-server <server> 在模拟系统上使用给定的DNS 服务-cpu-delay <cpudelay> 调节CUP 模拟-no-boot-anim 禁用动画来快速启动-no-window 禁用图形化窗口显示-version 显示模拟器版本号-report-console <socket> 向远程socket 报告控制台端口-gps <device> 重定向GPS 导航到个性化设备-keyset <name> 指定按键设置文件名-shell-serial <device> 根shell 的个性化设备-old-system 支持旧版本(pre 1.4)系统镜像-tcpdump <file> 把网络数据包捕获到文件中-bootchart <timeout> bootcharting 可用-qemu args…. 向qemu 传递参数-qemu -h 显示qemu 帮助-verbose 和"-debug-init"相同-debug <tags> 可用、禁用调试信息-debug-<tag> 使指定的调试信息可用-debug-no-<tag> 禁用指定的调试信息-help 打印出该帮助文档-help-<option> 打印出指定option 的帮助文档-help-disk-images 关于硬盘镜像帮助-help-keys 支持按钮捆绑(手机快捷键)-help-debug-tags 显示出-debug <tag>命令中的tag 可选值-help-char-devices 个性化设备说明-help-environment 环境变量-help-keyset-file 指定按键绑定设置文件-help-virtula-device 虚拟设备管理补充模拟器运行需要四个文件,分别是:Linux Kernelsystem.imguserdata.imgramdisk.img上面我 lunch 命令时选择的是 aosp_x86-eng,因此 linux 默认使用的 AOSP/prebuilds/qemu-kernel/x86/kernel-qemu 下的 kernel-qemu,而其他文件则是使用的 AOSP/out/target/product/generic_x86 目录下的 system.img、userdata.img、ramdisk.img。单编单编就是编译某个模块,比如 Setting,会在 out 目录对应的产品有 Settings.apk,例如:out/target/product/generic_x86/system/priv-app/Settings/Settings.apk,这是可以直接安装的。1、source build/envsetup.sh2、lunch3、选择单编版本序号4、编译4.1、mmmmmm packages/apps/Settings/编译指定目录下的模块,但不编译它所依赖的其它模块。4.2、mm先进入目录:cd packages/apps/Settings/再编译 mm编译当前目录下的模块,它和 mmm 一样,不编译依赖模块。4.3、mma编译当前目录下的模块及其依赖项。4.4、mmma [module_path] 编译指定路径下所有模块,且包含依赖4.5、makemake: 不带任何参数则是编译整个系统make MediaProvider单个模块编译,会把该模块及其依赖的其他模块一起编译,会搜索整个源代码来定位 MediaProvider 模块所使用的 Android.mk 文件,还要判断该模块依赖的其他模块是否有修改。make snod如果我们修改代码,想看效果,怎么办?1、可以在编译完成后,借助 adb install -r apk路径直接将生成的 apk 文件安装到设备上,如果不是 APK,直接 push 对应的文件。2、可以编译好完成后,再使用make snod,重新生成 system.img,再运行模拟器也可。公众号我的公众号:吴小龙同学,欢迎交流~ ...

January 5, 2019 · 3 min · jiezi