Android(安卓)Vibrator 框架总结
16lz
2021-01-24
前言
振动器小模块框架总结
基于 MTK 7.0 源码
驱动
内核配置:kernel-3.18\arch\arm64\configs\E266L_debug_defconfigCONFIG_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.javapublic 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(安卓)-- CursorAdapter
- Android(安卓)输入系统解析 (2)
- ARM cortex A8/9 - Android(安卓)NDK - NEON介绍以及优化
- Android(安卓)4.4KitKat AudioFlinger 流程分析
- Android(安卓)页面跳转
- Android硬件抽象层加调试信息
- Android下载文件时对MediaScanner的调用
- Android(安卓)OpenGL ES 开发教程(6):GLSurfaceView
- android 串口jni 开发流程