以下内容基于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文件。
- 先使用命令
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代码
-
找到编译aidl生成.class文件路径,上面代码编译出来的路径为:
out/soong/.intermediates/frameworks/base/android-non-updatable.stubs.module_lib/android_common/javac/classes/android/app/cameralift/aidl/
-
点击
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.java
将CameraLiftManagerSerice.java
注册到SystemServer.java
中 SystemServiceRegistry.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]
两种解决方法:
- 将aidl 编译错误解决方式重新操作一遍
- 让lint检查忽略掉自己的模块 在framework/base 下的Android.bp忽略掉代码检查
ini
metalava_framework_docs_args = "
"--api-lint-ignore-prefix android.app.cameralift." //其中 android.app.cameralift.是包名的前缀。
配置完之后再次启动编译
6.添加SELinux权限
- 配置
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
- 配置
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;
- 配置
31.0.ignore.cil
配置目录:system/sepolicy/private/compat/31.0/31.0.ignore.cil
在typeattributeset 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 , 这里不详细介绍,直接贴代码:
- 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",
],
}
- 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();
}
}