版權聲明
本文來自博客園,作者:觀心靜 ,轉載請註明原文鏈接:https://www.cnblogs.com/guanxinjing/p/17872077.html
前言
此博客講解如何在Android10版本的framework中添加系統服務。 在framework中添加我們自己的定製服務在系統開發中特別有意義。
大多數的設備開發場景,都會開發一個應用啓動一個後臺服務,預裝到系統中,讓他獲得系統級權限,調用大多數的系統級服務以提供外包應用調用系統級功能。 但是,這種方式有一個問題,此應用依然不是運行在系統進程中,他依然是獨立的進程。我們無法獲得系統進程中的一些參數。如何解決這種需求呢?
一些人會直接在ActivityManagerService、PowerManagerService、PhoneWindowManager 中直接修改或者增加代碼,用廣播的形式傳遞到應用層。但是這種方式問題很多,首先需要修改這些代碼量超級多的原生服務,一不小心很容易出現問題。
而最好的辦法就是我們也添加一個系統級服務,提供給外部使用,而在這個服務中,我們可以通過直接調用相關服務實現需求。
第一步創建AIDL文件
創建位置:frameworks/base/core/java/android/os/IMySystemService.aidl
// IMySystemService.aidl
package android.os;
interface IMySystemService {
String getText(String aString);
}
第二步將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",
"location/java/**/*.java",
"lowpan/java/**/*.java",
"media/java/**/*.java",
"media/mca/effect/java/**/*.java",
"media/mca/filterfw/java/**/*.java",
"media/mca/filterpacks/java/**/*.java",
"drm/java/**/*.java",
"opengl/java/**/*.java",
"sax/java/**/*.java",
"telecomm/java/**/*.java",
"telephony/java/**/*.java",
"wifi/java/**/*.java",
"keystore/java/**/*.java",
"rs/java/**/*.java",
":framework-javastream-protos",
//略.............
"core/java/android/speech/tts/EventLogTags.logtags",
"core/java/android/net/EventLogTags.logtags",
"core/java/android/os/EventLogTags.logtags",
"core/java/android/webkit/EventLogTags.logtags",
"core/java/com/android/internal/app/EventLogTags.logtags",
"core/java/com/android/internal/logging/EventLogTags.logtags",
"core/java/com/android/server/DropboxLogTags.logtags",
"core/java/org/chromium/arc/EventLogTags.logtags",
":apex-properties",
":platform-properties",
":framework-statslog-gen",
//在此處添加IMySystemService.aidl的路徑
"core/java/android/os/IMySystemService.aidl",
],
//略....................
第三步創建service文件
創建位置: frameworks/base/services/core/java/com/android/server/MySystemService.java
請主意下面的package 路徑,不可以隨便修改。
package com.android.server;
import android.os.IMySystemService;
import android.os.IBinder;
import android.os.RemoteException;
import android.content.Context;
import android.util.Log;
public class MySystemService extends IMySystemService.Stub{
private Context mContext;
public MySystemService(Context context){
mContext = context;
Log.v("zhou", "MySystemService is init");
}
@Override
public String getText(String aString) throws RemoteException {
return aString;
}
}
第四步在SystemServer添加服務,使其開機就啓動服務
文件路徑:/aosp/frameworks/base/services/java/com/android/server/SystemServer.java
SystemServer是Android系統中用於啓動service的入口。在Android系統啓動時,會啓動兩個重要的進程,一個是Zygote進程,另一個是由Zygote進程fork出來的system_server進程。SystemServer會啓動我們在系統中所需要的一系列service。
package com.android.server;
//別忘記這裏添加引用
import com.android.server.MySystemService;
public final class SystemServer {
private static final String TAG = "SystemServer";
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices() {
final Context context = mSystemContext;
//略....................
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
mActivityManagerService.systemReady(() -> {
//略......
}, BOOT_TIMINGS_TRACE_LOG);
//在此處添加代碼
try{
ServiceManager.addService(Context.MY_SYSTEM_SERVICE, new MySystemService(context));
} catch(Throwable e){
Slog.e(TAG, "Failure starting MySystemService", e);
}
}
}
第五步創建提供外部調用的服務管理
創建位置:frameworks/base/core/java/android/app/MySystemServiceManager.java
請主意下面的package 路徑,不可以隨便修改。
package android.app;
import android.os.IMySystemService;
import android.os.RemoteException;
public class MySystemServiceManager {
private IMySystemService mService;
public MySystemServiceManager(IMySystemService service){
mService = service;
}
public String getText(String text){
try {
return mService.getText(text);
} catch (RemoteException e) {
e.printStackTrace();
}
return "";
}
}
第六步在Context增加屬性
路徑:frameworks/base/core/java/android/content/Context.java
如下列圖,共2處添加:
第一處,添加常量
第二處
/** @hide */
@StringDef(suffix = { "_SERVICE" }, value = {
POWER_SERVICE,
//省略此處代碼......
PERMISSION_SERVICE,
MY_SYSTEM_SERVICE, //這裏添加上面的常量
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
第七步在SystemServiceRegistry上註冊服務管理
文件路徑:/aosp/frameworks/base/core/java/android/app/SystemServiceRegistry.java
//請別忘記import
import android.os.IMySystemService;
import android.app.MySystemServiceManager;
final class SystemServiceRegistry {
private static final String TAG = "SystemServiceRegistry";
//省略此處代碼.............
static {
//CHECKSTYLE:OFF IndentationCheck
//省略此處代碼.............
registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
new CachedServiceFetcher<DynamicSystemManager>() {
@Override
public DynamicSystemManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(
Context.DYNAMIC_SYSTEM_SERVICE);
return new DynamicSystemManager(
IDynamicSystemService.Stub.asInterface(b));
}});
// 在static代碼塊的最下面新增自己的服務管理MySystemServiceManager
registerService(Context.MY_SYSTEM_SERVICE, MySystemServiceManager.class,
new CachedServiceFetcher<MySystemServiceManager>() {
@Override
public MySystemServiceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.MY_SYSTEM_SERVICE);
return new MySystemServiceManager(IMySystemService.Stub.asInterface(b));
}});
//CHECKSTYLE:ON IndentationCheck
}
第七步selinux配置策略
這是最複雜的一步,需要特別耐心與仔細,任何的錯誤配置都能導致無法編譯成功。
配置service_contexts文件
一共有兩處需要配置service_contexts,此外這兩處的service_contexts文件在配置後需要一模一樣。
第一處
文件路徑: /aosp/system/sepolicy/private/service_contexts 在此文件中增加如下。
my_system u:object_r:my_system_service:s0
這個可以根據你的服務名稱修改,最關鍵的地方是這裏的my_system需要與上面的Context中配置的屬性一致。 此外其中my_system_service也是非常關鍵的,這個與下面的其他項配置有關。
增加的位置,如下圖:
第二處
文件路徑: /aosp/system/sepolicy/prebuilts/api/29.0/private/service_contexts 與上面一樣在文件中增加一樣的內容,注意!這裏的添加的位置也要一模一樣。如下圖:
配置service.te文件
一共有兩處文件需要配置service.te, 此外這兩處的service.te文件在配置後需要一模一樣
第一處
文件路徑:/aosp/system/sepolicy/public/service.te 在此文件中增加:
type my_system_service, system_api_service, system_server_service, service_manager_type;
請注意!這裏最關鍵的是my_system_service需要與上面的service_contexts文件中這部分 u:object_r:my_system_service:s0 的配置的一樣。
增加的位置,如下圖:
第二處
文件路徑: /aosp/system/sepolicy/prebuilts/api/29.0/public/service.te 與上面一樣在文件中增加一樣的內容,注意!這裏的添加的位置也要一模一樣。如下圖:
忽略安全策略,配置ignore.cil後綴文件
ignore.cil 後綴文件是一個用於忽略特定安全策略的文件。它通常與Android的安全模型和權限管理相關聯。
在Android操作系統中,爲了保護應用程序和系統的安全,系統會執行一系列的安全策略。這些策略包括權限管理和應用程序隔離等措施。然而,有時候某些應用程序可能需要訪問一些被禁止或限制的資源或執行某些被禁止的操作。
如下路徑的文件都要修改,請注意!這幾個文件的內容不是一樣的,所以需要單獨一個一個的去添加配置。不可以偷懶全部複製過去。
- /aosp/system/sepolicy/private/compat/26.0/26.0.ignore.cil
- /aosp/system/sepolicy/private/compat/27.0/27.0.ignore.cil
- /aosp/system/sepolicy/private/compat/28.0/28.0.ignore.cil
- /aosp/system/sepolicy/prebuilts/api/29.0/private/compat/26.0/26.0.ignore.cil
- /aosp/system/sepolicy/prebuilts/api/29.0/private/compat/27.0/27.0.ignore.cil
- /aosp/system/sepolicy/prebuilts/api/29.0/private/compat/28.0/28.0.ignore.cil
需要添加的內容與位置:
my_system_service需要與上面的service_contexts文件中這部分 u:object_r:my_system_service:s0 的配置的一樣。
第八步編譯與驗證結果
編譯部分
在編譯前記得先執行make installclean ,接着在執行make update-api, 最後在make。
驗證結果
用adb驗證
抓log驗證,前面的MySystemService的構造方法中,我增加了一個log
擴展:在應用中調用我們自己添加的系統服務
end