Android振动器android.os.Vibrator

1.Java层 frameworks/base/core/java/android/os/Vibrator.java

Vibrator类的实力可以通过getSystemService(VIBRATOR_SERVICE)获得实例。
两个方法:public abstract void vibrate(long milliseconds);/public abstract void vibrate(long[] pattern, int repeat);
public abstract void cancel();
查找路径:Activity.java-->ContextThemeWrapper.java-->ContextWrapper.java-->Context.java,getSystemService是Context.java类的抽象方法。其实现的类是ContextImpl.java,其中有段静态代码,注册所有context下能使用到的service。

registerService(VIBRATOR_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new SystemVibrator(); }}); 

Vibrator类只是个抽象类,具体实现的代码位于 SystemVibrator。位于\frameworks\base\core\java\android\os\目录下。两个方法的实现代码如下:

@Override    public void vibrate(long milliseconds) {        if (mService == null) {            Log.w(TAG, "Failed to vibrate; no vibrator service.");            return;        }        try {            mService.vibrate(milliseconds, mToken);        } catch (RemoteException e) {            Log.w(TAG, "Failed to vibrate.", e);        }    }

@Override    public void vibrate(long[] pattern, int repeat) {        if (mService == null) {            Log.w(TAG, "Failed to vibrate; no vibrator service.");            return;        }        // catch this here because the server will do nothing.  pattern may        // not be null, let that be checked, because the server will drop it        // anyway        if (repeat < pattern.length) {            try {                mService.vibratePattern(pattern, repeat, mToken);            } catch (RemoteException e) {                Log.w(TAG, "Failed to vibrate.", e);            }        } else {            throw new ArrayIndexOutOfBoundsException();        }    }

还有

@Override    public void cancel() {        if (mService == null) {            return;        }        try {            mService.cancelVibrate(mToken);        } catch (RemoteException e) {            Log.w(TAG, "Failed to cancel vibration.", e);        }    }

查看mService,其声明代码如下:

mService = IVibratorService.Stub.asInterface(                ServiceManager.getService("vibrator"));


/*这里跟Binder机制有关。。。断片ing*/

定义是private final IVibratorService mService;

所以找找这个IVibratorService吧。
查找下\frameworks\base\core\java\android\os\IVibratorService.aidl,这里定义了接口。

package android.os;/** {@hide} */interface IVibratorService{    boolean hasVibrator();    void vibrate(long milliseconds, IBinder token);    void vibratePattern(in long[] pattern, int repeat, IBinder token);    void cancelVibrate(IBinder token);}


具体的实现位于VibratorService.java。(\frameworks\base\services\java\com\android\server\)

public class VibratorService extends IVibratorService.Stub


然后是vibrate方法:

public void vibrate(long milliseconds, IBinder token) {        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)                != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException("Requires VIBRATE permission");        }        int uid = Binder.getCallingUid();        // 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, uid);        synchronized (mVibrations) {            removeVibrationLocked(token);            doCancelVibrateLocked();            mCurrentVibration = vib;            startVibrationLocked(vib);        }    }
然后是startVibrationLocked方法。
private void startVibrationLocked(final Vibration vib) {        if (vib.mTimeout != 0) {            doVibratorOn(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();        }    }
翻看了VibrateThread的run方法,最终还是调用了doVibratorOn方法。
所以看doVibratorOn方法:
private void doVibratorOn(long millis) {        synchronized (mInputDeviceVibrators) {            final int vibratorCount = mInputDeviceVibrators.size();            if (vibratorCount != 0) {                for (int i = 0; i < vibratorCount; i++) {                    mInputDeviceVibrators.get(i).vibrate(millis);                }            } else {                vibratorOn(millis);            }        }    }
|---------首先是vibratorCount这个,假如这个不为0,那么是调用 Vibrator的vibrate方法。。断片:vibratorCount这个表示什么意义!
mInputDeviceVibrators的声明如下:
private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
里面的每一个元素都是一个Vibrator的实力,Vibrator是个抽闲类。
mInputDeviceVibrators会在VibratorService.java中的updateInputDeviceVibrators方法添加元素:
mInputDeviceVibrators.clear();if (mVibrateInputDevicesSetting) {int[] ids = mIm.getInputDeviceIds();for (int i = 0; i < ids.length; i++) {InputDevice device = mIm.getInputDevice(ids[i]);Vibrator vibrator = device.getVibrator();if (vibrator.hasVibrator()) {mInputDeviceVibrators.add(vibrator);}}}
查看InputDevice类的getVibrator
public Vibrator getVibrator() {        synchronized (mMotionRanges) {            if (mVibrator == null) {                if (mHasVibrator) {                    mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);                } else {                    mVibrator = NullVibrator.getInstance();                }            }            return mVibrator;        }    }
所以数组 mInputDeviceVibrators中的元素有两种,都是抽象类Vibrator的子类:
一种是InputDeviceVibrator类,一种就是NullVibrator类了。
先说说InputDeviceVibrator类。
private final class InputDeviceVibrator extends Vibrator {        private final int mDeviceId;        private final Binder mToken;        public InputDeviceVibrator(int deviceId) {            mDeviceId = deviceId;            mToken = new Binder();        }        @Override        public boolean hasVibrator() {            return true;        }        @Override        public void vibrate(long milliseconds) {            vibrate(new long[] { 0, milliseconds}, -1);        }        @Override        public void vibrate(long[] pattern, int repeat) {            if (repeat >= pattern.length) {                throw new ArrayIndexOutOfBoundsException();            }            try {                mIm.vibrate(mDeviceId, pattern, repeat, mToken);            } catch (RemoteException ex) {                Log.w(TAG, "Failed to vibrate.", ex);            }        }        @Override        public void cancel() {            try {                mIm.cancelVibrate(mDeviceId, mToken);            } catch (RemoteException ex) {                Log.w(TAG, "Failed to cancel vibration.", ex);            }        }    }
这里关注public void vibrate(long[] pattern, int repeat)方法,最终调用mIm.vibrate(mDeviceId, pattern, repeat, mToken)。。坑爹的,mIm是个抽象类,又得去找其实例,然后穿越到InputManagerService.java,放看起vibrate方法:
public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {        if (repeat >= pattern.length) {            throw new ArrayIndexOutOfBoundsException();        }        VibratorToken v;        synchronized (mVibratorLock) {            v = mVibratorTokens.get(token);            if (v == null) {                v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);                try {                    token.linkToDeath(v, 0);                } catch (RemoteException ex) {                    // give up                    throw new RuntimeException(ex);                }                mVibratorTokens.put(token, v);            }        }        synchronized (v) {            v.mVibrating = true;            nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);        }    }
这里调用了JNI方法nativeVibrate,同样,InputDeviceVibrator的cancel方法也到了这里:
public void cancelVibrate(int deviceId, IBinder token) {        VibratorToken v;        synchronized (mVibratorLock) {            v = mVibratorTokens.get(token);            if (v == null || v.mDeviceId != deviceId) {                return; // nothing to cancel            }        }        cancelVibrateIfNeeded(v);    }
cancelVibrateIfNeeded方法最终调用nativeCancelVibrate方法。到达JNI层。
|||||||||
再来看看NullVibrator类。。不过既然是Null。。。那就是Null实现。
自此,vibrate跟cancel到达的JNI层的接口是:
private static native void nativeVibrate(int ptr, int deviceId, long[] pattern,            int repeat, int token);    private static native void nativeCancelVibrate(int ptr, int deviceId, int token);
|-------然后是vibratorCount为0的情况,直接调用vibratorOn,cancel同理。
自此,vibrate跟cancel到达的JNI层的接口是:

native static void vibratorOn(long milliseconds);    native static void vibratorOff();



2.JNI层
--对于nativeVibrate/nativeCancelVibrate,其实现位于com_android_server_input_InputManagerService.cpp中.

static void nativeVibrate(JNIEnv* env,        jclass clazz, jint ptr, jint deviceId, jlongArray patternObj,        jint repeat, jint token) {    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);    size_t patternSize = env->GetArrayLength(patternObj);    if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {        ALOGI("Skipped requested vibration because the pattern size is %d "                "which is more than the maximum supported size of %d.",                patternSize, MAX_VIBRATE_PATTERN_SIZE);        return; // limit to reasonable size    }    jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical(            patternObj, NULL));    nsecs_t pattern[patternSize];    for (size_t i = 0; i < patternSize; i++) {        pattern[i] = max(jlong(0), min(patternMillis[i],                MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL)) * 1000000LL;    }    env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);    im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token);}static void nativeCancelVibrate(JNIEnv* env,        jclass clazz, jint ptr, jint deviceId, jint token) {    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);    im->getInputManager()->getReader()->cancelVibrate(deviceId, token);}
-- 对于vibratorOn /vibratorOff,其实现位于com_android_server_VibratorService.cpp中
static JNINativeMethod method_table[] = {    { "vibratorExists", "()Z", (void*)vibratorExists },    { "vibratorOn", "(J)V", (void*)vibratorOn },    { "vibratorOff", "()V", (void*)vibratorOff }};
static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms){    // ALOGI("vibratorOn\n");    vibrator_on(timeout_ms);}static void vibratorOff(JNIEnv *env, jobject clazz){    // ALOGI("vibratorOff\n");    vibrator_off();}

3.HAL层
vib rator_on/vibrator_off的定义位于头文件<hardware_legacy/vibrator.h>(\hardware\libhardware_legacy\include\hardware_legacy\)
/** * Turn on vibrator * * @param timeout_ms number of milliseconds to vibrate * * @return 0 if successful, -1 if error */int vibrator_on(int timeout_ms);/** * Turn off vibrator * * @return 0 if successful, -1 if error */int vibrator_off();
HAL已经完成了实现。
\hardware\libhardware_legacy\vibrator\vibrator.c
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <hardware_legacy/vibrator.h>#include "qemu.h"#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#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){    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);}

这里使用的是Android的timed output机制,通过操纵/sys/class/timed_output/vibrator/enable节点启动或者停止启动器。
4.内核层
先看看timed output的驱动代码,位于Linux_Kernel_3x\drivers\staging\android\下。

#ifndef _LINUX_TIMED_OUTPUT_H#define _LINUX_TIMED_OUTPUT_Hstruct timed_output_dev {const char*name;/* enable the output and set the timer */void(*enable)(struct timed_output_dev *sdev, int timeout);/* returns the current number of milliseconds remaining on the timer */int(*get_time)(struct timed_output_dev *sdev);/* private data */struct device*dev;intindex;intstate;};extern int timed_output_dev_register(struct timed_output_dev *dev);extern void timed_output_dev_unregister(struct timed_output_dev *dev);#endif

所有的timed output实现都需要定义在结构体timed_output_dev中。
Timed Output驱动程序框架将为每个设备在/sys/class/timed_output/目录中建立一个子目录,设备子目录中的enable文件就是设备的控制文件。读enable文件表示获得剩余时间,写这个文件表示根据时间振动。
这个具体情况具体实现,参考:
http://tech.it168.com/a2012/0201/1305/000001305847.shtmlhttp://tech.it168.com/a2012/0201/1305/000001305847.shtml

更多相关文章

  1. Android中使用ViewPage进行广告轮播测试代码
  2. Android Wi-Fi 设置带宽代码流程
  3. Android 获取WIFI MAC地址的方法
  4. Android键盘自适应方法.
  5. Android第一行代码笔记
  6. Android的源代码结构
  7. Android的布局方法
  8. Android开发常用代码片段(二)
  9. 修改android框架代码

随机推荐

  1. Could not get resource 'https://dl.goo
  2. Android:Deprecated Thread methods are
  3. Android(安卓)获得手机屏幕大小
  4. Android_ScrollView
  5. android 跳动频谱 播放器(类似千千静听)
  6. android studio使用android annotations
  7. Android应用程序编译问题
  8. Timer的schedule和scheduleAtFixedRate的
  9. SeekBar 粗略小节
  10. 第一个android程序以及遇到问题解决办法