Android系统启动 ---- 主要流程类_MrDarly的博客-CSDN博客Android系统启动Zygote关系主要的类https://blog.csdn.net/weixin_68948960/article/details/125310042
前言
Android系统开发之系统服务开发。
问题:用户操作无界面,但是需要Android启动时,操作服务也进行启动,跟随系统关闭服务关闭。该服务提供打开某个APP功能,调用打开APP进行副屏投屏功能。移交给其他APP进行调用开启。系统提供服务,其他APP进行调用打开。
一、系统服务
Android开发过程中经常会用到各种各样的系统管理服务,
如进行窗口相关的操作会用到窗口管理服务WindowManager,
进行电源相关的操作会用到电源管理服务PowerManager,
还有很多其他的系统管理服务,如通知管理服务NotifacationManager、振动管理服务Vibrator、电池管理服务BatteryManager
这些Manager提供了很多对系统层的控制接口。对于App开发者,只需要了解这些接口的使用方式就可以方便的进行系统控制,获得系统各个服务的信息,而不需要了解这些接口的具体实现方式。而对于Framework开发者,则需要了解这些Manager服务的常用实现模式,维护这些Manager的接口,扩展这些接口,或者实现新的Manager。
Android中的系统服务分为两个部分:
1、C或C++层实现Service Framework。
2、Java层实现Service Framework
本次新加的系统服务就是Java层Service Framework。
由于本人对C和C++不熟悉,现阶段无法进入更深层次的Native Service Framework,所以只是浅层的进行Java Service Framework进行调整和增加。
二、实现步骤 1、环境搭建想进行Framework层开发,需要搭建基本的开发环境。本小节介绍环境的搭建
工具:Android Studio Ubuntu 系统。
默认已经参考网上教程已经下载好AOSP原始代码,并切编译成功。
第一步:生成iml和ipr文件
source build/envsetup.sh lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target make idegen development/tools/idegen/idegen.sh
情况一:代码在远程Ubuntu服务器中,电脑在本地使用putty进行链接操作,所有编译都在远程进行。由于我们只调整Framework代码,AOSP其他代码都不用同步到本地,当然网络好的情况下,直接打开也可以。
情况二:本地电脑是Ubuntu系统,代码下载到本地电脑,并使用Ubuntu进行了编译,安装了Android Studio工具,电脑性能可观可以进行全量打开,当然最好还是只打开我们调整的framework目录。
第二步:代码导入到Android Studio
在Project Structure下进行代码关联
选择源码位置进行关联,可以分目录,分文件进行关联,也可以一次性全部关联。AOSP代码在远程这里的错误可以不理会。AOSP代码在本地这里没有错误展示。
点击保存,进行代码同步关联后,查看frameworks中的代码就可以进行跳转,查看。
到此为止,可以在Android Studio中进行编写代码了,这里不能进行编译,需要在Ubuntu下使用命令进行编译。
2、代码分析第一步:分层
服务层
Java Service Framework没有Service Manager统一的管理类, 所以要单独自行实现一个Manager(应用可以获取该服务,并进行调用的管理类)
xxxManager源码位置
RPC层
AIDL编写的接口,系统编译器自动生成服务代理和服务Stub。直接可用Stub和Stub.Proxy
aidl源码位置
IPC层
新增的服务和Stub.Proxy通过Binder IPC进行交互。调用JNI也属于IPC层
xxxService 实现aidl的源码位置
代码包总览如下图:
第二步:调整代码
在frameworks/base/core/java/android/app/目录下新建ota文件夹,
存放两个类IOtaService.aidl文件和OtaManager.java文件
IOtaService.aidl是RPC层
package android.app.ota;
//测试OTA 第一步:添加接口
interface IOtaService{
int initDisplay();
int startVideo(String url);
int startImage(String url);
void openMediaCenter();
}
OtaManager.java是服务层
package android.app.ota;
import android.util.Slog;
import android.os.RemoteException;
import android.annotation.SystemService;
import android.content.Context;
//测试OTA 第三步:添加系统服务的Manager
public class OtaManager {
private final IOtaService mService;
public static final int SENT_STREAM_VIDEO = 0;
public static final int SENT_STREAM_IMAGE = 1;
public static final int SENT_STREAM_TEXT = 2;
public OtaManager(IOtaService mService) {
this.mService = mService;
}
public int initDisplay() {
int result = 0;
try {
result = mService.initDisplay();
Slog.i("OtaManager", "IOtaService getCpuTemperature:" + result);
} catch (RemoteException ex) {
ex.printStackTrace();
}
return result;
}
public int setInputFlowerToDisplay(String url, int type) {
int result = 0;
try {
if (type == SENT_STREAM_VIDEO) {
result = mService.startVideo(url);
} else if (type == SENT_STREAM_IMAGE || type == SENT_STREAM_TEXT) {
result = mService.startImage(url);
}
Slog.i("OtaManager", "setInputFlowerToDisplay:" + result);
} catch (RemoteException ex) {
ex.printStackTrace();
}
return result;
}
public void openMediaCenter(){
try {
mService.openMediaCenter();
Slog.i("OtaManager", "openMediaCenter");
} catch (RemoteException ex) {
ex.printStackTrace();
}
}
}
在frameworks/base/services/core/java/com/android/server/目录下,新建ota文件夹存放OtaManagerService.java是IPC层
package com.android.server.ota;
import android.hardware.display.DisplayManager;
import android.view.Display;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.app.ota.IOtaService;
import android.content.Context;
import android.util.Slog;
//测试OTA 第二步:添加系统服务,实现aidl文件的接口
public class OtaManagerService extends IOtaService.Stub {
private Context mContext;
private int display = 0;
public OtaManagerService(Context context) {
mContext = context;
Slog.d("OTAManagerService", "Construct");
}
@Override
public int initDisplay() {
DisplayManager mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);//屏幕管理类
Slog.i("initDisplay-->DisplayManager", "获取DisplayManager" + mDisplayManager);
if(mDisplayManager == null){
return -1;
}else{
Display[] displays = mDisplayManager.getDisplays(); //得到显示器数组
Slog.i("initDisplay-->Display", "获取Display显示器数组" + displays);
if (displays != null && displays.length >= 2) {
display = displays[1].getDisplayId();
return display;
} else {
return -1;
}
}
}
@Override
public int startVideo(String url) {
if(display == 0){
//没有拿到屏幕信息
Slog.i("startVideo-->display", "没有拿到屏幕信息" + display);
return -1;
}else{
// 启动客显屏Activity
Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.darly.otamedia");
Slog.i("startVideo-->intent", "拿到的Intent数据" + intent);
if (intent != null) {
intent.putExtra("video_url", url);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(display);
mContext.startActivity(intent, options.toBundle());
return 100;
}else{
return -1;
}
}
}
@Override
public int startImage(String url) {
if(display == 0){
//没有拿到屏幕信息
Slog.i("startImage-->display", "没有拿到屏幕信息" + display);
return -1;
}else{
// 启动客显屏Activity
Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.darly.otamedia");
Slog.i("startImage-->intent", "拿到的Intent数据" + intent);
if (intent != null) {
intent.putExtra("image_url", url);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(display);
mContext.startActivity(intent, options.toBundle());
return 100;
}else{
return -1;
}
}
}
@Override
public void openMediaCenter() {
Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.android.htmlviewer");
Slog.i("openMediaCenter-->intent", "拿到的Intent数据" + intent);
if (intent != null) {
mContext.startActivity(intent);
}
}
}
第三步:注册以及绑定
在frameworks/base/core/java/android/content/Context.java中增加新标签
//测试OTA 第四步:添加OTA_SERVICE常量
public static final String OTA_DM_SERVICE = "ota_dm";
在frameworks/base/core/java/android/app/SystemServiceRegistry.java中将新服务注册到系统中
//测试OTA 第五步:将实现的服务注册到系统中去
registerService(Context.OTA_DM_SERVICE, OtaManager.class,
new CachedServiceFetcher() {
@Override
public OtaManager createService(ContextImpl ctx) {
IBinder dm = ServiceManager.getService(Context.OTA_DM_SERVICE);
return new OtaManager(IOtaService.Stub.asInterface(dm));
}});
在frameworks/base/services/java/com/android/server/SystemServer.java的startOtherServices方法中进行IPC层注册和启动
//测试OTA 第六步:将注册的服务设置成开机启动服务
t.traceBegin("OtaManagerService");
ServiceManager.addService(Context.OTA_DM_SERVICE, new OtaManagerService(context));
t.traceEnd();
第四步:查看编译
首先查看Ubuntu下,修改文件的编码格式是不是UTF-8,其次查看文件权限是不是被调整。
其次进行如下操作,进行编译,将增加修改的代码编译到System.img中
source build/envsetup.sh lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target make update-api # 完成后,进行整体项目编译 make -j6
编译完成后,查看对应out目录下找到img文件。
3、运行调试情况一:有实体手机,运行烧录到手机中,测试APP中使用
OtaManager manager = (OtaManager) context.getSystemService(Context.OTA_DM_SERVICE);
获取调用,输出日志正常。
情况二:无实体手机,如果代码本地,直接启动虚拟机。测试APP中使用
OtaManager manager = (OtaManager) context.getSystemService(Context.OTA_DM_SERVICE);
进行调用,输出日志正常。
总结
其实如果只是Java代码,针对Android应用开发的朋友还是比较轻松的。AOSP 的Framework层概念比较多,有时候就是简单的一个调用,书本中能写一两页,赋予不同的名称不同的功能。看书和代码同步进行是最快的学习方式。
由于Framework层动不动就调到Native层代码,但AOSP源码超级大,导致源码查找不方便,学习成本增加。Native层代码看懂还真不容易。而且更多的是调用到内核中,更让人看不懂。所以学习Framework层,还是先从Java开始,遇到Native慢慢研究,慢慢深入,日后都是大牛。



