美文网首页
Android 源码系统添加系统服务

Android 源码系统添加系统服务

作者: mm_cuckoo | 来源:发表于2023-03-12 14:32 被阅读0次

    以下内容基于Android12 源码进行整理

    下面内容是基于Camera升降机服务添加过程整理

    1.在Context.java 中添加服务名称

    Context.java 在源码中位置:frameworks/base/core/java/android/content/Context.java

    /**
     * Use with {@link #getSystemService(String)} to retrieve a
     * {@link com.android.server.cameralift.CameraLiftManagerService}
     *
     * @see #getSystemService(String)
     * @see android.app.cameralift.CameraLiftManager
     */
    public static final String CAMERA_LIFT_SERVICE = "camera_lift";
    
    
    /** @hide */
    @StringDef(suffix = { "_SERVICE" }, value = {
            POWER_SERVICE,
            .... // 省略部分代码 
            CAMERA_LIFT_SERVICE,
    })  
        
    

    2.创建AIDL文件

    frameworks/base/core/java/android/app 添加cameralift/aidl目录, 在aidl目录中添加aidl 文件:
    path: frameworks/base/core/java/android/app/cameralift/aidl
    File name : CameraLiftEvent.aidl

    package android.app.cameralift.aidl;
    
    import android.app.cameralift.aidl.CameraLiftCallback;
    
    interface CameraLiftEvent {
        void registerCallback(CameraLiftCallback callback);
        void unregisterCallback(CameraLiftCallback callback);
        void sendEvent(int type, String value);
    }
    

    File name: CameraLiftCallback.aidl

    package android.app.cameralift.aidl;
    
    interface CameraLiftCallback {
        oneway void onStatusChange(int type, String msg);
    }
    

    小技巧:

    当完成上面的aidl文件后希望可以在实现Service时可以正常提示aidl生成的class文件。

    1. 先使用命令make -j16 framework-minus-apex编译一下framework,编译的时候会报如下错误:
      注:使用make update-api 也会出现这个错误
    out/srcjars/android/app/cameralift/aidl/CameraLiftCallback.java:129: error: Methods calling system APIs should rethrow `RemoteException` as `R
    untimeException` (but do not list it in the throws clause) [RethrowRemoteException]
    out/srcjars/android/app/cameralift/aidl/CameraLiftCallback.java:129: error: Missing nullability on parameter `msg` in method `onStatusChange` 
    [MissingNullability]
    out/srcjars/android/app/cameralift/aidl/CameraLiftCallback.java:10: error: Methods calling system APIs should rethrow `RemoteException` as `Ru
    ntimeException` (but do not list it in the throws clause) [RethrowRemoteException]
    out/srcjars/android/app/cameralift/aidl/CameraLiftCallback.java:10: error: Missing nullability on parameter `msg` in method `onStatusChange` [
    MissingNullability]
    out/srcjars/android/app/cameralift/aidl/CameraLiftCallback.java:13: error: Missing nullability on method `asBinder` return [MissingNullability
    ]
    

    解决方法:
    将文件:out/soong/.intermediates/frameworks/base/api-stubs-docs-non-updatable/android_common/metalava/api-stubs-docs-non-updatable_api.txt拷贝到frameworks/base/core/api/current.txt 替换current.txt 内容

    current.txt中添加了如下内容:

    package android.app.cameralift.aidl {
    
      public interface CameraLiftCallback extends android.os.IInterface {
        method public void onStatusChange(int, String) throws android.os.RemoteException;
        field public static final String DESCRIPTOR = "android.app.cameralift.aidl.CameraLiftCallback";
      }
    
      public static class CameraLiftCallback.Default implements android.app.cameralift.aidl.CameraLiftCallback {
        ctor public CameraLiftCallback.Default();
        method public android.os.IBinder asBinder();
        method public void onStatusChange(int, String) throws android.os.RemoteException;
      }
    
      public abstract static class CameraLiftCallback.Stub extends android.os.Binder implements android.app.cameralift.aidl.CameraLiftCallback {
        ctor public CameraLiftCallback.Stub();
        method public android.os.IBinder asBinder();
        method public static android.app.cameralift.aidl.CameraLiftCallback asInterface(android.os.IBinder);
        method public static android.app.cameralift.aidl.CameraLiftCallback getDefaultImpl();
        method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
        method public static boolean setDefaultImpl(android.app.cameralift.aidl.CameraLiftCallback);
      }
    
      public interface CameraLiftEvent extends android.os.IInterface {
        method public void registerCallback(android.app.cameralift.aidl.CameraLiftCallback) throws android.os.RemoteException;
        method public void sendEvent(int, String) throws android.os.RemoteException;
        method public void unregisterCallback(android.app.cameralift.aidl.CameraLiftCallback) throws android.os.RemoteException;
        field public static final String DESCRIPTOR = "android.app.cameralift.aidl.CameraLiftEvent";
      }
    
      public static class CameraLiftEvent.Default implements android.app.cameralift.aidl.CameraLiftEvent {
        ctor public CameraLiftEvent.Default();
        method public android.os.IBinder asBinder();
        method public void registerCallback(android.app.cameralift.aidl.CameraLiftCallback) throws android.os.RemoteException;
        method public void sendEvent(int, String) throws android.os.RemoteException;
        method public void unregisterCallback(android.app.cameralift.aidl.CameraLiftCallback) throws android.os.RemoteException;
      }
    
      public abstract static class CameraLiftEvent.Stub extends android.os.Binder implements android.app.cameralift.aidl.CameraLiftEvent {
        ctor public CameraLiftEvent.Stub();
        method public android.os.IBinder asBinder();
        method public static android.app.cameralift.aidl.CameraLiftEvent asInterface(android.os.IBinder);
        method public static android.app.cameralift.aidl.CameraLiftEvent getDefaultImpl();
        method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
        method public static boolean setDefaultImpl(android.app.cameralift.aidl.CameraLiftEvent);
      }
    }
    
    

    然后将上面current.txt文件中新增的内容需要添加到 :prebuilts/sdk/32/public/api/android.txt 文件中

    上面内容配置完成后,再次使用命令make -j16 framework-minus-apex编译一下framework代码

    1. 找到编译aidl生成.class文件路径,上面代码编译出来的路径为:
      out/soong/.intermediates/frameworks/base/android-non-updatable.stubs.module_lib/android_common/javac/classes/android/app/cameralift/aidl/
    1. 点击File -> Project Structure 打项目结构设置窗口, 选中 Global Libraries 后点击上面 + 号选择Java 配置上一步copy的路径,配置后等待配置信息同步完成即可实现提示跳转

    说明: 上面的配置是添加了aidl 后编译配置方式,如果继续添加新的类还会出现编译错误,后面会继续介绍

    3.创建服务

    frameworks/base/services/core/java/com/android/server目录添加cameralift目录,实现service
    path:frameworks/base/services/core/java/com/android/server/cameralift
    File name: CameraLiftManagerService.java

    package com.android.server.cameralift;
    
    import android.app.cameralift.aidl.CameraLiftCallback;
    import android.app.cameralift.aidl.CameraLiftEvent;
    import android.content.Context;
    import android.os.Binder;
    import android.os.RemoteCallbackList;
    import android.os.RemoteException;
    import android.util.Slog;
    
    /**
     * @hide
     */
    public class CameraLiftManagerService extends CameraLiftEvent.Stub {
        private static final String TAG = "CameraLiftManagerService";
    
        private final RemoteCallbackList<CameraLiftCallback> mCallbackList = new RemoteCallbackList<>();
        private Context mContext;
        public CameraLiftManagerService(Context context) {
            this.mContext = context;
        }
    
        @Override
        public void registerCallback(CameraLiftCallback cameraLiftCallback) throws RemoteException {
            boolean result = mCallbackList.register(cameraLiftCallback);
            Slog.i(TAG, "register  pid:" + Binder.getCallingPid() + "  uid:" + Binder.getCallingUid()  + "  result:" + result  + " size:");
        }
    
        @Override
        public void unregisterCallback(CameraLiftCallback cameraLiftCallback) throws RemoteException {
            boolean result = mCallbackList.unregister(cameraLiftCallback);
            Slog.i(TAG, "unregister  pid:" + Binder.getCallingPid() + "  uid:" + Binder.getCallingUid()  + "  result:" + result);
        }
    
        @Override
        public void sendEvent(int type, String msg) throws RemoteException {
            Slog.i(TAG, "sendEvent: type:" + type  + "   msg:" + msg);
            int count = mCallbackList.getRegisteredCallbackCount();
            Slog.i(TAG, "callback size:" + count);
            if (count > 0) {
                int size = mCallbackList.beginBroadcast();
                for (int i = 0; i < size; i++) {
                    CameraLiftCallback callback = mCallbackList.getBroadcastItem(i);
                    try {
                        callback.onStatusChange(type, "server:" + msg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                        Slog.i(TAG, "remote exception :" + e.getMessage());
                    }
                }
                mCallbackList.finishBroadcast();
            }
        }
    }
    
    

    4.创建服务Manager

    在目录frameworks/base/core/java/android/app/cameralift 目录下添加service 的 Manager 类

    package android.app.cameralift;
    
    import android.annotation.NonNull;
    import android.annotation.Nullable;
    import android.annotation.SystemService;
    import android.app.cameralift.aidl.CameraLiftCallback;
    import android.app.cameralift.aidl.CameraLiftEvent;
    import android.compat.annotation.UnsupportedAppUsage;
    import android.content.Context;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.os.ServiceManager;
    import android.util.Slog;
    
    @SystemService(Context.CAMERA_LIFT_SERVICE)
    public class CameraLiftManager {
        private static final String TAG = "CameraLiftManager";
        private static CameraLiftManager mInstance;
        private CameraLiftEvent mService;
    
        /**
         * @hide
         */
        public CameraLiftManager(CameraLiftEvent service) {
            Slog.i(TAG, "CameraLiftManager");
            this.mService = service;
        }
    
        /**
         * @hide
         */
        @NonNull
        @UnsupportedAppUsage
        public static CameraLiftManager getInstance() {
            synchronized (CameraLiftManager.class) {
                if (mInstance == null) {
                    try {
                        IBinder b = ServiceManager.getServiceOrThrow(Context.CAMERA_LIFT_SERVICE);
                        mInstance = new CameraLiftManager(CameraLiftEvent.Stub.asInterface(b));
                    } catch (ServiceManager.ServiceNotFoundException e) {
                        throw new IllegalStateException(e);
                    }
                }
            }
            return mInstance;
        }
    
        public void registerCallback(@Nullable CameraLiftCallback cameraLiftCallback)  {
            try {
                mService.registerCallback(cameraLiftCallback);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        public void unregisterCallback(@Nullable CameraLiftCallback cameraLiftCallback)  {
            try {
                mService.unregisterCallback(cameraLiftCallback);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        public void sendEvent(int type , @Nullable String value)  {
            try {
                mService.sendEvent(type, value);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    5.注册新服务到ServiceManager中

    首先需要在SystemServer.java 中添加 CameraLiftManagerService.java
    SystemServer.java文件位置:frameworks/base/services/java/com/android/server/SystemServer.java

    /**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
     */
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startOtherServices");
    
        .... // 省略部分代码
        CameraLiftManagerService cameraLiftManagerService = null;
        
         .... // 省略部分代码
        t.traceBegin("CameraLiftManagerService");
        try {
            cameraLiftManagerService = new CameraLiftManagerService(context);
            ServiceManager.addService(Context.CAMERA_LIFT_SERVICE, cameraLiftManagerService);
        } catch (Throwable e) {
            Slog.e(TAG, "Failure starting CameraLiftManagerService  ", e);
        }
        t.traceEnd();
         .... // 省略部分代码
    }
    
    

    然后在SystemServiceRegistry.java 静态代码块中通过CameraLiftManager.javaCameraLiftManagerSerice.java 注册到SystemServer.java
    SystemServiceRegistry.java 文件位置:frameworks/base/core/java/android/app/SystemServiceRegistry.java

    static {
        //CHECKSTYLE:OFF IndentationCheck
        registerService(Context.CAMERA_LIFT_SERVICE, CameraLiftManager.class,
            new CachedServiceFetcher<CameraLiftManager>() {
                @Override
                public CameraLiftManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                    return CameraLiftManager.getInstance();
                }
            });
    }
    

    添加好Service 和 Manager 后再次启动编译,会报下面的错误:

    frameworks/base/core/java/android/app/cameralift/CameraLiftManager.java:49: error: Registration methods should have overload that accepts deli
    very Executor: `registerCallback` [ExecutorRegistration]Error: metalava detected the following problems:
    frameworks/base/core/java/android/app/cameralift/CameraLiftManager.java:49: error: Registration methods should have overload that accepts deli
    very Executor: `registerCallback` [ExecutorRegistration]
    
    

    两种解决方法:

    1. 将aidl 编译错误解决方式重新操作一遍
    2. 让lint检查忽略掉自己的模块 在framework/base 下的Android.bp忽略掉代码检查
    metalava_framework_docs_args = "
    "--api-lint-ignore-prefix android.app.cameralift." //其中 android.app.cameralift.是包名的前缀。
    

    配置完之后再次启动编译

    6.添加SELinux权限

    1. 配置service_contexts
      service_contexts文件修改需要注意一下,需要修改两个文件的位置,并且修改的内容和下面 service.te中内容要对应

    service_contexts 文件修改位置为:
    位置1:system/sepolicy/prebuilts/api/32.0/private/service_contexts
    位置2:system/sepolicy/private/service_contexts
    两个文件中修改内容相同,方法如下:
    找到文件中的audio,仿照audio 的添加方式添加,添加内容如下:

    // 这是系统服务audio 
    audio                                     u:object_r:audio_service:s0
    // 新添加服务 camera_lift
    camera_lift                               u:object_r:camera_lift_service:s0
    
    1. 配置service.te
      service.te文件修改需要注意一下,需要修改两个文件的位置。文件修改位置为:
      位置1:system/sepolicy/prebuilts/api/32.0/public/service.te
      位置2:system/sepolicy/public/service.te
      两个文件中修改内容相同,方法如下:
      找到文件中的audio,仿照audio 的添加方式添加,添加内容如下:
      找到文件位置:system/sepolicy/prebuilts/api/32.0/public/service.te
    // 系统服务audio 的配置
    type audio_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
    
    // 新添加的服务camera_file,注意一下,这里的camera_lift_service 和service_contexts 中对应
    type camera_lift_service, app_api_service,system_api_service, system_server_service, service_manager_type;
    
    1. 配置31.0.ignore.cil
      配置目录:system/sepolicy/private/compat/31.0/31.0.ignore.cil
      typeattributeset new_objects 位置添加配置camera_lift_service,如下:
    (typeattributeset new_objects
      ( new_objects
        hypervisor_prop
        camera_lift_service
      ))
    
    

    这里修改的是 31, 修改那个文件要根据实际版本决定

    7.配置prebuilts

    要在这个目录中把新的服务名字配置上,这样app才能在Context 中找到这个服务
    文件路径:prebuilts/sdk/32/public/api/android.txt

    public abstract class Context {
        ... // 省略部分代码 
        field public static final String CAMERA_LIFT_SERVICE = "camera_lift";
        ... // 省略部分代码
    }  
    

    从上面的名字也可以看出这个是设置Context 的

    注意一下,修改这个目录后需要全编译一下源码才能生效,目前还没有找到其他生效的方法。

    8. 生成应用调用的jar

    服务已经添加完毕,下面需要在系统源码中基于之前修改,生成一个供应用使用的jar , 这里不详细介绍,直接贴代码:

    1. Android.bp 文件
    java_library_static {
        name: "camera_lift_lib",
        srcs:[
            "com/sgf/cameralift/CameraLiftCallbackProxy.java",
            "com/sgf/cameralift/CameraLiftCallbackWrapper.java",
            "com/sgf/cameralift/CameraLiftManagerProxy.java",
        ],
    }
    
    1. Java 代码实现
    package com.sgf.cameralift;
    
    public interface CameraLiftCallbackProxy {
        void onStatusChange(int type, String msg);
    }
    
    
    
    package com.sgf.cameralift;
    
    import android.app.cameralift.aidl.CameraLiftCallback;
    import android.os.RemoteException;
    import com.sgf.cameralift.*;
    
    class CameraLiftCallbackWrapper extends CameraLiftCallback.Stub {
    
        private CameraLiftCallbackProxy mCallbackProxy;
        CameraLiftCallbackWrapper(CameraLiftCallbackProxy callbackProxy) {
            this.mCallbackProxy = callbackProxy;
        }
    
        @Override
        public void onStatusChange(int type, String msg) throws RemoteException {
            if (mCallbackProxy != null) {
                mCallbackProxy.onStatusChange(type, msg);
            }
        }
    }
    
    
    package com.sgf.cameralift;
    
    import android.annotation.Nullable;
    import android.app.cameralift.CameraLiftManager;
    import android.content.Context;
    import android.util.Log;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class CameraLiftManagerProxy {
    
        private static final String TAG = "CameraLiftManagerProxy";
        private final CameraLiftManager mCameraLiftManager;
        private final HashMap<CameraLiftCallbackProxy, CameraLiftCallbackWrapper> mCallbackMap = new HashMap<>();
        public CameraLiftManagerProxy(Context context) {
            this.mCameraLiftManager = (CameraLiftManager) context.getSystemService(Context.CAMERA_LIFT_SERVICE);
        }
    
    
        public synchronized void registerCallback(@Nullable CameraLiftCallbackProxy callbackProxy)  {
            if (!mCallbackMap.containsKey(callbackProxy)){
                CameraLiftCallbackWrapper wrapper = new CameraLiftCallbackWrapper(callbackProxy);
                mCallbackMap.put(callbackProxy, wrapper);
                mCameraLiftManager.registerCallback(wrapper);
            } else  {
                Log.i(TAG, "this call back has registered");
            }
        }
    
        public synchronized void unregisterCallback(@Nullable CameraLiftCallbackProxy callbackProxy)  {
            if (mCallbackMap.containsKey(callbackProxy)) {
                CameraLiftCallbackWrapper wrapper = mCallbackMap.remove(callbackProxy);
                mCameraLiftManager.unregisterCallback(wrapper);
            }
        }
    
        public void sendEvent(int type , @Nullable String value)  {
            mCameraLiftManager.sendEvent(type, value);
        }
    
        public synchronized void release() {
            for (Map.Entry<CameraLiftCallbackProxy, CameraLiftCallbackWrapper> value : mCallbackMap.entrySet()) {
                CameraLiftCallbackWrapper wrapper = value.getValue();
                mCameraLiftManager.unregisterCallback(wrapper);
            }
            mCallbackMap.clear();
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Android 源码系统添加系统服务

          本文链接:https://www.haomeiwen.com/subject/cszfrdtx.html