AOSP學(xué)習(xí)(四)Android13自定義系統(tǒng)服務(wù)

前言

我們?cè)陂_(kāi)發(fā)當(dāng)中難免要自定義一個(gè)系統(tǒng)服務(wù)去獲取系統(tǒng)數(shù)據(jù)或者操作,常見(jiàn)的AMS、PWS、WMS等等都是系統(tǒng)服務(wù),運(yùn)行于system_server進(jìn)程,并且向servicemanager進(jìn)程注冊(cè)其Binder以便其他進(jìn)程獲取binder與對(duì)應(yīng)的服務(wù)進(jìn)行通信。為了新增自定義系統(tǒng)服務(wù),我們可以參考AMS等原生系統(tǒng)服務(wù)編寫(xiě)如下文件:

1、AIDL文件:生成Binder類,其中Stub即為Binder的服務(wù)端;

2、XXManagerService:系統(tǒng)服務(wù)類,繼承自Stub;

3、XXManager:封裝了AIDL接口方法的類,相當(dāng)于Binder客戶端(Proxy),其他進(jìn)程通過(guò)此類完成與系統(tǒng)服務(wù)的通信。

一、增加系統(tǒng)服務(wù)

1.1 AIDL

在frameworks/base/core/java/android/app/service中編寫(xiě)IZxxManager.aidl

package android.app;

/**
* {@hide}
*/
interface IZxxManager {
    String request(String msg);
}

1.2 系統(tǒng)服務(wù)

/frameworks/base/services/core/java/com/android/server/zxx/ZxxManagerService.java

package com.android.server.zxx;

import android.app.IZxxManager;
import android.os.RemoteException;
public class ZxxManagerService extends IZxxManager.Stub {
    @Override
    public String request(String msg) throws RemoteException {
        return "ZxxManagerService接收數(shù)據(jù):"+msg;
    }
}

注意:如果以當(dāng)前案例的方式新增自定義系統(tǒng)服務(wù),因?yàn)镾ystemServiceRegistry 中需要使用到com.zxx下的類,為了讓其獲取此包下類的引用,需要配置:build/core/tasks/check_boot_jars/package_whitelist.txt ,加入:com\.zxx\..*。否則會(huì)因?yàn)闊o(wú)法獲取類引用而編譯報(bào)錯(cuò)!

dalvik\..*
libcore\..*
android\..*
com\.android\..*
com\.zxx\..*  

1.3 添加上下文常量

/frameworks/base/core/java/android/context/Context.java
添加 public static final String ZXX_SERVICE = "zxx";

@StringDef(suffix = { "_SERVICE" }, value = {
            POWER_SERVICE,
            //@hide: POWER_STATS_SERVICE,
            WINDOW_SERVICE,
            LAYOUT_INFLATER_SERVICE,
            ACCOUNT_SERVICE,
            ACTIVITY_SERVICE,
            ZXX_SERVICE,

1.4 客戶端代理

/frameworks/base/core/java/android/app/ZxxManager.java

package android.app;

import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Singleton;
import android.os.ServiceManager;
import android.annotation.Nullable;
import android.app.IZxxManager;
//代表系統(tǒng)服務(wù)
@SystemService(Context.ZXX_SERVICE)
public class ZxxManager {

    /**
     * @hide 只能系統(tǒng)調(diào)用
     */
    public ZxxManager() {
    }

    /**
     * @hide 只能系統(tǒng)調(diào)用
     */
    public static IZxxManager getServerice(){
        return I_ZXX_MANAGER_SINGLETON.get();
    }
        //限制framework中的定義無(wú)法被外部應(yīng)用訪問(wèn)
    @UnsupportedAppUsage
    private static final Singleton<IZxxManager> I_ZXX_MANAGER_SINGLETON =
            new Singleton<IZxxManager>() {
                @Override
                protected IZxxManager create() {
                    final IBinder b= ServiceManager.getService(Context.ZXX_SERVICE);
                    final IZxxManager im=IZxxManager.Stub.asInterface(b);
                    return im;
                }
            };

    @Nullable
    public String request(@Nullable String msg){
        try{
            return getServerice().request(msg);
        }catch (RemoteException e){
            throw e.rethrowFromSystemServer();
        }
    }

}

1.5 注冊(cè)系統(tǒng)服務(wù)

1.5.1 SystemServer

1.5.1.1 無(wú)生命周期注冊(cè)

frameworks/base/services/java/com/android/server/SystemServer.java中 startOtherServices方法中注冊(cè)系統(tǒng)服務(wù)

import com.android.server.zxx.ZxxManagerService;

private void startOtherServices(){
    //......
     ServiceManager.addService(Context.ZXX_SERVICE,new ZxxManagerService());
    //......
}

1.5.1.2 有生命周期注冊(cè)

系統(tǒng)服務(wù)需要通過(guò)ServiceManager.addService("xx", new XXManagerService);將自己(Binder Stub)注冊(cè)進(jìn)入SM才能夠讓其他進(jìn)程利用Binder與之通信。而自定義系統(tǒng)服務(wù)如果需要根據(jù)系統(tǒng)啟動(dòng)的不同階段進(jìn)行不同的處理則需要注冊(cè)生命周期回調(diào)。以AMS為例:

/frameworks/base/services/java/com/android/server/SystemService中啟動(dòng)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方法的實(shí)現(xiàn)為:

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

setSystemProcess中會(huì)完成向SM注冊(cè)AMS的實(shí)現(xiàn)。而在setSystemProcess之前有一段代碼:

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

則為注冊(cè)生命周期監(jiān)聽(tīng),ActivityManagerService.Lifecycle就相當(dāng)于生命周期的回調(diào)接口對(duì)象,它繼承自:

/frameworks/base/services/core/java/com/android/server/SystemService。這個(gè)SystemService中主要需要實(shí)現(xiàn)兩個(gè)方法:

  • onStart() :mSystemServiceManager.startService第一時(shí)間回調(diào)該函數(shù)。

  • onBootPhase(int phase) : 系統(tǒng)啟動(dòng)的各個(gè)階段會(huì)回調(diào)該函數(shù)

    • SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY:這是一個(gè)依賴項(xiàng),只有DisplayManagerService中進(jìn)行了對(duì)應(yīng)處理;
    • SystemService.PHASE_LOCK_SETTINGS_READY:經(jīng)過(guò)這個(gè)引導(dǎo)階段后,服務(wù)才可以接收到wakelock相關(guān)設(shè)置數(shù)據(jù);
    • SystemService.PHASE_SYSTEM_SERVICES_READY:經(jīng)過(guò)這個(gè)引導(dǎo)階段 后,服務(wù)才可以安全地使用核心系統(tǒng)服務(wù)
    • SystemService.PHASE_ACTIVITY_MANAGER_READY:經(jīng)過(guò)這個(gè)引導(dǎo)階 段后,服務(wù)可以發(fā)送廣播
    • SystemService.PHASE_THIRD_PARTY_APPS_CAN_START:經(jīng)過(guò)這個(gè)引導(dǎo)階段后,服務(wù)可以啟動(dòng)第三方應(yīng)用,第三方應(yīng)用也可以通過(guò)Binder來(lái)調(diào)用服務(wù)。
    • SystemService.PHASE_BOOT_COMPLETED:經(jīng)過(guò)這個(gè)引導(dǎo)階段后,說(shuō)明服務(wù)啟動(dòng)完成,這時(shí)用戶就可以和設(shè)備進(jìn)行交互。

比如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) {
                // 準(zhǔn)備廣播處理
                mService.startBroadcastObservers();
            } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
                mService.mPackageWatchdog.onPackagesReady();
            }
        }
}

在AMS中會(huì)處理PHASE_ACTIVITY_MANAGER_READY ,經(jīng)過(guò)這個(gè)階段后,也就是需要在下一個(gè)階段PHASE_THIRD_PARTY_APPS_CAN_START才可以發(fā)送廣播。

1.5.2 SystemServiceRegistry

在frameworks/base/core/java/android/app/SystemServiceRegistry.java注冊(cè)應(yīng)用系統(tǒng)服務(wù)獲取器,有一個(gè)static塊 執(zhí)行了registerService用于注冊(cè)

import android.app.ZxxManager;
static{
    registerService(Context.ZXX_SERVICE, ZxxManager.class,
                new CachedServiceFetcher<ZxxManager>() {
                    @Override
                    public ZxxManager createService(ContextImpl ctx) {
                        return new ZxxManager();
                    }});
}

1.6 配置SELinux權(quán)限

1.6.1 修改的文件路徑有:

system/sepolicy/private/service_contexts;

activity                                  u:object_r:activity_service:s0                       
zxx                                         u:object_r:zxx_service:s0

system/sepolicy/private/untrusted_app_all.te;

allow untrusted_app zxx_service:service_manager find;

system/sepolicy/public/service.te;

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

注意:system/sepolicy/prebuilt/api/底下也有28.0、29.0、30.0、31.0、32.0、33.0里面的private/public對(duì)應(yīng)的文件也要同樣添加以上代碼

1.6.2 去除檢查權(quán)限校準(zhǔn)

在system/sepolicy/build/soong/service_fuzzer_bindings.go

var (
    ServiceFuzzerBindings = map[string][]string{
        ...
        "activity":           EXCEPTION_NO_FUZZER,
        "zxx":                EXCEPTION_NO_FUZZER,
        ...
    }
)

1.7 更新并編譯、刷機(jī)

#方式一:更新編譯運(yùn)行
# 更新api
make update-api
# 編譯
m
#運(yùn)行模擬器
emulator

#方式一:更新編譯刷機(jī)
#編譯
make update-api
make –j4 
#刷機(jī)
adb reboot bootloader
reboot flashall -w

1.8 驗(yàn)證服務(wù)是否添加成功

adb shell service list | grep zxx
3731683730369.jpg

二、使用自定義服務(wù)

2.1 方式一 創(chuàng)建相同的殼類

創(chuàng)建同樣的包和類,方法可以不實(shí)現(xiàn),利用雙親委托機(jī)制一般只是用來(lái)調(diào)試自己的服務(wù)功能是否正常

package android.app;

public class ZxxManager {
    
    public String request(String msg){
            return null;
    }

}

2.2 方式二 通過(guò)修改SDK配置自定義SDK

make sdk

2.2.1 復(fù)制SDK

把正在使用的SDK復(fù)制一份并改名為android-33.car,android-33.car中的platforms和sources下的平臺(tái)同樣也復(fù)制一份

2.2.2 替換android.jar

將復(fù)制出來(lái)的原生SDK/platforms中的android.jar用自己編譯出的替換
out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes-header.jar
或者
out/target/common/obj/PACKAGING/android_jar_intermediates 目錄下面,會(huì)生成 android.jar 和 android--stubs-src.jar 兩個(gè)文件,將這個(gè)兩個(gè)文件替換到Android Studio使用的sdk的對(duì)應(yīng)平臺(tái)目錄下面,我使用的是api33,目錄為 platforms/android-66(自定義)/

2.2.3 修改SDK配置

2.2.3.1 source.properties

修改android-33.car\platforms\android-66\source.properties

#指定自定義平臺(tái)標(biāo)識(shí)為66(可以是任意數(shù)字,但為了與原生標(biāo)識(shí)區(qū)分) 
#修改: 
Pkg.Desc=Android SDK Platform 66 
Pkg.UserSrc=false 
#修改: 
Platform.Version=66 
Platform.CodeName= 
Pkg.Revision=1 
#修改: 
AndroidVersion.ApiLevel=66 
Layoutlib.Api=15 
Layoutlib.Revision=1 
Platform.MinToolsRev=22

2.2.3.2 package.xml

修改 android-32.car\platforms\android-321\package.xml

<localPackage path="platforms;android-66" obsolete="false"> 
 <type-details xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:type="ns5:platformDetailsType"> 
 <!-- 修改 --> 
 <api-level>66</api-level> 
 <codename></codename> 
 <layoutlib api="15"/></type-details> 
 <revision> 
 <major>1</major> 
 </revision> 
 <!-- 修改 --> 
 <display-name>Android SDK Platform 66</display-name> 
 <uses-license ref="android-sdk-license"/> 
</localPackage>

2.2.4 配置源碼跳轉(zhuǎn)

修改android-33.car\sources\android-66目錄下的參考第3步source.properties和package.xml文件

2.3 方式三 使用framework.jar

make javac-check-framework

在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates拷貝classes.jar重新命名framework.jar,AS導(dǎo)入jar使用

三、常見(jiàn)問(wèn)題

1、在system/sepolicy/prebuilt/api/* 底下所以sdk版本的private/public按照1.6的形式所有都給它添加


3721683728201.jpg

2、$ANDROID_BUILD_TOP/system/sepolicy/BUILD/soong/service_fuzzer_bindings.go,按activity這種格式,自定義的服務(wù)的加進(jìn)去,就不會(huì)檢查了

//system/sepolicy/contexts:fuzzer_bindings_test running service:fu
FAILED: out/soong/.intermediates/system/sepolicy/contexts/fuzzer_bindings_test/android_common/timestamp
out/host/linux-x86/bin/fuzzer_bindings_check -s out/soong/.intermediates/system/sepolicy/contexts/plat_service_contexts/android_common/gen/plat_service_contexts -b out/soong/.intermediates/bindings.json && touch out/soong/.intermediates/system/sepolicy/contexts/fuzzer_bindings_test/android_common/timestamp # hash of input list: d6d7c35d085ab532427370293bbe7778939ca920eb7f04227649468b94741599

error: Service 'zxx' is being added, but we have no fuzzer on file for it. Fuzzers are listed at $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go 

NOTE: automatic service fuzzers are currently not supported in Java (b/232439254) and Rust (b/164122727). In this case, please ignore this for now and add an entry for yournew service in service_fuzzer_bindings.go 

If you are writing a new service, it may be subject to attack from other potentially malicious processes. A fuzzer can be written automatically by adding these things: 
- a cc_fuzz Android.bp entry 
- a main file that constructs your service and calls 'fuzzService' 

An examples can be found here: 
- $ANDROID_BUILD_TOP/hardware/interfaces/vibrator/aidl/default/fuzzer.cpp 
- https://source.android.com/docs/core/architecture/aidl/aidl-fuzzing 

This is only ~30 lines of configuration. It requires dependency injection for your service which is a good practice, and (in AOSP) you will get bugs automatically filed on you. You will find out about issues without needing to backport changes years later, and the system will automatically find ways to reproduce difficult to solve issues for you. 

This error can be bypassed by adding entry for new service in $ANDROID_BUILD_TOP/system/sepolicy/build/soong/service_fuzzer_bindings.go 

- Android Fuzzing and Security teams
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容