本文所有源码均是基于安卓8.0进行分析的,安卓12对振动服务做了比较多的变动。
本文适合阅读的人群为:3-5年开发经验,有一定系统源码阅读经历的人。
安卓开发做久了,经常觉得一切都理所当然。这导致我们遇到问题时,不能很理解本质,所以我们很有必要分析系统的源码。
本文侧重调用流程,不侧重具体的实现。
如果读者对硬件实现和粗略流程感兴趣,可以分别读以下两个文章:
粗略流程
硬件实现
Vibrator vibrator = (Vibrator)this.getSystemService(this.VIBRATOR_SERVICE);
vibrator.vibrate(1000);//振动一下
long[] patter = {1000, 1000, 2000, 50};
vibrator.vibrate(patter, 0);//有不同幅度的振动
vibrator.cancel();//取消振动
首先 getSystemService(this.VIBRATOR_SERVICE) 相信各位做了这么久的安卓开发,肯定知道他的内部实实现,所以我就不再赘述。
通过getSystemService,我们把拿到的Object类型强转成了Vibrator。所以接下来我们的目光就放到这个类上面。
Vibrator的包名是android.os.Vibrator
,所以它在安卓源码中的位置是\frameworks\base\core\java\android\os
vibrate方法的源码如下:
public void vibrate(long milliseconds) {
vibrate(milliseconds, null);
}
public void vibrate(long[] pattern, int repeat) {
vibrate(pattern, repeat, null);
}
如果参数只传入long,或者long[],int 实际上会调用另一个方法(不再展示),将他们封装为VibrationEffect,AudioAttributes
并调用此方法:
public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
vibrate(Process.myUid(), mPackageName, vibe, attributes);
}
mPackageName在Vibrator类创建的时候会初始化,获得当前程序的包名
当你尝试跳转四个参数的vibrate时,你会发现它居然是abstract修饰的 !
当年在回头看Vibrator这个类的时候,会发现它居然也是abstract修饰的 !
当你使用Ctrl+Alt+B查看Vibrator的实现时,居然是红色的No Implement Found !
纳尼 难道振动的具体实现是ROM厂商写的吗?
并不是这样
我们之所以产生这样的想法,是因为我们习惯了只是使用AndroidStudio查看开放的源码。但实际上,AOSP中还有很多被@hide修饰的类。
Vibrator根本不是振动的实现,只是一个基类,在其内部只实现了对振动参数的封装。
想要知道它的具体实现,我们可以写如下代码:
Object vibrator = getSystemService(this.VIBRATOR_SERVICE);
Toast.makeText(this, vibrator.getClass().getName(), Toast.LENGTH_SHORT).show();
运行后,发现vibrator 的真身是android.os.SystemVibrator。
这个SystemVibrator是一个被@hide修饰的类,我们无法通过AndroidStudio阅读它。
它的路径为\frameworks\base\core\java\android\os
观察源码,发现这个SystemVibrator也是一个空壳,所有的函数都是通过Aidl和Binder与系统进行交互的。
合情合理,毕竟用户的进程不允许直接与硬件交互,必须通过系统的中转,不然可能会出现恶意的操控。
安卓的系统服务都是通过SystemServer(\frameworks\base\services\java\com\android\server)创建的,然后保存到ServiceManager(\frameworks\base\core\java\android\os)中
在创建服务时,会把服务分为三类Bootstrap,Core,Other。而VibratorService正是属于最后一种。
我们可以在SystemServer中找到如下代码:
private Context mSystemContext;
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
}
private void startOtherServices(){
final Context context = mSystemContext;
VibratorService vibrator = null;
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
try {
vibrator.systemReady();
} catch (Throwable e) {
reportWtf("making Vibrator Service ready", e);
}
}
流程很简单,拿到系统的Context,然后创建VibratorService ,并存入ServiceManager中,最后调用systemRead完成创建。
我们再去VibratorService (\frameworks\base\services\core\java\com\android\server)
native static boolean vibratorExists();//是否存在嵌入式的振动设备
native static void vibratorInit();//初始化硬件
native static void vibratorOn(long milliseconds);//开始振动,并设置持续时长
native static void vibratorOff();//关闭振动
native static boolean vibratorSupportsAmplitudeControl();//是否支持振动强度控制
native static void vibratorSetAmplitude(int amplitude);//设置振动强度
native static long vibratorPerformEffect(long effect, long strength);//effect是系统预设的振动模式,strength是振动模式
VibratorService(Context context) {
vibratorInit();
vibratorOff();
mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
mContext = context;//经过分析,这里传入的Context是SystemContext
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
mWakeLock.setReferenceCounted(true);//通过PM拿到休眠锁,让振动的时候可以在后台运行
mAppOpsService=IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));//权限检查作用
mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect };
}
public void systemReady() {//向ServiceManager添加后会调用此方法
//本质就是监听系统的设置或者振动设备是否有变化,如果有变化就调用updateVibrators
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateVibrators();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
updateVibrators();
}
private void updateVibrators() {//更改锁的状态
synchronized (mLock) {
boolean devicesUpdated = updateInputDeviceVibratorsLocked();
boolean lowPowerModeUpdated = updateLowPowerModeLocked();
if (devicesUpdated || lowPowerModeUpdated) {
doCancelVibrateLocked();
}
}
}
private void doCancelVibrateLocked() {
mH.removeCallbacks(mVibrationEndRunnable);
if (mThread != null) {
mThread.cancel();
mThread = null;
}
doVibratorOff();
reportFinishVibrationLocked();
//解除当前的振动
}
走了这么远,我们再回头看看vibrate方法的具体实现
@Override // 实现了IVibratorService.Stub,所以是Override
public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
IBinder token) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires VIBRATE permission");
}//检查振动权限
if (token == null) {
Slog.e(TAG, "token must not be null");
return;
}//记录每次振动的token,实质上是一个IBinder对象
verifyIncomingUid(uid);//认证id
if (!verifyVibrationEffect(effect)) {//判断振动是否合法
//这个判断实际上是调用effect本身的validate方法
return;
}
//和上一次振动比较
if (effect instanceof VibrationEffect.OneShot
&& mCurrentVibration != null
&& mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) {
VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
VibrationEffect.OneShot currentOneShot =
(VibrationEffect.OneShot) mCurrentVibration.mEffect;
if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
&& newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
if (DEBUG) {
Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration");
}
return;
}
}
Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
//Vibration是VibratiorService的一个内部类,对vibrate方法的参数进行封装
if (effect instanceof VibrationEffect.Waveform) {
try {
token.linkToDeath(vib, 0);//将token和本次振动的生命周期绑定到一起
//这里实际上会调用binderDied
} catch (RemoteException e) {
return;
}
}
long ident = Binder.clearCallingIdentity();//开始锁,并执行振动
try {
synchronized (mLock) {
doCancelVibrateLocked();
startVibrationLocked(vib);//真正执行振动的函数
addToPreviousVibrationsLocked(vib);//把当前的振动数据储存起来
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void verifyIncomingUid(int uid) {//认证id
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);
}
上述代码中,真正使得设备振动的代码在startVibrationLocked中,我们来一窥天机
private void startVibrationLocked(final Vibration vib) {
if (!isAllowedToVibrate(vib))
return;
if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE &&
!shouldVibrateForRingtone()) {
return;
}
final int mode = getAppOpMode(vib);
if (mode != AppOpsManager.MODE_ALLOWED) {
if (mode == AppOpsManager.MODE_ERRORED) {
// We might be getting calls from within system_server, so we don't actually want
// to throw a SecurityException here.
Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
}
return;
}
startVibrationInnerLocked(vib);
}
检查是否可以振动,然后检查权限,再通过startVibrationInnerLocked执行振动再上锁
private void startVibrationInnerLocked(Vibration vib) {
mCurrentVibration = vib;
if (vib.mEffect instanceof VibrationEffect.OneShot) {
VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect;
doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint);
mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming());//1
} else if (vib.mEffect instanceof VibrationEffect.Waveform) {
VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect;
mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint);
mThread.start();
} else if (vib.mEffect instanceof VibrationEffect.Prebaked) {
long timeout = doVibratorPrebakedEffectLocked(vib);
if (timeout > 0) {
mH.postDelayed(mVibrationEndRunnable, timeout);//2
}
}
//因为Waveform 是一种长时间,强度多次变化的,所以使用线程振动
}
留意一下注释1,2.我们在分析doVibratorOn后会分析
我们先来看一下doVibratorOn,他是核心振动方法
private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) {
synchronized (mInputDeviceVibrators) {//对当前振动设备加锁
if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
amplitude = mDefaultVibrationAmplitude;
}
final int vibratorCount = mInputDeviceVibrators.size();
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);
//mInputDeviceVibrators存放的是Vibrator,最终仍然会走这个doVibratorOn方法,并且所有振动设备都持有锁
}
} else {//调用native方法设置振动并设置强度。
//安卓源码在这里有一个贴心提示,让先开启振动,再设置强度,这个排序很重要
vibratorOn(millis);
doVibratorSetAmplitude(amplitude);
}
}
}
private void doVibratorSetAmplitude(int amplitude) {
if (mSupportsAmplitudeControl) {
vibratorSetAmplitude(amplitude);
}
}
在回头看注释1,2。其中的mVibrationEndRunnable
,会在振动结束后(通过postDaly实现)异步调用onVibrationFinished
public void onVibrationFinished() {
synchronized (mLock) {
doCancelVibrateLocked();//这个方法我们已经在前面介绍过,不再赘述
}
}
注意一下,我们在vibrate方法中,对振动对象绑定了振动的生命周期,所以会在结束时调用Vibration对象(实现了IBinder.DeathRecipient接口)的binderDied
public void binderDied() {
synchronized (mLock) {
if (this == mCurrentVibration) {
doCancelVibrateLocked();
}
}
}//即使postDaly出现了问题,也能在振动超时的时候停止
以上我们已经分析了onShot振动的实现,现在我们来看看Wave的实现
Wave振动是开启了一个类型为VibrateThread的线程,代码如下:
private class VibrateThread extends Thread {
private final VibrationEffect.Waveform mWaveform;
private final int mUid;
private final int mUsageHint;
private boolean mForceStop;
VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) {
mWaveform = waveform;
mUid = uid;
mUsageHint = usageHint;
}
private long delayLocked(long duration) {//延时的实现
long durationRemaining = duration;
if (duration > 0) {
final long bedtime = duration + SystemClock.uptimeMillis();
do {
try {
this.wait(durationRemaining);
}
catch (InterruptedException e) { }
if (mForceStop) {
break;
}
durationRemaining = bedtime - SystemClock.uptimeMillis();
} while (durationRemaining > 0);
return duration - durationRemaining;
}
return 0;
}
public void run() {
mWakeLock.acquire();//拿到唤醒锁
try {
boolean finished = playWaveform();//阻塞式实现振动
if (finished) {
onVibrationFinished();
}
} finally {
mWakeLock.release();
}
}
public boolean playWaveform() {
synchronized (this) {
final long[] timings = mWaveform.getTimings();
final int[] amplitudes = mWaveform.getAmplitudes();
final int len = timings.length;
final int repeat = mWaveform.getRepeatIndex();
int index = 0;
long onDuration = 0;
while (!mForceStop) {
if (index < len) {
final int amplitude = amplitudes[index];
final long duration = timings[index++];
if (duration <= 0) {
continue;
}
if (amplitude != 0) {
if (onDuration <= 0) {
onDuration =
getTotalOnDuration(timings, amplitudes, index - 1, repeat);
doVibratorOn(onDuration, amplitude, mUid, mUsageHint);
} else {
doVibratorSetAmplitude(amplitude);
}
}
long waitTime = delayLocked(duration);
if (amplitude != 0) {
onDuration -= waitTime;
}
} else if (repeat < 0) {
break;
} else {
index = repeat;
}
}
return !mForceStop;
}
}
public void cancel() {//强制取消
//doCancelVibrateLocked方法中会调用
synchronized (this) {
mThread.mForceStop = true;
mThread.notify();
}
}
private long getTotalOnDuration(//获得总时长
long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
int i = startIndex;
long timing = 0;
while(amplitudes[i] != 0) {
timing += timings[i++];
if (i >= timings.length) {
if (repeatIndex >= 0) {
i = repeatIndex;
} else {
break;
}
}
if (i == startIndex) {
return 1000;
}
}
return timing;
}
}
实质上振动的实现还是native方法doVibratorOn
与doVibratorSetAmplitude
我们再简单分析一下硬件层
首先设备的载入在server.cpp(\device\google\marlin\vibrator)中
核心代码如下
static const char *ENABLE_PATH = "/sys/class/timed_output/vibrator/enable";
static const char *AMPLITUDE_PATH = "/sys/class/timed_output/vibrator/voltage_level";
status_t registerVibratorService() {
std::ofstream enable{ENABLE_PATH};
if (!enable) {
int error = errno;
ALOGE("Failed to open %s (%d): %s", ENABLE_PATH, error, strerror(error));
return -error;
}
std::ofstream amplitude{AMPLITUDE_PATH};
if (!amplitude) {
int error = errno;
ALOGE("Failed to open %s (%d): %s", AMPLITUDE_PATH, error, strerror(error));
return -error;
}
sp<IVibrator> vibrator = new Vibrator(std::move(enable), std::move(amplitude));
vibrator->registerAsService();
return OK;
}
int main() {
configureRpcThreadpool(1, true);
status_t status = registerVibratorService();
if (status != OK) {
return status;
}
joinRpcThreadpool();
}
振动设备的配置信息在Vibrator.cpp(\device\google\marlin\vibrator)
代码如下
//振动器的强度通过电压控制
static constexpr int MAX_VOLTAGE = 3596;//最大电压
static constexpr int MIN_VOLTAGE = 116;//最小电压
static constexpr uint32_t CLICK_TIMING_MS = 20;//单位持续时长
Vibrator::Vibrator(std::ofstream&& enable, std::ofstream&& amplitude) :
mEnable(std::move(enable)),
mAmplitude(std::move(amplitude)) {}
Return<Status> Vibrator::on(uint32_t timeout_ms) {
mEnable << timeout_ms << std::endl;
if (!mEnable) {
ALOGE("Failed to turn vibrator on (%d): %s", errno, strerror(errno));
return Status::UNKNOWN_ERROR;
}
return Status::OK;
}
Return<Status> Vibrator::off() {
mEnable << 0 << std::endl;
if (!mEnable) {
ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
return Status::UNKNOWN_ERROR;
}
return Status::OK;
}
Return<bool> Vibrator::supportsAmplitudeControl() {
return true;
}
Return<Status> Vibrator::setAmplitude(uint8_t amplitude) {
if (amplitude == 0) {
return Status::BAD_VALUE;
}
long voltage =
std::lround((amplitude - 1) / 254.0 * (MAX_VOLTAGE - MIN_VOLTAGE) + MIN_VOLTAGE);
ALOGE("Setting amplitude to: %ld", voltage);
mAmplitude << voltage << std::endl;
if (!mAmplitude) {
ALOGE("Failed to set amplitude (%d): %s", errno, strerror(errno));
return Status::UNKNOWN_ERROR;
}
return Status::OK;
}
Return<void> Vibrator::perform(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {//系统预设的振动
if (effect == Effect::CLICK) {
uint8_t amplitude;
switch (strength) {
case EffectStrength::LIGHT:
amplitude = 36;
break;
case EffectStrength::MEDIUM:
amplitude = 128;
break;
case EffectStrength::STRONG:
amplitude = 255;
break;
default:
_hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
return Void();
}
on(CLICK_TIMING_MS);
setAmplitude(amplitude);
_hidl_cb(Status::OK, CLICK_TIMING_MS);
} else {
_hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
}
return Void();
}
振动的HAL层实现在Vibrator.cpp(\hardware\interfaces\vibrator\1.0\default)
就不贴代码了,因为厂商的实现都不一样的。
至此,振动服务的调用已经从Java API层到HAL层,我们来做一个总结。
首先系统在启动时,通过ZygoteInit中handleSystemServerProcess函数的最后一步,调用SystemServer的静态函数main方法。
在SystemServer的main函数中,根据service的类型分三类进行服务加载,振动服务属于Other类。
创建了VibratorService对象后,将其加入到系统服务map中。
在VibratorService中调用native方法vibratorInit,初始化硬件振动器。至此系统振动服务加载完成。
开发者通过getSystemService拿到SystemVibrator ,SystemVibrator继承自Vibrator,内部实现了对振动参数的检验和封装。
开发者调用vibrate方法,SystemVibrator将参数封装,并通过Binder与系统振动服务进行通信。
系统振动服务最终调用native的doVibratorOn与doVibratorSetAmplitude操控硬件。通过加锁和Handler的postDaly实现结束时监听。
doVibratorOn与doVibratorSetAmplitude会调用厂商封装好的HAL层操作硬件设备。