精华内容
下载资源
问答
  • Android vibrator方法关闭和打开振动功能,通过Android vibrator方法设置不同的参数,来关闭和打开手机振动功能:  ToggleButton tb2 = (ToggleButton)findViewById(R.id.tb2); //获得ToggleButton对象  tb2....
  • Android中手机震动的设置(Vibrator)的步骤: a、通过系统服务获得手机震动服务,Vibrator vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE); b、得到震动服务后检测vibrator是否存在: vibrator....
  • 这会将 Vibrator 加载到全局可访问变量vibrator 。 NPM(推荐) 首先在您的项目根目录中安装 Vibrator。 $ npm install --save vibrator 然后使用 require() 包含在您的模块中。 var vibrator = require ( '...
  • 使用Vibrator的vibrate()可调节震动时间;cancel()取消震动。 代码如下:  <!—震动权限–> ”android.permission.VIBRATE”/> //振动器实例化 private Vibrator mVibrator1; mVibrator1=(Vibrator) ...
  • 本节我们介绍的是Vibrator(振动器),是手机自带的振动器,其实就是Android给我们提供的用于机身震动的一个服务!当收到推送消息的时候我们可以设置震动提醒。
  • Vibrator 振动器,是手机自带的振动器哦,不要想成岛国用的那种神秘东西哦~~ Vibrator是Android给我们提供的用于机身震动的一个服务哦 更多详情可见官方API文档:Vibrator 如何使用? 首先添加震动权限: 获得...
  • Rez Trancevibrator的开源,跨平台驱动程序集
  • 自己写的一个vibration驱动,创建节点在sys/class/timed_output下,供Hal调用,可在shell下debug运行,其中gpio根据实际硬件设计更改即可。
  • 介绍了Android 如何定制vibrator的各种震动模式M 具体方法,有需要的朋友可以参考一下
  • Android Vibrator 框架总结

    千次阅读 2019-03-06 11:20:22
    前言 振动器小模块框架总结 基于 MTK 7.0 源码 驱动 内核配置:kernel-3.18\arch\arm64\configs\E266L_debug_defconfig ...// Vibrator_drv.c (kernel-3.18\drivers\misc\mediatek\vibrator) module_init(vib_...

    前言

    振动器小模块框架总结
    基于 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();
    
    展开全文
  • Vibrator控制手机震动的Demo,博客示例的源代码。
  • Vibrator

    千次阅读 2014-04-13 21:37:24
    While not strictly an input device, it nevertheless is a kind of a peripheral. We felt it belonged in the input model. ...The vibrator allows you to vibrate the phone of a user. This can be used simil

    While not strictly an input device, it nevertheless is a kind of a peripheral. We felt it belonged in the input model.

    The vibrator allows you to vibrate the phone of a user. This can be used similar to more sophisticated force feedback functionality found commonly in game console controllers.

    The vibrator is only available on Android and needs a special permission in the manifest file

    android.permission.VIBRATE
    

    See the application configuration section if you are unsure how to specify permissions in your Android manifest.

    Vibrating the phone works as follows:

    Gdx.input.vibrate(2000);
    

    As the parameter is given in milliseconds the example above will vibrate the phone for 2 seconds.

    More sophisticated patterns can be specified via the second vibrate() method:

    Gdx.input.vibrate(new long[] { 0, 200, 200, 200}, -1); 
    

    This will turn the vibrator on for 200 milliseconds, then turn it off for 200 milliseconds then on again for another 200 milliseconds. The second parameter specifies that the pattern should not be repeated. Refer to the Javadocs for more information.

    展开全文
  • MTK 驱动开发---Vibrator

    2020-05-15 17:16:02
    MTK 驱动开发(33)—Vibrator 概述 pmic mt6357为振动器提供ldo稳压电源。 主要文件 驱动 drivers/misc/mediatek/vibrator/mt6765/vibrator.c drivers/misc/mediatek/vibrator/vibrator_drv.c DTS kernel-4.9...

    参考

    MTK 驱动开发(33)—Vibrator


    概述

    pmic mt6357为振动器提供ldo稳压电源。


    主要文件

    • 驱动
    drivers/misc/mediatek/vibrator/mt6765/vibrator.c
    drivers/misc/mediatek/vibrator/vibrator_drv.c
    
    • DTS
      kernel-4.9/arch/arm64/boot/dts/mediatek/M50.dts:
    &odm {
    ...
            vibrator0:vibrator@0 {
                    compatible = "mediatek,vibrator";
                    vib_timer = <25>; //持续时间
                    vib_limit = <9>; //最短持续时间限定
                    vib_vol= <9>;  //LDO电压2.8v
            };
    
    }
    
    • 分析如下
    vib_vol:
     *  hw->vib_vol:  Voltage selection
     * 4'b0000 :1.2V
     * 4'b0001 :1.3V
     * 4'b0010 :1.5V
     * 4'b0100 :1.8V
     * 4'b0101 :2.0V
     * 4'b1001 :2.8V
     * 4'b1011 :3.0V
     * 4'b1101 :3.3V
     默认值是9则选择2.8v
     
     vib_timer :
     
     根据:
     static void vibrator_enable(unsigned int dur, unsigned int activate)
    {
                ...
     #ifdef CUST_VIBR_LIMIT
    		if (dur > hw->vib_limit && dur < hw->vib_timer)
    #else
    		if (dur >= 10 && dur < hw->vib_timer)
    #endif
    			dur = hw->vib_timer;
    			...
    ktime_set(dur / 1000, (dur % 1000) * 1000000)			
     }
     可知这个就是持续时间的设定,单位是毫秒,则为25ms。
     
     vib_limit:
     
     mt6765/vibrator.h
    18:#define CUST_VIBR_LIMIT
    
     以上代码定义了CUST_VIBR_LIMIT可知,这个是持续时间最小值限定。
    

    驱动分析

    数据结构
    struct mt_vibr {
    	struct workqueue_struct *vibr_queue;
    	struct work_struct vibr_work;
    	struct hrtimer vibr_timer;
    	int ldo_state;
    	int shutdown_flag;
    	atomic_t vibr_dur; //原子操作
    	spinlock_t vibr_lock;
    	atomic_t vibr_state;  //原子操作
    };
    
    probe分析
    static int vib_probe(struct platform_device *pdev)
    {
    	int ret = 0;
    	struct mt_vibr *vibr;
    
    	init_vibr_oc_handler(vibrator_oc_handler); //初始化pmic中断函数为vibrator_oc_handler
    
    	vibr = devm_kzalloc(&pdev->dev, sizeof(*vibr), GFP_KERNEL);
    	if (!vibr)
    		return -ENOMEM;
    
    	ret = devm_led_classdev_register(&pdev->dev, &led_vibr);
    	if (ret < 0) {
    		pr_err(VIB_TAG "led class register fail\n");
    		return ret;
    	}
    
    	vibr->vibr_queue = create_singlethread_workqueue(VIB_DEVICE); //创建工作队列
    	if (!vibr->vibr_queue) {
    		pr_err(VIB_TAG "unable to create workqueue\n");
    		return -ENODATA;
    	}
    
    	INIT_WORK(&vibr->vibr_work, update_vibrator);   //创建工作队列函数update_vibrator
    	spin_lock_init(&vibr->vibr_lock);
    	vibr->shutdown_flag = 0;
    	atomic_set(&vibr->vibr_state, 0);
    	hrtimer_init(&vibr->vibr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    	vibr->vibr_timer.function = vibrator_timer_func;  //创建定时器,用于震动时间的控制。
    
    	dev_set_drvdata(&pdev->dev, vibr);
    	g_mt_vib = vibr;
    	init_cust_vibrator_dtsi(pdev); //读取dts
    	vibr_power_set();  //给振动器上电
    
    	pr_debug(VIB_TAG "probe done\n");
    
    	return 0;
    }
    
    • 工作队列线程:
    static void update_vibrator(struct work_struct *work)
    {
    	struct mt_vibr *vibr = container_of(work, struct mt_vibr, vibr_work);
    
    	if (atomic_read(&vibr->vibr_state) == 0)
    		vibr_Disable();
    	else
    		vibr_Enable();
    }
    
    static int vibr_Enable(void)
    {
    	if (!g_mt_vib->ldo_state) {
    		vibr_Enable_HW();
    		g_mt_vib->ldo_state = 1;
    	}
    	return 0;
    }
    
    void vibr_Enable_HW(void)
    {
    #ifdef CONFIG_MTK_PMIC_CHIP_MT6357
    	pmic_set_register_value(PMIC_RG_LDO_VIBR_EN, 1); //使能LDO_VIBR
    #endif
    	mdelay(OC_INTR_INIT_DELAY);
    	pmic_enable_interrupt(INT_VIBR_OC, 1, "vibr");
    }
    
    static int vibr_Disable(void)
    {
    	if (g_mt_vib->ldo_state) {
    		vibr_Disable_HW();
    		g_mt_vib->ldo_state = 0;
    	}
    	return 0;
    }
    
    void vibr_Disable_HW(void)
    {
    	pmic_enable_interrupt(INT_VIBR_OC, 0, "vibr");
    #ifdef CONFIG_MTK_PMIC_CHIP_MT6357
    	pmic_set_register_value(PMIC_RG_LDO_VIBR_EN, 0);
    #endif
    }
    
    • 定时器函数
    static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
    {
    	struct mt_vibr *vibr = container_of(timer, struct mt_vibr, vibr_timer);
    
    	atomic_set(&vibr->vibr_state, 0);
    	queue_work(vibr->vibr_queue, &vibr->vibr_work);
    	return HRTIMER_NORESTART;
    }
    
    • pmic中断函数
    static void vibrator_oc_handler(void)
    {
    	pr_debug(VIB_TAG "vibrator_oc_handler: disable vibr due to oc intr happened\n");
    	vibrator_enable(0, 0); //关闭震动
    }
    
    void init_vibr_oc_handler(void (*vibr_oc_func)(void))
    {
    	pmic_register_interrupt_callback(INT_VIBR_OC, vibr_oc_func);
    }
    
    static void vibrator_enable(unsigned int dur, unsigned int activate)
    {
    	unsigned long flags;
    	struct vibrator_hw *hw = mt_get_cust_vibrator_hw();
    
    	spin_lock_irqsave(&g_mt_vib->vibr_lock, flags);
    	hrtimer_cancel(&g_mt_vib->vibr_timer);
    	pr_debug(VIB_TAG "cancel hrtimer, cust:%dms, value:%u, shutdown:%d\n",
    			hw->vib_timer, dur, g_mt_vib->shutdown_flag);
    
    	if (activate == 0 || g_mt_vib->shutdown_flag == 1) {
    		atomic_set(&g_mt_vib->vibr_state, 0);
    	} else {
    #ifdef CUST_VIBR_LIMIT
    		if (dur > hw->vib_limit && dur < hw->vib_timer)
    #else
    		if (dur >= 10 && dur < hw->vib_timer)
    #endif
    			dur = hw->vib_timer;
    
    		dur = (dur > 15000 ? 15000 : dur);
    		atomic_set(&g_mt_vib->vibr_state, 1);
    		hrtimer_start(&g_mt_vib->vibr_timer,
    			      ktime_set(dur / 1000, (dur % 1000) * 1000000),
    			      HRTIMER_MODE_REL);
    	}
    	spin_unlock_irqrestore(&g_mt_vib->vibr_lock, flags);
    	queue_work(g_mt_vib->vibr_queue, &g_mt_vib->vibr_work);
    }
    
    • sysfs文件节点创建
    static ssize_t vibr_activate_show(struct device *dev,
    		struct device_attribute *attr, char *buf)
    {
    	return sprintf(buf, "%d\n", atomic_read(&g_mt_vib->vibr_state));
    }
    
    static ssize_t vibr_activate_store(struct device *dev,
    		struct device_attribute *attr, const char *buf, size_t size)
    {
    	unsigned int activate, dur;
    	ssize_t ret;
    
    	ret = kstrtouint(buf, 10, &activate);
    	if (ret) {
    		pr_err(VIB_TAG "set activate fail\n");
    		return ret;
    	}
    	dur = atomic_read(&g_mt_vib->vibr_dur);
    	vibrator_enable(dur, activate);
    	ret = size;
    	return ret;
    }
    
    static ssize_t vibr_state_show(struct device *dev,
    		struct device_attribute *attr, char *buf)
    {
    	return sprintf(buf, "%d\n", atomic_read(&vib_state));
    }
    
    static ssize_t vibr_state_store(struct device *dev,
    		struct device_attribute *attr, const char *buf, size_t size)
    {
    	unsigned int state;
    	ssize_t ret;
    
    	ret = kstrtouint(buf, 10, &state);
    	if (ret) {
    		pr_err(VIB_TAG "set state fail\n");
    		return ret;
    	}
    	atomic_set(&vib_state, state);
    
    	ret = size;
    	return ret;
    }
    static ssize_t vibr_duration_store(struct device *dev,
    		struct device_attribute *attr, const char *buf, size_t size)
    {
    	unsigned int duration;
    	ssize_t ret;
    
    	ret = kstrtouint(buf, 10, &duration);
    	if (ret) {
    		pr_err(VIB_TAG "set duration fail\n");
    		return ret;
    	}
    
    	atomic_set(&g_mt_vib->vibr_dur, duration);
    	ret = size;
    	return ret;
    }
    
    static DEVICE_ATTR(activate, 0644, vibr_activate_show, vibr_activate_store);
    static DEVICE_ATTR(state, 0644, vibr_state_show, vibr_state_store);
    static DEVICE_ATTR(duration, 0644, NULL, vibr_duration_store);
    
    • 节点目录/sys/class/leds/vibrator:
    activate
    duration 
    state
    

    具体应用详解

    上层调用步骤
    echo value > /sys/class/leds/vibrator/duration  //设置持续时间 ,单位毫秒
    echo 1 > /sys/class/leds/vibrator/activate    //激活震动 
    
    vibrator_enable分析
    • hrtimer_cancel(&g_mt_vib->vibr_timer); 删除定时器

    • if (activate == 0) else 判断是否激活

      • atomic_set(&g_mt_vib->vibr_state, 1); 设置vibr_state原子为1
      • hrtimer_start(&g_mt_vib->vibr_timer,ktime_set(dur / 1000, (dur %1000) * 1000000),HRTIMER_MODE_REL); 打开定时器,设置持续时间ktime_set(秒,纳秒),时间到则调用vibrator_timer_func
      • queue_work(g_mt_vib->vibr_queue, &g_mt_vib->vibr_work); 打开工作队列update_vibrator
    • 工作队列是根据vibr_state原子判定的

    static void update_vibrator(struct work_struct *work)
    {
    	struct mt_vibr *vibr = container_of(work, struct mt_vibr, vibr_work);
    
    	if (atomic_read(&vibr->vibr_state) == 0)
    		vibr_Disable();
    	else
    		vibr_Enable();
    }
    
    • 当时间到了,调用定时器函数,调用工作队列关闭震动马达
    static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
    {
    	struct mt_vibr *vibr = container_of(timer, struct mt_vibr, vibr_timer);
    
    	atomic_set(&vibr->vibr_state, 0);
    	queue_work(vibr->vibr_queue, &vibr->vibr_work);
    	return HRTIMER_NORESTART;
    }
    

    调试

    • APK调试

    madaceshi_V1.0.apk

    • 打印
    (200511_10:17:34.753)[    4.198009] <2>.(2)[1:swapper/0]calling  vib_mod_init+0x0/0xa8 @ 1
    (200511_10:17:34.754)[    4.203067] <2>.(2)[1:swapper/0][name:vibrator&]vibratorvib_timer:25
    (200511_10:17:34.754)[    4.203880] <2>.(2)[1:swapper/0][name:vibrator&]vibratorvib_limit : 9
    (200511_10:17:34.754)[    4.204698] <2>.(2)[1:swapper/0][name:vibrator&]vibratorvib_vol: 9
    (200511_10:17:34.754)[    4.205480] <2>.(2)[1:swapper/0][name:vibrator&]vibratorpvib_cust = 25, 9, 9
    (200511_10:17:34.754)[    4.206370] <2>.(2)[1:swapper/0][name:vibrator&]vibratorvibr_init: set voltage = 9
    (200511_10:17:34.754)[    4.207405] <2>.(2)[1:swapper/0][name:vibrator_drv&][vibrator]probe done
    (200511_10:17:34.754)[    4.208840] <2>.(2)[1:swapper/0][name:vibrator_drv&][vibrator]init Done
    
    展开全文
  • 转载于:http://www.cnblogs.com/skywang12345/p/3404808.html,内容有所修改,这篇vibrator源码是基于安卓7.1分析。 系列:安卓硬件访问服务框架 安卓从零添加硬件服务实例(驱动到app调用) 目的是想和大家...

         

          转载于:http://www.cnblogs.com/skywang12345/p/3404808.html,内容有所修改,这篇vibrator源码是基于安卓7.1分析。

         系列:安卓硬件访问服务框架

                    安卓从零添加硬件服务实例(驱动到app调用)

         目的是想和大家分享自己对Android系统的一点认识:以马达为代表,来考究“Android是如何一步步工作的。它从硬件设计,到Linux驱动,再到HAL,再到JNI,再到Framework,最后到被应用调用,这整套的流程到底是怎么样的!

    Part 1 马达的硬件设计

        马达的震动原理很简单,给马达通电,马达就能震动。至于马达是如何工作,如何将电能转化为机械能,这不是我们关心的重点。但是,我们要需要了解如何控制马达的通电。在硬件上,我们是通过一个IO口(GPIO)去控制;对于马达而言,我们可以将IO理解为一个开关。当开关合上时,马达震动;开关断开,马达停止震动。

        GPIO(General Purpose Input Output),称为通用输入/输出。它可以被配置为中断、输入、输出等类型,从而对各个IO进行控制。对于马达而已,GPIO就相当于一个开关。下面看看硬件原理图中的马达部分,如下图:

     

    注:上面原理图对应CPU是“三星A8”。不同平台的马达,马达的接法和GPIO都不一样;但原理都是类似的。

    原理图中红线标注部分的含义:GPH3_3是马达的GPIO。三星A8中有很多组GPIO,而马达对应和GPH3_3连接。

     

    Part 2 马达的驱动代码

        知道马达的硬件设计之后,我们就可以进行Linux Driver开发工作,也就是编写马达的驱动。Linux的一个非常重要的特点,一切都是文件!而我们进行Linux Driver开发的目的,就是将硬件设备映射成一个文件;然后,我们可以通过操作文件,来操作对应的硬件设备。

        OK!理解了驱动的作用和原理之后,我们接下来开发讲解马达的驱动开发。

     

    1. Datasheet中相关信息

        我们知道,马达是通过GPIO去控制;接下来,我们就是找到马达对应的GPIO信息,然后控制该GPIO即可。

        通过马达的原理图,我们知道马达和GPH3_3相连接。我们查阅“三星A8 的Datasheet”,查找GPH3_3的相关信息。

        三星A8的Datasheet中,关于GPH3_3的信息如下:

    所谓Datasheet,就是CPU芯片的数据手册。
       上面记载了CPU的功能特性和操作方式等信息。任何一个厂家在发布它的芯片时,都会提供对应的Datasheet给它的客户;客户根据Datasheet上面所描述的CPU的特性,就可以进行相关的开发(当然,实际开发中可能还需要芯片厂商的支持)。例如,国内手机都是采用MTK平台,对于MTK方案开发商来说,它要开发MTK6577的产品。那么首先,MTK原厂会提供一份MTK6577的BSP包,BSP包中包括了MTK6577的Datasheet,也就是该芯片的数据手册。方案开发商有任何关于MTK6577的问题,都可以查阅该Datasheet。
     

    说明

    (01) GPH3_3对应CPU中的寄存器是GPH3CON[3]。

    (02) [15:12] 表示寄存器的第12~15位,一个寄存器共32 bits。而第三列的 0000, 0001, 0010, 0011, 1111表示“寄存器取不同值的时候,该GPIO的功能”。

    例如, 0000表示将该GPIO作为输入,0001表示将GPIO作为输出,1111表示将该GPIO作为中断。

               前面,我们已经说过,操作马达就是相当与将它作为一个开关操作。因此,我们需要将马达的GPIO设为“输入”类型;然后输入1,相当于开启马达;输入0,则是关闭马达!

    下面,我们需要做的就是在Driver中将GPH3_3(也就是GPH3CON[3])映射为一个文件节点,并将它配置为“输入”类型,即将GPH3CON[3]的寄存器值设为0000。

     

    2. 马达的驱动

        我们编写马达驱动(drivers/misc/misc_sysfs.c),将马达(vibrator)注册道platform总线上。源码如下:

     1 #include <linux/kernel.h>
      2 #include <linux/types.h>
      3 #include <linux/module.h>
      4 #include <linux/device.h>
      5 #include <linux/platform_device.h>
      6 #include <linux/delay.h>
      7 #include <linux/irq.h>
      8 #include <linux/interrupt.h>
      9 #include <linux/sysfs.h>
     10 #include <linux/input.h>
     11 #include <mach/gpio.h>
     12 
     13 // vibrator 对应的GPIO
     14 #define  VIBRATOR_POWER_PORT (S5PV210_GPH3(3))
     15 
     16 typedef struct combo_module__t    {
     17     unsigned char            status_vibrator;
     18 }    combo_module_t    ;
     19 
     20 static combo_module_t combo_module;
     21 
     22 /*
     23  * vibrator初始化函数:申请GPIO,并初始化vibrator状态。
     24  */
     25 static void combo_module_init(void)
     26 {
     27     if(gpio_request(VIBRATOR_POWER_PORT, "vibrator power"))    {
     28         printk("misc_sysfs.c request vibrator gpio failse.\n");
     29     }
     30     gpio_pull_updown(VIBRATOR_POWER_PORT, PullDisable);
     31       gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW);    
     32 
     33     combo_module.status_vibrator  = 0;
     34 }
     35 
     36 /*
     37  * vibrator控制函数
     38  */
     39 staticvoid combo_module_control(void)
     40 {
     41     if(combo_module.status_vibrator)
     42     {
     43         gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_HIGH);
     44     }
     45     else    
     46     {
     47         gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW);
     48     }
     49 
     50 }
     51 
     52 
     53 ///
     54 
     55 static ssize_t show_vibrator_onoff (struct device *dev, struct device_attribute *attr, char *buf)
     56 {
     57     return    sprintf(buf, "%d\n", combo_module.status_vibrator);
     58 }
     59 
     60 static ssize_t set_vibrator_onoff (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
     61 {
     62      unsigned int    val;
     63 
     64     if(!(sscanf(buf, "%u\n", &val)))     return    -EINVAL;
     65 
     66     //printk("set_vibrator_onoff:%d\n",val);
     67 
     68     if(!val )    
     69     {
     70         combo_module.status_vibrator = 0;
     71         combo_module_control();
     72     }
     73     else        
     74     {
     75         combo_module.status_vibrator = 1;
     76         combo_module_control();
     77 
     78         msleep(val);
     79 
     80         combo_module.status_vibrator = 0;
     81         combo_module_control();
     82     }
     83     
     84     return count;
     85 }
     86 
     87 static    ssize_t show_vibrator_onoff    (struct device *dev, struct device_attribute *attr, char *buf);
     88 static     ssize_t set_vibrator_onoff    (struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
     89 // 将vibrator注册到sysfs文件系统。
     90 // 参数说明:
     91 //       vibrator_onoff      : vibrator对应在sysfs下的文件节点名称
     92 //       S_IRWXUGO           : 文件节点的属性
     93 //       show_vibrator_onoff : 对应的读函数
     94 //       set_vibrator_onoff  : 对应的写函数
     95 static DEVICE_ATTR(vibrator_onoff, S_IRWXUGO, show_vibrator_onoff, set_vibrator_onoff);
     96 
     97 
     98 static struct attribute *control_sysfs_entries[] = {
     99     &dev_attr_vibrator_onoff.attr,
    100     NULL
    101 };
    102 
    103 static struct attribute_group control_sysfs_attr_group = {
    104     .name   = NULL,
    105     .attrs  = control_sysfs_entries,
    106 };
    107 
    108 static int control_sysfs_probe(struct platform_device *pdev)    
    109 {
    110     printk("vibrator probe");
    111     combo_module_init();
    112     combo_module_control();
    113     return    sysfs_create_group(&pdev->dev.kobj, &control_sysfs_attr_group);
    114 }
    115 
    116 staticint control_sysfs_remove(struct platform_device *pdev)    
    117 {
    118     sysfs_remove_group(&pdev->dev.kobj, &control_sysfs_attr_group);
    119     
    120     return    0;
    121 }
    122 
    123 #ifdef CONFIG_PM
    124 static int control_sysfs_resume(struct platform_device *dev)
    125 {
    126 
    127     combo_module_control();
    128 
    129     return  0;
    130 }
    131 
    132 static int control_sysfs_suspend(struct platform_device *dev, pm_message_t state)
    133 {
    134     
    135     combo_module_control();
    136     
    137     return  0;
    138 }
    139 #else
    140 #define control_sysfs_suspend NULL
    141 #define control_sysfs_resume NULL
    142 #endif
    143 
    144 
    145 static struct platform_driver control_sysfs_driver = {
    146     .driver = {
    147         .name = "misc_ctl",
    148         .owner = THIS_MODULE,
    149     },
    150     .probe         = control_sysfs_probe,
    151     .remove     = control_sysfs_remove,
    152     .suspend    = control_sysfs_suspend,
    153     .resume        = control_sysfs_resume,
    154 };
    155 
    156 static int __init control_sysfs_init(void)
    157 {    
    158     // 将vibrator注册到platform总线
    159     printk("vibrator init");
    160     return platform_driver_register(&control_sysfs_driver);
    161 }
    162 
    163 static void __exit control_sysfs_exit(void)
    164 {
    165    platform_driver_unregister(&control_sysfs_driver);
    166 }
    167 
    168 
    169 module_init(control_sysfs_init);
    170 module_exit(control_sysfs_exit);
    171 
    172 
    173 MODULE_DESCRIPTION("misc control driver");
    174 MODULE_AUTHOR("other");
    175 MODULE_LICENSE("GPL");

    说明

    若您熟悉驱动开发,应该很容易理解上面的代码。不熟悉也不要紧,您只需要了解“Linux系统中,一切都是文件”,上面代码的作用是,将马达(vibrator)映射到“/sys/devices/platform/misc_ctl/vibrator_onoff”文件上,我们可以通过读写vibrator_onoff来操作马达的开启和关闭。

        有了马达的源码之后,我们还需要将该源码编译到Linux内核中。这就是通过Kconfig和Makefile来完成的,关于Kconfig和Makefile的知识,这里就不过多说明了。目前您只需要了解,通过Kconfig和Makefile,我们能将马达驱动编译到内核中,该驱动会在驱动加载的时候自动运行就可以了!

    马达对应的Kconfig(driver/misc/Kconfig)内容如下:

    config MISC_VIBRATOR
           tristate"misc vabrator"
           default y

      马达对应的Makefile(driver/misc/Makefile)内容如下:

    obj-$(CONFIG_MISC_VIBRATOR)   += misc_sysfs.o

          至此,我们已经完成马达的驱动开发了!也就是说,我们已经成功的将马达映射到文件节点上;接下来,我们通过操作文件节点,就可以操作马达了。下面从HAL层到Framework曾,基于Android7.1系统进行分析的。(设备节点:/sys/class/timed_output/vibrator/enable)

     

    Part 3 马达的HAL实现

    HAL (Hardware Abstraction Layer), 又称为“硬件抽象层”。在Linux驱动中,我们已经将马达设为映射为文件了;而该HAL层的存在的意义,就是“对设备文件进行操作,从而相当于硬件进行操作”。HAL层的作用,一是操作硬件设备,二是操作接口封装,外界能方便的使用HAL提供的接口直接操作硬件设备。

    理解了HAL之后,我们看看Android中如何在HAL层对马达进行操作。

    在Android系统中,我们在libhardware_legacy中,实现马达的HAL层控制。
    马达在HAL中的代码路径:hardware/libhardware/modules/vibrator/vibrator.c

    头文件:hardware/libhardware/include/hardware/vibrator.h

    vibrator.c的代码如下:

    /*
     * Copyright (C) 2013 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    #include <hardware/vibrator.h>
    #include <hardware/hardware.h>
    
    #include <cutils/log.h>
    
    #include <malloc.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <math.h>
    
    static const char THE_DEVICE[] = "/sys/devices/platform/misc_ctl/vibrator_onoff";
    
    static int vibra_exists() {
        int fd;
    
        fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));
        if(fd < 0) {
            ALOGE("Vibrator file does not exist : %d", fd);
            return 0;
        }
    
        close(fd);
        return 1;
    }
    
    static int sendit(unsigned int timeout_ms)
    {
        int to_write, written, ret, fd;
    
        char value[20]; /* large enough for millions of years */
    
        fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));
        if(fd < 0) {
            return -errno;
        }
    
        to_write = snprintf(value, sizeof(value), "%u\n", timeout_ms);
        written = TEMP_FAILURE_RETRY(write(fd, value, to_write));
    
        if (written == -1) {
            ret = -errno;
        } else if (written != to_write) {
            /* even though EAGAIN is an errno value that could be set
               by write() in some cases, none of them apply here.  So, this return
               value can be clearly identified when debugging and suggests the
               caller that it may try to call vibraror_on() again */
            ret = -EAGAIN;
        } else {
            ret = 0;
        }
    
        errno = 0;
        close(fd);
    
        return ret;
    }
    
    static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
    {
        /* constant on, up to maximum allowed time */
        return sendit(timeout_ms);
    }
    
    static int vibra_off(vibrator_device_t* vibradev __unused)
    {
        return sendit(0);
    }
    
    static int vibra_close(hw_device_t *device)
    {
        free(device);
        return 0;
    }
    
    static int vibra_open(const hw_module_t* module, const char* id __unused,
                          hw_device_t** device __unused) {
        if (!vibra_exists()) {
            ALOGE("Vibrator device does not exist. Cannot start vibrator");
            return -ENODEV;
        }
    
        vibrator_device_t *vibradev = calloc(1, sizeof(vibrator_device_t));
    
        if (!vibradev) {
            ALOGE("Can not allocate memory for the vibrator device");
            return -ENOMEM;
        }
    
        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;
        vibradev->vibrator_off = vibra_off;
    
        *device = (hw_device_t *) vibradev;
    
        return 0;
    }
    
    /*===========================================================================*/
    /* Default vibrator HW module interface definition                           */
    /*===========================================================================*/
    
    static struct hw_module_methods_t vibrator_module_methods = {
        .open = vibra_open,
    };
    
    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,
    };

          在kernel的驱动中,我们已经将马达注册到sys文件系统中(/sys/devices/platform/misc_ctl/vibrator_onoff)。在vibrator.c中,我们就是通过读写“vibrator_onoff文件节点”来实现对马达的操作。

     

    Part 4 马达的JNI部分

    1 马达的JNI实现

    JNI(Java Native Interface),中文是“Java本地接口”。

    JNI是Java中一种技术,它存在的意义,是保证本地代码(C/C++代码)能在任何Java虚拟机下工作。简单点说,Java通过JNI接口,能够调用到C/C++代码。 关于“JNI的更多内容”,请参考“Android JNI和NDK学习系列文章”。

    在了解了vibrator的HAL层实现之后,我们再来看看android是如何通过JNI将震动马达注册到android系统中。马达对应的JNI层代码路径如下:frameworks/base/services/core/jni/com_android_server_VibratorService.cpp

    com_android_server_VibratorService.cpp的源码如下:

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    #define LOG_TAG "VibratorService"
    
    #include "jni.h"
    #include "JNIHelp.h"
    #include "android_runtime/AndroidRuntime.h"
    
    #include <utils/misc.h>
    #include <utils/Log.h>
    #include <hardware/vibrator.h>
    
    #include <stdio.h>
    
    namespace android
    {
    
    static hw_module_t *gVibraModule = NULL;
    static vibrator_device_t *gVibraDevice = NULL;
    
    static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
    {
        if (gVibraModule != NULL) {
            return;
        }
    
        int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);
    
        if (err) {
            ALOGE("Couldn't load %s module (%s)", VIBRATOR_HARDWARE_MODULE_ID, strerror(-err));
        } else {
            if (gVibraModule) {
                vibrator_open(gVibraModule, &gVibraDevice);
            }
        }
    }
    
    static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
    {
        if (gVibraModule && gVibraDevice) {
            return JNI_TRUE;
        } else {
            return JNI_FALSE;
        }
    }
    
    static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
    {
        if (gVibraDevice) {
            int err = gVibraDevice->vibrator_on(gVibraDevice, timeout_ms);
            if (err != 0) {
                ALOGE("The hw module failed in vibrator_on: %s", strerror(-err));
            }
        } else {
            ALOGW("Tried to vibrate but there is no vibrator device.");
        }
    }
    
    static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
    {
        if (gVibraDevice) {
            int err = gVibraDevice->vibrator_off(gVibraDevice);
            if (err != 0) {
                ALOGE("The hw module failed in vibrator_off(): %s", strerror(-err));
            }
        } else {
            ALOGW("Tried to stop vibrating but there is no vibrator device.");
        }
    }
    
    static const JNINativeMethod method_table[] = {
        { "vibratorExists", "()Z", (void*)vibratorExists },
        { "vibratorInit", "()V", (void*)vibratorInit },
        { "vibratorOn", "(J)V", (void*)vibratorOn },
        { "vibratorOff", "()V", (void*)vibratorOff }
    };
    
    int register_android_server_VibratorService(JNIEnv *env)
    {
        return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
                method_table, NELEM(method_table));
    }
    
    };

    下面,对这部分的JNI代码进行简单说明。

    (01) 通过 jniRegisterNativeMethods(),我们将method_table中的方法注册到 com.android.server.VibratorService.java 中。配对表格如下:

    ​
    ---------------------------------------------------++++-------------------------------------------
                 VibratorService.java                          com_android_server_VibratorService.cpp   
    native static boolean vibratorExists();                static jboolean vibratorExists(JNIEnv *env, jobject clazz)
    native static void vibratorInit();                      static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)                                                       
    native static void vibratorOn(long milliseconds);      static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms)
    native static void vibratorOff();                      static void vibratorOff(JNIEnv *env, jobject clazz)
    
    ​

    通过JNI,我们就能将Java层和HAL层的代码联系起来。
    以vibratorOff()来说,我们在VibratorService.java中调用vibratorOff();实际上会调用到com_android_server_VibratorService.cpp中的vibratorOff()函数;进一步会调用到vibrator_off()函数,而vibrator_off()是我们在 “HAL层的vibrator.c中的接口”。


    2 马达的JNI如何和HAL关联方式

    在继续接下来的研究之前,我们先搞清楚:JNI如何和HAL层代码关联起来的。即com_android_server_VibratorService.cpp是如何调用到vibrator.c中的代码的。
    实际上道理很简单,我们先将vibrator.c封装成.so库;然后在com_android_server_VibratorService.cpp中导入该库,就可以调用vibrator.c的接口了。下面,看看Android中具体是如何做到的。

    (01) vibrator.c封装到vibrator.default.so中的步骤

    在hardware/libhardware/modules/vibrator/Android.mk中,会将vibrator.c添加到 LOCAL_SRC_FILES 变量中。
    hardware/libhardware_legacy/vibrator/Android.mk源码如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := vibrator.default
    
    # HAL module implementation stored in
    # hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
    LOCAL_MODULE_RELATIVE_PATH := hw
    LOCAL_C_INCLUDES := hardware/libhardware
    LOCAL_SRC_FILES := vibrator.c
    LOCAL_SHARED_LIBRARIES := liblog
    LOCAL_MODULE_TAGS := optional
    
    include $(BUILD_SHARED_LIBRARY)

        在“我们编译Android系统”或“通过 mmm hardware/libhardware/modules/vibrator/进行模块编译”的时候,就会生成库vibrator.default.so;而且vibrator.c被包含在该库中。

    (02) 在 com_android_server_VibratorService.cpp 对应的Android.mk中,会导入vibrator.default.so。
    com_android_server_VibratorService.cpp 对应的frameworks/base/services/core/jni/Android.mk的源码如下:

    LOCAL_SRC_FILES += \
        $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \

    Part 5 马达的Framework层实现

    应用层操作马达,是通过马达服务进行操作的。而马达服务是通过aidl实现的,aidl是Android进程间的通信方式。关于aidl的更多说明可以参考“Android Service总结06 之AIDL”。

    马达服务涉及的主要文件如下:

    ​
    1 frameworks/base/services/java/com/android/server/SystemServer.java
    2 frameworks/base/services/core/java/com/android/server/VibratorService.java
    3 frameworks/base/core/java/android/os/IVibratorService.aidl
    4 frameworks/base/core/java/android/os/Vibrator.java
    5 frameworks/base/core/java/android/os/SystemVibrator.java
    
    ​

    下面,对这几个文件的功能进行简要说明。

    文件1: SystemServer.java
               它是系统服务,作用是启动、管理系统服务,包括“马达服务、Wifi服务、Activity管理服务”等等。
               SystemServer是通过Zygote启动的,而Zygote又是在init中启动的,init则是kernel加载完毕之后启动的第一个进程。在这里,我们只需要知道“SystemServer是用来启动/管理马达服务即可。”

    文件2: IVibratorService.aidl
               它是马达服务对应的aidl配置文件。我们在aidl中定义了其它进程可以访问的外部接口;然后再通过VibratorService.java实现这些接口。

    文件3: VibratorService.java
               它是马达服务对应的aidl接口的实现程序。它实现IVibratorService.aidl的接口,从而实现马达服务;它的函数接口,是通过调用JNI层对应的马达控制函数来实现的。

    文件4: Vibrator.java
               它是马达服务开放给应用层的调用类。理论上讲,我们完全可以通过aidl直接调用马达服务,而不需要Vibrator.java类。但是!既然它存在,就肯定有它的理由。事实的确如此,Google之所以这么做。有以下几个原因:
               第一,提供统一而且方便的服务调用方式。这里的“统一”,是指和所有其它的系统服务一样,我们调用服务时,需先通过getSystemService()获取服务,然后再调用服务的函数接口。这里的“方便”,是指若我们直接通过aidl调用,操作比较繁琐(若你用过aidl就会知道,需要先实现ServiceConnection接口以获取IBinder对象,然后再通过IBinder对象调用aidl的接口); 而Vibrator.java封装之后的接口,将许多细节都隐藏了,非常便于应用者调用!
              第二,基于安全的考虑。Vibrator.java封装隐藏了许多细节,而这些都是应用开发者不必要知道的。
              第三,Vibrator是抽象类。它便于我们支持不同类型的马达:包括“将马达直接映射到文件”以及“将马达注册到输入子系统”中。

    文件5: SystemVibrator.java
             它是Vibrator.java的子类,实现了马达的服务接口。

    下面,我们继续Read The Fucking Source Code,加深对上面知识的理解。

    1 SystemServer.java

    在frameworks/base/services/java/com/android/server/SystemServer.java中关于马达的代码如下:

    1 {
     2     VibratorService vibrator = null;
     3 
     4     Slog.i(TAG, "Vibrator Service");
     5     vibrator = new VibratorService(context);
     6     ServiceManager.addService("vibrator", vibrator);
     7 
     8     ...
     9 
    10     try {
    11         vibrator.systemReady();
    12     } catch (Throwable e) {
    13         reportWtf("making Vibrator Service ready", e);
    14     }
    15 }

    从中,我们知道:
    (01) SystemServer中会通过VibratorService()新建马达服务,并将其添加到ServiceManager中。
    (02) 在Android系统启动完成之后,SystemServer会调用vibrator.systemReady()。

    2 IVibratorService.aidl

    在查看VibratorService.java之前,我们先看看它对应的aidl文件。frameworks/base/core/java/android/os/IVibratorService.aidl源码如下:

    package android.os;
    
    /** {@hide} */
    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 cancelVibrate(IBinder token);
    }

    3 VibratorService.java

    frameworks/base/services/java/com/android/server/VibratorService.java源码如下:

    
     package com.android.server;
    
     public class VibratorService extends IVibratorService.Stub
            implements InputManager.InputDeviceListener {
           ......
    
          native static boolean vibratorExists();
          native static void vibratorOn(long milliseconds);
          native static void vibratorOff();
           ......
    

    其中,VibratorService实际上是通过“本地方法”去控制马达的。例如,hasVibratora()最终是通过vibratorExists()来判断马达是否存在的。

    4 Vibrator.java

    frameworks/base/core/java/android/os/Vibrator.java源码如下:

    package android.os;
    import android.app.ActivityThread;
    import android.content.Context;
    import android.media.AudioAttributes;
    public abstract class Vibrator {
    
        private final String mPackageName;
        public Vibrator() {
            mPackageName = ActivityThread.currentPackageName();
        }
        protected Vibrator(Context context) {
            mPackageName = context.getOpPackageName();
        }
    
        public abstract boolean hasVibrator();
    
        public void vibrate(long milliseconds) {
            vibrate(milliseconds, null);
        }
    
        public void vibrate(long milliseconds, AudioAttributes attributes) {
            vibrate(Process.myUid(), mPackageName, milliseconds, attributes);
        }
    
        public void vibrate(long[] pattern, int repeat) {
            vibrate(pattern, repeat, null);
        }
    
        public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
            vibrate(Process.myUid(), mPackageName, pattern, repeat, attributes);
        }
    
        public abstract void vibrate(int uid, String opPkg, long milliseconds,
                AudioAttributes attributes);
    
        public abstract void vibrate(int uid, String opPkg, long[] pattern, int repeat,
                AudioAttributes attributes);
    
        public abstract void cancel();
    }

    5 SystemVibrator.java

    frameworks/base/core/java/android/os/SystemVibrator.java源码如下:

    package android.os;
    
    import android.content.Context;
    import android.media.AudioAttributes;
    import android.util.Log;
    
    /**
     * Vibrator implementation that controls the main system vibrator.
     *
     * @hide
     */
    public class SystemVibrator extends Vibrator {
        private static final String TAG = "Vibrator";
    
        private final IVibratorService mService;
        private final Binder mToken = new Binder();
    
        public SystemVibrator() {
            mService = IVibratorService.Stub.asInterface(
                    ServiceManager.getService("vibrator"));
        }
    
        public SystemVibrator(Context context) {
            super(context);
            mService = IVibratorService.Stub.asInterface(
                    ServiceManager.getService("vibrator"));
        }
    
        @Override
        public boolean hasVibrator() {
            if (mService == null) {
                Log.w(TAG, "Failed to vibrate; no vibrator service.");
                return false;
            }
            try {
                return mService.hasVibrator();
            } catch (RemoteException e) {
            }
            return false;
        }
    
        /**
         * @hide
         */
        @Override
        public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
            if (mService == null) {
                Log.w(TAG, "Failed to vibrate; no vibrator service.");
                return;
            }
            try {
                mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to vibrate.", e);
            }
        }
    
        /**
         * @hide
         */
        @Override
        public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
                AudioAttributes attributes) {
            if (mService == null) {
                Log.w(TAG, "Failed to vibrate; no vibrator service.");
                return;
            }
            // catch this here because the server will do nothing.  pattern may
            // not be null, let that be checked, because the server will drop it
            // anyway
            if (repeat < pattern.length) {
                try {
                    mService.vibratePattern(uid, opPkg, pattern, repeat, usageForAttributes(attributes),
                            mToken);
                } catch (RemoteException e) {
                    Log.w(TAG, "Failed to vibrate.", e);
                }
            } else {
                throw new ArrayIndexOutOfBoundsException();
            }
        }
    
        private static int usageForAttributes(AudioAttributes attributes) {
            return attributes != null ? attributes.getUsage() : AudioAttributes.USAGE_UNKNOWN;
        }
    
        @Override
        public void cancel() {
            if (mService == null) {
                return;
            }
            try {
                mService.cancelVibrate(mToken);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to cancel vibration.", e);
            }
        }
    }

    说明
    (01) 在构造函数SystemVibrator()中,我们通过 IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")) 获取马达服务,实际上获取的是VibratorService对象。
    (02) SystemVibrator的接口都是调用VibratorService接口实现的。

    在讲解“应用层如何通过getSystemService(VIBRATOR_SERVICE)获取马达服务,然后进一步的操作马达”之前,我们先看看应用层的马达操作示例!

     

    Part 6 马达的应用示例

    1 权限

    调用马达服务,需要在manifest中添加相应的权限:

    <!-- 震动马达权限 -->
    <uses-permission android:name="android.permission.VIBRATE"/>

    2 源码

    源码如下:

    1 package com.test;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Vibrator;
     6 import android.view.View;
     7 import android.view.View.OnClickListener;
     8 import android.widget.Button;
     9 import android.widget.ToggleButton;
    10 import android.util.Log;
    11 
    12 public class VibratorTest extends Activity {
    13     private static final String TAG = "skywang-->VibratorTest";
    14 
    15     private Vibrator mVibrator;
    16     private Button mOnce = null;
    17     private ToggleButton mEndless = null;
    18 
    19     @Override
    20     protected void onCreate(Bundle savedInstanceState) {
    21         super.onCreate(savedInstanceState);
    22         setContentView(R.layout.main);
    23 
    24         // 获取震动马达服务
    25         mVibrator= (Vibrator) getSystemService(VIBRATOR_SERVICE);
    26 
    27         mOnce = (Button) findViewById(R.id.vib_once);
    28         mOnce.setOnClickListener(new View.OnClickListener() {
    29             
    30             @Override
    31             public void onClick(View view) {
    32                 //震动指定时间
    33                 mVibrator.vibrate(100);
    34             }
    35         });
    36 
    37         mEndless = (ToggleButton) findViewById(R.id.vib_endless);
    38         mEndless.setOnClickListener(new OnClickListener() {
    39             @Override
    40             public void onClick(View v) {
    41                 if (mEndless.isChecked()) {
    42                     //等待100ms后,按数组所给数值间隔震动;其后为重复次数,-1为不重复,0一直震动
    43                     mVibrator.vibrate(new long[]{100,20,100,40,100,60}, 0);
    44                 } else {
    45                     // 取消震动 
    46                     mVibrator.cancel();
    47                 }
    48             }
    49         });
    50 
    51     }
    52 
    53     @Override
    54     protected void onStop() {
    55         super.onStop();
    56         if (mVibrator != null)
    57             mVibrator= null;
    58     }
    59 }

    点击下载:Android马达应用代码

     

    Part 7 马达的应用如何调用到马达服务的

    接下来,我们分析一下如何获取马达服务的:即 mVibrator= (Vibrator) getSystemService(VIBRATOR_SERVICE) 的工作原理。

    1. Context.java中的getSystemService()

    getSystemService()定义在frameworks/base/core/java/android/content/Context.java中,源码如下:

    ​
    public abstract Object getSystemService(String name);
    
    ​
    public static final String VIBRATOR_SERVICE = "vibrator";

    Context.java中的getSystemService() 是个抽象方法,它的实现在ContextImpl.java中。

    2. ContextImpl.java中的getSystemService()

    frameworks/base/core/java/android/app/ContextImpl.java中的 getSystemService() 源码如下:

      @Override
        public Object getSystemService(String name) {
            return SystemServiceRegistry.getSystemService(this, name);
        }

    3.  SystemServiceRegistry.java的getSystemService(ContextImpl ctx, String name)

    frameworks/base/core/java/android/app/SystemServiceRegistry.java的源码如下:

      public static Object getSystemService(ContextImpl ctx, String name) {
            ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
            return fetcher != null ? fetcher.getService(ctx) : null;
        }

    4. SystemServiceRegistry.java中的SYSTEM_SERVICE_FETCHERS

    SYSTEM_SERVICE_FETCHERS是一个HashMap对象,它的相关代码如下:

    ​
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
                new HashMap<String, ServiceFetcher<?>>();
    
    SYSTEM_SERVICE_FETCHERS 的初始化,是在SystemServiceRegistry.java通过static静态模块完成的。源码如下:
    static {
      
          ...
      
          // 注册“传感器服务”
          registerService(Context.SENSOR_SERVICE, SensorManager.class,
                    new CachedServiceFetcher<SensorManager>() {
                @Override
                public SensorManager createService(ContextImpl ctx) {
                    return new SystemSensorManager(ctx.getOuterContext(),
                      ctx.mMainThread.getHandler().getLooper());
                }});
     
         // 注册其它服务 ...
     
         // 注册马达服务
        registerService(Context.VIBRATOR_SERVICE, Vibrator.class,
                    new CachedServiceFetcher<Vibrator>() {
                @Override
                public Vibrator createService(ContextImpl ctx) {
                    return new SystemVibrator(ctx);
                }});
     
         ...
     }
    
    ​

    说明:在上面的static静态模块中,会通过registerService()注册一系列的服务,包括马达服务。注册服务是通过registerService()实现的,下面我们看看registerService()的定义。

    private static <T> void registerService(String serviceName, Class<T> serviceClass,
                ServiceFetcher<T> serviceFetcher) {
            SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
            SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
        }

        从中,我们知道,在registerService()中,会通过 SYSTEM_SERVICE_FETCHERS.put(serviceName, fetcher) 将serviceName和fetcher添加到哈希表SYSTEM_SERVICE_FETCHERS中。
        对马达服务而言,添加到哈希表SYSTEM_SERVICE_FETCHERS中的key-value中的key是VIBRATOR_SERVICEvalue则是ServiceFetcher对象;而且该匿名ServiceFetcher对象的createService()方法会“通过new SystemVibrator()”返回SystemVibrator对象。而SystemVibrator我们在前面已经介绍过了,它是马达服务对外提供接口的类。

    OK,接着往下看。

    我们已经知道SYSTEM_SERVICE_FETCHERS是哈希表,通过SYSTEM_SERVICE_FETCHERS.get(name)返回的是ServiceFetcher对象。由于fetcher不为null,所以,getSystemService()会返回fetcher.getService(this)。我们看看ServiceFetcher中getService()源码:

        static abstract interface ServiceFetcher<T> {
            T getService(ContextImpl ctx);
        }
    
        /**
         * Override this class when the system service constructor needs a
         * ContextImpl and should be cached and retained by that context.
         */
        static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
            private final int mCacheIndex;
    
            public CachedServiceFetcher() {
                mCacheIndex = sServiceCacheSize++;
            }
    
            @Override
            @SuppressWarnings("unchecked")
            public final T getService(ContextImpl ctx) {
                final Object[] cache = ctx.mServiceCache;
                synchronized (cache) {
                    // Fetch or create the service.
                    Object service = cache[mCacheIndex];
                    if (service == null) {
                        service = createService(ctx);
                        cache[mCacheIndex] = service;
                    }
                    return (T)service;
                }
            }
    
            public abstract T createService(ContextImpl ctx);
        }

    从中,我们发现,getService()实际上返回的是“通过createService(ctx)创建的service对象”。
    而在registerService()注册马达服务时,我们匿名实现了createService()方法:它实际上是通过 new SystemVibrator() 返回SystemVibrator对象。

    至此,我们知道:getSystemService(VIBRATOR_SERVICE) 返回的是 SystemVibrator对象!SystemVibrator前面已经分析过,这里就不再说明了。

    8. 震动器hal层到app源文件目录及重要代码:  

    hal:
     hardware/libhardware/modules/vibrator/vibrator.c
     hardware/libhardware/include/hardware/vibrator.h
    		./lib64/hw/vibrator.default.so
    JNI:
     frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
    	jniRegisterNativeMethods(env, "com/android/server/VibratorService",method_table, NELEM(method_table));
     frameworks/base/services/core/jni/onload.cpp
    	register_android_server_VibratorService(env);
    
    framework:	
     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 cancelVibrate(IBinder token);
    	}
    
    //震动器实际操作类,服务,通过JNI调用com_android_server_VibratorService中函数
      frameworks/base/services/core/java/com/android/server/VibratorService.java
    	VibratorService extends IVibratorService.Stub
    	native static boolean vibratorExists();
        native static void vibratorInit();
        native static void vibratorOn(long milliseconds);
        native static void vibratorOff();
    	
      frameworks/base/services/java/com/android/server/SystemServer.java
    	vibrator = new VibratorService(context);
        ServiceManager.addService("vibrator", vibrator);
    
    		vibrator.systemReady();
    
    //这两个类client使用:
      frameworks/base/core/java/android/os/Vibrator.java
      frameworks/base/core/java/android/os/SystemVibrator.java
    	SystemVibrator extends Vibrator
    	IVibratorService mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
    	
    app:
    	Vibrator mVibrator= (Vibrator) getSystemService(VIBRATOR_SERVICE)
    	frameworks/base/core/java/android/content/Context.java
    		public abstract Object getSystemService(String name);
    		frameworks/base/core/java/android/app/ContextImpl.java(在这个类里实现)
    			public Object getSystemService(String name) {
    				return SystemServiceRegistry.getSystemService(this, name);
    			}
    			frameworks/base/core/java/android/app/SystemServiceRegistry.java
    				registerService(Context.VIBRATOR_SERVICE, Vibrator.class,
                    new CachedServiceFetcher<Vibrator>() {
    				@Override
    				public Vibrator createService(ContextImpl ctx) {
    					return new SystemVibrator(ctx);
    				}});
    				public static Object getSystemService(ContextImpl ctx, String name) {
    					ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    					return fetcher != null ? fetcher.getService(ctx) : null;
    				}
    			最后返回SystemVibrator对象。

     

     Q:  自己在源码里添加的硬件服务,eclipse或者android studio编写测试app时,需要把源码编译生成的classes.jar包导入项目或者把app源码直接放入源码编译。源码编译完成会生成许多classes.jar。我们要导入的classes.jar路径为:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar

     

     

    展开全文
  • Android 10.0.0_r30 android code search地址:点我 平台:MTK6779 相关文件 Application Framework frameworks/base/core/java/android/os/SystemVibrator.java frameworks/base/core/java/android/os/Vibrator....
  • A、通过系统服务获得手机震动服务,Vibrator vibrator =(Vibrator)getSystemService(VIBRATOR_SERVICE);  B、得到震动服务后检测vibrator是否存在: vibrator.hasVibrator(); 检测当前硬件是否有vibrator,...
  • 一个简单的SystemService(vibrator)

    千次阅读 2018-08-16 12:01:42
    Android 6.0 ... Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); //获取Vibrator实例  mVibrator.vibrate(500);  frameworks/base/core/java/android/app/Sy...
  • Vibrator.zip

    2020-08-18 09:37:15
    Android打开震动,设置震动等级,关闭震动。
  • 首先申请权限 ...vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); 震动:震动参数有两种,一种是节奏震动 long [] pattern = {600,300,600,300,600,300}; // 停止 开启 停.
  • 添加权限 在AndroidManifest.xml文件中添加如下震动权限 <uses-permission android:name="android.permission....vibrator = (Vibrator)context.getSystemService(this.VIBRATOR_SERVICE); 简单震动 先...
  • 下面来从APP一直分析到kernel的driver,因为vibrator是我所知的最简单的系统服务,分析过程过来,可以获取整个安卓服务的运行思路,把相关知识点都串联起来,又不至于被很多复杂的功能性逻辑结构卡住。在vibrator中...
  • vibrator.patch

    2021-08-22 10:52:59
    驱动开发
  • Vibrator的使用方法

    千次阅读 2016-09-16 00:09:06
    1、MainActivity.java package com.example.vibratordemo; import android.app.Activity; import android.os.Bundle;...import android.os.Vibrator; import android.view.Menu; import android.view.MenuItem;
  • } 三、Vibrator ① 应用场景 当设备需要设置不同的振动效果时,可以调用 Vibrator 模块,例如,设备的按键可以设置不同强度和时长的振动,闹钟和来电可以设置不同强度和时长的单次或周期性振动。 ② Vibrator 的 ...
  • Vibrator kaufen-crx插件

    2021-04-01 19:30:40
    http://www.vibrator-erfahrungen.de 购买广告牌目前始终略微尖叫。 但这不一定是这样。 在互联网上,有一些门户网站可以在没有羞耻的情​​况下完全扫描这个话题,所以你可以做出正确的购买,并且可以在床上遇到...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,492
精华内容 2,996
关键字:

vibrator