系列文章目录
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");}@Overridepublic 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;}}}@Overridepublic int startVideo(String url) {if(display == 0){//没有拿到屏幕信息Slog.i("startVideo-->display", "没有拿到屏幕信息" + display);return -1;}else{// 启动客显屏ActivityIntent 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;}}}@Overridepublic int startImage(String url) {if(display == 0){//没有拿到屏幕信息Slog.i("startImage-->display", "没有拿到屏幕信息" + display);return -1;}else{// 启动客显屏ActivityIntent 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;}}}@Overridepublic 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<OtaManager>() {@Overridepublic 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慢慢研究,慢慢深入,日后都是大牛。


















