Android System Server大纲之VibratorService

Android System Server大纲之VibratorService

vibrator

  • Android System Server大纲之VibratorService
    • 前言
    • VibratorService类型
    • APP使用VibratorService
    • VibratorService驱动硬件

前言

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

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

Android System Server大纲之VibratorService_第1张图片

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> SYSTEM_SERVICE_FETCHERS =
            new HashMap>();
}

上述代码可知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  void registerService(String serviceName, Class serviceClass,
            ServiceFetcher 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() {
        @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层的整过流程详细记录下来。

你可能感兴趣的:(Android,system,server,area,Android系统服务)