Android System Server大纲之VibratorService

来源:互联网 发布:沙发什么意思网络语言 编辑:程序博客网 时间:2024/06/02 02:03

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.Vibrator     */    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层的整过流程详细记录下来。

0 0
原创粉丝点击