Android 13系统服务的添加

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

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaowang_lj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值