[小制作]手机震动坏了,重新实现震动为闪烁LED

来源:互联网 发布:白云江夏什么网络好 编辑:程序博客网 时间:2024/04/19 17:27


最近手里的xt897 震动坏了。

正好重温一下Android的Service机制和Hal实现,把震动变为LED闪烁。

11月19日:

首先找到震动打调用方法:

vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);   long[] pattern = {800, 50, 400, 30}; // OFF/ON/OFF/ON...   vibrator.vibrate(pattern, 2);

VibratorService.java 在 frameworks/base/services/java/com/android/server/VibratorService.java


里面是关于震动调用打一些业务逻辑

最终会调用到

    native static boolean vibratorExists();
    native static void vibratorOn(long milliseconds);
    native static void vibratorOff();


因为最后只是为了适配我的手机。所以怎么方便怎么改来。

如果修改VibratorService.java 要编译Android系统 显然比较麻烦。

修改native只需要编译内核。

------------JNI层----------------------------

对应的native函数在

android/frameworks/base/services/jni/

com_android_server_VibratorService.cpp

查看Android.mk  ,这个需要学习一下Android.mk语法

这里的文件最终会生成libandroid_servers.so

jni层的vibratorOff 实现:

static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms){    // LOGI("vibratorOn\n");    vibrator_on(timeout_ms);}

vibrator_on 是Hal层的函数

-----------Hal层------------------------

目录:$A10_ANDROID_SRC_PATH/hardware/lighardware_legacy/

<vibrator/Android.mk>:

# Copyright 2006 The Android Open Source Project

LOCAL_SRC_FILES += vibrator/vibrator.c


<Android.mk>:

#这个文件有好几个Local_module 不过这个才是我们关心的

LOCAL_MODULE:= libhardware_legacy

输出:

ls /disk1/sources/cyanogenmod/source_cm11/out/target/product/xt897/system/lib/libhardware_legacy.so

实现:

static int sendit(int timeout_ms){    int nwr, ret, fd;    char value[20];#ifdef QEMU_HARDWARE    if (qemu_check()) {        return qemu_control_command( "vibrator:%d", timeout_ms );    }#endif    fd = open(THE_DEVICE, O_RDWR);    if(fd < 0)        return errno;    nwr = sprintf(value, "%d\n", timeout_ms);    ret = write(fd, value, nwr);    close(fd);    return (ret == nwr) ? 0 : -1;}int vibrator_on(int timeout_ms){    /* constant on, up to maximum allowed time */    return sendit(timeout_ms);}

THE_DEVICE 即 


#define THE_DEVICE "/sys/class/timed_output/sun4i-vibrator/enable"



想要在Hal层修改为闪烁LED 还得看LED的实现:

jni:

com_android_server_LightsService.cpp

msm8960 lights hal :

/disk1/sources/cyanogenmod/source_cm11/hardware/qcom/display/msm8960/liblight/

lights.c

不用看实现函数,看开头的几个宏就知道怎么回事了:

char const*const RED_LED_FILE        = "/sys/class/leds/red/brightness";char const*const GREEN_LED_FILE        = "/sys/class/leds/green/brightness";char const*const BLUE_LED_FILE        = "/sys/class/leds/blue/brightness";char const*const WHITE_LED_FILE        = "/sys/class/leds/white/brightness";char const*const LCD_FILE        = "/sys/class/leds/lcd-backlight/brightness";char const*const LED_FREQ_FILE        = "/sys/class/leds/%s/device/grpfreq";char const*const LED_PWM_FILE        = "/sys/class/leds/%s/device/grppwm";char const*const LED_BLINK_FILE        = "/sys/class/leds/%s/device/blink";char const*const LED_LOCK_UPDATE_FILE        = "/sys/class/leds/%s/device/lock";

搜一下RED_LED_FILE

    if (rgb) {
        write_int(RED_LED_FILE, (colorRGB >> 16) & 0xFF);
        write_int(GREEN_LED_FILE, (colorRGB >> 8) & 0xFF);
        write_int(BLUE_LED_FILE, colorRGB & 0xFF);
    }

使用adb shell

echo 255 > /sys/class/leds/red/brightness

确实能亮。

那就直接回到vibrator.c 改吧:

添加 :

char const*const RED_LED_FILE        = "/sys/class/leds/red/brightness";char const*const GREEN_LED_FILE        = "/sys/class/leds/green/brightness";char const*const BLUE_LED_FILE        = "/sys/class/leds/blue/brightness";char const*const BLINK_VALUE = "255";static int write_max(int fd){    int ret = write(fd,BLINK_VALUE,strlen(BLINK_VALUE));    return ret;}static int lights_reset(int fdr,int fd_g,int fd_b){    int ret;    ret = write(fdr,"0",strlen("0"));    ret = write(fd_g,"0",strlen("0"));    ret = write(fd_b,"0",strlen("0"));    return ret;}#define INTERVAL 200static int sendit(int timeout_ms){    int fd_r,fd_g,fd_b,ret,i,cur_time_ms = 0,mod,div;    fd_r = open(RED_LED_FILE,O_RDWR);    fd_g = open(GREEN_LED_FILE,O_RDWR);    fd_b = open(BLUE_LED_FILE,O_RDWR);    ret = fd_r<0?-1:(fd_g<0?-1:fd_b<0?-1:0);    if((fd_r<0)||(fd_g<0)||(fd_b<0))        return -1;    if(timeout_ms < INTERVAL){        write_max(fd_r);        write_max(fd_g);        write_max(fd_b);        for(i=0;i<timeout_ms;i++)            usleep(1000);        lights_reset(fd_r,fd_g,fd_b);        printf("!!!!timeout_ms is %d\n",timeout_ms);        return 0;    }            while(cur_time_ms<timeout_ms){        if(cur_time_ms%INTERVAL==0)        {// call once in INTERVAL ms;            div = cur_time_ms/INTERVAL;            mod = div%3;            lights_reset(fd_r,fd_g,fd_b);            if(mod==0)                write_max(fd_r);            else if(mod == 1)                write_max(fd_g);            else if(mod==2)                write_max(fd_b);        }        usleep(1000);        cur_time_ms++;    }    return 0;}

然后

source build/envsetup.sh

breakfast xt897

cd /disk1/sources/cyanogenmod/source_cm11/hardware/libhardware_legacy

mm


[root@ libhardware_legacy]# adb push /disk1/sources/cyanogenmod/source_cm11/out/target/product/xt897/obj/lib/libhardware_legacy.so /sdcard/
[root@ libhardware_legacy]# adb shell
shell@asanti_c:/ $ su   
root@asanti_c:/ # cat /sdcard/remount.sh 2>&0|sh                               
root@asanti_c:/ # cp /sdcard/lib
libhardware_legacy.so     libs/                     
root@asanti_c:/ # cp /sdcard/libhardware_legacy.so /system/lib


即可.

威信设置的震动时间200ms,所以小于200ms的干脆让它常亮得了。

done









0 0