android8.1 为AudioManager AudioService 添加底层JNI接口

驱动的同事在声卡的驱动层上做了一个功能, 需要提供一个接口开放给上层调用. 

每一步都有系统原来的代码作为参考, 添加起来也不算太难, 但是就是太麻烦了, 所以记录一下

1驱动:  android\hardware\libhardware\include\hardware\audio.h 的audio_hw_device 结构体添加声明:

    /* mic mute */
    int (*set_mic_mute)(struct audio_hw_device *dev, bool state);
    int (*get_mic_mute)(const struct audio_hw_device *dev, bool *state);
    //lwt
    int (*set_vibrator_mode)(struct audio_hw_device *dev, bool state);
    int (*get_vibrator_mode)(const struct audio_hw_device *dev, bool* state);

2. android\hardware\aw\audio\audio_hw.c 中添加实现:

static int adev_set_vibrator_mode(struct audio_hw_device *dev, bool state)
{
    ALOGD("%s: state %d\n", __func__, state);
    struct sunxi_audio_device *adev = (struct sunxi_audio_device *)dev;
    //....具体功能略
    return 0;
}

static int adev_get_vibrator_mode(const struct audio_hw_device *dev, bool *state)
{
    struct sunxi_audio_device *adev = (struct sunxi_audio_device*)dev;
    //...具体功能略
    ALOGD("adev_get_vibrator_mode, ret:%d", state);
    return 0;
}

并且在static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device)函数中添加赋值

    adev->device.set_vibrator_mode = adev_set_vibrator_mode;
    adev->device.get_vibrator_mode = adev_get_vibrator_mode;

3. \android\frameworks\av\services\audioflinger\AudioFlinger.h 中添加声明:

    //lwt
    virtual     status_t    setVibratorMode(bool state);
    virtual     bool        getVibratorMode() const;

android\frameworks\av\services\audioflinger\AudioFlinger.cpp 实现:

//lwt added
status_t AudioFlinger::setVibratorMode(bool state)
{
    status_t ret = initCheck();
    status_t result = NO_ERROR;
	ALOGD("AudioFlinger.cpp, setVibratorMode:%d", state);

    
    if (ret != NO_ERROR) {
        return ret;
    }

    // check calling permissions
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }

	
    AutoMutex lock(mHardwareLock);
    mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();


        if(dev != 0 && dev->set_vibrator_mode != 0)
        {
        	result = dev->set_vibrator_mode(dev, state);
	        if (result != NO_ERROR) {
	            ret = result;
	        }
        }
    }
    mHardwareStatus = AUDIO_HW_IDLE;
    return ret;
}

bool AudioFlinger::getVibratorMode() const
{
    status_t ret = initCheck();
    if (ret != NO_ERROR) {
        return false;
    }
    bool vibStat = true;
    AutoMutex lock(mHardwareLock);
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
        if(dev != 0 && dev->set_vibrator_mode != 0){
        	dev->get_vibrator_mode(dev, &vibStat);
       	}
    }
    ALOGD("AudioFlinger.cpp, getVibratorMode ret:%d", vibStat);

    return vibStat;
}
//lwt added end

4. android\frameworks\av\include\media\IAudioFlinger.h 

    //lwt added
    virtual     status_t    setVibratorMode(bool state) = 0;
    virtual     bool        getVibratorMode() const = 0;

android\frameworks\av\media\libmedia\IAudioFlinger.cpp : 有三处修改:

1) 代码enum {
    CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,处, 添加枚举:

    //lwt added
    SET_VIB_MODE,
    GET_VIB_MODE,
    //lwt added end

2) 类中实现:

virtual status_t setVibratorMode(bool state)
    {//lwt added
        Parcel data, reply;
        ALOGD("IAudioFlinger.cpp setVibratorMode");
        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
        data.writeInt32(state);
        remote()->transact(SET_VIB_MODE, data, &reply);

        
        return reply.readInt32();
    }

    virtual bool getVibratorMode() const
    {//lwt added
        Parcel data, reply;
        ALOGD("IAudioFlinger.cpp getVibratorMode");
        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
        remote()->transact(GET_VIB_MODE, data, &reply);
        return reply.readInt32();
    }

3) status_t BnAudioFlinger::onTransact 函数中添加消息处理:
 

        case SET_VIB_MODE: {
            CHECK_INTERFACE(IAudioFlinger, data, reply);
            int state = data.readInt32();
            reply->writeInt32( setVibratorMode(state) );
            return NO_ERROR;
        } break;
        case GET_VIB_MODE: {
            CHECK_INTERFACE(IAudioFlinger, data, reply);
            reply->writeInt32( getVibratorMode() );
            return NO_ERROR;
        } break;

5. \android\frameworks\av\include\media\AudioSystem.h 

    //lwt added 
    static status_t asSetVibratorMode(bool state);
    static status_t asIsVibratorMode(bool *state);

\android\frameworks\av\media\libmedia\AudioSystem.cpp 

//lwt added
status_t AudioSystem::asSetVibratorMode(bool state)
{
    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    if (af == 0) return PERMISSION_DENIED;
	ALOGD("AudioSystem.cpp::asSetVibratorMode");

    return af->setVibratorMode(state);
}

status_t AudioSystem::asIsVibratorMode(bool* state)
{
    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    if (af == 0) return PERMISSION_DENIED;
	ALOGD("AudioSystem.cpp::asIsVibratorMode");
    *state = af->getVibratorMode();
    return NO_ERROR;
}
//lwt added end

6.\android\frameworks\base\core\jni\android_media_AudioSystem.cpp:

//lwt added
static jint
android_media_AudioSystem_asSetVibratorMode(JNIEnv *env, jobject thiz, jboolean on)
{
    return (jint) check_AudioSystem_Command(AudioSystem::asSetVibratorMode(on));
}

static jboolean
android_media_AudioSystem_asIsVibratorMode(JNIEnv *env, jobject thiz)
{
    bool state = false;
    AudioSystem::asIsVibratorMode(&state);
    return state;
}
//lwt added end

static const JNINativeMethod gMethods[] 数组中添加:

	//lwt added    
	{"asSetVibratorMode",	"(Z)I",	    (void *)android_media_AudioSystem_asSetVibratorMode},
	{"asIsVibratorMode",    "()Z",	    (void *)android_media_AudioSystem_asIsVibratorMode},
	//lwt added end

7.android\frameworks\base\media\java\android\media\AudioSystem.java:


    //lwt added
    public static native int asSetVibratorMode(boolean on);
    public static native boolean asIsVibratorMode();
    //lwt added end

8.\android\frameworks\base\services\core\java\com\android\server\audio\AudioService.java

//lwt added
    public void AsSetVibratorMode(boolean on) {
        Log.d(TAG, String.format("AudioService.java AsSetVibratorMode val: %s", on));
        AudioSystem.asSetVibratorMode(on);
    }
    
    public boolean AsGetVibratorMode() {
        boolean ret = AudioSystem.asIsVibratorMode();
        Log.d(TAG, String.format("AudioService.java AsgetVibratorMode ret: %s", ret));

        return ret;
    }
    //lwt added end

9.android\frameworks\base\media\java\android\media\IAudioService.aidl

    //lwt added
    void AsSetVibratorMode(boolean on) ;
    boolean AsGetVibratorMode();
    //lwt added end

10. \android\frameworks\base\media\java\android\media\AudioManager.java

//lwt added
    public void AmSetVibratorMode(boolean on) {
        IAudioService service = getService();
        try {
            
            Log.d(TAG, "AmSetVibratorMode:"+on);
            service.AsSetVibratorMode(on);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


    public boolean AmGetVibratorMode() {
        IAudioService service = getService();
        boolean ret = false;
        try {
            ret = service.AsGetVibratorMode();
            Log.d(TAG, "AmGetVibratorMode ret:"+ret);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return ret;
    }
    //lwt added end

11. 至此, 整个从上到下的通道就打通了.  使用:

                    AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);;
                    mAudioManager.AmSetVibratorMode(true);

                    boolean ret = mAudioManager.AmGetVibratorMode();

12. 注意的地方: 因为修改了AudioManager 的对外接口, 所以需要在android 目录下执行  make update-api 命令, 来更新/frameworks/base/api/下面三个文件:

            current.txt            system-current.txt         test-current.txt

上一篇:Dialog显示引起的问题 Activity has leaked window DecorView@5704632[] that was originally added here


下一篇:elementui中的table组件单元格可以输入