您的位置:首页 > 移动开发 > Android开发

Android System Server大纲之VibratorService

2017-02-15 15:14 405 查看

Android System Server大纲之VibratorService

vibrator

Android System Server大纲之VibratorService
前言

VibratorService类型

APP使用VibratorService

VibratorService驱动硬件

前言

VibratorService即安卓震动服务,是Android系统中一个和硬件相关的服务,管理和驱动着设备的振动器。在Android手持设备,如手机,平板等,振动器是不可或缺的硬件设备,在给用户震动反馈的用户交互中发挥了举足轻重的作用。

既然是和硬件相关的服务,那么以Android系统的架构模式,VibratorService将对应以下架构



VibratorService类型

直接上代码:

public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
}


上述代码可以看到,VibratorService继承了IVibratorService.Stub,也就是说,VibratorService直接支持Android IPC Binder通信,那么上层APP就可以通过AIDL使用VibratorService,驱动设备上的振动器,从而给用户震动的反馈。

VibratorService提供哪些接口可以给上层使用呢?看看接口IVibratorService:

public interface IVibratorService extends android.os.IInterface{
public boolean hasVibrator();
public void vibrate();
public void vibratePattern();
public void cancelVibrate();
}


上述代码可以看到,VibratorService提供上述四个接口给上层调用,hasVibrator()判断是当前设备否有支持振动器,然后通过vibrate()或vibratePattern()驱动震动器发起震动,前者只需要关心参数milliseconds,即震动的时间,时间结束后,震动停止,后者需要关心的参数有pattern和repeat,pattern是long型的数组,保存的是每次震动持续的时间,即milliseconds,repeat固然就是重复的次数。所以vibrate()是一次性振动器,vibratePattern()是重复多次震动。cancelVibrate()固然是取消震动了。

APP使用VibratorService

Android针对上层APP使用System Server的功能,提供了一套机制,首先是获取到封装了VibratorService Binder句柄的对象,然后通过该对象间接调用System Server中service的接口。Android通用的代码实现方式如下:

Context.getSystemService()


通过上下文Context的getSystemService()方法获取封装了Binder句柄的framework对象实例,返回值是一个Object类型,需要相应向下强制转换成对应的类型。对于VibratorService,通过getSystemService()传入的参数是Context.VIBRATOR_SERVICE。

public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
* android.os.Vibrator} for interacting with the vibration hardware.
*
* @see #getSystemService
* @see android.os.Vibrato
f4f2
r
*/
public static final String VIBRATOR_SERVICE = "vibrator";
}


getSystemService(Context.VIBRATOR_SERVICE)返回的是一个android.os.Vibrator的实例。Context.VIBRATOR_SERVICE的值是vibrator,获取的对应的远程是否就是VibratorService呢?先来回顾一下另外一篇文章《Android系统之System Server大纲》中的服务启动过程,VibratorService是继承了IPC通信接口,所以是通过ServiceManager.addService()的方式启动该系统服务,读者可以参考Android系统之System Server大纲,看VibratorService的启动代码:

vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);


VibratorService启动后正是以”vibrator”这个标签加入到ServiceManager中,所以getSystemService(Context.VIBRATOR_SERVICE)返回的android.os.Vibrator实例刚好是对应了VibratorService。在看看android.os.Vibrator这个类:

public abstract class Vibrator {
}


android.os.Vibrator是一个抽象类,而Java是不能new一个抽象类的实例的,所以getSystemService(Context.VIBRATOR_SERVICE)返回来的只是android.os.Vibrator的子类的实例,到底是那个实现类呢?追踪Context.getSystemService(Context.VIBRATOR_SERVICE)的过程寻找点线索,然而Context也是一个抽象了,所以Context.getSystemService(Context.VIBRATOR_SERVICE)也是在Context的实现类中去执行

public abstract class Context {
public abstract Object getSystemService(@ServiceName @NonNull String name);
}


Context的实现类是android/app/ContextImpl.java,getSystemService()的实现如下:

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


这里直接调用了SystemServiceRegistry的getSystemService()方法,继续往下看代码:

final class SystemServiceRegistry {
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
}


通过name作为key在SYSTEM_SERVICE_FETCHERS中获取ServiceFetcher

final class SystemServiceRegistry {
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
}


上述代码可知SYSTEM_SERVICE_FETCHERS是一个HashMap的对象实例,通过name = vibrator作为Map的查询values,查看SYSTEM_SERVICE_FETCHERS中保存的values对象,就可以寻找到Context.getSystemService(Context.VIBRATOR_SERVICE)返回的真正的对象实例是什么类型。看SYSTEM_SERVICE_FETCHERS的填充数据过程:

final class SystemServiceRegistry {
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()的方式注册,再继续跟踪vibrator在哪里被注册到SYSTEM_SERVICE_FETCHERS:

final class SystemServiceRegistry {
static {
registerService(Context.VIBRATOR_SERVICE, Vibrator.class,
new CachedServiceFetcher<Vibrator>() {
@Override
public Vibrator createService(ContextImpl ctx) {
return new SystemVibrator(ctx);
}});
}
}


上述代码中可以看到,registerService()传入的key正好是Context.VIBRATOR_SERVICE,和Context.getSystemService(Context.VIBRATOR_SERVICE)中的参数一致,registerService()中传入的android.os.Vibrator是android/os/SystemVibrator.java,所以Context.getSystemService(Context.VIBRATOR_SERVICE)返回的真正的实例是SystemVibrator:

public class SystemVibrator extends Vibrator {
private final IVibratorService mService;
public SystemVibrator() {
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("vibrator"));
}

public void cancel() {}
public boolean hasVibrator() {}
public void vibrate(..... long milliseconds .....) {}
public void vibrate(..... long[] pattern, int repeat .....) {
}


上述代码可以看到,SystemVibrator的构造方法中初始化了IVibratorService的对象mService,通过ServiceManager.getService(“vibrator”)获取到VibratorService的句柄。

因此,APP通过Context.getSystemService(Context.VIBRATOR_SERVICE)获取到的SystemVibrator对象,通过android.os.Vibrator的方法vibrate(),hasVibrator()和cancel()通过SystemVibrator的对象实例mService实现对VibratorService的控制,从而实现对硬件震动器的控制。

VibratorService驱动硬件

以APP请求震动服务为例,看看这个过程,首先是APP调用Vibrator.vibrate(),然后IPC通信到VibratorService到:

public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
@Override // Binder call
public void vibrate(int uid, String opPkg, long milliseconds, int usageHint,
IBinder token) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires VIBRATE permission");
}
Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg);
try {
synchronized (mVibrations) {
......
startVibrationLocked(vib);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}


看上述代码,首先是通过checkCallingOrSelfPermission()检测调用者APP是否已经有android.Manifest.permission.VIBRATE这个权限,所以APP要使用震动服务,需要在AndroidManifest.xml中声明权限android.Manifest.permission.VIBRATE的值android.permission.VIBRATE权限,权限保护等级为normal,即安装时授权。

随后,把token, milliseconds, usageHint, uid, opPkg封装到Vibration对象中,那么就把震动更好地抽象成一次震动对象,通过startVibrationLocked继续传输:

private void startVibrationLocked(final Vibration vib) {
......
if (vib.mTimeout != 0) {
doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint);
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();
}
}


这里有一个分支,判断依据是vib.mTimeout,vib.mTimeout什么时候等于0,什么时候不等于0呢?回顾Vibration的初始化过程:

public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
@Override // Binder call
public void vibrate(int uid, String opPkg, long milliseconds, int usageHint,
IBinder token) {
......
Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg);
......
}
}

private class Vibration implements IBinder.DeathRecipient {
private final IBinder mToken;
private final long    mTimeout;
......

Vibration(IBinder token, long millis, int usageHint, int uid, String opPkg) {
this(token, millis, null, 0, usageHint, uid, opPkg);
}

private Vibration(IBinder token, long millis, long[] pattern,
int repeat, int usageHint, int uid, String opPkg) {
mToken = token;
mTimeout = millis;
......
}


在vibrate()这个方法中可以看到,实例化Vibration对象时,传入了milliseconds,在Vibration的构造方法中,把milliseconds赋值给mTimeout,也就是说mTimeout保存的是震动持续的时间。前文提到,启动震动有两个接口,如下:

public class SystemVibrator extends Vibrator {
......
public void vibrate(..... long milliseconds .....) {}
public void vibrate(..... long[] pattern, int repeat .....) {
}


一个是带milliseconds的作为参数的,另外一个是不带milliseconds参数的,前文有说明,前者是一次性震动,后者是重复多次震动,那么,也就是在下面的代码中:

private void startVibrationLocked(final Vibration vib) {
......
if (vib.mTimeout != 0) {
doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint);
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();
}
}


一次性震动走的是vib.mTimeout != 0的情况,重复震动的走的是!(vib.mTimeout != 0)的情况,那么这里的代码就很符合这个实际情况了,vib.mTimeout != 0时,直接调用doVibratorOn()启动震动,而重复震动时,通过VibrateThread线程实现重复震动的功能,这里就不在赘述这个重复的实现过程了。

接着追踪doVibratorOn()方法:

private void doVibratorOn(long millis, int uid, int usageHint) {
synchronized (mInputDeviceVibrators) {
......
if (vibratorCount != 0) {
......
for (int i = 0; i < vibratorCount; i++) {
mInputDeviceVibrators.get(i).vibrate(millis, attributes);
}
} else {
vibratorOn(millis);
}
}
}


这里会考虑多个振动器的情况,本文默认只有一个,则直接调用vibratorOn(millis)这个方法:

public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
native static void vibratorOn(long milliseconds);
}


如上述代码,vibratorOn()是一个native方法,也就通过JNI,调用到Native framework了,传递的参数只有一个,就是mills,震动持续的时间。VibratorService的JNI实现是frameworks/base/services/core/jni/com_android_server_VibratorService.cpp中,继续看vibratorOn()这个方法:

static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
if (gVibraDevice) {
int err = gVibraDevice->vibrator_on(gVibraDevice, timeout_ms);
......
} else {
ALOGW("Tried to vibrate but there is no vibrator device.");
}
}


这里有个对象gVibraDevice,gVibraDevice实际代表的就是振动器,有振动器,才会实例化gVibraDevice。gVibraDevice调用了vibrator_on函数。先看gVibraDevice的定义,在hardware/libhardware/include/hardware/vibrator.h中:

typedef struct vibrator_device {
struct hw_device_t common;

/** Turn on vibrator
*/
int (*vibrator_on)(struct vibrator_device* vibradev, unsigned int timeout_ms);

/** Turn off vibrator
*/
int (*vibrator_off)(struct vibrator_device* vibradev);
} vibrator_device_t;


vibrator.h中定义了vibrator_device_t,以及它的函数vibrator_on和vibrator_off,再继续看调用gVibraDevice->vibrator_on(gVibraDevice, timeout_ms)如何发起震动。vibrator_on的具体实现是在hardware/libhardware/modules/vibrator/vibrator.c 中,先看如下代码:

static int vibra_open(const hw_module_t* module, const char* id __unused,
hw_device_t** device __unused) {
......
vibrator_device_t *vibradev = calloc(1, sizeof(vibrator_device_t));
......
vibradev->vibrator_on = vibra_on;
vibradev->vibrator_off = vibra_off;

*device = (hw_device_t *) vibradev;

return 0;
}


上述C语言代码中,vibra_open函数中在初始化震动器是就被调用了,vibra_open在vibrator_on的前面,在本文就不再赘述这个过程。通过上述代码可知,gVibraDevice->vibrator_on(gVibraDevice, timeout_ms)实际是调用了函数vibra_on,继续看vibra_on的实现:

static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
{
/* constant on, up to maximum allowed time */
return sendit(timeout_ms);
}


直接调用了函数sendit(timeout_ms),往下看:

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));

to_write = snprintf(value, sizeof(value), "%u\n", timeout_ms);
written = TEMP_FAILURE_RETRY(write(fd, value, to_write));
......
return ret;
}


在这里,打开设备,写入数据。到此,本文就不再往下继续分析这个过程了,有兴趣的读者可以自行分析研究。

总结

本文赘述了VibratorService的创建过程,上层APP如何使用VibratorService提供的震动服务,以及APP发起震动时,从APP到HAL层的整过流程详细记录下来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: