版权声明
本文来自博客园,作者:观心静 ,转载请注明原文链接: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, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
请注意!这里最关键的是my_system_service需要与上面的service_contexts文件中这部分 u:object_r:my_system_service:s0 的配置的一样。
上面的配置,可以更改的api类型上面是app_app_service,如果你不想暴露给普通应用可以改成system_api_service,然后在删除ephemeral_app_api_service,这样就成了系统级服务api了
增加的位置,如下图:
第二处
文件路径: /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
扩展:在应用中调用我们自己添加的系统服务
在应用中调用系统服务,首先得知道如何将framework架包到应用中。 这部分知识,请参考我的个人博客 :https://www.cnblogs.com/guanxinjing/p/16613716.html
然后我们在一个应用项目中调用代码,如下图:
上面红色提示错误的代码,请直接无视,因为framework架包无法避免Android studio不提示错误。 我们只需要Android studio能编译成功apk就行。
应用运行的效果图:
关于selinux配置的额外内容
如果有人依然不明白如何配置selinux或者是项目上压根就没需求,这边可以直接通过关闭selinux权限。就可以直接调用服务了
关闭服务如下, 将0改成1,可以设置成开启服务
$adb shell
#setenfore 0
查询selinux权限当前状态,Permissive为关闭状态
my_device_01:/ # getenforce
Permissive
end
本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/17872077.html