一、环境
高通865 Android10
二、添加服务具体步骤
1、添加aidl文件
frameworks/base/core/java/android/os/IMyService.aidl
package android.os;
interface IMyService{
int getSum(int data1,int data2);
}
2、 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",
..................
"core/java/android/os/IMyService.aidl",
],
3、创建service文件,也就是aidl的具体实现
frameworks/base/services/core/java/com/android/server/MyService.java
服务中的逻辑可能每个人的都不同,这里演示服务的定义
package com.android.server;
import android.os.IMyService;
import java.lang.Exception;
import android.os.RemoteException;
import android.util.Log;
import android.content.Intent;
import android.content.Context;
import android.os.SystemProperties;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.app.AlarmManager;
import java.util.Calendar;
import android.app.PendingIntent;
import android.os.Build;
import android.os.SystemClock;
import android.text.TextUtils;
import java.util.concurrent.TimeUnit;
import java.io.IOException;
import android.os.Handler;
public class MyService extends IMyService.Stub{
private static final String ACTION_TIME_UPDATE_MINUTE = "com.vclusters.runshell.MINUTE_UPDATE_TIME";
private String TAG="MyService";
private Context mContext;
private PendingIntent mTimeUpdateIntent;
private AlarmManager mAlarmManager;
private boolean mHasRegistered;
public MyService(Context context){
mContext=context;
Log.d(TAG, "MyService <- is open6...");
try{
registerBroadcastReceiver();
startAlarm();
}catch (Exception exception){
Log.e(TAG, "MyService startTimerTask exception:"+exception.getMessage());
}
}
@Override
public int getSum(int data1,int data2) throws RemoteException{
return data1+data2;
}
private void removeTimeUpdateHourlyAlarm() {
if ((mTimeUpdateIntent != null) && (mAlarmManager != null)) {
// Log.d(TAG, "[removeTimeUpdateHourlyAlarm]#");
mAlarmManager.cancel(mTimeUpdateIntent);
}
}
private void startAlarm(){
Intent intent = new Intent();
intent.setAction(ACTION_TIME_UPDATE_MINUTE);
mTimeUpdateIntent = PendingIntent.getBroadcast(mContext, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager= (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setTimeUpdateHourlyAlarm();
}
}, 5000);//注意:服务中调用AlarmManager服务,这里延迟5秒加载,这里有坑,服务中立即使用服务,存在mAppOps还没加载,checkpackage()时报错问题
}
private void setTimeUpdateHourlyAlarm() {
if (mTimeUpdateIntent!=null&&mAlarmManager != null) {
Log.d(TAG, "[setTimeUpdateHourlyAlarm]#");
int actionShellTime = 1;
long triggerAtMills = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(actionShellTime);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMills, mTimeUpdateIntent);
}
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.equals(action, ACTION_TIME_UPDATE_MINUTE)) {
Log.d(TAG, "onReceive ACTION_TIME_UPDATE_MINUTE");
removeTimeUpdateHourlyAlarm();
setTimeUpdateHourlyAlarm();
}else if (TextUtils.equals(action, Intent.ACTION_TIME_CHANGED)) {
Log.d(TAG, "onReceive Intent.ACTION_TIME_CHANGED");
//removeTimeUpdateHourlyAlarm();
//setTimeUpdateHourlyAlarm();
}
}
};
private void registerBroadcastReceiver() {
if (mHasRegistered) {
return;
}
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(ACTION_TIME_UPDATE_MINUTE);
mContext.registerReceiver(mBroadcastReceiver, filter);
mHasRegistered = true;
}
private void unregisterBroadcastReceiver() {
if (mHasRegistered) {
mContext.unregisterReceiver(mBroadcastReceiver);
mHasRegistered = false;
}
}
}
4、将MyService.java 添加到系统服务管理器中(即开机启动服务)
frameworks/base/services/java/com/android/server/SystemServer.java
在startOtherServices()
中添加服务
import com.android.server.MyService;
private void startOtherServices(){
traceBeginAndSlog("StartAlarmManagerService");
mSystemServiceManager.startService(new AlarmManagerService(context));
traceEnd();
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);
traceEnd();
...................//上面省略无关代码
Slog.i(TAG, "addService----MyService");
try {
ServiceManager.addService(Context.MY_SERVICE, new MyService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting MyService", e);
}
// 注意:添加服务最好添加到最后,例如,博主服务MyService.java中用到了AlarmManagerService,所以这//里的注册得放到AlarmManagerService后面,不然编译报错
}
5、创建可由外部使用的接口(app中getSystemService(String serviceName)获取的服务将调用下面MyServiceManager.java中的函数)
frameworks/base/core/java/android/app/MyServiceManager.java
package android.app;
import android.util.Log;
import android.os.IMyService;
import android.content.Context;
import java.lang.Exception;
import android.os.RemoteException;
public class MyServiceManager{
public static final String TAG = "MyServiceManager";
private IMyService mService;
public MyServiceManager(IMyService service){
mService = service;
}
public int getSum(int data1,int data2){
try{
return mService.getSum(data1,data2);
}catch(RemoteException e){
Log.e(TAG,"error getSum "+e.toString());
e.printStackTrace();
}
return 0;
}
}
6、在Context 配置接口名称
frameworks/base/core/java/android/content/Context.java
public static final String MY_SERVICE ="myservice";
@StringDef(suffix = { "_SERVICE" }, value = {
POWER_SERVICE,
WINDOW_SERVICE,
LAYOUT_INFLATER_SERVICE,
ACCOUNT_SERVICE,
ACTIVITY_SERVICE,
ALARM_SERVICE,
NOTIFICATION_SERVICE,
ACCESSIBILITY_SERVICE,
CAPTIONING_SERVICE,
KEYGUARD_SERVICE,
LOCATION_SERVICE,
MY_SERVICE,
7、注册服务(app中getSystemService()将调用创建服务)
frameworks/base/core/java/android/app/SystemServiceRegistry.java
import android.os.IMyService;
import android.app.MyServiceManager;
final class SystemServiceRegistry {
private static final String TAG = "SystemServiceRegistry";
// Service registry information.
// This information is never changed once static initialization has completed.
private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =
new ArrayMap<Class<?>, String>();
private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new ArrayMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
// Not instantiable.
private SystemServiceRegistry() {
}
static {
//CHECKSTYLE:OFF IndentationCheck
registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
new CachedServiceFetcher<AccessibilityManager>() {
@Override
public AccessibilityManager createService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}
});
................................//省略中间代码
registerService(Context.MY_SERVICE, MyServiceManager.class,
new CachedServiceFetcher<MyServiceManager>() {
@Override
public MyServiceManager createService(ContextImpl ctx) throws
ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.MY_SERVICE);
if (b == null) {
return null;
}
IMyService service = IMyService.Stub.asInterface(b);
return new MyServiceManager(service);
}
});
}
三、新增api之后需要更新api
1、source build/envsetup.sh
2、lunch kona-userdebug
3、更新api(下面的命令如果没有执行,编译报错的时候会提示类似下面的命令,根据提示的命令执行,
不一定就是这里说的这两个命令去更新api)
make api-stubs-docs-update-current-api
或者make update-api
4、执行完步骤3后,current.txt会自动更新
frameworks/base/api/current.txt
类似下面这种:
field public static final String MY_SERVICE = "myservice";
public interface IMyService extends android.os.IInterface {
method public int getSum(int, int) throws android.os.RemoteException;
}
public static class IMyService.Default implements android.os.IMyService {
ctor public IMyService.Default();
method public android.os.IBinder asBinder();
method public int getSum(int, int) throws android.os.RemoteException;
}
public abstract static class IMyService.Stub extends android.os.Binder implements android.os.IMyService {
ctor public IMyService.Stub();
method public android.os.IBinder asBinder();
method public static android.os.IMyService asInterface(android.os.IBinder);
method public static android.os.IMyService getDefaultImpl();
method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
method public static boolean setDefaultImpl(android.os.IMyService);
}
四、selinux配置策略(没有配置权限的话,服务中相关api供外部调用会提示错误)
1、在文件system/sepolicy/private/service_contexts添加如下内容
myservice u:object_r:myservice_service:s0
2、在文件system/sepolicy/prebuilts/api/29.0/private/service_contexts添加如下内容
system/sepolicy/prebuilts/api/29.0/private/service_contexts
3、在文件system/sepolicy/public/service.te添加如下内容
type myservice_service, system_api_service, system_server_service, service_manager_type;
4、在文件system/sepolicy/prebuilts/api/29.0/public/service.te添加如下内容
type myservice_service, system_api_service, system_server_service, service_manager_type;
注意:如下两个文件中的内容必须完全一致,多一行空格都不行
system/sepolicy/public/service.te
system/sepolicy/prebuilts/api/29.0/public/service.te
其他api和29.0的类似添加即可:
system/sepolicy/prebuilts/api/28.0/public/service.te
system/sepolicy/prebuilts/api/27.0/public/service.te
system/sepolicy/prebuilts/api/26.0/public/service.te
system/sepolicy/prebuilts/api/28.0/private/service_contexts
system/sepolicy/prebuilts/api/27.0/private/service_contexts
system/sepolicy/prebuilts/api/26.0/private/service_contexts
//经测试,只添加system/sepolicy/29.0,上面的没添加编译会报错,最好都添加上
五、编译
六、查看服务是否添加成功
1、根据服务名称去查看定义的服务是否存在
服务名称为上面在Context.txt中定义的服务名称
public static final String MY_SERVICE ="myservice";
2、还可以通过连接卡,Android Studio中查看服务中的日志
七、app使用添加的服务
编译生成的代码位置:
out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar 包含代码的
out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes-header.jar 这个就只有方法名, 不提供内容实现代码
如果不想要把整个framework层代码提供出去,还有一种简单的方法, 自己新建个app,打成jar包,包名和framewrok层写的一样,最后打包成一个jar包,compileOnly files(‘libs\classes.jar’) 这样使用
使用示例:
MyServiceManager myServiceManager=(MyServiceManager)getSystemService("myservice");
int sumVlaue=myServiceManager.getSum(2,3);