收藏 分销(赏)

android+静音与马达振动流程.doc

上传人:xrp****65 文档编号:7672861 上传时间:2025-01-11 格式:DOC 页数:15 大小:75KB 下载积分:10 金币
下载 相关 举报
android+静音与马达振动流程.doc_第1页
第1页 / 共15页
android+静音与马达振动流程.doc_第2页
第2页 / 共15页


点击查看更多>>
资源描述
android 静音与马达振动流程 1,设置静音和振动 静音和振动都属于来电后的动作.所以在设置静音和振动时都只是设置一些标识,并往数据库写入相应标识. 文件:packages/apps/settings/src/com/android/settings/SoundAndDisplaySettings.java private CheckBoxPreference mSilent; private CheckBoxPreference mVibrate; private void setRingerMode(boolean silent, boolean vibrate) { if (silent) { mAudioManager.setRingerMode(vibrate ? AudioManager.RINGER_MODE_VIBRATE : AudioManager.RINGER_MODE_SILENT); } else { mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, vibrate ? AudioManager.VIBRATE_SETTING_ON : AudioManager.VIBRATE_SETTING_OFF); } } public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference == mSilent || preference == mVibrate) { setRingerMode(mSilent.isChecked(), mVibrate.isChecked()); if (preference == mSilent) updateState(false); } ... 静音和振动是复选框按钮,两个中有一个发生变化时调用setRingerMode对状态进行设置;如下状态描术: RINGER_MODE_SILENT 静音,且无振动 RINGER_MODE_VIBRATE 静音,但有振动 RINGER_MODE_NORMAL 正常声音,振动开关由setVibrateSetting决定. 铃响模式的设置是通过mAudioManager(音频管理器)来实现的. 2 音频管理器服务 mAudioManager所在服务如下: 文件: frameworks/base/media/java/android/media/AudioManager.java public static final int RINGER_MODE_SILENT = 0; public static final int RINGER_MODE_VIBRATE = 1; public static final int RINGER_MODE_NORMAL = 2; public void setRingerMode(int ringerMode) { IAudioService service = getService(); try { service.setRingerMode(ringerMode); } catch (RemoteException e) { Log.e(TAG, "Dead object in setRingerMode", e); } } 将铃响模式值传给音频接口服务IaudioService public static final int VIBRATE_TYPE_RINGER = 0; public static final int VIBRATE_TYPE_NOTIFICATION = 1; public static final int VIBRATE_SETTING_OFF = 0; public static final int VIBRATE_SETTING_ON = 1; public static final int VIBRATE_SETTING_ONLY_SILENT = 2; public void setVibrateSetting(int vibrateTyp , int vibrateSetting) { IAudioService service = getService(); try { service.setVibrateSetting(vibrateType, vibrateSetting); } catch (RemoteException e) { Log.e(TAG, "Dead object in setVibrateSetting", e); } } 将振动类型和振动设置传给音频接口服务IaudioService,IaudioService的定义如下: frameworks/base/media/java/android/media/IAudioService.aidl frameworks/base/media/java/android/media/AudioService.java 文件: frameworks/base/media/java/android/media/AudioService.java 文件: frameworks/base/core/java/android/provider/Settings.java public void setRingerMode(int ringerMode) { synchronized (mSettingsLock) { if (ringerMode != mRingerMode) { setRingerModeInt(ringerMode, true); // Send sticky broadcast broadcastRingerMode(); } } } 将对应模式下的音量写入数据库,并将该模式广播. public void setVibrateSetting(int vibrateType, int vibrateSetting) { mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); // Broadcast change broadcastVibrateSetting(vibrateType); // Post message to set ringer mode (it in turn will post a message // to persist) sendMsg(mAudioHandler, MSG_PERSIST_VIBRATE_SETTING, SHARED_MSG, SENDMSG_NOOP, 0, 0, null, 0); } 同样将振动模式写入数据库,并广播该模式. 3 硬件服务 文件:frameworks/base/services/java/com/android/server/HardwareService.java 开始振动: public void vibrate(long milliseconds, IBinder token) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires VIBRATE permission"); } // We're running in the system server so we cannot crash. Check for a // timeout of 0 or negative. This will ensure that a vibration has // either a timeout of > 0 or a non-null pattern. if (milliseconds <= 0 || (mCurrentVibration != null && mCurrentVibration.hasLongerTimeout(milliseconds))) { // Ignore this vibration since the current vibration will play for // longer than milliseconds. return; } Vibration vib = new Vibration(token, milliseconds); synchronized (mVibrations) { removeVibrationLocked(token); doCancelVibrateLocked(); mCurrentVibration = vib; startVibrationLocked(vib); } } private void startVibrationLocked(final Vibration vib) { if (vib.mTimeout != 0) { vibratorOn(vib.mTimeout); mH.postDelayed(mVibrationRunnable, vib.mTimeout); } else { // mThread better be null here. doCancelVibrate should always be // called before startNextVibrationLocked or startVibrationLocked. mThread = new VibrateThread(vib); mThread.start(); } } 该接口允许设置振动的时间长度,通过调用vibratorOn(vib.mTimeout);实现对底层硬件的操作。 取消振动: public void cancelVibrate(IBinder token) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.VIBRATE, "cancelVibrate"); // so wakelock calls will succeed long identity = Binder.clearCallingIdentity(); try { synchronized (mVibrations) { final Vibration vib = removeVibrationLocked(token); if (vib == mCurrentVibration) { doCancelVibrateLocked(); startNextVibrationLocked(); } } } finally { Binder.restoreCallingIdentity(identity); } } private void doCancelVibrateLocked() { if (mThread != null) { synchronized (mThread) { mThread.mDone = true; mThread.notify(); } mThread = null; } vibratorOff (); mH.removeCallbacks(mVibrationRunnable); } 该接口允许停止振动,通过调用vibratorOff();实现对底层硬件的操作。 4 硬件调用 vibratorOn、vibratorOff对应的jni代码如下: 文件:frameworks/base/services/jni/com_android_server_HardwareService.cpp static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms) { // LOGI("vibratorOn\n"); vibrator_on(timeout_ms); } static void vibratorOff(JNIEnv *env, jobject clazz) { // LOGI("vibratorOff\n"); vibrator_off(); } vibrator_on、vibrator_off 接口的提供者为如下硬件原型。 5, 硬件原型 文件:hardware/libhardware_legacy/vibrator/vibrator.c #define THE_DEVICE "/sys/class/timed_output/vibrator/enable" static int sendit(int timeout_ms) { int nwr, ret, fd; char value[20]; #ifdef QEMU_HARDWARE if (qemu_check()) { return qemu_control_command( "vibrator:%d", timeout_ms ); } #endif fd = open(THE_DEVICE, O_RDWR); if(fd < 0) return errno; nwr = sprintf(value, "%d\n", timeout_ms); ret = write(fd, value, nwr); close(fd); return (ret == nwr) ? 0 : -1; } int vibrator_on(int timeout_ms) { /* constant on, up to maximum allowed time */ return sendit(timeout_ms); } int vibrator_off() { return sendit(0); } 由以上代码可知,开启振动时是往文件/sys/class/timed_output/vibrator/enable写入振动的时间长度;关闭振动时,其时间长度为0。/sys/class/timed_output/vibrator/enable 的真实路径根据实际作修改。 6,驱动代码 创建timed_output类 kernel\drivers\staging\android\Timed_output.c 在sys/class目录创建timed_output子目录和文件enable timed_output_class = class_create(THIS_MODULE, "timed_output");创建timed_output子目录 ret = device_create_file(tdev->dev, &dev_attr_enable);在sys/class/timed_output子目录创建文件enable static int create_timed_output_class(void) { if (!timed_output_class) { timed_output_class = class_create(THIS_MODULE, "timed_output"); if (IS_ERR(timed_output_class)) return PTR_ERR(timed_output_class); atomic_set(&device_count, 0); } return 0; } int timed_output_dev_register(struct timed_output_dev *tdev) { int ret; if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time) return -EINVAL; ret = create_timed_output_class(); if (ret < 0) return ret; tdev->index = atomic_inc_return(&device_count); tdev->dev = device_create(timed_output_class, NULL, MKDEV(0, tdev->index), NULL, tdev->name); if (IS_ERR(tdev->dev)) return PTR_ERR(tdev->dev); ret = device_create_file(tdev->dev, &dev_attr_enable); if (ret < 0) goto err_create_file; dev_set_drvdata(tdev->dev, tdev); tdev->state = 0; return 0; err_create_file: device_destroy(timed_output_class, MKDEV(0, tdev->index)); printk(KERN_ERR "timed_output: Failed to register driver %s\n", tdev->name); return ret; } EXPORT_SYMBOL_GPL(timed_output_dev_register); 驱动注册马达的驱动,注册一个定时器用于控制震动时间(回调函数vibrator_timer_func),注册两个队列,一共给马达打开用,一共为马达震动关闭用。 static void pmic_vibrator_on(struct work_struct *work) { set_pmic_vibrator(1); } static void pmic_vibrator_off(struct work_struct *work) { set_pmic_vibrator(0); } static void timed_vibrator_on(struct timed_output_dev *sdev) { schedule_work(&work_vibrator_on); } static void timed_vibrator_off(struct timed_output_dev *sdev) { schedule_work(&work_vibrator_off); } static void vibrator_enable(struct timed_output_dev *dev, int value) { hrtimer_cancel(&vibe_timer); if (value == 0) timed_vibrator_off(dev); else { value = (value > 15000 ? 15000 : value); timed_vibrator_on(dev); hrtimer_start(&vibe_timer, ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL); } } static int vibrator_get_time(struct timed_output_dev *dev) { if (hrtimer_active(&vibe_timer)) { ktime_t r = hrtimer_get_remaining(&vibe_timer); return r.tv.sec * 1000 + r.tv.nsec / 1000000; } else return 0; } static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer) { timed_vibrator_off(NULL); return HRTIMER_NORESTART; } static struct timed_output_dev pmic_vibrator = { .name = "vibrator", .get_time = vibrator_get_time, .enable = vibrator_enable, }; void __init pxa_init_pmic_vibrator(void) { INIT_WORK(&work_vibrator_on, pmic_vibrator_on); INIT_WORK(&work_vibrator_off, pmic_vibrator_off); hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); vibe_timer.function = vibrator_timer_func; timed_output_dev_register(&pmic_vibrator); } 当上层要设置马达震动时,往文件/sys/class/timed_output/vibrator/enable写入振动的时间长度,通过 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); int value; sscanf(buf, "%d", &value); tdev->enable(tdev, value); return size; } 调用驱动的enable函数也就是vibrator_enable( .enable = vibrator_enable,) vibrator_enable | | v timed_vibrator_on(dev); | | v schedule_work(&work_vibrator_on); | | v pmic_vibrator_on | | v set_pmic_vibrator(1); //给马达供电震动 | | v hrtimer_start(&vibe_timer, ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL); 最终是设置马达的硬件控制驱动管给马达供电,并且启动定时器,定时时间是上层给的参数。 定时时间到了就调用定时器的回调函数vibrator_timer_func vibrator_timer_func | | v timed_vibrator_off(NULL); | | v schedule_work(&work_vibrator_off); | | v pmic_vibrator_off | | v set_pmic_vibrator(0); //断开马达的供电,马达停止震动 最终是设置马达的硬件控制驱动管断开马达供电,停止马达震动 本文来自CSDN博客,转载请标明出处:
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服