Android12 源码系统添加系统服务

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

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

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

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

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

java 复制代码
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

java 复制代码
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 也会出现这个错误
go 复制代码
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中添加了如下内容:

java 复制代码
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/

  2. 点击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

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 类

java 复制代码
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

less 复制代码
/**
 * 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.javaSystemServiceRegistry.java 文件位置:frameworks/base/core/java/android/app/SystemServiceRegistry.java

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 后再次启动编译,会报下面的错误:

yaml 复制代码
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忽略掉代码检查
ini 复制代码
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 的添加方式添加,添加内容如下:

less 复制代码
// 这是系统服务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
go 复制代码
// 系统服务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.ciltypeattributeset new_objects 位置添加配置camera_lift_service,如下:
java 复制代码
(typeattributeset new_objects
  ( new_objects
    hypervisor_prop
    camera_lift_service
  ))

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

7.配置prebuilts

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

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

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

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

8. 生成应用调用的jar

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

  1. Android.bp 文件
css 复制代码
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 代码实现
java 复制代码
package com.sgf.cameralift;

public interface CameraLiftCallbackProxy {
    void onStatusChange(int type, String msg);
}
scala 复制代码
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);
        }
    }
}
java 复制代码
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();
    }
}
相关推荐
拓端研究室几秒前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
zhangphil1 小时前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_512744641 小时前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.1 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao1 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee2 小时前
PHP伪协议总结
android·开发语言·php
mmsx8 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人11 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌12 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
_Shirley13 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙