近日,谷歌在一份提交给法庭的文件中称,iPhone 和 iPad 可以有不同的默认搜索引擎,试图捍卫其与苹果公司每年高达 200 亿美元的合作协议。这项合作正面临被法院禁止的风险,谷歌正积极提出一系列反制方案。本篇文章转自FerdinandHu的博客,文章主要分享了手机振动从应用层到硬件抽象层的代码,相信会对大家有所帮助!https://juejin.cn/post/7451418558770626595
在 Android 系统中,“振动”功能是应用层进行操作,传递到系统的 HAL 层,最终接通硬件驱动器实现。本文将基于Android14源码分析振动功能的全过程。本文主要想通过振动器的on函数将整个调用链串联起来,中间Framework层分析冗长且不够完善。如果想快速建立起框架概念,可直接看章节-分析验证。整个过程旨在记录分析过程,难免会有理解不到位的地方,感谢指正请多多包涵。在应用层,我们通过android.os.Vibrator和android.os.VibratorManager类调用振动功能,示例代码如下:Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator != null && vibrator.hasVibrator()) {
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
}
android.os.VibratorManagerVibratorManager vibratorManager = (VibratorManager) context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
if (vibratorManager != null) {
Vibrator vibrator = vibratorManager.getDefaultVibrator();
if (vibrator.hasVibrator()) {
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
}
}
由于前面这种方法渐渐的被弃用,本文主要通过下面这种方法来继续往下分析。应用层代码中是通过 context.getSystemService函数获取到VibratorManager类的。该函数的具体实现在ContextImpl.java中:public Object getSystemService(String name) {
if (vmIncorrectContextUseEnabled()) {
// Check incorrect Context usage.
if (WINDOW_SERVICE.equals(name) && !isUiContext()) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
+ " from a non-visual Context:" + getOuterContext();
final String message = "WindowManager should be accessed from Activity or other "
+ "visual Context. Use an Activity or a Context created with "
+ "Context#createWindowContext(int, Bundle), which are adjusted to "
+ "the configuration and visual bounds of an area on screen.";
final Exception exception = new IllegalAccessException(errorMessage);
StrictMode.onIncorrectContextUsed(message, exception);
Log.e(TAG, errorMessage + " " + message, exception);
}
}
return SystemServiceRegistry.getSystemService(this, name);
}
这段代码不用细看,直接看return,它指向了SystemServiceRegistry类的getSystemService函数。在SystemServiceRegistry.java中找到它:public static Object getSystemService(ContextImpl ctx, String name) {
if (name == null) {
return null;
}
// SYSTEM_SERVICE_FETCHERS是一个HashMap,它存储着
// 通过name找到对应服务的fetcher
final ServiceFetcher> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
if (fetcher == null) {
if (sEnableServiceNotFoundWtf) {
Slog.wtf(TAG, "Unknown manager requested: " + name);
}
return null;
}
// 通过fetcher找到对应的服务
final Object ret = fetcher.getService(ctx);
if (sEnableServiceNotFoundWtf && ret == null) {
// Some services do return null in certain situations, so don't do WTF for them.
switch (name) {
case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
case Context.APP_PREDICTION_SERVICE:
case Context.INCREMENTAL_SERVICE:
case Context.ETHERNET_SERVICE:
case Context.CONTEXTHUB_SERVICE:
case Context.VIRTUALIZATION_SERVICE:
case Context.VIRTUAL_DEVICE_SERVICE:
return null;
}
Slog.wtf(TAG, "Manager wrapper not available: " + name);
return null;
}
return ret;
}
这段代码首先通过name在哈希表SYSTEM_SERVICE_FETCHERS中找到对应的fetcher,然后通过fetcher获取到对应的服务。通过寻找SYSTEM_SERVICE_FETCHERS的使用者,找到了registerService函数,最后找到VIBRATOR_MANAGER_SERVICE服务注册的地方。registerService(Context.VIBRATOR_MANAGER_SERVICE, VibratorManager.class,
new CachedServiceFetcher<VibratorManager>() {
@Override
public VibratorManager createService(ContextImpl ctx) {
return new SystemVibratorManager(ctx);
}});
这个registerService函数的内部实现是:private static void registerService(@NonNull String serviceName,
@NonNull Class serviceClass, @NonNull ServiceFetcher serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}
从这两个函数可以知道,在注册振动器服务时,SYSTEM_SERVICE_FETCHERS表中插入的fetcher是CachedServiceFetcher类,并且这个类重写了createService函数,它返回的是SystemVibratorManager类。那让我们看看CachedServiceFetcher类的getService函数的实现:public final T getService(ContextImpl ctx) {
// 记录一个java和cpp的不同,这里的cache和gates实际上是引用类型,java中默认数组和对象是引用传递,所以对cache和gates的修改会反应到ctx.mServiceCache和ctx.mServiceInitializationStateArray中。
// 服务对象的缓存数组,每种服务在特定索引(mCacheIndex)存储对应实例
final Object[] cache = ctx.mServiceCache;
// 缓存状态数组,记录每个服务的初始化状态,可能取值:
// STATE_UNINITIALIZED:服务未初始化。
// STATE_INITIALIZING:服务正在初始化。
// STATE_READY:服务已初始化。
// STATE_NOT_FOUND:服务不可用(例如设备不支持)。
final int[] gates = ctx.mServiceInitializationStateArray;
boolean interrupted = false;
T ret = null;
for (;;) {
boolean doInitialize = false;
synchronized (cache) {
// 缓存中存在服务实例,直接返回
T service = (T) cache[mCacheIndex];
if (service != null) {
ret = service;
break; // exit the for (;;)
}
// 检查并更新服务状态
if (gates[mCacheIndex] == ContextImpl.STATE_READY
|| gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
}
// 如果服务未初始化,设置状态为 INITIALIZING,doInitialize为true
if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
doInitialize = true;
gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
}
}
// 第一次初始化服务进入
if (doInitialize) {
T service = null;
@ServiceInitializationState
int newState = ContextImpl.STATE_NOT_FOUND;
try {
// 通过重写的createService函数来获取服务
service = createService(ctx);
newState = ContextImpl.STATE_READY;
} catch (ServiceNotFoundException e) {
onServiceNotFound(e);
} finally {
// 缓存服务对象,更新服务状态
synchronized (cache) {
cache[mCacheIndex] = service;
gates[mCacheIndex] = newState;
cache.notifyAll();
}
}
ret = service;
break; // exit the for (;;)
}
// The other threads will wait for the first thread to call notifyAll(),
// and go back to the top and retry.
synchronized (cache) {
// 非初始化线程会在此等待,直到服务状态变为STATE_READY或STATE_NOT_FOUND状态
while (gates[mCacheIndex] try {
// Clear the interrupt state.
interrupted |= Thread.interrupted();
cache.wait();
} catch (InterruptedException e) {
Slog.w(TAG, "getService() interrupted");
interrupted = true;
}
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
return ret;
}
- 多线程安全:通过 cache 锁和状态数组 gates,确保多个线程不会同时初始化服务。因为 Android 系统服务是全局性的,可能被应用程序或系统内部多个线程同时访问。
- 延迟初始化:它的意思是仅在服务首次请求时调用createService函数来创建对应的服务,这样在没有使用到该服务的情况下不会创建对应的服务对象。
- 缓存服务实例:通过cache数组缓存服务实例,减少重复创建,提高性能。
所以最终在App应用层中使用context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE)函数返回的对象实例是SystemVibratorManager。下面继续分析SystemVibratorManager类:Framework 层:SystemVibratorManager和VibratorManagerServiceSystemVibratorManager类继承自VibratorManager,应用层通过它与系统服务VibratorManagerService通信。它的构造函数如下:public SystemVibratorManager(Context context) {
super(context);
mContext = context;
mService = IVibratorManagerService.Stub.asInterface(
ServiceManager.getService(Context.VIBRATOR_MANAGER_SERVICE));
}
其中ServiceManager.getService(Context.VIBRATOR_MANAGER_SERVICE)函数会在ServiceManager中的缓存sCache查询对应的IBinder,sCache的类型是Map。函数具体实现如下:public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(rawGetService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
拿到对应的IBinder就会通过振动器接口类IVibratorManagerService将其转换成具体的接口实例,下面是IVibratorManagerService.Stub.asInterface函数的代码:public static IVibratorManagerService asInterface(IBinder obj) {
if (obj == null) {
return null;
} else {
IInterface iin = obj.queryLocalInterface("android.os.IVibratorManagerService");
return (IVibratorManagerService)(iin != null && iin instanceof IVibratorManagerService ? (IVibratorManagerService)iin : new Proxy(obj));
}
}
这段代码说明首先会使用obj.queryLocalInterface("android.os.IVibratorManagerService")来尝试获取本地接口实例。如果本地没有接口实现,则创建一个代理对象Proxy。Proxy 是远程代理的实现,它可以通过底层的 IBinder 与远程进程进行通信。下面是Proxy的部分代码:private static class Proxy implements IVibratorManagerService {
private IBinder mRemote;
Proxy(IBinder remote) {
this.mRemote = remote;
}
public IBinder asBinder() {
return this.mRemote;
}
public String getInterfaceDescriptor() {
return "android.os.IVibratorManagerService";
}
...
}
从上面的分析中总结一下:SystemVibratorManager类内部有一个变量mService,它指向的其实是一个继承自IVibratorManagerService的Proxy实例。这个Proxy内部有一个VibratorManagerService对应的IBinder对象,通过它来实现跨进程通信,以此完成远程调用。从而实现在App的进程内完成对system_server进程内的振动器服务。下面将重点介绍system_server进程中的VibratorManagerService类,它是实现振动器功能和提供振动器服务的关键类。- VibratorManagerService类的注册与初始化
VibratorManagerService服务被注册的位置位于SystemServer.java中startOtherServices函数中,大部分服务的注册也是在这个地方。下面是VibratorManagerService被注册的代码:t.traceBegin("StartVibratorManagerService");
mSystemServiceManager.startService(VibratorManagerService.Lifecycle.class);
t.traceEnd();
SystemServiceManager的startServie函数的具体实现如下:public T startService(Class serviceClass) {
try {
final String name = serviceClass.getName();
Slog.i(TAG, "Starting " + name);
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
// Create the service.
if (!SystemService.class.isAssignableFrom(serviceClass)) {
throw new RuntimeException("Failed to create " + name
+ ": service must extend " + SystemService.class.getName());
}
final T service;
try {
Constructor constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service could not be instantiated", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service must have a public constructor with a Context argument", ex);
} catch (NoSuchMethodException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service must have a public constructor with a Context argument", ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service constructor threw an exception", ex);
}
startService(service);
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
这段代码运用了反射机制,通过传入VibratorManagerService.Lifecycle.class对象,动态创建服务实例VibratorManagerService.Lifecycle类,这个类是VibratorManagerService类内部专门用来管理生命周期的。最后再次通过内部函数startService来注册和开启服务,下面继续看startService函数的具体实现:public void startService(@NonNull final SystemService service) {
// Check if already started
String className = service.getClass().getName();
if (mServiceClassnames.contains(className)) {
Slog.i(TAG, "Not starting an already started service " + className);
return;
}
mServiceClassnames.add(className);
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
try {
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
这段代码就是将服务注册,使用数组mServiceClassnames和mServices保存服务的信息,最后会调用被注册服务本身的onStart()函数完成初始化工作。VibratorManagerService的onStart()函数实现如下:public void onStart() {
mService = new VibratorManagerService(getContext(), new Injector());
publishBinderService(Context.VIBRATOR_MANAGER_SERVICE, mService);
}
初始化的过程就是 new 一个VibratorManagerService类,然后通过Binder服务真正完成服务的注册过程。这里就不具体分析Binder注册服务的过程了。这里总结一下:上面这部分过程完成了VibratorManagerService类的初始化过程。其他的服务类初始化过程和它类似,下面重点关注VibratorManagerService类的功能实现。vibrate函数是VibratorManagerService类的最主要的功能。这里解释一下,虽然我们App层具体使用vibrate函数实现振动效果时调用的是SystemVibrator类的vibrate函数,但在其内部最终还是调用的SystemVibratorManager的vibrate函数,而SystemVibratorManager是通过Binder通信调用VibratorManagerService服务来实现的。下面代码展现了这一点,SystemVibrator内部有一个SystemVibratorManager类。public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect,
String reason, @NonNull VibrationAttributes attributes) {
if (mVibratorManager == null) {
Log.w(TAG, "Failed to vibrate; no vibrator manager.");
return;
}
CombinedVibration combinedEffect = CombinedVibration.createParallel(effect);
mVibratorManager.vibrate(uid, opPkg, combinedEffect, reason, attributes);
}
所以我们只需要分析VibratorManagerService类的vibrate函数实现即可。下面是vibrate函数的代码:public void vibrate(int uid, int displayId, String opPkg, @NonNull CombinedVibration effect,
@Nullable VibrationAttributes attrs, String reason, IBinder token) {
vibrateInternal(uid, displayId, opPkg, effect, attrs, reason, token);
}
vibrate函数内部转而使用vibrateInternal函数来完成具体功能,那我们继续看vibrateInternal函数:HalVibration vibrateInternal(int uid, int displayId, String opPkg,
@NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
try {
// 首先进行振动权限检查,确保调用者具备`android.permission.VIBRATE`权限
// 这也提示我们,在app开发过程中要通过Manifest文件声明vibrate权限
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.VIBRATE, "vibrate");
// 然后进行一些基本参数的检查
if (token == null) {
Slog.e(TAG, "token must not be null");
return null;
}
enforceUpdateAppOpsStatsPermission(uid);
if (!isEffectValid(effect)) {
return null;
}
// 修正或补全VibrationAttributes
attrs = fixupVibrationAttributes(attrs, effect);
// 创建HalVibration实例,封装振动请求及相关信息(如调用者信息CallerInfo)
HalVibration vib = new HalVibration(token, effect,
new Vibration.CallerInfo(attrs, uid, displayId, opPkg, reason));
fillVibrationFallbacks(vib, effect);
// 检查是否需要更新用户设置缓存
if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
mVibrationSettings.mSettingObserver.onChange(false);
}
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "Starting vibrate for vibration " + vib.id);
}
// 调用 shouldIgnoreVibrationLocked 检查是否由于用户设置或 DND 模式而忽略此次振动请求
Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo);
// 调用 shouldIgnoreVibrationForOngoingLocked 判断当前是否有更重要的振动任务正在执行
if (vibrationEndInfo == null) {
vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vib);
}
// 如果不需要忽略振动则开始启动振动
if (vibrationEndInfo == null) {
final long ident = Binder.clearCallingIdentity();
try {
// 当前有外部振动请求,优先结束外部振动
if (mCurrentExternalVibration != null) {
mCurrentExternalVibration.mute();
vib.stats.reportInterruptedAnotherVibration(
mCurrentExternalVibration.callerInfo);
endExternalVibrateLocked(
new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
vib.callerInfo),
/* continueExternalControl= */ false);
} else if (mCurrentVibration != null) {
// 当前有内部振动请求,检查是否可以与新振动并行
if (mCurrentVibration.getVibration().canPipelineWith(vib)) {
// 如果可以并行,直接加入管道
if (DEBUG) {
Slog.d(TAG, "Pipelining vibration " + vib.id);
}
} else {
// 如果不可以并行,取消当前振动
vib.stats.reportInterruptedAnotherVibration(
mCurrentVibration.getVibration().callerInfo);
mCurrentVibration.notifyCancelled(
new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
vib.callerInfo),
/* immediate= */ false);
}
}
// 启动新振动请求
vibrationEndInfo = startVibrationLocked(vib);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
// 如果振动请求被忽略或启动失败,调用 endVibrationLocked 处理失败状态,并记录统计信息。
if (vibrationEndInfo != null) {
endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ true);
}
return vib;
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
- 权限和参数校验:确保调用者具有合法权限,检查振动参数是否有效。
- 振动请求初始化:创建 HalVibration 实例,封装请求参数。
- 检查冲突与条件:判断用户设置、DND 模式或是否有更高优先级的振动请求。
- 执行或取消振动:根据条件选择启动新振动、并行执行或取消当前振动。
可以知道,我们接下来需要重点关心的是HalVibration 实例和 startVibrationLocked函数。下面是startVibrationLocked函数的具体实现:private Vibration.EndInfo startVibrationLocked(HalVibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
try {
// 通过 mVibrationScaler 对振动效果(VibrationEffect)进行缩放调整
// 不同的使用场景(attrs.getUsage)可能需要不同的振动强度或持续时间。例如,通知振动和触觉反馈的需求不同。
vib.updateEffects(
effect -> mVibrationScaler.scale(effect, vib.callerInfo.attrs.getUsage()));
// 检查当前振动是否可以直接交给输入设备(如手柄或外设)处理
boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable(
vib.callerInfo, vib.getEffect());
if (inputDevicesAvailable) {
return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES);
}
// 创建振动调度器VibrationStepConductor, 这是振动请求的具体执行者
VibrationStepConductor conductor = new VibrationStepConductor(vib, mVibrationSettings,
mDeviceVibrationEffectAdapter, mVibrators, mVibrationThreadCallbacks);
// 如果当前没有正在执行的振动,则直接启动新的振动
if (mCurrentVibration == null) {
return startVibrationOnThreadLocked(conductor);
}
// 如果当前有正在执行的振动,将等待中的振动请求清楚
// 将当前请求设置为 mNextVibration,在正在执行的振动结束后再执行该请求。
clearNextVibrationLocked(
new Vibration.EndInfo(Vibration.Status.IGNORED_SUPERSEDED, vib.callerInfo));
mNextVibration = conductor;
return null;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
startVibrationLocked 是振动请求处理的核心方法,负责协调硬件资源、动态调整振动效果并处理振动冲突。其中将HalVibration数据进一步封装成VibrationStepConductor,用于表示振动请求。最终会通过startVibrationOnThreadLocked函数执行这次新的振动请求。下面继续分析startVibrationOnThreadLocked函数:private Vibration.EndInfo startVibrationOnThreadLocked(VibrationStepConductor conductor) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationThreadLocked");
try {
HalVibration vib = conductor.getVibration();
int mode = startAppOpModeLocked(vib.callerInfo);
// 判断应用程序是否有权限启动振动
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
// 在振动线程中执行振动操作
mCurrentVibration = conductor;
if (!mVibrationThread.runVibrationOnVibrationThread(mCurrentVibration)) {
mCurrentVibration = null; // Aborted.
return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_SCHEDULING);
}
return null;
case AppOpsManager.MODE_ERRORED:
Slog.w(TAG, "Start AppOpsManager operation errored for uid "
+ vib.callerInfo.uid);
return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_APP_OPS);
default:
return new Vibration.EndInfo(Vibration.Status.IGNORED_APP_OPS);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
startVibrationOnThreadLocked() 其实就是将振动操作交给振动线程去操作。我们继续看看振动线程是如何执行振动操作的。VibrationThread类是具体执行振动功能的线程类。 boolean runVibrationOnVibrationThread(VibrationStepConductor conductor) {
synchronized (mLock) {
if (mRequestedActiveConductor != null) {
Slog.wtf(TAG, "Attempt to start vibration when one already running");
return false;
}
// 唤醒工作线程,进入run函数
mRequestedActiveConductor = conductor;
mLock.notifyAll();
}
return true;
}
@Override
public void run() {
// 设置线程优先级
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
while (true) {
// waitForVibrationRequest等待振动请求,直到有新的振动请求进来并被唤醒
mExecutingConductor = Objects.requireNonNull(waitForVibrationRequest());
// 一旦获得一个振动控制器mExecutingConductor,则通过 runCurrentVibrationWithWakeLock() 来执行振动操作,确保执行期间不会被系统休眠。
mCalledVibrationCompleteCallback = false;
runCurrentVibrationWithWakeLock();
// 如果当前振动操作没有正常完成
if (!mExecutingConductor.isFinished()) {
Slog.wtf(TAG, "VibrationThread terminated with unfinished vibration");
}
// 表示当前振动操作已完成,可以开始下一个振动请求
synchronized (mLock) {
mRequestedActiveConductor = null;
}
// 通知外部(如钩子函数),当前的振动线程已释放,可以进行资源清理或其他操作。
mVibratorManagerHooks.onVibrationThreadReleased(
mExecutingConductor.getVibration().id);
synchronized (mLock) {
mLock.notifyAll();
}
mExecutingConductor = null;
}
}
runVibrationOnVibrationThread函数主要用于唤醒振动线程,从而使得振动线程从wait过程中唤醒过来,随后根据新的振动控制器mExecutingConductor来执行振动操作,最后通过runCurrentVibrationWithWakeLock来完成具体操作。下面继续分析runCurrentVibrationWithWakeLock函数:private void runCurrentVibrationWithWakeLock() {
// 创建WorkSource对象,WorkSource 用于标识正在执行的任务来源
// 通常用于电池和功耗的管理
WorkSource workSource = new WorkSource(
mExecutingConductor.getVibration().callerInfo.uid);
// mWakeLock用于防止设备进入休眠状态,确保振动任务在执行时设备不被休眠
mWakeLock.setWorkSource(workSource);
mWakeLock.acquire();
// 执行振动任务
try {
try {
runCurrentVibrationWithWakeLockAndDeathLink();
} finally {
clientVibrationCompleteIfNotAlready(
new Vibration.EndInfo(Vibration.Status.FINISHED_UNEXPECTED));
}
} finally {
mWakeLock.release();
mWakeLock.setWorkSource(null);
}
}
runCurrentVibrationWithWakeLock函数的主要任务是确保任务在设备的休眠管理中能正常进行。接下来继续分析runCurrentVibrationWithWakeLockAndDeathLink函数:private void runCurrentVibrationWithWakeLockAndDeathLink() {
// 获取当前振动任务的IBinder对象,由调用者提供
IBinder vibrationBinderToken = mExecutingConductor.getVibration().callerToken;
// 链接到调用者的Binder生命周期
try {
vibrationBinderToken.linkToDeath(mExecutingConductor, 0);
} catch (RemoteException e) {
Slog.e(TAG, "Error linking vibration to token death", e);
clientVibrationCompleteIfNotAlready(
new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_TOKEN));
return;
}
try {
// 执行振动任务
playVibration();
} finally {
// 取消与调用者Binder的生命周期绑定
try {
vibrationBinderToken.unlinkToDeath(mExecutingConductor, 0);
} catch (NoSuchElementException e) {
Slog.wtf(TAG, "Failed to unlink token", e);
}
}
}
runCurrentVibrationWithWakeLockAndDeathLink函数的主要作用是将振动任务与调用者的生命周期绑定。如果调用者进程死亡,会自动终止振动任务,避免僵尸任务。下面继续分析playVibration()函数:private void playVibration() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "playVibration");
try {
// 准备振动任务
mExecutingConductor.prepareToStart();
// 精准控制振动时序
while (!mExecutingConductor.isFinished()) {
boolean readyToRun = mExecutingConductor.waitUntilNextStepIsDue();
if (readyToRun) {
// 执行下一个步骤
mExecutingConductor.runNextStep();
}
// 处理振动完成后的回调和清理工作
if (!mCalledVibrationCompleteCallback) {
Vibration.EndInfo vibrationEndInfo = mExecutingConductor.calculateVibrationEndInfo();
if (vibrationEndInfo != null) {
clientVibrationCompleteIfNotAlready(vibrationEndInfo);
}
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
playVibration() 是一个负责管理振动任务的完整执行过程的方法,具体的执行过程还得看VibrationStepConductor类的runNextStep函数。VibrationStepConductor 是 Android 振动框架中的一个关键类,用于管理振动操作的逻辑执行。它负责将振动请求分解为多个步骤(Step),并按顺序执行这些步骤,确保振动按预期的效果运行。public void runNextStep() {
if (Build.IS_DEBUGGABLE) {
expectIsVibrationThread(true);
}
// 在这里获取下一步振动操作
Step nextStep = pollNext();
if (nextStep != null) {
// 输出调试日志,记录当前执行的振动步骤
if (DEBUG) {
Slog.d(TAG, "Playing vibration id " + getVibration().id
+ ((nextStep instanceof AbstractVibratorStep)
? " on vibrator " + ((AbstractVibratorStep) nextStep).getVibratorId() : "")
+ " " + nextStep.getClass().getSimpleName()
+ (nextStep.isCleanUp() ? " (cleanup)" : ""));
}
// 执行当前步骤
List nextSteps = nextStep.play();
// 更新步骤状态信息
if (nextStep.getVibratorOnDuration() > 0) {
mSuccessfulVibratorOnSteps++;
}
if (nextStep instanceof StartSequentialEffectStep) {
mRemainingStartSequentialEffectSteps--;
}
if (!nextStep.isCleanUp()) {
mPendingVibrateSteps--;
}
for (int i = 0; i mPendingVibrateSteps += nextSteps.get(i).isCleanUp() ? 0 : 1;
}
mNextSteps.addAll(nextSteps);
}
}
这里的nextStep实际上是在playVibration()函数中mExecutingConductor.prepareToStart()生成的,它指向了StartSequentialEffectStep类(继承自Step类),因此我们接下来关注StartSequentialEffectStep类的play()函数StartSequentialEffectStep类public List play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "StartSequentialEffectStep");
List nextSteps = new ArrayList<>();
mVibratorsOnMaxDuration = -1;
try {
if (VibrationThread.DEBUG) {
Slog.d(VibrationThread.TAG,
"StartSequentialEffectStep for effect #" + currentIndex);
}
// 使用 currentIndex 获取当前的振动效果 (sequentialEffect.getEffects() 返回的列表中的一项)。
// 尝试将当前效果映射到振动器上
CombinedVibration effect = sequentialEffect.getEffects().get(currentIndex);
DeviceEffectMap effectMapping = createEffectToVibratorMapping(effect);
if (effectMapping == null) {
// Unable to map effects to vibrators, ignore this step.
return nextSteps;
}
// 调用 startVibrating 方法开始振动,并返回振动的最大持续时间
mVibratorsOnMaxDuration = startVibrating(effectMapping, nextSteps);
conductor.vibratorManagerHooks.noteVibratorOn(
conductor.getVibration().callerInfo.uid, mVibratorsOnMaxDuration);
} finally {
if (mVibratorsOnMaxDuration >= 0) {
// 振动持续时间大于0,则代表启动振动器成功
Step nextStep =
mVibratorsOnMaxDuration > 0 ? new FinishSequentialEffectStep(this)
: nextStep();
if (nextStep != null) {
nextSteps.add(nextStep);
}
}
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
return nextSteps;
}
private long startVibrating(
DeviceEffectMap effectMapping, List nextSteps) {
// 通过effectMapping检查是否有振动器被映射
int vibratorCount = effectMapping.size();
if (vibratorCount == 0) {
// No effect was mapped to any available vibrator.
return 0;
}
// 根据映射的振动器数量,创建相应数量的振动步骤 (steps)。每个振动器对应一个振动步骤,通过 conductor.nextVibrateStep 方法设置振动的具体行为。
AbstractVibratorStep[] steps = new AbstractVibratorStep[vibratorCount];
long vibrationStartTime = SystemClock.uptimeMillis();
for (int i = 0; i steps[i] = conductor.nextVibrateStep(vibrationStartTime,
conductor.getVibrators().get(effectMapping.vibratorIdAt(i)),
effectMapping.effectAt(i),
/* segmentIndex= */ 0, /* vibratorOffTimeout= */ 0);
}
// 如果只有一个振动器
if (steps.length == 1) {
// No need to prepare and trigger sync effects on a single vibrator.
return startVibrating(steps[0], nextSteps);
}
// 对于多个振动器进行同步处理
boolean hasPrepared = false;
boolean hasTriggered = false;
boolean hasFailed = false;
long maxDuration = 0;
hasPrepared = conductor.vibratorManagerHooks.prepareSyncedVibration(
effectMapping.getRequiredSyncCapabilities(),
effectMapping.getVibratorIds());
for (AbstractVibratorStep step : steps) {
long duration = startVibrating(step, nextSteps);
if (duration 0) {
// One vibrator has failed, fail this entire sync attempt.
hasFailed = true;
break;
}
maxDuration = Math.max(maxDuration, duration);
}
// Check if sync was prepared and if any step was accepted by a vibrator,
// otherwise there is nothing to trigger here.
if (hasPrepared && !hasFailed && maxDuration > 0) {
hasTriggered = conductor.vibratorManagerHooks.triggerSyncedVibration(
getVibration().id);
hasFailed &= hasTriggered;
}
if (hasFailed) {
// Something failed, possibly after other vibrators were activated.
// Cancel and remove every pending step from output list.
for (int i = nextSteps.size() - 1; i >= 0; i--) {
nextSteps.remove(i).cancelImmediately();
}
}
// Cancel the preparation if trigger failed or all
if (hasPrepared && !hasTriggered) {
// Trigger has failed or was skipped, so abort the synced vibration.
conductor.vibratorManagerHooks.cancelSyncedVibration();
}
return hasFailed ? -1 : maxDuration;
}
多个振动器同步处理的情况比较复杂,我们重点关注单个振动器的情况。通过conductor.nextVibrateStep创建了一个新的振动器步骤(区别于前面的steps)。AbstractVibratorStep nextVibrateStep(long startTime, VibratorController controller,
VibrationEffect.Composed effect, int segmentIndex, long pendingVibratorOffDeadline) {
if (Build.IS_DEBUGGABLE) {
expectIsVibrationThread(true);
}
// 如果 segmentIndex 超过了片段列表的范围,尝试获取重复的起始索引
if (segmentIndex >= effect.getSegments().size()) {
segmentIndex = effect.getRepeatIndex();
}
// 如果 segmentIndex 小于 0,表示没有更多片段需要播放。此时,创建并返回CompleteEffectVibratorStep 实例,表示振动完成的步骤。
if (segmentIndex 0) {
return new CompleteEffectVibratorStep(this, startTime, /* cancelled= */ false,
controller, pendingVibratorOffDeadline);
}
// 获取当前片段(segment)对应的振动效果段(VibrationEffectSegment)
VibrationEffectSegment segment = effect.getSegments().get(segmentIndex);
// 不同类型的振动片段处理
// PrebakedSegment表示一个预定义的震动模式(例如触觉反馈中常见的“点击”或“双击”)
// 创建并返回 PerformPrebakedVibratorStep
if (segment instanceof PrebakedSegment) {
return new PerformPrebakedVibratorStep(this, startTime, controller, effect,
segmentIndex, pendingVibratorOffDeadline);
}
// 创建并返回 ComposePrimitivesVibratorStep
if (segment instanceof PrimitiveSegment) {
return new ComposePrimitivesVibratorStep(this, startTime, controller, effect,
segmentIndex, pendingVibratorOffDeadline);
}
// RampSegment表示一个逐渐变化的振动模式(例如线性强度变化)
// 创建并返回 ComposePwleVibratorStep
if (segment instanceof RampSegment) {
return new ComposePwleVibratorStep(this, startTime, controller, effect, segmentIndex,
pendingVibratorOffDeadline);
}
// 默认创建并返回 SetAmplitudeVibratorStep
return new SetAmplitudeVibratorStep(this, startTime, controller, effect, segmentIndex,
pendingVibratorOffDeadline);
}
nextVibrateStep函数会根据不同的类型的振动片段返回不同的step,我们这里分析默认的振动片段步骤SetAmplitudeVibratorStep。根据前面的startVibrating函数了解到,创建出来的振动片段步骤会被startVibrating(step, nextSteps)函数调用,下面继续分析这个函数:private long startVibrating(AbstractVibratorStep step, List nextSteps) {
nextSteps.addAll(step.play());
long stepDuration = step.getVibratorOnDuration();
if (stepDuration 0) {
// Step failed, so return negative duration to propagate failure.
return stepDuration;
}
// Return the longest estimation for the entire effect.
return Math.max(stepDuration, step.effect.getDuration());
}
这个函数内部实际上就是调用这些振动片段步骤的play()函数,因此我们分析SetAmplitudeVibratorStep类的play函数。public List play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "SetAmplitudeVibratorStep");
try {
// 保证振动效果的时间点正确
long now = SystemClock.uptimeMillis();
long latency = now - startTime;
if (VibrationThread.DEBUG) {
Slog.d(VibrationThread.TAG,
"Running amplitude step with " + latency + "ms latency.");
}
if (mVibratorCompleteCallbackReceived && latency 0) {
turnVibratorBackOn(/* remainingDuration= */ -latency);
return Arrays.asList(new SetAmplitudeVibratorStep(conductor, startTime, controller,
effect, segmentIndex, mPendingVibratorOffDeadline));
}
// 片段类型检查,不符合的话跳过
VibrationEffectSegment segment = effect.getSegments().get(segmentIndex);
if (!(segment instanceof StepSegment)) {
Slog.w(VibrationThread.TAG,
"Ignoring wrong segment for a SetAmplitudeVibratorStep: " + segment);
// Use original startTime to avoid propagating latencies to the waveform.
return nextSteps(startTime, /* segmentsPlayed= */ 1);
}
StepSegment stepSegment = (StepSegment) segment;
if (stepSegment.getDuration() == 0) {
// Use original startTime to avoid propagating latencies to the waveform.
return nextSteps(startTime, /* segmentsPlayed= */ 1);
}
// 获取该步骤的振幅并设置振幅
float amplitude = stepSegment.getAmplitude();
if (amplitude == 0) {
if (mPendingVibratorOffDeadline > now) {
// Amplitude cannot be set to zero, so stop the vibrator.
stopVibrating();
}
} else {
if (startTime >= mPendingVibratorOffDeadline) {
long onDuration = getVibratorOnDuration(effect, segmentIndex);
// 振动一段时间
if (onDuration > 0) {
startVibrating(onDuration);
}
}
changeAmplitude(amplitude);
}
// Use original startTime to avoid propagating latencies to the waveform.
long nextStartTime = startTime + segment.getDuration();
return nextSteps(nextStartTime, /* segmentsPlayed= */ 1);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
从这个函数中可以看到实际振动还是调用了startVibrating(onDuration)函数,让我们继续看这个函数的内容:private long startVibrating(long duration) {
if (VibrationThread.DEBUG) {
Slog.d(VibrationThread.TAG,
"Turning on vibrator " + controller.getVibratorInfo().getId() + " for "
+ duration + "ms");
}
long vibratorOnResult = controller.on(duration, getVibration().id);
handleVibratorOnResult(vibratorOnResult);
getVibration().stats.reportVibratorOn(vibratorOnResult);
return vibratorOnResult;
}
这个函数实现了持续振动一段时间,它是通过controller.on(duration, getVibration().id)这个函数来实现的。controller这里指向了VibratorController类,说明振动的真正底层实现是通过这个类来完成的。它调用on则表明开启振动,并可为其设定一定的时间。这个振动函数的实现绕了一层又一层,终于找到了最终实现类VibratorController。接下来的任务就是看VibratorController类的来龙去脉了。VibratorController类是通过conductor.getVibrators().get(effectMapping.vibratorIdAt(i))创建的。每个振动器都有一个对应的VibratorController。这最终指向了VibrationStepConductor类的成员变量SparseArray,而构造VibrationStepConductor实例时传入的是VibratorManagerService实例的成员变量mVibrators。我们找到VibratorController类的on函数实现如下:public long on(long milliseconds, long vibrationId) {
synchronized (mLock) {
long duration = mNativeWrapper.on(milliseconds, vibrationId);
if (duration > 0) {
mCurrentAmplitude = -1;
notifyListenerOnVibrating(true);
}
return duration;
}
}
发现on函数的内部实现实际是调用mNativeWrapper的on函数,而mNativeWrapper是NativeWrapper类的实例。而NativeWrapper类的on函数是一个native函数。public long on(long milliseconds, long vibrationId) {
return on(mNativePtr, milliseconds, vibrationId);
}
// 最终调用到这个native函数
private static native long on(long nativePtr, long milliseconds, long vibrationId);
JNI层:VibratorControllerWrapper类在com_android_server_vibrator_VibratorController.cpp文件中定义了一个VibratorControllerWrapper类,它实际上就是前面提到的NativeWrapper类。它的初始化函数如下:static jlong vibratorNativeInit(JNIEnv* env, jclass /* clazz */, jint vibratorId,
jobject callbackListener) {
std::unique_ptr wrapper =
std::make_unique(env, vibratorId, callbackListener);
wrapper->initHal();
return reinterpret_cast(wrapper.release());
}
这个JNI函数会构造VibratorControllerWrapper类,这个wrapper智能指针会指向它。然后会调用VibratorControllerWrapper类的initHal()函数。initHal()函数内部实际是通过内部变量mHal来完成的:void initHal() { mHal->init(); }
因此我们要看一下mHal是怎么被初始化的,于是找到VibratorControllerWrapper的构造函数:VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener)
: mHal(findVibrator(vibratorId)),
mVibratorId(vibratorId),
mCallbackListener(env->NewGlobalRef(callbackListener)) {
LOG_ALWAYS_FATAL_IF(mHal == nullptr,
"Failed to connect to vibrator HAL, or vibratorId is invalid");
LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
"Unable to create global reference to vibration callback handler");
}
可以看到mHal是通过findVibrator(vibratorId)函数来进行初始化的:static std::shared_ptr<:halcontroller> findVibrator(int32_t vibratorId) {
vibrator::ManagerHalController* manager =
android_server_vibrator_VibratorManagerService_getManager();
if (manager == nullptr) {
return nullptr;
}
auto result = manager->getVibrator(vibratorId);
return result.isOk() ? std::move(result.value()) : nullptr;
}
findVibrator传入一个vibratorId,然后通过ManagerHalController类获取到一个HalController,专门用来控制这个振动器。所以wrapper->initHal()实际上是HalController进行初始化。static jlong vibratorOn(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong timeoutMs,
jlong vibrationId) {
// 获取 VibratorControllerWrapper 对象
VibratorControllerWrapper* wrapper = reinterpret_cast(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorOn failed because native wrapper was not initialized");
return -1;
}
// 创建振动回调
auto callback = wrapper->createCallback(vibrationId);
// 定义振动逻辑
// onFn是一个Lambda表达式, hal为振动器HAL层的接口对象, 调用hal->on方法
auto onFn = [timeoutMs, &callback](vibrator::HalWrapper* hal) {
return hal->on(std::chrono::milliseconds(timeoutMs), callback);
};
// 调用HAL层接口
auto result = wrapper->halCall<void>(onFn, "on");
return result.isOk() ? timeoutMs : (result.isUnsupported() ? 0 : -1);
}
这段代码通过 VibratorControllerWrapper 间接调用AIDL HAL通信的 on 方法,开启振动器。接下来我们寻找Native层的实现代码。Native层:Vibrator::AidlHalWrapper在源码目录中找到VibratorHalWrapper.cpp这个文件,里面定义了Vibrator::AidlHalWrapper这个类,它实际上是AIDL HAL通信的客户端,但依然把它划为Native层。我们继续看它的on函数:HalResult<void> AidlHalWrapper::on(milliseconds timeout,
const std::function<void()>& completionCallback) {
HalResult capabilities = getCapabilities();
bool supportsCallback = capabilities.isOk() &&
static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK);
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb));
if (!supportsCallback && ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
}
return ret;
}
这个部分代码实际上是振动器HAL的AIDL客户端代码,通过getHal()->on(timeout.count(), cb)来调用振动器HAL的服务端实现函数。接下来我们需要看AIDL HAL服务端是如何定义的:HAL层:aidl::android::hardware::vibrator::Vibrator类在hardware/interfaces/vibrator/aidl/default/Vibrator.cpp这个位置实现了振动器的AIDL HAL服务端。直接看它的on函数实现:ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
const std::shared_ptr& callback) {
LOG(VERBOSE) <"Vibrator on for timeoutMs: " < if (callback != nullptr) {
// 通过开启新线程来完成振动任务
std::thread([timeoutMs, callback] {
LOG(VERBOSE) <"Starting on on another thread";
usleep(timeoutMs * 1000);
LOG(VERBOSE) <"Notifying on complete";
if (!callback->onComplete().isOk()) {
LOG(ERROR) <"Failed to call onComplete";
}
}).detach();
}
return ndk::ScopedAStatus::ok();
}
可以看到这段代码并没有真正实现振动功能,而是通过开启新线程并打印日志来模拟振动过程。在这一章节我将通过开发一个App来简单验证前面章节所讲述的振动器工作流程。根据前面的分析:在App层执行一次振动后,依次经过Framework层SystemVibratorManager类和VibratorManagerService类,它们之间是通过Binder服务完成通信的。然后到达JNI层的VibratorControllerWrapper类,它实际上是Native层AidlHalWrapper的包装,方便Framework层调用。最后就是Native层AidlHalWrapper类和HAL层Vibrator类之间进行Binder通信了。本文简单开发了一个测试App,里面加入一个按钮,点击按钮将通过App层API发起一次振动请求。测试前已经在AOSP源码中加入了关键节点的调试信息。测试App的代码如下:button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
VibratorManager vibratorManager = (VibratorManager) getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
if (vibratorManager != null) {
Log.d("Ferdinand-Vibrator", "App层:有振动管理器");
Vibrator vibrator = vibratorManager.getDefaultVibrator();
if (vibrator.hasVibrator()) {
Log.d("Ferdinand-Vibrator", "App层:有振动器, id = " + vibrator.getId());
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
}
}
Log.d("Ferdinand-Vibrator", "App层:按钮被点击了");
}
});
从输出日志中可以看到,日志记录从App层到Framework层,再到JNI层和Native层,最后到达HAL层。通过on方法将整个流程串联起来。结果和前面的分析一致。分析下来,整个Vibrator的调用过程十分的冗长,主要原因是在Framework层的多层封装和跨层调用。因此很容易在Framework层分析不下去。实际上如果自己测试一个AIDL HAL,可以简单的通过Native层和HAL层进行Binder通信。官方也给出了一个简单的例子(hardware/interfaces/vibrator/aidl/default/example_java_client/example/vib/MyActivity.java):public void onCreate(Bundle b) {
super.onCreate(b);
System.loadLibrary("example_vib_getter");
IVibrator v =
IVibrator.Stub.asInterface(gimme("android.hardware.vibrator.IVibrator/default"));
try {
v.on(100 /*ms*/, null /*cb*/);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
finish();
}
这种方式调用振动服务更加简单方便,但是不适应多线程的环境下使用。接下来可以尝试自己模拟一个硬件,实现简单的AIDL HAL服务。