Android Studio Debug Android Open Source Project

来源:互联网 发布:tscttp244plus软件 编辑:程序博客网 时间:2024/05/23 15:41

调试前的准备工作

环境搭建

  1. 下载源代码Source Websit
  2. 按照官方下载和构建的教程,编译源代码树,生成system.img
  3. 使用命令行工具,输入emulator启动模拟器,加载system.img。

在编译时,由于我的设备是x86_64位(Mac可以通过命令行 uname -a 查看),所以选择aosp_x86_64-eng。

编译目标有很多个,格式为BUILD-BUILDTYPE,BUILDTYPE具体含义可以看选择目标

BUILD具体含义不清,可以参考自己动手编译Android源码(超详细)

启动emulator需要四个镜像文件:

  • system.img
  • userdata.img
  • ramdisk.img
  • kernel-qemu or kernel-ranchu

其中前三个镜像文件是编译AOSP源代码树生成的。启动emulator没有指定kernel-qemu or kernel-ranchu文件,默认使用AOSP directory/prebuilts/qemu-kernel/x86_64。也可以单独模块编译kernel模块,使用编译生成的相应kernel镜像。

Android Studio Import AOSP

网上有很多AOSP使用Android Studio的教程,不再赘述。这里提供一片参考博文Android Studio导入android源码技巧

Remote Debugger

调试AOSP的Java源码需要通过一系列的设置,这里给出参考博文Debugging AOSP Platform code with Android Studio - Part I - Java Debugger

调式流程

基础概念

为何需要使用编译的system.img运行emulator,并在此模拟器上运行demo进行调试?因为JVM告诉Android Studio代码行和类名。因此需要使用demo运行的Platform必须和AOSP的platform frameworks相同,才会使JVM返回给Android Studio的code line和ClassName相对应,所以必须使用编译的system.img运行emulator。

开发应用时,使用SDK工具进行开发。但是SDK中下载的SDK Platform都是.jar包,通过代码中进行跳转查看API,都是反编译.jar中的Class文件。所以无法作为源代码学习。

编译Application Project必须有一个SDK Platform,该文件下包含了对应平台的类库(图片,android.jar文件)。

sdk/platforms

而在sdk目录下,还有一个sources文件夹,里面包含了对应SDK Platform下载的平台部分源码(图片包括文件大小完全不及AOSP源码大小)。

sdk/sources

在编写项目时,有时可以通过command+鼠标左键查看API的源代码,但是这些源代码有些是从.jar文件中反编译出来的,只有方法名,而能显示完整的一般都是sources目录下对应的部分源码、第三方类库(如Support Library等)和项目代码。

在设备上run App时,出现异常后,Logcat会打印出异常抛出的相关Stack Trace。一般每一行后都会有一个括弧显示类名和相应的代码行,一部分是显示蓝色,可以点击查看源码(可能是第三方库或项目代码或sources目录下的部分源码);而另一部分是灰色的,因为没有相应的源码,只是.jar类库提供的方法名以及相应的代码行。

所以想要调试AOSP必须是通过编译整个AOSP源码树运行的emulator,否则在其他设备上的Platform即便API级别相同,相应方法在类文件中的代码行并不相同。无法精确断点调试定位源码。

而APK文件,会打包所有应用所需要的Resources,包括项目代码,项目图片等资源以及第三方库。所以只要AOSP源码树中frameworks/support下的支持库revision和项目使用的Support Library revision相同,可以精确的断点调试定位到源代码上。

流程

  1. 使用emulator启动模拟器。
  2. 在Application Project中,在模拟器中安装该app,并且run。
  3. 打开Android Studio的AOSP项目,开启monitor监听emulator,并且选择好debug对象,App的Process。
  4. 在需要调试的源代码处打上断点,使用remote debugger开始调试App,触发断点,进行调试。

注意,一定要在debug调试前通过Monitor选择对象,否则可能提示ConnectionRefuse异常。

选择调试的Process对象

出现connection refuse异常是因为Android Studio无法连接LocalHost的8700port,因为这是给DDMS使用的。所以在调试前必须先打开Monitor中的DDMS。当选择需要调试的进程对象后,在port那一列中,可以看到选择的Process显示为emulator port/localhost port(8700)

原理

参考博文用Android Studio调试Frameworks层代码

Java平台的调试是有一个规范化的标准的,那就是JPDA(Java Platform Debugger Architecture);通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。

JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),Java 调试线协议(JDWP),以及 Java 调试接口(JDI)。

调试需要堆栈、符号等信息都保存在JVM中,调试器(debugger)需要通过一种渠道获取这些信息,并通过这个渠道发送调试指令给JVM,JDWP就是调试器与JVM通信的渠道。在JVM内部有一个专门的jdwp线程,Android系统的adbd守护进程通过socket与各个虚拟机的jdwp线程进行通信,外部调试器通过主机的adb与adbd通信进而完成与jdwp的通信。

在断点调试时,JVM会告诉AS自己在xx.java的第xx行被断住了,AS就会定位到这个位置。就和Stack Trace打印的异常日志一样,会在括弧内显示详细的类名和代码行。

目的

使用Android Studio调试源代码,是为了学习Frameworks层代码,而非业务代码,当然如果是开发Frameworks,也属于业务范畴。所以一般断点都是打在demo中所调用的API代码上,这样可以通过运行自己的demo进行Frameworks源码调试。

而一般UI、业务代码可以通过项目的Android Studio进行调试。

Android Studio 关于Stack Trace的知识

Logcat

logcat,一个可以显示调试消息的监视器。监视器既可以显示系统消息(例如何时发生了垃圾回收),也能显示您可以使用 Log 类添加到应用中的消息。

默认显示最近运行的应用信息,当有异常时,Logcat显示有关异常的调用栈-Stack Trace。

Logcat可以通过filter和选择应用进程进行消息筛选。例如一般在模拟器或devices run一个项目时,都只显示该应用的信息。

异常抛出Stack Trace

每当有异常抛出或应用crash时,Logcat都会打印出一个Stack Trace。打印的信息是指抛出异常的方法调用链。而非整个App从启动到异常抛出crash的所有方法调用情况。

也可以通过类似Thread.dumpStack()等方法,在代码中指定一个点去打印Stack Trace,而不是等应用crash时再去打印。

内置demo编写

Android Open Source Project的源代码树编译完成输出的system.im文件可以作为模拟器的系统文件,而在模拟器的Android系统中,有许多自带的应用,那么可以在编译时放入自己的demo,写入system.im文件,实现在AOSP项目中debug自己demo的源代码。

此思路参考自在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务

流程

  1. 使用Android Studio构建好需要debug的demo项目;
  2. AOSP内置的系统应用放置在AOSP/packages目录下(AOSP dir是指AOSP源代码树的根目录),可以打开其中一个Application package查看其目录,主要有src目录、res目录、AndroidManifest.xml、Android.mk四部分;
  3. 把构建的demo项目中,app module的目录拷贝至AOSP/packages中相应目录(可以是apps或者其它目录),且仅保留src目录、res目录、AndroidManifest.xml。并且将app module目录名改为相应的Application名;
  4. 编写Android.mk文件,这是给编译AOSP的Build System系统编译时使用的脚本文件(因为整个AOSP项目不是使用Gradle构建编译的,而是GUN Make,最主要的就是Make file)。
  5. 在编写脚本时需要注意两点:如果demo项目中还要其他Module,那么将其拷贝到Application目录下,并在该Module中编写Android.mk文件,BUILD类型为各种Library,供Application Module 源代码调用;而在Application根目录下的Android.mk文件中,BUILD类型为PACKAGE(include $(BUILD_XXX)),就是把整个Application源代码和需要的libraries打包成package。
  6. 使用命令mmm packages/Directory_Name/Application_Name单独编译demo项目;
  7. 使用命令make snod编译system.im文件;
  8. 最后使用命令emulator打开模拟器,启动系统,就可以自己的demo变成了系统内置的应用。

Android.mk语法参考:Android.mk、android.mk

Android.mk文件一般用于NDK开发,官方文档中介绍把它放在jni/目录下,用于把开发者自己编写的native code编译成一个Module,而这个Module有可能是static Library或Shared Library或executable。这样就可以被真正的Application Module的源代码(可能是Java部分,采用JNI技术调用)调用。

CPP的static&shared library的区别Difference between static and shared libraries?

问题

当写入自己的demo到AOSP的源代码树,导入Android Studio查看源码时,发现自己demo的源码无法被Android Studio识别。比如Java文件出现红色的J而不是C。此时需要把源码目录设置为source。

在工具栏的File-File Structure-Module中选择自己demo的源代码目录:src,通过make as设置为Source。

参考Android studio java文件显示j爆红

原创粉丝点击