Android Vibrator 框架总结

前言

振动器小模块框架总结
基于 MTK 7.0 源码

驱动

内核配置:kernel-3.18\arch\arm64\configs\E266L_debug_defconfig
CONFIG_MTK_VIBRATOR=y

驱动初始化流程:
// Vibrator_drv.c (kernel-3.18\drivers\misc\mediatek\vibrator)
module_init(vib_mod_init);
static int vib_mod_init(void)
        /////////////////////////////////////////////////////////
        // 1. 获得 dts 设置,配置 PMIC 电压输出
        vibr_power_set();
                /////////////////////////////////////////////////////////
                // 获得 dts 中相应的配置 
                // E266L.dts (kernel-3.18\arch\arm64\boot\dts)
                //      vibrator0:vibrator@0 {
                //          compatible = "mediatek,vibrator";
                //          vib_timer = <25>;
                //          vib_limit = <9>;
                //      
                //          vib_vol= <6>;
                //              //////////////////////////////////////
                //              // hw->vib_vol:  Voltage selection
                //              // 3'b000: 1.2V
                //              // 3'b001: 1.3V
                //              // 3'b010: 1.5V
                //              // 3'b011: 1.8V
                //              // 3'b100: 2.0V, if PMIC6353, 2.5V
                //              // 3'b101: 2.8V
                //              // 3'b110: 3.0V
                //              // 3'b111: 3.3V
                //      };
                struct vibrator_hw *hw = get_cust_vibrator_dtsi();
                                                    struct device_node *led_node = NULL;
                                                    pvib_cust = kmalloc(sizeof(struct vibrator_hw), GFP_KERNEL);
                                                    led_node = of_find_compatible_node(NULL, NULL, "mediatek,vibrator");
                                                    ret = of_property_read_u32(led_node, "vib_timer",&(pvib_cust->vib_timer));
                                                    ret =of_property_read_u32(led_node, "vib_limit",&(pvib_cust->vib_limit));        
                                                    ret =of_property_read_u32(led_node, "vib_vol",&(pvib_cust->vib_vol));    
                // 设置 vibrator 电压  
                pmic_set_register_value(PMIC_RG_VIBR_VOSEL, hw->vib_vol);
                
        ///////////////////////////////////////////////////////////////
        // 2. 注册平台设备 
        //      static struct platform_device vibrator_device = {
        //          .name = "mtk_vibrator",
        //          .id = -1,
        //      };
        ret = platform_device_register(&vibrator_device);
        
        ///////////////////////////////////////////////////////////////
        // 3. 创建工作队列
        vibrator_queue = create_singlethread_workqueue(VIB_DEVICE);
        INIT_WORK(&vibrator_work, update_vibrator);
        
        ///////////////////////////////////////////////////////////////
        // 4. 创建定时器
        hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        vibe_timer.function = vibrator_timer_func;
        
        ///////////////////////////////////////////////////////////////
        // 5. 【核心】创建一个定时输出设备?使用 sys 实现的 Android 特有驱动
        //      static struct timed_output_dev mtk_vibrator = {
        //          .name = "vibrator",
        //          .get_time = vibrator_get_time,
        //          .enable = vibrator_enable,
        //      };
        ////////////////////////////////////////////////////////////////
        // 生成节点路径:
        //      /sys/class/timed_output/vibrator 
        //      /sys/devices/virtual/timed_output/vibrator 
        timed_output_dev_register(&mtk_vibrator);
                // 先看这个目录有没有,没有 sys 下目录的话,创建一个:/sys/devices/virtual/timed_output/
                ret = create_timed_output_class();
                            // Timed_output.c (kernel-3.18\drivers\staging\android)
                            static int create_timed_output_class(void)
                                    // 创建 sys/class/timed_output/ 类目录 
                                    timed_output_class = class_create(THIS_MODULE, "timed_output");
                                    atomic_set(&device_count, 0);
                                    timed_output_class->dev_groups = timed_output_groups;
                // 引用加 1             
                tdev->index = atomic_inc_return(&device_count);
                
                // 创建 /sys/devices/virtual/timed_output/vibrator 目录 
                tdev->dev = device_create(timed_output_class, NULL,MKDEV(0, tdev->index), NULL, "%s", tdev->name);                            
                                                dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
                                                            return device_create_groups_vargs(class, parent, devt, drvdata, NULL,fmt, args);
                                                                            retval = device_add(dev);
                                                                                    error = device_create_file(dev, &dev_attr_uevent);
                                                                                    if (MAJOR(dev->devt))
                                                                                        error = device_create_file(dev, &dev_attr_dev);
                                                                                        error = device_create_sys_dev_entry(dev);
                                                                                        devtmpfs_create_node(dev);
                                                                                    //////////////////////////////////////////////
                                                                                    // 一系列调用之后,添加了 class 的 dev_groups,他已经有两个默认属性了 
                                                                                    error = device_add_groups(dev, class->dev_groups);
                                                                                                if (class)
                                                                                                    error = device_add_groups(dev, class->dev_groups);                                                                                              
                                                                                                
                                                                                    error = bus_add_device(dev);
                                                                                    error = dpm_sysfs_add(dev);
                                                                                    device_pm_add(dev);
                                                                                    
                                                                                    
                
                dev_set_drvdata(tdev->dev, tdev);
        
        
        
        
        ///////////////////////////////////////////////////////////////
        // 6. 注册平台驱动
        //      static struct platform_driver vibrator_driver = {
        //          .probe = vib_probe,
        //          .remove = vib_remove,
        //          .shutdown = vib_shutdown,
        //          .driver = {
        //                 .name = VIB_DEVICE,
        //                 .owner = THIS_MODULE,
        //                 },
        //      };
        ret = platform_driver_register(&vibrator_driver);
                    /////////////////////////////////////////////////////////
                    // 进入对应的 probe 函数,为空的?作用?
        
        ////////////////////////////////////////////////////////////////////
        // 7. 创建 sys 属性节点: /sys/class/timed_output/vibrator/vibr_on
        ret = device_create_file(mtk_vibrator.dev, &dev_attr_vibr_on);
        
        
       

//////////////////////////////////////////////////////////////////////////////////////////////
// 上层调用流程:
// 目前 HAL 层是通过 sys/class/timed_output/vibrator/enable 节点来控制马达的启停的 
// 初始化的时候此节点已设置为 timed_output 类的操作操作 


///////////////////////////////////////////////////////////
// 1. 打开马达
//      echo 时间 > sys/class/timed_output/vibrator/enable
// Timed_output.c (kernel-3.18\drivers\staging\android)
static ssize_t enable_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size)
                struct timed_output_dev *tdev = dev_get_drvdata(dev);
                rc = kstrtoint(buf, 0, &value);
                tdev->enable(tdev, value);
                        //////////////////////////////////////////////////////////////////
                        // 本驱动的 enable 函数 
                        static void vibrator_enable(struct timed_output_dev *dev, int value)
                                            struct vibrator_hw *hw = mt_get_cust_vibrator_hw();
                                            while (hrtimer_cancel(&vibe_timer))
                                            // limit 配置项的使用 
                                            if (value > hw->vib_limit && value < hw->vib_timer)
                                                value = hw->vib_timer;
                        
                                            value = (value > 15000 ? 15000 : value);
                                            vibe_state = 1;
                                            // 启动了定时器 
                                            hrtimer_start(&vibe_timer,ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL);
                                            
                                            // 调用工作队列打开马达?
                                            queue_work(vibrator_queue, &vibrator_work);
                                                    static void update_vibrator(struct work_struct *work)
                                                                        	if (!vibe_state)
                                                                                vibr_Disable();
                                                                            else
                                                                                vibr_Enable();
                                                                                        if (!ldo_state)
                                                                                            vibr_Enable_HW();
                                                                                                    ///////////////////////////////////////////////////
                                                                                                    // 调用 PMIC 操作函数打开马达 
                                                                                                    pmic_set_register_value(PMIC_LDO_VIBR_EN, 1);     // [bit 1]: VIBR_EN,  1=enable 
                                                                                            ldo_state = 1;
                            
                        
///////////////////////////////////////
// 2. 获得振动剩余时间 
//      cat sys/class/timed_output/vibrator/enable                        
static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf)                        
                int remaining = tdev->get_time(tdev);
                        //////////////////////////////////////////////////////////////////
                        // 本驱动的 get_time 函数 
                        static int vibrator_get_time(struct timed_output_dev *dev)
                                        if (hrtimer_active(&vibe_timer))
                                            ktime_t r = hrtimer_get_remaining(&vibe_timer);
                                            return ktime_to_ms(r);

HAL

 振动器的 HAL 库实现还是蛮简单的,主要是往节点:
    /sys/class/timed_output/vibrator/enable
写入振动时间就行了。

文件位置:
Vibrator.c (hardware\libhardware\modules\vibrator)
【初始化流程】
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .module_api_version = VIBRATOR_API_VERSION,
    .hal_api_version = HARDWARE_HAL_API_VERSION,
    .id = VIBRATOR_HARDWARE_MODULE_ID,
    .name = "Default vibrator HAL",
    .author = "The Android Open Source Project",
    .methods = &vibrator_module_methods,
                //////////////////////////////////////////////////////////////////
                // static struct hw_module_methods_t vibrator_module_methods = {
                //     .open = vibra_open,
                // };
};
//////////////////////////////////////////////////////////////
static int vibra_open(const hw_module_t* module, const char* id __unused,hw_device_t** device __unused)
                ///////////////////////////////////////////////////////
                // 1. 判断是否有振动器设备存在,open() 打开设备
                vibra_exists()
                        //////////////////////////////////////////////////////
                        // static const char THE_DEVICE[] = "/sys/class/timed_output/vibrator/enable";
                        static int vibra_exists()
                                fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));
                                close(fd);

                ////////////////////////////////////////////////////// 
                // 2. 分配设置 vibrator_device_t 结构体 
                vibrator_device_t *vibradev = calloc(1, sizeof(vibrator_device_t)); 
                vibradev->common.tag = HARDWARE_DEVICE_TAG;
                vibradev->common.module = (hw_module_t *) module;
                vibradev->common.version = HARDWARE_DEVICE_API_VERSION(1,0);
                vibradev->common.close = vibra_close;
                //振动器操作函数 
                vibradev->vibrator_on = vibra_on;
                                ///////////////////////////////////////////////////////////////////
                                // 打开振动器 
                                static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms) 
                                                return sendit(timeout_ms);
                vibradev->vibrator_off = vibra_off;
                                ///////////////////////////////////////////////////////////////////
                                // 关闭振动器 
                                static int vibra_off(vibrator_device_t* vibradev __unused)
                                                /////////////////////////////////////////////////////////////////////////
                                                // 此函数直接往:/sys/class/timed_output/vibrator/enable 写振动时间就行了
                                                return sendit(0);
                                                        fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));
                                                        to_write = snprintf(value, sizeof(value), "%u\n", timeout_ms);
                                                        written = TEMP_FAILURE_RETRY(write(fd, value, to_write));
                                                        close(fd);
                                
                                
                ///////////////////////////////////////////////////////
                // 3. 返回 hw_device_t 结构体给 jni 层调用 
                *device = (hw_device_t *) vibradev;        

Framework

本文件位置:frameworks\base\services\core\java\com\android\server\VibratorService.java


【服务启动流程】:
// frameworks\base\services\java\com\android\server\SystemServer.java
public final class SystemServer
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
                ///////////////////////////////////////////
                // 1. 创建一个 VibratorService 对象 
                VibratorService vibrator = null;
                vibrator = new VibratorService(context);
                                    /////////////////////////////////////////////////////////////////////
                                    // frameworks\base\services\core\java\com\android\server\VibratorService.java
                                    // 头文件一看就是个 aidl 接口继承实现 binder 通信的货
                                    // aidl 位置: frameworks\base\core\java\android\os\IVibratorService.aidl
                                    //          interface IVibratorService
                                    //          {   // 这些定义的都是服务端需要提交实现的接口
                                    //              boolean hasVibrator();
                                    //              void vibrate(int uid, String opPkg, long milliseconds, int usageHint, IBinder token);
                                    //              void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int usageHint, IBinder token);
                                    //              void vibrateLevel(int uid, String opPkg, long milliseconds, int usageHint, int level, int category, IBinder token);
                                    //              void vibratePatternLevel(int uid, String opPkg, in long[] pattern, int repeat, int usageHint, int level, int category, IBinder token);
                                    //              void cancelVibrate(IBinder token);
                                    //          }
                                    public class VibratorService extends IVibratorService.Stub implements InputManager.InputDeviceListener
                                    {
                                        //////////////////////////////////////////////
                                        // 构造函数 
                                        VibratorService(Context context)
                                        {
                                            /////////////////////////////////////////////////////////////////////
                                            // 调用对应的 jni 初始化函数 
                                            // com_android_server_VibratorService.cpp (frameworks\base\services\core\jni)
                                            
                                            // 获得 HAL 层实现库 
                                            vibratorInit();
                                                    int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);
                                                    vibrator_open(gVibraModule, &gVibraDevice);
                                                            return module->methods->open(module, VIBRATOR_DEVICE_ID_MAIN, (struct hw_device_t**)device);
                                                            
                                            // 关闭振动器,即向 /sys/class/timed_output/vibrator/enable 写 0  
                                            vibratorOff();                                                    
                                                    int err = gVibraDevice->vibrator_off(gVibraDevice);
                                            
                                            
                                            
                                            
                                            
                                            PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
                                            
                                            /////////////////////////////////////////////////////////
                                            // 获得华硕添加的 setting 震动设置
                                            mRingstoneVibLevel = Settings.System.getInt(mContext.getContentResolver(),
                                                    Settings.System.VIBRATION_LEVEL_RINGTONE, AudioAttributes.LEVEL_GENERAL_0);

                                            mNotificationVibLevel = Settings.System.getInt(mContext.getContentResolver(),
                                                    Settings.System.VIBRATION_LEVEL_NOTIFICATION, AudioAttributes.LEVEL_GENERAL_0);

                                            mTouchVibLevel = Settings.System.getInt(mContext.getContentResolver(),
                                                    Settings.System.VIBRATION_LEVEL_TOUCH, AudioAttributes.LEVEL_GENERAL_0);
                                           
                                            /////////////////////////////////////////////////////////
                                            // 注册了一个广播接收者,接收屏幕关闭广播
                                            IntentFilter filter = new IntentFilter();
                                            filter.addAction(Intent.ACTION_SCREEN_OFF);
                                            context.registerReceiver(mIntentReceiver, filter);
                                            
                                        }
                                        
                                    }
                
                ///////////////////////////////////////////
                // 2. 将本服务添加到 servicemanager 中进行管理
                ServiceManager.addService("vibrator", vibrator);

                。。。 // 一系列其他初始化函数  
                
                ///////////////////////////////////////////
                // 3. 将本服务添加到 servicemanager 中进行管理
                vibrator.systemReady();
                            //////////////////////////////////////////////////////////////////////////////
                            // frameworks\base\services\core\java\com\android\server\VibratorService.java
                            public void systemReady()
                                            /////////////////////////////////////////////////////
                                            // 1. 监听手机设置 setting 的相关变化,变化后都是调用
                                            //    updateInputDeviceVibrators() 来更新马达状态 
                                            mSettingObserver = new SettingsObserver(mH);
                                            //+++ aras_yin: add vibrator level feature
                                            mVibLvRingtoneObserver = new VibLvRingtoneObserver(mH);
                                            mVibLvNotificationObserver = new VibLvNotificationObserver(mH);
                                            mVibLvTouchObserver = new VibLvTouchObserver(mH);
                                            //--- aras_yin
                                            
                                            //////////////////////////////////////////////////////
                                            // 2. 注册了一系列需要状态变化,改变马达 
                                            mPowerManagerInternal.registerLowPowerModeObserver(
                                                    new PowerManagerInternal.LowPowerModeListener() {
                                                @Override
                                                public void onLowPowerModeChanged(boolean enabled) {
                                                    updateInputDeviceVibrators();
                                                }
                                            });

                                            mContext.getContentResolver().registerContentObserver(
                                                    Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
                                                    true, mSettingObserver, UserHandle.USER_ALL);

                                            mContext.registerReceiver(new BroadcastReceiver() {
                                                @Override
                                                public void onReceive(Context context, Intent intent) {
                                                    updateInputDeviceVibrators();
                                                }
                                            }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
        
                                             //+++ aras_yin: add vibrator level feature
                                            mContext.getContentResolver().registerContentObserver(
                                                    Settings.System.getUriFor(Settings.System.VIBRATION_LEVEL_RINGTONE),
                                                    true, mVibLvRingtoneObserver, UserHandle.USER_ALL);
                                            mContext.getContentResolver().registerContentObserver(
                                                    Settings.System.getUriFor(Settings.System.VIBRATION_LEVEL_NOTIFICATION),
                                                    true, mVibLvNotificationObserver, UserHandle.USER_ALL);
                                            mContext.getContentResolver().registerContentObserver(
                                                    Settings.System.getUriFor(Settings.System.VIBRATION_LEVEL_TOUCH),
                                                    true, mVibLvTouchObserver, UserHandle.USER_ALL);
                                            //--- aras_yin
                                            
                                            //////////////////////////////////////////////////////////
                                            // 3. 马达输入设备?看不懂,看完输入子系统再看
                                            updateInputDeviceVibrators();
                                                        doCancelVibrateLocked();
                                                                doVibratorOff();
                                                                    ////////////////////////////////////
                                                                    // 调用 native 层关马达 
                                                                    vibratorOff();
        
                                                        synchronized (mInputDeviceVibrators)
                                                        { // 一票输入设备相关操作  }
                                                        
                                                        
                                                        startNextVibrationLocked();
                                                                startVibrationLocked(mVibrations.getFirst());
                                                                            if (vib.mTimeout != 0)
                                                                                    doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint, vib.mVibrationLevel, vib.mVibrationCategory);
                                                                                            /////////////////////////////////////////////////////
                                                                                            // 调用 HAL 层开马达 
                                                                                            vibratorOn(millis);
                                                                                            
                                                                                    // 振动一段时间后,再来更新马达状态         
                                                                                    mH.postDelayed(mVibrationRunnable, vib.mTimeout);
        
                                                                            else
                                                                                // 这里创建了一个 VibrateThread 线程 
                                                                                mThread = new VibrateThread(vib);
                                                                                mThread.start();
                                                                                        /////////////////////////////////////////////////
                                                                                        // 启动线程操作:
                                                                                         private class VibrateThread extends Thread
                                                                                         {
                                                                                            public void run()
                                                                                            {
                                                                                                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
                                                                                                while (!mDone)
                                                                                                {
                                                                                                    // sleep until it is time to start the vibrator
                                                                                                    delay(duration);
                                                                                                    
                                                                                                    // 启动马达 
                                                                                                    VibratorService.this.doVibratorOn(duration, uid, usageHint, vibLevel, vibCate);
                                                                                                    
                                                                                                    // 本次振动结束,开始处理下一个 
                                                                                                    if (!mDone) {
                                                                                                        // If this vibration finished naturally, start the next
                                                                                                        // vibration.
                                                                                                        unlinkVibration(mVibration);
                                                                                                        startNextVibrationLocked();
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                             
                                                                                         }

App

【马达的应用进程的使用】:
代码位置:vendor\mediatek\proprietary\packages\apps\Emode\src\com\wind\emode\testcase\VibratorStressTest.java
    ////////////////////////////////////////
    // 1. 导入库,声明变量
    import android.os.Vibrator;
    private Vibrator mVibrator;
    
    ////////////////////////////////////////
    // 2. 获得马达服务
    mVibrator = ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE));

    ////////////////////////////////////////
    // 3. 启动马达 
    mVibrator.vibrate(array, 0);
                //////////////////////////////////////
                //  @param pattern an array of longs of times for which to turn the vibrator on or off.
                //  @param repeat the index into pattern at which to repeat, or -1 if you don't want to repeat.
                public void vibrate(long[] pattern, int repeat) 

    ////////////////////////////////////////
    // 4. 关闭马达 
    mVibrator.cancel();

你可能感兴趣的:(Android)