Android10 Framework layer adds system services

1. Environment

Qualcomm 865 Android10

2. Specific steps for adding services

1. Add aidl file

frameworks/base/core/java/android/os/IMyService.aidl

package android.os;
 
interface IMyService{
   int getSum(int data1,int data2);
}

2. Add aidl to 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. Create a service file, which is the specific implementation of aidl

 frameworks/base/services/core/java/com/android/server/MyService.java

The logic in the service may be different for everyone, here is the definition of the service

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. Add MyService.java to the system service manager (that is, start the service at startup)

 frameworks/base/services/java/com/android/server/SystemServer.java

startOtherServices()Add the service in

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. Create an interface that can be used externally (the service obtained by getSystemService(String serviceName) in the app will call the function in MyServiceManager.java below)

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. Configure the interface name in 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. Register service (getSystemService() in app will call to create service)

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);
                    }
                });
           }

3. After the new API is added, the API needs to be updated

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);
  }

4. Selinux configuration strategy (if there is no configuration permission, the relevant api in the service will prompt an error for external calls)

1. Add the following content to the file system/sepolicy/private/service_contexts

myservice                                 u:object_r:myservice_service:s0

2. Add the following content in the file system/sepolicy/prebuilts/api/29.0/private/service_contexts

system/sepolicy/prebuilts/api/29.0/private/service_contexts

3. Add the following content to the file system/sepolicy/public/service.te

type myservice_service, system_api_service, system_server_service, service_manager_type;

4. Add the following content in the file system/sepolicy/prebuilts/api/29.0/public/service.te

type myservice_service, system_api_service, system_server_service, service_manager_type;

Note: The content in the following two files must be exactly the same, and one more line of space will not work

system/sepolicy/public/service.te

 system/sepolicy/prebuilts/api/29.0/public/service.te

Similar additions for other APIs and 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,上面的没添加编译会报错,最好都添加上

Five, compile

6. Check whether the service is added successfully

1. Check whether the defined service exists according to the service name

The service name is the service name defined above in Context.txt

 public static final String MY_SERVICE ="myservice";

2. You can also view the logs in the service in Android Studio through the connection card

7. The app uses the added service

编译生成的代码位置:
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);

Guess you like

Origin blog.csdn.net/banzhuantuqiang/article/details/131062050