4月 252019
 
一、启动init进程

init程序是Linux启动的和经一个程序

init程序的源文件在system/core/init/init.cpp里

二、解析init.rc

在init的main函数里,会先做一些系统初始化的工作,然后通过Parser对象来解析init.rc文件

parser对象的源文件在system/core/init/init_parser.cpp里面

在8.1系统源码里面,rc文件分别存在几个不同的目录里面

  • 主rc文件,init.rc在device/设备名/型号名/目录里,init.rc通过import的形式导入其他的rc文件
  • 还有一些其他的rc文件也在这个目录里面
  • init.zygote.rc文件在system/core/rootdir里面

但是在把系统镜像烧录到车机后,rc文件都在根目录/下

三、启动zygote

init进程解析完init.rc,将根据配置文件启动zygote

zygote是所有安卓服务和应用的父进程,承载着创建java虚拟机并且孵化安卓层的SystemServer和安卓应用的功能

zygote源码在frameworks/base/cmds/app_process/app_main.cpp中

四、启动SystemServer

在zygote中其实并没有fork出来一个SystemServer,而是先启动了java层的ZygoteInit类(通过runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote))

当然fork是不能java层直接调用的,ZygoteInit.java中又通过Zygote类,Zygote类又通过jni调用了Linux层的函数fork出来了SystemServer

ZygoteInit.java的源码在:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

Zygote.java的源码在:frameworks/base/core/java/com/android/internal/os/Zygote.java

Zygote jni层的代码在:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

SystemServer启动后,会启动一大堆系统服务,安卓的基础运行环境就起来了,启动服务的几个函数为:

SystemServer的代码在:frameworks/base/services/java/com/android/SystemServer.java

五、Launcher的启动

在SystemServer的startOtherServices函数中调用了mActivityManagerService.systemReady,

在ActivityManagerService的systemReady函数中通过startHomeActivityLocked来启动Launcher

六、待续问题:

init.rc中的服务是怎么启动的

 Posted by on 2019-04-25
3月 262019
 

一、必要的系统环境

  硬盘200G,内存4G+,交换分区(swap)4G+(可装完系统后添加,见后面错误处理部分)

二、下载源码,国内可以在清华镜像站下载 

  地址:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

  网上有很多教程,这里就不再累述了

三、然后安装编译时需要的三方库

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

安装open-jdk-8

sudo add-apt-repository ppa:openjdk-r/ppa

sudo apt-get update

sudo apt-get install openjdk-8-jdk

四、开始编译

  然后进入到Android源码目录,假设源码在用户根目录的aosp目录中:

cd ~/aosp

  然后初始化编译环境,使用下面的命令:

source build/envsetup.sh

  然后选择要编译的目标版本,先输入lunch命令

lunch

  然后在显示的列表中选择你的目标版本,输入相应的数字,按回车即可

  然后使用make开始编译,可以使用-j参数增加编译的线程以提高速度,线程数量为cpu核心数的2倍比较合适,比如你的cpu是4核的使用

make -j8

  就可以了

五、遇到的错误

1、错误1:

03:00:11 ckati failed with: signal: killed
build/core/main.mk:21: recipe for target ‘run_soong_ui’ failed
make: *** [run_soong_ui] Error 1

解决方案1:
增加swap空间
增加办法:
cd /
增加4个G的交换空间
sudo dd if=/dev/zero of=/swp bs=10M count=400
sudo mkswap /swp
sudo swapon /swp

用free -m查看交换空间的情况
这个方法增加的是临时交换空间,如需一直保留,需要其他操作
参考链接:
https://blog.csdn.net/yellow_hill/article/details/38894317

解决方案2:
export LC_ALL=C

 

2、错误2:
JackServer提示out of memory

解决方案1:
增加虚拟机内存至最少4G

解决方案2:
修改jack server内存
步骤:
打开./prebuilts/sdk/tools/jack-admin
找到下面这一行
JACK_SERVER_VM_ARGUMENTS=”${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8}”
修改为
JACK_SERVER_VM_ARGUMENTS=”${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096M}”
保存jack-admin文件
在命令行执行
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
重启jack server
然后重新编译

3、错误3:

Error while parsing ‘/media/liuderu/新加卷/android-8.0.0_r1/out/target/common/obj/APPS/QuickSearchBox_intermediates/with-local/classes.dex.flags’:1

原因:路径中包含中文字符

 Posted by on 2019-03-26

Android中aidl开发步骤

 分类:Android, Java 阅读 (147)  Android中aidl开发步骤已关闭评论
2月 242019
 
一、常见问题回顾

1、为什么要使用aidl?

答:aidl可以进行跨进程通讯。

2、aidl文件是怎么变成java代码的?

答:aidl是Android interface definition language的缩写,是一种中间语言,用于描述跨进程通信时的业务逻辑。aidl文件是通过android sdk中的名为aidl的程序生成java文件的,一般在{android-sdk}/build-tools/{android版本}/这个目录下。

3、aidl中都可以使用哪些数据类型?

答:可以使用基本的java数据类型(除了short以外),比如int, boolean, String,也可以使用List类型,如果要使用自己的类则该类需要实现Parcelable接口。

4、服务端中aidl接口的改变会不会导致未更新aidl的客户端崩溃或者出现数据混乱?

答:假如服务端中aidl更新了,客户端未更新,客户端不会报错。假如更新的接口是在接口的尾部添加的,不会出现数据混乱,如果接口在中间添加则会引发后面的函数返回结果混乱。即aidl的函数列表顺序不能乱。

二、aidl服务端开发步骤(使用Android Studio)

1、新建一个android工程

2、新建一个Service,本例为MyAidlService.java

3、新建一个aidl文件,比如IMyAidlInterface

4、为此aidl增加一个函数,比如如下,然后使用Android Studio重新编译一下项目:

5、在MyAidlService.java中,定义一个内部类,继承自IMyAidlInterface.Stub,比如AidlInterfaceStub

6、在MyAidlService.java中定义一个AidlInterfaceStub对象并初始化,如AidlInterfaceStub mAidlInterfaceStub = new AidlInterfaceStub();

7、在MyAidlService.java的onBind函数中返回上一步定义的对象,这样服务端的开发就完成了。

三、aidl客户端开发步骤

1、新建一个android工程

2、将服务端的aidl文件拷贝到客户端工程中,要保持aidl文件所在相对路径与服务端的路径结构一致,即让这个aidl的包名和服务端的包名一致

3、在客户端的Activity中定义一个IMyAidlInterface的对象,如:mIClientAidlInterface

4、在Activity的定义一个ServiceConnection对象,并用new进行实例化,这个ServiceConnection对象会生成以下两个回调函数的结构onServiceConnected和onServiceDisconnected

5、在上一个函数的onServiceConnected的回调中给mIClientAidlInterface赋值,如下

6、通过上一步得到的mIClientAidlInterface就可以调用远端的函数了

7、哦哦、忘了还没有绑定服务,为方便简单说明,我们直接在onCreate里绑定远端服务吧,如下:

8、客户端到此也完成了,看后面的全部代码试着写一下吧

四、代码

客户端:

服务端:

五、完整代码下载地址

https://download.csdn.net/download/wintergoes/11200474

六、其他问题

1、为什么byte[]数组不能作为参数传递?

传递byte数组时需要添加上in、out、inout修饰符,如下:

 

 Posted by on 2019-02-24
2月 222019
 

  本文基于Android4.4版本源码进行分析。

  一直以为ActivityThread是一个继承自Thread类的子线程,今天初看这个类发现里面的业务逻辑这么多,看了看网上的其他文章,原来这个Thread指的是Android应用的主线程啊。

问:安卓应用的入口函数是哪个?

答:Application.onCreate。错错错

正确的答案是ActivityThraed的main函数。

Android应用入口,ActivityThread.main  

下面咱们就看看ActivityThread.main函数:

首先,第一步启动SamplingProfilerIntegration,这个封装类集成了Dalvik的性能分析工具,用于监测记录应用的性能参数?待进一步查看代码
  相关源码:./frameworks/base/core/java/com/android/internal/os/SamplingProfilerIntegration.java
./frameworks/base/services/java/com/android/server/SamplingProfilerService.java
./libcore/dalvik/src/main/java/dalvik/system/profiler/SamplingProfiler.java
紧接着CloseGuard.setEnabled(false); 
  CloseGuard类实现了一种机制用于检查是否有内存泄露,默认是关闭,可以通过setEnabled(true)开启。
  源码路径:libcore/dalvik/src/main/java/dalvik/system/CloseGuard.java
Environment.initForCurrentUser();初始化Environment类,主要是一些目录的设置,比如我们通常用的获取外部存储路径函数Environment.getExternalStorageDirectory()的返回值就是在这里进行初始化的。
   源码路径:libcore/luni/src/main/java/libcore/io/EventLogger.java
EventLogger.setReporter(new EventLoggingReporter());
  没看懂怎么用的
  相关源码:libcore/luni/src/main/java/libcore/io/EventLogger.java
Security.addProvider(new AndroidKeyStoreProvider());
  为应用添加安全检测管理器,使用AndroidKeyStoreProvider,keystore就是指打release包时的数字证书吧
 

相关源码:frameworks/base/keystore/java/android/security/AndroidKeyStoreProvider.java
frameworks/base/keystore/java/android/security/AndroidKeyStore.java

Process.setArgV0(“<pre-initialized>”);
  因为应用还未启动完成,先给进程设置一个名字为<pre-initialized>
  相关源码:frameworks/base/core/java/android/os/Process.java
Looper.prepareMainLooper();
  将当前线程初始化为一个Looper,用Looper来管理线程内的各种请求。并将该Looper做为程序的主Looper。
  相关源码:frameworks/base/core/java/android/os/Looper.java
ActivityThread thread = new ActivityThread();
thread.attach(false);
   
   
AsyncTask.init();
  初始化AsyncTask,这是一个静态函数,由此可见AsyncTask的串行执行。
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, “ActivityThread”));
}
   
Looper.loop();
  开始循环主线程里的MessageQueue
 Posted by on 2019-02-22
6月 282018
 
1.简单介绍

Android.mk是Android源码编译系统的Makefile,用于编译系统中的C++和Java的动态库\静态库\可执行文件和apk等.
其大概格式如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Calculator
include $(BUILD_PACKAGE)

##################################################
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libarity:arity-2.1.2.jar
include $(BUILD_MULTI_PREBUILT)

# Use the folloing include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))

2.常用语法格式介绍

上面的示例中共涉及到三类语法
1)变量的定义,比如其中的LOCAL_PATH为定义的变量,可以在其他地方被调用
变量不是必须全部大写或者必须以LOCAL_开头,可以是其他形式的,因为安卓的编译系统会加载所有的mk文件到一个环境里面,所以定义变量应该加上一个特殊的前缀,防止覆盖一些全局的变量.
2)my-dir为mk系统中预定义的宏,通过$(call my-dir)来调用
mk系统中还定义了很多其他的宏,这些定义均在build/core/definitions.mk中,有兴趣的可以浏览一下这个文件
3)include语法包含其他的mk文件
我们可以看到示例中有一个include $(BUILD_PACKAGE),其实BUILD_PACKAGE是在buile/core/config.mk中定义一个变量,如下:
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
这一行代码其实是把package.mk包含到了编译步骤中,用于编译Calculator这个apk
4)shell命令

3.mk文件结构介绍

1)通常都以LOCAL_PATH开始,指定当前工程的路径,一般也是使用my-dir宏指定,如下:
LOCAL_PATH := $(call my-dir)

2)编写具体模块编译脚本
首先确定编译模块的类型,是静态c++库\动态C++库还是可执行程序,或者jar包或者apk,参见"模块编译类型定义"部分.
a. 一个mk文件中可以编译多种类型的模块,每个模块一般都是以include $(CLEAR_VARS)开始
CLEAR_VARS实际上是引用的build/core/clear_vars.mk文件,用于清除部分以LOCAL_开始的变量(不会清除LOCAL_PATH),具体可以浏览clear_vars.mk

b. 然后定义编译这个模块所需要用到的一些LOCAL_变量,比如如下:
LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava  #编译apk用到的静态库
LOCAL_SRC_FILES := $(call all-java-files-under, src) # 要编译的源码
LOCAL_PACKAGE_NAME := Calculator #包名

c. include + 编译类型 结尾,如:
include $(BUILD_PACKAGE)

4.模块编译类型定义

mk系统支持多种类型的编译,这些类型都在build/core/config.mk中定义,每种编译类型由一个特定的mk文件去处理,如下是在Android4.4系统中抓取的编译类型定义.
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE – 构建一个Android apk
BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk

5. Local变量介绍

LOCAL_PATH – 工程路径,通常为$(call my-dir),代表本目录和所有子目录

LOCAL_SRC_FILES – 项目源文件,不只是c或者java代码,也可以是apk或者so等文件,可添加多个,使用\加换行连接多个源文件

LOCAL_MODULE_CLASS – 可以为以下值:EXECUTABLES、FIRMWARE、SHARED_LIBRARIES、ETC、APPS、STATIC_LIBRARIES、NATIVE_TESTS、JAVA_LIBRARIES、FAKE、HEADER_LIBRARIES等

LOCAL_MODULE_TAGS – 在哪些系统版本下编译此项目,可以为eng、user、debug、tests、optional,optional表示在所有版本下都

LOCAL_MODULE – 项目名称

LOCAL_CERTIFICATE – 项目签名类型,可以为testkey、platform、shared、media、PRESIGNED(使用原签名),platform代表为系统应用

LOCAL_MODULE_PATH – 项目输出路径

LOCAL_PRIVILEGED_MODULE – 不设置或者设置为false,安装位置为system/app,如果设置为true,则安装位置为system/priv-app

LOCAL_MODULE_SUFFIX – module的后缀,可不设置

LOCAL_DEX_PREOPT – 是否对apk或者jar包进行odex优化,不设置代表默认优化,设置为false代表不优化

LOCAL_JACK_ENABLED – 有三种模式:full、incremental、disabled

 Posted by on 2018-06-28

gradle命令大全

 分类:Android, Java, Others, Others 阅读 (1,058)  No Responses »
6月 182018
 

一、任务相关基本命令

  1. 查看所有任务

  2. 如果你的项目有多个模块,只想查看某个模块,使用如下命令(app为模块的名称):

  3. 显示任务的详细信息

  4. 执行一个任务

二、一些可能用到的辅助任务命令,这些任务名称会显示在./gradlew tasks的执行结果中

  1. 显示项目的Android依赖树

  2. 显示项目的源码定义

  3. 显示项目的签名信息

  4. 打印子模块列表

  5. 打印项目中用到的所有依赖树

三、其他命令

  1. 查看gradle版本和构建环境信息

 

 

 

 Posted by on 2018-06-18

Android开机动画修改记录

 分类:Android, Java 阅读 (251)  Android开机动画修改记录已关闭评论
5月 272018
 
一、概述

需要修改bootanimation.zip

这个文件一般位于下面几个位置:

#define USER_BOOTANIMATION_FILE “/data/local/bootanimation.zip”
#define SYSTEM_BOOTANIMATION_FILE “/system/media/bootanimation.zip”
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE “/system/media/bootanimation-encrypted.zip”

二、压缩包目录结构

|-part0
|-part1
|-desc.txt

1、关于part0和part1目录,安卓开机动画分成两个阶段(目录名字应该是可以随便命名的,在desc.txt里指定目录的名字就可以):

part0里的为第一阶段,按设定的帧率播放动画

part1为第二阶段,如果动画播放完还没启动完成,就循环播放这一段动画

2、关于desc.txt

文件内容如下:

506 505 15
p 1 0 part0 #000000 10 10
p 0 0 part1
s 1 /system/media/poweron.ogg

第一行506为动画图片的宽度,505为动画图片的高度,15为每秒播放的图片数

第二行:第二个参数为循环次数(0应该为无限循环?),第三个参数为暂时时间(不清楚具体运行原理)?,第四参数为图片目录,第五个参数为背景色,第六七参数为显示时钟的坐标,其中五六七参数可以不写

三、注意事项

1、将制作好的素材压缩时,要设置压缩率为0,即不压缩,只是打个zip包。即在winrar中压缩方式选择“存储”,在ubuntu使用zip命令的时候,加上-0选项

 Posted by on 2018-05-27
5月 252018
 

  Settings Provider是指通过如下方式设置的系统变量数据库

  Settings共有三种分类,分别如下:

  • Global:所有的偏好设置对系统的所有用户公开,第三方APP有读没有写的权限;
  • System:包含各种各样的用户偏好系统设置;
  • Secure:安全性的用户偏好系统设置,第三方APP有读没有写的权限。

  当我们调试时,需要查看设置里面的值,通过调试程序会比较慢,其实我们通过adb就可以查看,命令行如下:

  其中的get system可以根据设置的具体情况改成get global或者get secure

  如果返回null说明没有这个选项

  当然我们也可以设置相关选项的值,通过put命令,示例如下: