一、系统源码下载编译
1、下载AOSP源码
基于 AOSP 的开发推荐选择是 Ubuntu 系统。如果不选择 Ubuntu 系统,也可以使用 Deepin、Debian 等环境相似的系统。假设你对AOSP 有一定的了解,但还没有真正实践,请按照下面的步骤操作。
- 在开始之前,我们先安装编译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
2. 如果你电脑没有repo工具需要先安装 repo 工具,命令如下
mkdir ~/bin
# 使用tuna镜像下载repo
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o ~/bin/repo
chmod +x ~/bin/repo
# 以下这条命令可以添加到 `~/.bashrc` 文件中
export PATH=~/bin:$PATH
3. 假设电脑已经包含了git工具,接下来需要同步源代码,命令如下
mkdir aosp
cd asop
# 初始化repo,指定源码分支为 `android-10.0.0_r41`
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-10.0.0_r41
# 同步远程代码
repo sync
4. 同步源码的耗时较长,耐心等待即可。源码同步完成后,即可进行第二步以后的操作。
2、编译AOSP并启动模拟器
- 初始化 AOSP 编译的目标运行设备,这里我们选择 aosp_x86_64-eng
# 初始化环境
source build/envsetup.sh
# 选择编译目标
lunch aosp_x86_64-eng
终端输出信息如下
liuzhi@liuzhi-HP:~/aosp$ lunch aosp_x86_64-eng
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=10
TARGET_PRODUCT=aosp_x86_64
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_ARCH=x86_64
TARGET_ARCH_VARIANT=x86_64
TARGET_2ND_ARCH=x86
TARGET_2ND_ARCH_VARIANT=x86_64
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-6.8.0-45-generic-x86_64-Ubuntu-24.04.1-LTS
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=QQ3A.200805.001
OUT_DIR=out
============================================
2. 编译
# 使用 make 数值 的命令进行指定线程数编译,也可以使用 m 命令自动选择最大线程数
make -j$(nproc)
3. 编译完成之后,使用如下命令启动模拟器
emulator
二、预装系统内置app,配置系统权限
1、基础说明
预置apk进入到五个特定目录,提取每个apk所包含的so文件。各目录对应的apk和so文件的安装路径不同,如下所示:
将应用添加到系统中,编译前只有packages/apps 目录可以存放应用
编译后有如下五个目录,在配置Android.mk文件,可以将应用编译到如下目标文件:
-
/system/app 用于存放系统应用,不能卸载
-
/systme/priv-app Android4.4+ 新增,系统 [ 核心 ] 应用存放路径(最高权限)
-
/vendor/app 用于存放厂商应用,可以卸载,恢复出厂时恢复
-
/data/app 用于存放用户应用,可以卸载,恢复出厂时不能恢复
-
/data/app-private Android4.4+ 新增,受 DRM(数字版权管理) 保护的应用存放路径
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#Palmstore为应用名称
LOCAL_MODULE := Palmstore
# P用来指定该app在编译什么样子的版本的时候会被安装到机器上;
# Puser: 指该模块只在user版本下才编译
# Peng: 指该模块只在eng版本下才编译
# Ptests: 指该模块只在tests版本下才编译
# Poptional:指该模块在所有版本下都编译
LOCAL_MODULE_TAGS := optional
# Palmstore.apk为安装包文件名,这里也可以用$(LOCAL_MODULE).apk代替
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
#在采用预装这种形式的时候,该变量来指定预装的模块的类型,此处为APPS;
LOCAL_MODULE_CLASS := APPS
#不用定义,module的后缀,=.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
#决定了其编译后的在ROM中的安装位置:
#如果不设置或者设为false,安装位置为system/app;
#如果设置为true,安装位置为system/priv-app。
LOCAL_PRIVILEGED_MODULE := true
#LOCAL_CERTIFICATE 参数说明
#1.testkey:普通APK,默认情况下使用。
#2.platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
#3.shared:该APK需要和home/contacts进程共享数据。
#4.media:该APK是media/download系统中的一环。
#5.PRESIGNED:使用apk原来的签名(这里应为是第三方应用,所以直接使用原签名)。
LOCAL_CERTIFICATE := PRESIGNED
#手动解压lib文件到当前apk的编译目录并添加
LOCAL_PREBUILT_JNI_LIBS := \
lib/$(my_src_arch)/libBugly_Native.so
#指定目标lib库的类型 可选值arm/arm x86/arm64
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
参考文档:mp.weixin.qq.com/s/LfNVJ_Sha…
2、内置无源码apk
-
新建应用文件夹**
Palmstore**- 进入到**
aosp/packages/apps目录,新建Palmstore**文件夹
- 进入到**
-
拷贝应用安装包到指定目录 将应用安装包**
Palmstore.apk文件拷贝到aosp/packages/apps/Palmstore**目录下 -
新建**
Android.mk配置文件 在该目录新建Android.mk**文件,输入如下内容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Palmstore
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PRIVILEGED_MODULE := true
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_PREBUILT_JNI_LIBS := \
lib/$(my_src_arch)/libBugly_Native.so
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
4. 添加so库文件,如果没有不需要此步骤
手动解压lib文件到当前apk的编译目录并添加
LOCAL_PREBUILT_JNI_LIBS := \
lib/$(my_src_arch)/libBugly_Native.so
最终Palmstore目录如下
- 添加系统权限
编译到系统priv-app下面要修改frameworks/base/data/etc/privapp-permissions-platform.xml增加
<privapp-permissions package="com.transsnet.store">
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<permission name="android.permission.READ_EXTERNAL_STORAGE"/>
<permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<permission name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<permission name="android.permission.INSTALL_PACKAGES"/>
<permission name="android.permission.DELETE_PACKAGES"/>
<permission name="android.permission.READ_INSTALL_SESSIONS"/>
<permission name="android.permission.MANAGE_APP_OPS_MODES"/>
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
</privapp-permissions>PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
6. 将 Palmstore 添加到系统编译配置文件中 打开/home/liuzhi/aosp/build/target/product/product/aosp_x86_64.mk文件,在PRODUCT_PACKAGES中添加自己的app名称:
PRODUCT_PACKAGES += \
Palmstore \
#实测这个需要加上,否则编译报错
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST +=\
systme/priv-app/Palmstore/Palmstore.apk \
7. 重新编译即可完成应用内置
- 应用下载自动安装,现场演示
三、添加系统服务
1、添加系统服务 showme
- 添加aidl接口,编辑文件frameworks/base/core/java/android/os/IShowmeManager.aidl
package android.os;
/** @hide */
interface IShowmeManager
{
String getVal();
}
2. aidl 添加到 android.bp,编辑文件frameworks/base/Android.bp
java_defaults {
name: "framework-defaults",
installable: true,
srcs: [
// From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
"core/java/**/*.java",
"graphics/java/**/*.java",
"core/java/android/os/IShowmeManager.aidl",
"core/java/android/permission/IPermissionController.aidl",
":keystore_aidl",
3. 创建service文件,也就是aidl的具体实现
- 首先在frameworks/base/services/core/java/com/android/server/中创建showme文件夹
- 再在showme文件夹中添加ShowmeManagerService.java文件
frameworks/base/services/core/java/com/android/server/showme/ShowmeManagerService.java
package com.android.server.showme;
import com.android.server.SystemService;
import android.content.Context;
import android.util.Log;
import java.util.HashMap;
import android.os.IShowmeManager;
public final class ShowmeManagerService extends IShowmeManager.Stub{
private static final String TAG = "ShowmeManagerService";
final Context mContext;
public ShowmeManagerService(Context context) {
mContext = context;
}
@Override
public String getVal(){
try{
Log.d(TAG, "GetFromJni ");
return "GetFromJni showme ";
}catch(Exception e){
Log.d(TAG, "nativeReadPwd Exception msg = " + e.getMessage());
return " read nothings!!!";
}
}
}
4. 将ShowmeManagerService添加到系统服务管理器中,
编辑文件frameworks/base/services/java/com/android/server/SystemServer.java
导入具体实现
import com.android.server.showme.ShowmeManagerService;
在private void startOtherServices()中添加服务
ShowmeManagerService showmeManagerService = null;
// ShowmeManagerService begin
traceBeginAndSlog("StartShowmeManService");
try {
if(showmeManagerService==null){
showmeManagerService = new ShowmeManagerService(context);
}
ServiceManager.addService("showme", showmeManagerService);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting ShowmeManagerService ", e);
}
traceEnd();
// ShowmeManagerService end
5. 创建可由外部使用的接口
frameworks/base/core/java/android/os/ShowmeManager.java
package android.os;
import android.annotation.SystemService;
import android.content.Context;
import android.util.Log;
import android.os.Handler;
import android.os.SystemProperties;
import java.io.IOException;
import java.io.DataInputStream;
//@SystemService(Context.SHOWME_SERVICE)
public final class ShowmeManager {
private static final String TAG = "ShowmeManager";
final Context mContext;
final IShowmeManager mService;
final Handler mHandler;
/**
* {@hide}
*/
public ShowmeManager(Context context, IShowmeManager service, Handler handler) {
mContext = context;
mService = service;
mHandler = handler;
}
public String getVal() {
Log.d(TAG,"ShowmeManager getVal ");
try {
return mService.getVal();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
6. 在Context 配置接口名称
frameworks/base/core/java/android/content/Context.java
public static final String SHOWME_SERVICE = "showme";
@StringDef(suffix = { "_SERVICE" }, value = {
VIBRATOR_SERVICE,
SHOWME_SERVICE,
7. 注册服务
frameworks/base/core/java/android/app/SystemServiceRegistry.java
import android.os.ShowmeManager;
import android.os.IShowmeManager;
// 在 final class SystemServiceRegistry 的静态块中添加
registerService(Context.SHOWME_SERVICE, ShowmeManager.class,
new CachedServiceFetcher<ShowmeManager>() {
@Override
public ShowmeManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.SHOWME_SERVICE);
IShowmeManager service = IShowmeManager.Stub.asInterface(b);
return new ShowmeManager(ctx.getOuterContext(),
service, ctx.mMainThread.getHandler());
}});
8. 新增service “showme” 的 selinux配置策略
在文件system/sepolicy/private/service_contexts中添加如下内容
showme u:object_r:showme_service:s0
在文件system/sepolicy/prebuilts/api/29.0/private/service_contexts中添加如下内容
showme u:object_r:showme_service:s0
在文件system/sepolicy/public/service.te中添加如下内容
type showme_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
在文件system/epolicy/prebuilts/api/29.0/public/service.te中添加如下内容
type showme_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
注意:如下两个文件中的内容必须完全一致,多一行空格都不行
system/sepolicy/public/service.te
system/epolicy/prebuilts/api/29.0/public/service.te
- 更新接口与并编译
source build/envsetup.sh
#ulimit -S -n 2048 如果报错内存不足,则需要
lunch aosp_x86_64-eng
# 更新接口
make update-api
# 编译
make SELINUX_IGNORE_NEVERALLOWS=true -j16
验证服务是否添加成功
adb shell service list | grep showme
2、app 使用系统服务
目录aosp/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates中的class.jar导入到android studio
示例代码如下
ShowmeManager showmeManager = (ShowmeManager) getApplicationContext().getSystemService("showme");
String result = showmeManager.getVal();
Log.v("my_serviec","showme result = " + result);
四、调试系统源码
Android Studio导入系统源码
- 生成对应的android.ipr和android.iml文件
make idegen -j4
sudo chmod 777 android.iml android.ipr
2. 有了ipr和iml,删减一部分android.iml的内容,主要原因源码太多,要排除部分没用项目,还有就是依赖部分只留下自己moudle就可以
把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$/compatibility" />
<excludeFolder url="file://$MODULE_DIR$/cts" />
<excludeFolder url="file://$MODULE_DIR$/dalvik" />
<excludeFolder url="file://$MODULE_DIR$/developers" />
<excludeFolder url="file://$MODULE_DIR$/developers/samples" />
<excludeFolder url="file://$MODULE_DIR$/development" />
<excludeFolder url="file://$MODULE_DIR$/device" />
<excludeFolder url="file://$MODULE_DIR$/device/google" />
<excludeFolder url="file://$MODULE_DIR$/device/sample" />
<excludeFolder url="file://$MODULE_DIR$/docs" />
<excludeFolder url="file://$MODULE_DIR$/external" />
<excludeFolder url="file://$MODULE_DIR$/flashing-files" />
<excludeFolder url="file://$MODULE_DIR$/frameworks/base/docs" />
<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$/out/soong/.intermediates" />
<excludeFolder url="file://$MODULE_DIR$/pdk" />
<excludeFolder url="file://$MODULE_DIR$/platform_testing" />
<excludeFolder url="file://$MODULE_DIR$/prebuilt" />
<excludeFolder url="file://$MODULE_DIR$/prebuilts" />
<excludeFolder url="file://$MODULE_DIR$/sdk" />
<excludeFolder url="file://$MODULE_DIR$/shortcut-fe" />
<excludeFolder url="file://$MODULE_DIR$/system" />
<excludeFolder url="file://$MODULE_DIR$/test" />
<excludeFolder url="file://$MODULE_DIR$/toolchain" />
<excludeFolder url="file://$MODULE_DIR$/tools" />
3. 把orderEntry标签都删除,只剩下如下两个即可以,这样跳转时候就不会跳其他jar
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="jdk" jdkName="Android API 33 Platform" jdkType="Android SDK" />
4. 使用Android studio打开,选择android.ipr
- 等待同步完成,设置断点