AndroidM 振动器系统
来源:互联网 发布:页面加载完毕后调用js 编辑:程序博客网 时间:2024/05/01 08:03
1.马达的使用
在使用马达服务时需要在manifest中加<uses-permission android:name="android.permission.VIBRATE"/>权限
public void testVibrator(Context context, int command) {
Vibrator mVibrator = (Vibrator)context.getSystemService(context.VIBRATOR_SERVICE);
switch(command){
case 0:
mVibrator.vibrate(1000); // 震动1s
break;
case 1:
// 等待100ms后,按数组所给数值间隔震动,0为一直震动,-1为不重复
mVibrator.vibrate(new long[]{100,200,100,40,60}, 0);
break;
case 2:
break;
default :
mVibrator.cancel(); // 取消震动
}
}
2.马达服务的framework层的实现
马达系统包含了驱动程序,硬件抽象层,JNI部分,Java框架等几个部分
/frameworks/base/core/java/android/os/Vibrator.java
/frameworks/base/core/java/android/os/SystemVibrator.java
/frameworks/base/services/core/java/com/android/server/VibratorService.java
/frameworks/base/core/java/android/os/IVibratorService.aidl
/frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
/hardware/libhardware_legacy/include/hardware_legacy/vibrator.h
/hardware/libhardware_legacy/vibrator/vibrator.c
// Vibrator的实现代码
public abstract class Vibrator {
........
// 是否有马达
public abstract boolean hasVibrator();
// 各种构造函数
public void vibrate(long milliseconds) {
vibrate(milliseconds, null); // 震动
}
........
// 取消震动
public abstract void cancel();
}
// SystemVibrator的实现代码
public class SystemVibrator extends Vibrator {
private static final String TAG = "Vibrator";
private final IVibratorService mService; // 保存VibratorService对象
private final Binder mToken = new Binder();
// 构造函数,初始化VibratorService对象
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() {
........
try { // 调用VibratorService对象的hasVibrator()方法来判断是否有马达
return mService.hasVibrator(); // 最终将调用到VibratorService的本地方法vibratorExists
} catch (RemoteException e) {
}
return false;
}
@Override
public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
........
try { // 调用VibratorService对象的vibrate方法来使马达震动
mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
}
@Override
public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
AudioAttributes attributes) {
........
if (repeat < pattern.length) {
try { // 调用VibratorService对象的vibratePattern方法来使马达震动
mService.vibratePattern(uid, opPkg, pattern, repeat, usageForAttributes(attributes),
mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
........
@Override
public void cancel() {
if (mService == null) {
return;
}
try { // 调用VibratorService对象的cancelVibrate方法来取消振动
mService.cancelVibrate(mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to cancel vibration.", e);
}
}
}
// IVibratorService的定义
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);
}
// VibratorService的实现
// VibratorService实际上是通过调用本地方法来控制马达,
// 开始震动vibrate,vibratePattern; 结束震动cancelVibrate; 判断是否有振动器hasVibrator
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
private static final String TAG = "VibratorService";
private static final boolean DEBUG = false;
private final LinkedList<Vibration> mVibrations; // 记录所有马达
private final LinkedList<VibrationInfo> mPreviousVibrations; // 记录所有马达的信息
........
native static boolean vibratorExists(); // 本地方法,判断是否存在马达
native static void vibratorOn(long milliseconds); // 开始震动,震动时长为milliseconds
native static void vibratorOff(); // 停止震动
........
// VibrationInfo 马达信息
private static class VibrationInfo {
long timeout; // 震动时长
long startTime; // 开始时间
long[] pattern; // 震动模式
int repeat; // 重复次数
int usageHint; //
int uid; // 调用马达的线程ID
String opPkg;
public VibrationInfo(long timeout, long startTime, long[] pattern, int repeat,
int usageHint, int uid, String opPkg) {
........
}
@Override
public String toString() {
........
}
}
VibratorService(Context context) {
vibratorOff(); // 关闭马达的震动
mContext = context;
PowerManager pm = (PowerManager)context.getSystemService(
Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
mWakeLock.setReferenceCounted(true);
mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
mPreviousVibrationsLimit = mContext.getResources().getInteger(
com.android.internal.R.integer.config_previousVibrationsDumpLimit);
mVibrations = new LinkedList<>();
mPreviousVibrations = new LinkedList<>();
// 注册屏幕关闭广播的监听器,当屏幕关闭时取消一些应用发出的震动
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(mIntentReceiver, filter);
}
public void systemReady() { // 当system ready时systemserver将会调用此方法
mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
mSettingObserver = new SettingsObserver(mH);
// 低电模式改变时调用updateInputDeviceVibrators方法
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
updateInputDeviceVibrators();
}
});
// VIBRATE_INPUT_DEVICES发生变化时调用updateInputDeviceVibrators方法,在mSettingObserver监听器中进行
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
true, mSettingObserver, UserHandle.USER_ALL);
// 用户切换时调用updateInputDeviceVibrators方法
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateInputDeviceVibrators();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
//当切换用户,有效的输入设备发生变化,以及低电模式改变时调用以下方法
updateInputDeviceVibrators();
}
private final class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean SelfChange) {
updateInputDeviceVibrators();
}
}
@Override
public boolean hasVibrator() {
return doVibratorExists(); // 最终调用本地方法来进行判断
}
private void verifyIncomingUid(int uid) {
if (uid == Binder.getCallingUid()) {
return;
}
if (Binder.getCallingPid() == Process.myPid()) {
return;
}
mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
@Override // Binder call
public void vibrate(int uid, String opPkg, long milliseconds, int usageHint,
IBinder token) {
// 做一些基础检查,是否有申请权限,检查线程ID权限,震动时长检查等
........
Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mVibrations) {
removeVibrationLocked(token);
doCancelVibrateLocked();
mCurrentVibration = vib;
addToPreviousVibrationsLocked(vib);
startVibrationLocked(vib);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
public void vibratePattern(int uid, String packageName, long[] pattern, int repeat,
int usageHint, IBinder token) {
// 做一些基础检查,是否申请权限,检查线程ID权限等
........
long identity = Binder.clearCallingIdentity();
try {
........
synchronized (mVibrations) {
removeVibrationLocked(token);
doCancelVibrateLocked();
if (repeat >= 0) {
mVibrations.addFirst(vib);
startNextVibrationLocked();
} else {
// A negative repeat means that this pattern is not meant
// to repeat. Treat it like a simple vibration.
mCurrentVibration = vib;
startVibrationLocked(vib);
}
addToPreviousVibrationsLocked(vib);
}
}
finally {
Binder.restoreCallingIdentity(identity);
}
}
........
private boolean doVibratorExists() {
........
return vibratorExists();
}
private void doVibratorOn(long millis, int uid, int usageHint) {
synchronized (mInputDeviceVibrators) {
.build();
for (int i = 0; i < vibratorCount; i++) {
mInputDeviceVibrators.get(i).vibrate(millis, attributes);
}
} else {
vibratorOn(millis); // 调用本地方法启动马达震动
}
}
}
private void doVibratorOff() {
synchronized (mInputDeviceVibrators) {
........
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
mInputDeviceVibrators.get(i).cancel();
}
} else {
vibratorOff(); // 调用本地方法关闭马达震动
}
}
}
........
BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
synchronized (mVibrations) {
// 当系统进入一个非交互式的状态,我们想取消应用程序的振动行为。
// 然而它可能是系统目前正在进行触觉反馈。所以我们不取消系统振动。
if (mCurrentVibration != null
&& !mCurrentVibration.isSystemHapticFeedback()) {
doCancelVibrateLocked();
}
// 清除所有其他的震动
Iterator<Vibration> it = mVibrations.iterator();
while (it.hasNext()) {
Vibration vibration = it.next();
if (vibration != mCurrentVibration) {
unlinkVibration(vibration);
it.remove();
}
}
}
}
}
};
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
........
// 打印mPreviousVibrations保存的信息
synchronized (mVibrations) {
for (VibrationInfo info : mPreviousVibrations) {
pw.print(" ");
pw.println(info.toString());
}
}
}
}
3.马达服务的JNI层实现 com_android_server_VibratorService.cpp
........
#include <hardware_legacy/vibrator.h> // 此处是直接调用hardware层代码来实现
#include <stdio.h>
static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
{
// 调用hardware层vibrator_exists
return vibrator_exists() > 0 ? JNI_TRUE : JNI_FALSE;
}
static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
// 调用hardware层vibrator_on
vibrator_on(timeout_ms);
}
static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{
// 调用hardware层vibrator_off
vibrator_off();
}
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff }
};
// 注册method_table,在加载库完成后会调用此方法
int register_android_server_VibratorService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
method_table, NELEM(method_table));
}
};
4.马达服务的hardware层实现
// vibrator.h
........
int vibrator_exists(); // 判断是否存在马达,返回1存在,0不存在
int vibrator_on(int timeout_ms); // 打开马达,返回0成功,-1失败
int vibrator_off(); // 关闭马达,返回0成功,-1失败
........
vibrator.c
........
// 写此文件表示使能指定的时间,读表示获取剩余的时间
#define THE_DEVICE "/sys/class/timed_output/vibrator/enable"
int vibrator_exists()
{
int fd;
#ifdef QEMU_HARDWARE //模拟器环境
if (qemu_check()) {
return 1;
}
#endif
fd = open(THE_DEVICE, O_RDWR); // 如果打开成功则表示有马达
if(fd < 0)
return 0;
close(fd);
return 1;
}
static int sendit(int timeout_ms) //往THE_DEVICE中写数据表示设置马达震动时长
{
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) // 打开马达,设置震动时长
{
return sendit(timeout_ms);
}
int vibrator_off() //关闭马达
{
return sendit(0);
}
在使用马达服务时需要在manifest中加<uses-permission android:name="android.permission.VIBRATE"/>权限
public void testVibrator(Context context, int command) {
Vibrator mVibrator = (Vibrator)context.getSystemService(context.VIBRATOR_SERVICE);
switch(command){
case 0:
mVibrator.vibrate(1000); // 震动1s
break;
case 1:
// 等待100ms后,按数组所给数值间隔震动,0为一直震动,-1为不重复
mVibrator.vibrate(new long[]{100,200,100,40,60}, 0);
break;
case 2:
break;
default :
mVibrator.cancel(); // 取消震动
}
}
2.马达服务的framework层的实现
马达系统包含了驱动程序,硬件抽象层,JNI部分,Java框架等几个部分
/frameworks/base/core/java/android/os/Vibrator.java
/frameworks/base/core/java/android/os/SystemVibrator.java
/frameworks/base/services/core/java/com/android/server/VibratorService.java
/frameworks/base/core/java/android/os/IVibratorService.aidl
/frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
/hardware/libhardware_legacy/include/hardware_legacy/vibrator.h
/hardware/libhardware_legacy/vibrator/vibrator.c
// Vibrator的实现代码
public abstract class Vibrator {
........
// 是否有马达
public abstract boolean hasVibrator();
// 各种构造函数
public void vibrate(long milliseconds) {
vibrate(milliseconds, null); // 震动
}
........
// 取消震动
public abstract void cancel();
}
// SystemVibrator的实现代码
public class SystemVibrator extends Vibrator {
private static final String TAG = "Vibrator";
private final IVibratorService mService; // 保存VibratorService对象
private final Binder mToken = new Binder();
// 构造函数,初始化VibratorService对象
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() {
........
try { // 调用VibratorService对象的hasVibrator()方法来判断是否有马达
return mService.hasVibrator(); // 最终将调用到VibratorService的本地方法vibratorExists
} catch (RemoteException e) {
}
return false;
}
@Override
public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
........
try { // 调用VibratorService对象的vibrate方法来使马达震动
mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
}
@Override
public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
AudioAttributes attributes) {
........
if (repeat < pattern.length) {
try { // 调用VibratorService对象的vibratePattern方法来使马达震动
mService.vibratePattern(uid, opPkg, pattern, repeat, usageForAttributes(attributes),
mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
........
@Override
public void cancel() {
if (mService == null) {
return;
}
try { // 调用VibratorService对象的cancelVibrate方法来取消振动
mService.cancelVibrate(mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to cancel vibration.", e);
}
}
}
// IVibratorService的定义
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);
}
// VibratorService的实现
// VibratorService实际上是通过调用本地方法来控制马达,
// 开始震动vibrate,vibratePattern; 结束震动cancelVibrate; 判断是否有振动器hasVibrator
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
private static final String TAG = "VibratorService";
private static final boolean DEBUG = false;
private final LinkedList<Vibration> mVibrations; // 记录所有马达
private final LinkedList<VibrationInfo> mPreviousVibrations; // 记录所有马达的信息
........
native static boolean vibratorExists(); // 本地方法,判断是否存在马达
native static void vibratorOn(long milliseconds); // 开始震动,震动时长为milliseconds
native static void vibratorOff(); // 停止震动
........
// VibrationInfo 马达信息
private static class VibrationInfo {
long timeout; // 震动时长
long startTime; // 开始时间
long[] pattern; // 震动模式
int repeat; // 重复次数
int usageHint; //
int uid; // 调用马达的线程ID
String opPkg;
public VibrationInfo(long timeout, long startTime, long[] pattern, int repeat,
int usageHint, int uid, String opPkg) {
........
}
@Override
public String toString() {
........
}
}
VibratorService(Context context) {
vibratorOff(); // 关闭马达的震动
mContext = context;
PowerManager pm = (PowerManager)context.getSystemService(
Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
mWakeLock.setReferenceCounted(true);
mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
mPreviousVibrationsLimit = mContext.getResources().getInteger(
com.android.internal.R.integer.config_previousVibrationsDumpLimit);
mVibrations = new LinkedList<>();
mPreviousVibrations = new LinkedList<>();
// 注册屏幕关闭广播的监听器,当屏幕关闭时取消一些应用发出的震动
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(mIntentReceiver, filter);
}
public void systemReady() { // 当system ready时systemserver将会调用此方法
mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
mSettingObserver = new SettingsObserver(mH);
// 低电模式改变时调用updateInputDeviceVibrators方法
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
updateInputDeviceVibrators();
}
});
// VIBRATE_INPUT_DEVICES发生变化时调用updateInputDeviceVibrators方法,在mSettingObserver监听器中进行
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
true, mSettingObserver, UserHandle.USER_ALL);
// 用户切换时调用updateInputDeviceVibrators方法
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateInputDeviceVibrators();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
//当切换用户,有效的输入设备发生变化,以及低电模式改变时调用以下方法
updateInputDeviceVibrators();
}
private final class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean SelfChange) {
updateInputDeviceVibrators();
}
}
@Override
public boolean hasVibrator() {
return doVibratorExists(); // 最终调用本地方法来进行判断
}
private void verifyIncomingUid(int uid) {
if (uid == Binder.getCallingUid()) {
return;
}
if (Binder.getCallingPid() == Process.myPid()) {
return;
}
mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
@Override // Binder call
public void vibrate(int uid, String opPkg, long milliseconds, int usageHint,
IBinder token) {
// 做一些基础检查,是否有申请权限,检查线程ID权限,震动时长检查等
........
Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mVibrations) {
removeVibrationLocked(token);
doCancelVibrateLocked();
mCurrentVibration = vib;
addToPreviousVibrationsLocked(vib);
startVibrationLocked(vib);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
........
public void vibratePattern(int uid, String packageName, long[] pattern, int repeat,
int usageHint, IBinder token) {
// 做一些基础检查,是否申请权限,检查线程ID权限等
........
long identity = Binder.clearCallingIdentity();
try {
........
synchronized (mVibrations) {
removeVibrationLocked(token);
doCancelVibrateLocked();
if (repeat >= 0) {
mVibrations.addFirst(vib);
startNextVibrationLocked();
} else {
// A negative repeat means that this pattern is not meant
// to repeat. Treat it like a simple vibration.
mCurrentVibration = vib;
startVibrationLocked(vib);
}
addToPreviousVibrationsLocked(vib);
}
}
finally {
Binder.restoreCallingIdentity(identity);
}
}
........
private boolean doVibratorExists() {
........
return vibratorExists();
}
private void doVibratorOn(long millis, int uid, int usageHint) {
synchronized (mInputDeviceVibrators) {
........
if (vibratorCount != 0) {
final AudioAttributes attributes = new AudioAttributes.Builder().setUsage(usageHint).build();
for (int i = 0; i < vibratorCount; i++) {
mInputDeviceVibrators.get(i).vibrate(millis, attributes);
}
} else {
vibratorOn(millis); // 调用本地方法启动马达震动
}
}
}
private void doVibratorOff() {
synchronized (mInputDeviceVibrators) {
........
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
mInputDeviceVibrators.get(i).cancel();
}
} else {
vibratorOff(); // 调用本地方法关闭马达震动
}
}
}
........
BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
synchronized (mVibrations) {
// 当系统进入一个非交互式的状态,我们想取消应用程序的振动行为。
// 然而它可能是系统目前正在进行触觉反馈。所以我们不取消系统振动。
if (mCurrentVibration != null
&& !mCurrentVibration.isSystemHapticFeedback()) {
doCancelVibrateLocked();
}
// 清除所有其他的震动
Iterator<Vibration> it = mVibrations.iterator();
while (it.hasNext()) {
Vibration vibration = it.next();
if (vibration != mCurrentVibration) {
unlinkVibration(vibration);
it.remove();
}
}
}
}
}
};
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
........
// 打印mPreviousVibrations保存的信息
synchronized (mVibrations) {
for (VibrationInfo info : mPreviousVibrations) {
pw.print(" ");
pw.println(info.toString());
}
}
}
}
3.马达服务的JNI层实现 com_android_server_VibratorService.cpp
........
#include <hardware_legacy/vibrator.h> // 此处是直接调用hardware层代码来实现
#include <stdio.h>
static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
{
// 调用hardware层vibrator_exists
return vibrator_exists() > 0 ? JNI_TRUE : JNI_FALSE;
}
static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
// 调用hardware层vibrator_on
vibrator_on(timeout_ms);
}
static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{
// 调用hardware层vibrator_off
vibrator_off();
}
// 关联本地方法与JAVA方法
static JNINativeMethod method_table[] = {{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff }
};
// 注册method_table,在加载库完成后会调用此方法
int register_android_server_VibratorService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
method_table, NELEM(method_table));
}
};
4.马达服务的hardware层实现
// vibrator.h
........
int vibrator_exists(); // 判断是否存在马达,返回1存在,0不存在
int vibrator_on(int timeout_ms); // 打开马达,返回0成功,-1失败
int vibrator_off(); // 关闭马达,返回0成功,-1失败
........
vibrator.c
........
// 写此文件表示使能指定的时间,读表示获取剩余的时间
#define THE_DEVICE "/sys/class/timed_output/vibrator/enable"
int vibrator_exists()
{
int fd;
#ifdef QEMU_HARDWARE //模拟器环境
if (qemu_check()) {
return 1;
}
#endif
fd = open(THE_DEVICE, O_RDWR); // 如果打开成功则表示有马达
if(fd < 0)
return 0;
close(fd);
return 1;
}
static int sendit(int timeout_ms) //往THE_DEVICE中写数据表示设置马达震动时长
{
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) // 打开马达,设置震动时长
{
return sendit(timeout_ms);
}
int vibrator_off() //关闭马达
{
return sendit(0);
}
0 0
- AndroidM 振动器系统
- AndroidM: Build(编译系统)
- android 振动器系统
- Android 振动器系统架构
- Android振动器(Vibrator)系统详解
- Android振动器(Vibrator)系统详解
- Android振动器(Vibrator)系统详解
- Android振动器(Vibrator)系统详解
- Android平台中振动器系统详解
- Android开发平台振动器系统详解
- Android开发平台振动器系统详解
- Android平台中振动器系统详解
- Android开发平台振动器系统详解
- 安卓框架振动器系统浅析
- Android_Android系统服务—Vibrator(振动器)
- Android提供的系统服务之--Vibrator(振动器)
- android系统自带的振动器以及倒计时器
- 在全志R16平台的androidM系统下调通OV5640(分色排版)
- 鼠标滚轮监测
- 主备同步
- Java 多线程(六) synchronized关键字详解(牛叉)
- 解决每次运行Xcode , 都需要输入密码 问题
- OC如何读取本地文件和网络文件
- AndroidM 振动器系统
- mysql常用字符串操作函数大全,以及实例
- 深入理解 AngularJS 的 Scope
- git实践题目
- android webview
- javascript:对象基础
- 蓝桥杯—阶乘计算 ,高精度加法 ,Huffuman树
- 创建纯css下拉菜单
- Understanding Scopes