【二】车载FrameWork添加系统服务

自定义系统服务

常见的AMS、PWS、WMS等等都是系统服务,运行于system_server进程,并且向servicemanager进程注册其Binder以便其他进程获取binder与对应的服务进行通信。为了新增自定义系统服务,我们可以参考AMS等原生系统服务编写如下文件:

1、AIDL文件:生成Binder类,其中Stub即为Binder的服务端;

2、XXManagerService:系统服务类,继承自Stub;

3、XXManager:封装了AIDL接口方法的类,相当于Binder客户端(Proxy),其他进程通过此类完成与系统服务的通信。

增加系统服务

1、AIDL

在frameworks/base/core/java/com/enjoy/service中编写IEnjoyManager.aidl

// IEnjoyManager.aidl
package com.enjoy.service;

// Declare any non-default types here with import statements

interface IEnjoyManager {
   void sendMessage(String msg);
}

在frameworks/base/Android.mk中声明AIDL文件:

LOCAL_SRC_FILES += ....
    core/java/android/app/IActivityManager.aidl \
    core/java/com/enjoy/service/IEnjoyManager.aidl \
    ....

2、系统服务

在frameworks/base/services/core/java/com/enjoy/service中编写EnjoyManagerService.java

package com.enjoy.service;

import android.os.RemoteException;
import android.util.Log;

public class EnjoyManagerService extends IEnjoyManager.Stub {

    private static final String TAG = "Enjoy";

    @Override
    public void sendMessage(String msg) throws RemoteException {
        Log.i(TAG, "sendMessage: " + msg);
    }
}

3、客户端代理

在frameworks/base/core/java/com/enjoy/service下编写EnjoyManager.java

package com.enjoy.service;

import android.os.RemoteException;
import android.util.Log;

public class EnjoyManager {

    private static final String TAG = "Enjoy";
    private IEnjoyManager service;

    public EnjoyManager(IEnjoyManager service) {
        this.service = service;
    }

    public void sendMessage(String msg) {
        try {
            service.sendMessage(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

framework/base/Android.mk:

packages_to_document := \
	android \
	javax/microedition/khronos \
	org/apache/http/conn \
	org/apache/http/params \
  	com/enjoy/service

4、修改Context

在frameworks/base/core/java/android/content/Context.java中加入常量:

public static final String ENJOY_SERVICE="enjoy";

5、注册系统服务

在frameworks/base/services/java/com/android/server/SystemServer.java中 注册系统服务

import com.enjoy.service.EnjoyManagerService;
private void startOtherServices(){
    //......
	ServiceManager.addService(Context.ENJOY_SERVICE,new EnjoyManagerService());
    //......
}

6、注册应用系统服务获取器

在frameworks/base/core/java/android/app/SystemServiceRegistry.java注册服务获取器:

import com.enjoy.service.IEnjoyManager;
import com.enjoy.service.EnjoyManager;
static{
    registerService(Context.ENJOY_SERVICE, EnjoyManager.class,
                new CachedServiceFetcher<EnjoyManager>() {
            @Override
            public EnjoyManager createService(ContextImpl ctx) throws ServiceNotFoundException  {
		 // 获取服务
		IBinder b = ServiceManager.getServiceOrThrow(Context.ENJOY_SERVICE);
		IEnjoyManager service = IEnjoyManager.Stub.asInterface(b);
                return new EnjoyManager(service);
            }});
}

7、配置SELinux权限

system/sepolicy/private/service_contexts

activity                                  u:object_r:activity_service:s0					   
enjoy                                     u:object_r:enjoy_service:s0

system/sepolicy/public/service.te:

type activity_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
type enjoy_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;

system/sepolicy/private/untrusted_app_all.te :

allow untrusted_app enjoy_service:service_manager find;

*8、配置白名单

如果以当前案例的方式新增自定义系统服务,因为SystemServiceRegistry 中需要使用到com.enjoy下的类,为了让其获取此包下类的引用,需要配置:build/core/tasks/check_boot_jars/package_whitelist.txt ,加入:com\.enjoy\..* 。否则会因为无法获取类引用而编译报错!

dalvik\..*
libcore\..*
android\..*
com\.android\..*
com\.enjoy\..*  

若新增的服务像AMS等原有系统服务的IActivityManager.aidl与ActivityManager一样放在android.app包下即可不用进行此步处理!

9、编译并刷机

#编译
make update-api
make –j4 
#刷机
adb reboot bootloader
reboot flashall -w

10、使用自定义服务

10.1 利用双亲委托机制

在需要使用自定义服务的app中编写EnjoyManager(包名与framework中一致):

package com.enjoy.service;

import android.os.RemoteException;
import android.util.Log;

public class EnjoyManager {

    public void sendMessage(String msg) {
       
    }
}

此时由于类加载的双亲委托机制,app在运行时实际使用的是framework中的EnjoyManager。app中的EnjoyManager仅仅只是为了编译成功编写的空壳。

10.2 修改SDK

修改app使用的sdk,可以通过make sdk 将SDK完成编译出来。也可以直接在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates中找到EnjoyManager类将其加入原生SDK中的android.jar

SystemService

系统服务需要通过ServiceManager.addService("xx", new XXManagerService);将自己(Binder Stub)注册进入SM才能够让其他进程利用Binder与之通信。而自定义系统服务如果需要根据系统启动的不同阶段进行不同的处理则需要注册生命周期回调。以AMS为例:

/frameworks/base/services/java/com/android/server/SystemService中启动AMS:

private void startBootstrapServices() {
    //...
    // Activity manager runs the show.
    traceBeginAndSlog("StartActivityManager");
    mActivityManagerService = mSystemServiceManager.startService(
                    ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    traceEnd(); 
    //...
    mActivityManagerService.setSystemProcess();
    //...
}

AMS中的setSystemProcess方法的实现为:

public void setSystemProcess() {
    //...
            
	ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
    
	//...
}

setSystemProcess中会完成向SM注册AMS的实现。而在setSystemProcess之前有一段代码:

 mActivityManagerService = mSystemServiceManager.startService(
                    ActivityManagerService.Lifecycle.class).getService();

则为注册生命周期监听,ActivityManagerService.Lifecycle就相当于生命周期的回调接口对象,它继承自:

/frameworks/base/services/core/java/com/android/server/SystemService。这个SystemService中主要需要实现两个方法:

  • onStart() :mSystemServiceManager.startService第一时间回调该函数。

  • onBootPhase(int phase) : 系统启动的各个阶段会回调该函数

    • SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY:这是一个依赖项,只有DisplayManagerService中进行了对应处理;
    • SystemService.PHASE_LOCK_SETTINGS_READY:经过这个引导阶段后,服务才可以接收到wakelock相关设置数据;
    • SystemService.PHASE_SYSTEM_SERVICES_READY:经过这个引导阶段 后,服务才可以安全地使用核心系统服务
    • SystemService.PHASE_ACTIVITY_MANAGER_READY:经过这个引导阶 段后,服务可以发送广播
    • SystemService.PHASE_THIRD_PARTY_APPS_CAN_START:经过这个引导阶段后,服务可以启动第三方应用,第三方应用也可以通过Binder来调用服务。
    • SystemService.PHASE_BOOT_COMPLETED:经过这个引导阶段后,说明服务启动完成,这时用户就可以和设备进行交互。

比如AMS中的Lifecycle:

public static final class Lifecycle extends SystemService {
   	 	@Override
        public void onBootPhase(int phase) {
            mService.mBootPhase = phase;
            if (phase == PHASE_SYSTEM_SERVICES_READY) {
                mService.mBatteryStatsService.systemServicesReady();
                mService.mServices.systemServicesReady();
            } else if (phase == PHASE_ACTIVITY_MANAGER_READY) {
                // 准备广播处理
                mService.startBroadcastObservers();
            } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
                mService.mPackageWatchdog.onPackagesReady();
            }
        }
}

在AMS中会处理PHASE_ACTIVITY_MANAGER_READY ,经过这个阶段后,也就是需要在下一个阶段PHASE_THIRD_PARTY_APPS_CAN_START才可以发送广播。

同步问题

在修改了SDK之后,可能出现同步错误:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

此时我们需要去修改AGP插件中的一个类:MockableJarGenerator

在我的工程当中当前使用的AGP版本为:7.2.1,从C:\Users\Administrator\.gradle\caches\modules-2\files-2.1\com.android.tools.build\builder\7.2.1 目录下找到builder-7.2.1-sources.jar 并将其解压,找到com.android.builder.testing 中的MockableJarGenerator。

将此类放入Android Studio工程app模块的单元测试中,并在app的gradle中加入:

dependencies {   
	testImplementation 'org.ow2.asm:asm:7.1'
    testImplementation 'org.ow2.asm:asm-commons:7.1'

    //    testImplementation 'com.google.guava:guava:23.6-jre'
    testImplementation group:'com.google.guava', name:'guava', version:'23.6-jre'
}

操作步骤为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后将C:\Users\Administrator\.gradle\caches\modules-2\files-2.1\com.android.tools.build\builder\7.2.1builder-7.2.1.jarMockableJarGenerator.class替换成刚刚编译的class文件。

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
车载ivi(In-Vehicle Infotainment)开发是指开发车辆中的娱乐和信息系统。在这个系统中,MCU(Microcontroller Unit,微控制器单元)和SOC(System-on-a-Chip,片上系统)是两个重要的组成部分。Framework(框架)则指的是一种开发的基础架构,提供了开发过程中的基本结构和工具。 在车载ivi开发中,MCU被用于控制硬件设备和外围接口,以及处理实时数据。它可以通过提供各种输入和输出接口来与其他设备进行通信,包括触摸屏、按钮、摄像头、声音系统等。MCU还可以处理来自传感器的数据,并根据这些数据控制车辆的不同功能,如温度控制、空调控制等。同时,MCU还与SOC之间通过总线进行通信,以便将数据传输到SOC进行处理。 SOC在车载ivi开发中扮演着处理和存储数据的角色。它集成了处理器、内存、图形加速器、网络接口等功能,可以高效地处理和管理各种媒体数据,如音频、视频、导航系统等。SOC还负责提供操作系统的支持和运行其他应用程序所需的资源。 在开发车载ivi系统时,需要使用框架来简化开发过程。这个框架提供了一套通用的库和工具,以便开发者可以更容易地构建和定制车载ivi应用程序。框架通常包括界面、控制逻辑、数据管理和硬件访问等基本模块,开发者可以在此基础上进行开发。通过使用框架,开发者可以节省时间和精力,实现系统的快速开发和调试。 综上所述,车载ivi开发中,MCU和SOC是实现系统功能的核心组件,而框架则是简化开发过程的基础架构。这些元素共同协作,为车载ivi系统开发和优化提供支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值