专栏名称: 郭霖
Android技术分享平台,每天都有优质技术文章推送。你还可以向公众号投稿,将自己总结的技术心得分享给大家。
目录
相关文章推荐
郭霖  ·  Android振动分析:从App层到HAL层 ·  昨天  
鸿洋  ·  一波深入的Android 性能优化 ·  2 天前  
郭霖  ·  activityGuard:Android ... ·  3 天前  
鸿洋  ·  Android anr排查之sp卡顿 ·  4 天前  
51好读  ›  专栏  ›  郭霖

Android振动分析:从App层到HAL层

郭霖  · 公众号  · android  · 2024-12-27 08:00

正文



/   今日科技快讯   /

近日,谷歌在一份提交给法庭的文件中称,iPhone 和 iPad 可以有不同的默认搜索引擎,试图捍卫其与苹果公司每年高达 200 亿美元的合作协议。这项合作正面临被法院禁止的风险,谷歌正积极提出一系列反制方案。

/   作者简介   /

明天是2024最后的周末,提前祝大家周末愉快!

本篇文章转自FerdinandHu的博客,文章主要分享了手机振动从应用层到硬件抽象层的代码相信会对大家有所帮助!

原文地址:
https://juejin.cn/post/7451418558770626595

/   引言   /

在 Android 系统中,“振动”功能是应用层进行操作,传递到系统的 HAL 层,最终接通硬件驱动器实现。本文将基于Android14源码分析振动功能的全过程。

本文主要想通过振动器的on函数将整个调用链串联起来,中间Framework层分析冗长且不够完善。如果想快速建立起框架概念,可直接看章节-分析验证。整个过程旨在记录分析过程,难免会有理解不到位的地方,感谢指正请多多包涵。

/   APP层   /

App 层:Vibrator 类

在应用层,我们通过android.os.Vibrator和android.os.VibratorManager类调用振动功能,示例代码如下:

android.os.Vibrator

Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator != null && vibrator.hasVibrator()) {
    vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
}

android.os.VibratorManager

VibratorManager 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层   /

Framework 层:SystemVibratorManager和VibratorManagerService

SystemVibratorManager类

SystemVibratorManager类继承自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类的注册与初始化

VibratorManagerService服务被注册的位置位于SystemServer.java中startOtherServices函数中,大部分服务的注册也是在这个地方。下面是VibratorManagerService被注册的代码:

t.traceBegin("StartVibratorManagerService");
mSystemServiceManager.startService(VibratorManagerService.Lifecycle.class);
t.traceEnd();

SystemServiceManager的startServie函数的具体实现如下:

public  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 振动功能实现

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类

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类

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;
    }

接下来看startVibrating函数:

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类

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层   /

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进行初始化。

我们接着看一下on函数的Native层实现:

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层   /

Native层:Vibrator::AidlHalWrapper

在源码目录中找到VibratorHalWrapper.cpp这个文件,里面定义了Vibrator::AidlHalWrapper这个类,它实际上是AIDL HAL通信的客户端,但依然把它划为Native层。我们继续看它的on函数:

HalResult<voidAidlHalWrapper::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   /

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,里面加入一个按钮,点击按钮将通过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部署到Cuttlefish模拟器中:


输出日志分析


从输出日志中可以看到,日志记录从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服务。

推荐阅读:
我的新书,《第一行代码 第3版》已出版!
高效稳定 | Compose 的类型安全导航
原创:写给初学者的Jetpack Compose教程,edge-to-edge全面屏体验

欢迎关注我的公众号
学习技术或投稿

长按上图,识别图中二维码即可关注