Android 11系统服务的添加_android 11 添加服务-CSDN博客
前景
我们作为android系统的开发者、工作者,很多时候需要暴露我们的接口给应用层使用。或者是承担一个承上启下的作用,向下需要调用硬件抽象层的代码,封装给应用层,由此我们需要新建自己的服务来实现此功能。
目标
1、创建一个系统服务, VSAudioService
2、在android13中使用getSystemService方法获取该服务并调用里面的方法。
添加系统服务步骤
1、定义系统服务aidl接口和代理manager类
因为系统服务是运行在system_server进程中,所以app要调用我们的自定义service需通过跨进程通讯,Android中跨进程通讯使用AIDL,所以我们这里定义一个IVSAudio.aidl文件,另外还需要定一个服务的代理manager类,用于app调用。
frameworks/base/core/java/android/os/test/aidl/audio/IVSAudio.aidl
package android.os.test.aidl.audio;
import android.os.test.aidl.audio.IMuteChangeListener;//此处是我们添加的回调接口,暂不考虑
import android.os.test.aidl.audio.IVolumeChangeListener;
interface IVSAudio {
void setVolume(int level);
int getVolume();
void registerOnVolumeChanged(IVolumeChangeListener changeListener);
void unregisterOnVolumeChanged(IVolumeChangeListener changeListener);
void setMute(boolean muted);
boolean getMute();
void registerOnMuteChanged(IMuteChangeListener changeListener);
void unregisterOnMuteChanged(IMuteChangeListener changeListener);
}
frameworks/base/core/java/com/test/vsapi/VSAudioManager.java
package com.test.vsapi;
import android.os.test.aidl.audio.IVSAudio;
import android.util.Log;
import android.content.Context;
import android.os.Handler;
import android.os.test.aidl.audio.IVolumeChangeListener;
import android.os.test.aidl.audio.IMuteChangeListener;
import java.util.ArrayList;
import android.os.RemoteException;
public class VSAudioManager {
IVSAudio mService;
public VSAudioManager(Context context,IVSAudio service){
mService=service;
try {
if(mService != null){
mService.registerOnVolumeChanged(iVolumeChangeListener);
mService.registerOnMuteChanged(iMuteChangeListener);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
private static ArrayList<VSStatusCallback.IVolumeChangedCallback> iVolumeChangedCallback = new ArrayList<VSStatusCallback.IVolumeChangedCallback>();
private static ArrayList<VSStatusCallback.IMuteChangedCallback> iMuteChangedCallback = new ArrayList<VSStatusCallback.IMuteChangedCallback>();
public void setVolume(int level){
try{
mService.setVolume(level);
}catch(Exception e){
Log.e("VSAudioManager",e.toString());
e.printStackTrace();
}
}
public int getVolume(){
try{
return mService.getVolume();
}catch(Exception e){
Log.e("VSAudioManager",e.toString());
e.printStackTrace();
}
return -1;
}
public void registerOnVolumeChanged(Handler handler,VSStatusCallback.IVolumeChangedCallback callback){
if (callback != null) {
iVolumeChangedCallback.add(callback);
}
}
public void unregisterOnVolumeChanged(VSStatusCallback.IVolumeChangedCallback callback){
iVolumeChangedCallback.remove(callback);
}
public void setMute(boolean muted){
try{
mService.setMute(muted);
}catch(Exception e){
Log.e("VSAudioManager",e.toString());
e.printStackTrace();
}
}
public boolean getMute(){
try{
return mService.getMute();
}catch(Exception e){
Log.e("VSAudioManager",e.toString());
e.printStackTrace();
}
return false;
}
public void registerOnMuteChanged(Handler handler,VSStatusCallback.IMuteChangedCallback callback){
if (callback != null) {
iMuteChangedCallback.add(callback);
}
}
public void unregisterOnMuteChanged(VSStatusCallback.IMuteChangedCallback callback){
iMuteChangedCallback.remove(callback);
}
static IVolumeChangeListener iVolumeChangeListener = new IVolumeChangeListener.Stub(){
@Override
public void onVolumeChanged(int level) {
for (int i = 0; i < iVolumeChangedCallback.size(); i++) {
if (iVolumeChangedCallback.get(i) != null){
iVolumeChangedCallback.get(i).onVolumeChanged(level);
}
}
}
};
static IMuteChangeListener iMuteChangeListener = new IMuteChangeListener.Stub(){
@Override
public void onMuteChanged(boolean muted) {
for (int i = 0; i < iMuteChangedCallback.size(); i++) {
if (iMuteChangedCallback.get(i) != null){
iMuteChangedCallback.get(i).onMuteChanged(muted);
}
}
}
};
}
因为我们app端是通过反射调用的,所以规定了我们Manager类的路径,如果是自己用的话,存放的路径可以参考系统原生的Manager类
2、关闭lint代码检查
我们需要在base/Android.bp添加一下内容
diff --git a/release/frameworks/base/Android.bp b/release/frameworks/base/Android.bp
old mode 100644
new mode 100755
index 14a2bff8ad1..714ecd095a4
--- a/release/frameworks/base/Android.bp
+++ b/release/frameworks/base/Android.bp
@@ -1218,6 +1218,8 @@ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.x
"--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
"--api-lint-ignore-prefix android.icu. " +
"--api-lint-ignore-prefix java. " +
+ "--api-lint-ignore-prefix android.os. " +
+ "--api-lint-ignore-prefix com.test. " +
"--api-lint-ignore-prefix junit. " +
"--api-lint-ignore-prefix org. "
我们添加在framework/base/core 下面的aidl和java文件是不需要重现加入编译的,因为默认是编译这个路径下面所有的java和aidl文件的。
3、添加系统服务VSAudioService
我们添加路径时参考着系统原生服务的位置
frameworks/base/services/core/java/com/android/server/VSAudioService.java
package com.android.server;
import android.os.test.aidl.audio.IVSAudio;
import android.os.test.aidl.audio.IVolumeChangeListener;
import android.os.test.aidl.audio.IMuteChangeListener;
import android.os.RemoteException;
import android.content.Context;
import android.util.Log;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.RemoteCallbackList;
public class VSAudioService extends IVSAudio.Stub {
private Context mContext;
private AudioManager mAudioManager;
private final String TAG = this.getClass().getSimpleName();
private final RemoteCallbackList<IVolumeChangeListener> mVolumeListenerList = new RemoteCallbackList<>();
private final RemoteCallbackList<IMuteChangeListener> mMuteListenerList = new RemoteCallbackList<>();
VSAudioService(Context context) {
mContext=context;
}
public AudioManager getAudioManager() {
if (mAudioManager == null) {
mAudioManager = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE));
}
return mAudioManager;
}
/**
* Sets volume.
*
* @param level Volume Level
*/
@Override
public void setVolume(int level) throws RemoteException{
Log.d(TAG,"------setVolume-----"+level);
if (level > 100 || level < 0) {
return;
}
getAudioManager().setStreamVolume(AudioSystem.STREAM_MUSIC, level, AudioManager.FLAG_SHOW_UI);
try {
int callBackSize = mVolumeListenerList.beginBroadcast();
if (callBackSize == 0) {
Log.d(TAG,"DisplayChangeLisrenerArrayList callBackSize : 0");
return ;
}
for (int i = 0; i < callBackSize; i++) {
if (mVolumeListenerList.getBroadcastItem(i) != null){
mVolumeListenerList.getBroadcastItem(i).onVolumeChanged(level);
}
}
} catch (RemoteException e) {
e.printStackTrace();
} finally {
mVolumeListenerList.finishBroadcast();
}
}
/**
* Gets volume.
*
* @return the volume
*/
@Override
public int getVolume() throws RemoteException{
Log.d(TAG,"------getVolume-----");
int result = getAudioManager().getStreamVolume(AudioSystem.STREAM_MUSIC);
return result;
}
/**
* Register on volume changed.
*
* @param handler do handler.post(callback)
* @param callback the callback
*/
@Override
public void registerOnVolumeChanged(IVolumeChangeListener changeListener) throws RemoteException{
Log.d(TAG,"------registerOnVolumeChanged-----");
if (mVolumeListenerList != null) {
mVolumeListenerList.register(changeListener);
}
}
/**
* Un register on volume changed.
*
* @param callback the callback
*/
@Override
public void unregisterOnVolumeChanged(IVolumeChangeListener changeListener) throws RemoteException{
Log.d(TAG,"------unregisterOnVolumeChanged-----");
if (mVolumeListenerList != null) {
mVolumeListenerList.unregister(changeListener);
}
}
/**
* Sets mute.
*
* @param muted mute on(true) / off(false)
*/
@Override
public void setMute(boolean muted) throws RemoteException{
Log.d(TAG,"------setMute-----"+muted);
if (muted == getMute()){
Log.d(TAG,"muted: "+muted+" getMute: "+getMute());
return;
}
int isMute = AudioManager.ADJUST_UNMUTE;//100;
if (muted) {
isMute = AudioManager.ADJUST_MUTE;//-100;
}
int showUI = AudioManager.FLAG_SHOW_UI;
getAudioManager().adjustStreamVolume(AudioSystem.STREAM_MUSIC, isMute, showUI);
try {
int callBackSize = mMuteListenerList.beginBroadcast();
if (callBackSize == 0) {
Log.d(TAG,"DisplayChangeLisrenerArrayList callBackSize : 0");
return ;
}
for (int i = 0; i < callBackSize; i++) {
if (mMuteListenerList.getBroadcastItem(i) != null){
mMuteListenerList.getBroadcastItem(i).onMuteChanged(muted);
}
}
} catch (RemoteException e) {
e.printStackTrace();
} finally {
mMuteListenerList.finishBroadcast();
}
}
/**
* Gets mute.
*
* @return mute on/off
*/
@Override
public boolean getMute(){
Log.d(TAG,"------getMute-----");
boolean result = getAudioManager().isStreamMute(AudioSystem.STREAM_MUSIC);
return result;
}
/**
* Register on mute changed.
*
* @param handler do handler.post(callback)
* @param callback the callback
*/
@Override
public void registerOnMuteChanged(IMuteChangeListener changeListener) throws RemoteException{
Log.d(TAG,"------registerOnMuteChanged-----");
if (mMuteListenerList != null) {
mMuteListenerList.register(changeListener);
}
}
/**
* Un register on mute changed.
*
* @param callback the callback
*/
@Override
public void unregisterOnMuteChanged(IMuteChangeListener changeListener) throws RemoteException{
Log.d(TAG,"------unregisterOnMuteChanged-----");
if (mMuteListenerList != null) {
mMuteListenerList.unregister(changeListener);
}
}
}
4、将VSAudioService加入到android的系统服务
1、添加string 变量VS_AUDIO_SERVICE= "vsaudio" 到系统中,这样客户端可以使用 getSystemService(Context.VS_AUDIO_SERVICE) 获取客户端的实例
diff --git a/release/frameworks/base/core/java/android/content/Context.java b/release/frameworks/base/core/java/android/content/Context.java
old mode 100644
new mode 100755
index 8472144a92c..84a61645f62
--- a/release/frameworks/base/core/java/android/content/Context.java
+++ b/release/frameworks/base/core/java/android/content/Context.java
@@ -3494,6 +3494,14 @@ public abstract class Context {
//@hide: TIME_ZONE_DETECTOR_SERVICE,
PERMISSION_SERVICE,
LIGHTS_SERVICE,
+ VS_AUDIO_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -5152,6 +5160,47 @@ public abstract class Context {
*/
public static final String LIGHTS_SERVICE = "lights";
+ /**
+ * The constant VS_AUDIO_SERVICE.
+ */
+ @SuppressLint("ServiceName")
+ public static final String VS_AUDIO_SERVICE = "vsaudio";
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.DreamManager} for controlling Dream states.
2、修改 frameworks/base/services/java/com/android/server/SystemServer.java 文件,在 startOtherServices 方法里面增加以下代码:
diff --git a/release/frameworks/base/services/java/com/android/server/SystemServer.java b/release/frameworks/base/services/java/com/android/server/SystemServer.java
index 240ab83b488..649c13d2212 100755
--- a/release/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/release/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -191,6 +191,14 @@ import java.util.Locale;
import java.util.Timer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
+import com.android.server.VSAudioService;
public final class SystemServer {
@@ -2453,7 +2461,48 @@ public final class SystemServer {
context.startService(intent1);
Slog.i(TAG, "Startup2 KTCService Apk....");
t.traceEnd();
-
+
+ t.traceBegin("VSAudioService");
+ ServiceManager.addService(Context.VS_AUDIO_SERVICE,
+ new VSAudioService(context));
+ t.traceEnd();
+
if (mIncrementalServiceHandle != 0) {
t.traceBegin("MakeIncrementalServiceReady");
setIncrementalServiceSystemReady(mIncrementalServiceHandle);
3、在frameworks/base/core/java/com/android/app/SystemServiceRegistry.java 注册VSAudioManager.java
diff --git a/release/frameworks/base/core/java/android/app/SystemServiceRegistry.java b/release/frameworks/base/core/java/android/app/SystemServiceRegistry.java
old mode 100644
new mode 100755
index e599a5ce81e..ac6b6914a7e
--- a/release/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/release/frameworks/base/core/java/android/app/SystemServiceRegistry.java
@@ -213,6 +213,23 @@ import com.android.internal.util.Preconditions;
import java.util.Map;
import java.util.Objects;
+import android.os.test.aidl.audio.IVSAudio;
+import com.test.vsapi.VSAudioManager;
/**
* Manages all of the system services that can be returned by {@link Context#getSystemService}.
* Used by {@link ContextImpl}.
@@ -1334,6 +1351,77 @@ public final class SystemServiceRegistry {
return new DreamManager(ctx);
}});
+ registerService(Context.VS_AUDIO_SERVICE, VSAudioManager.class,
+ new CachedServiceFetcher<VSAudioManager>() {
+ @Override
+ public VSAudioManager createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(Context.VS_AUDIO_SERVICE);
+ IVSAudio service = IVSAudio.Stub.asInterface(b);
+ return new VSAudioManager(ctx, service);
+ }});
+
sInitializing = true;
try {
// Note: the following functions need to be @SystemApis, once they become mainline
编译
切记一定要先在根目录执行make update-api更新一下 api 接口,再整编系统,否则会报错。编译完可以看到一下几个文件更新
release/frameworks/base/api/current.txt
release/frameworks/base/api/system-current.txt
release/frameworks/base/api/test-current.txt
验证service添加是否成功
输入一下指令
console:/ # service list | grep VS
可以看到
162 vsaudio: [android.os.test.aidl.audio.IVSAudio]
则表示添加成功。
APP端调用
APP端这里有好几种调用方式,可以采取反射的方式,这里不予介绍,介绍一下我从来验证的方式。我们在整包编译完以后,用一下指令去编译fameworks.jar
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-mt9950_cn.ninja framework-minus-apex
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-qssi.ninja framework-minus-apex
我这边是基于mtk的9950芯片去开发的,这里的指令和你的开发板也有关系,基本就是变一下out/combined-mt9950_cn.ninja。也可以采用mmm的方式,但是太慢了,不推荐。
将生成的jar导入As工程就完活了。
VSAudioManager vsAudioManager = (VSAudioManager)getSystemService(VSContext.VS_AUDIO_SERVICE);
vsAudioManager.setVolume(50);