在 Frameworks 中使用 AIDL

话不多说,直接切入正题。我们就以 Android 源码为例来说明如何在 Frameworks 中使用 AIDL。
下面是系统的 audio 服务,一个典型的 Frameworks 层 AIDL 的写法。由 AIDL 接口、服务实现、服务发布、服务包装四个部分组成(这里服务实现和发布在一个文件中)。
在这里插入图片描述

1 定义 AIDL 接口

定义后缀名为 aidl 的接口文件 IAudioService.aidl,然后定义需要的方法,这里就只关注 isMasterMute() 这一个方法。

/frameworks/base/media/java/android/media/IAudioService.aidl
17  package android.media;
...
50  /**
51   * {@hide}
52   */
53  interface IAudioService {
    
    
...
96      boolean isMasterMute();//我们就只关注这一个方法
...
395  }

2 实现具体的服务并注册

想先看完 audio 服务实现流程的同学,看完 2.1 节就可以到第 3 章了,后面其他小节只是为了展示 binder 服务的不同写法。

2.1 写法一:直接继承 IAudioService.Stub,内部类继承 SystemServer

定义的 AudioService.java 直接继承 IAudioService.Stub,然后在该类里实现之前定义的方法。

/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
17  package com.android.server.audio;
...
90  import android.media.IAudioService;
187  /**
197   * @hide
198   */
199  public class AudioService extends IAudioService.Stub
200          implements AccessibilityManager.TouchExplorationStateChangeListener,
201              AccessibilityManager.AccessibilityServicesStateChangeListener {
    
    
...
4025      public boolean isMasterMute() {
    
    
4026          return AudioSystem.getMasterMute();
4027      }
...
10525  }

服务实现好后,必须要告诉系统,然后才知道有这么一个服务。所以通过 publishBinderService(Context.AUDIO_SERVICE, mService) 将该服务发布出去,第一个参数是我们给该服务起的名字,第二个参数是实现该服务的类对象,也就是 AudioService 对象。

这个 AudioService 是把服务的注册放在了内部类 Lifecycle 中,而 Lifecycle 继承了 SystemService,因为我们要实现的是一个系统服务,必须要继承它才行。

为了不影响阅读的连贯性,publishBinderService 具体实现请看这篇 AIDL 服务的发布 publishBinderService 和 获取 getService,此处我们先知道它能注册一个 binder 服务就行了。

785      public static final class Lifecycle extends SystemService {
    
    
786          private AudioService mService;
787  
788          public Lifecycle(Context context) {
    
    
789              super(context);
790              mService = new AudioService(context);
791          }
792  
793          @Override
794          public void onStart() {
    
    
795              publishBinderService(Context.AUDIO_SERVICE, mService);
796          }
797  
798          @Override
799          public void onBootPhase(int phase) {
    
    
800              if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
    
    
801                  mService.systemReady();
802              }
803          }
804      }

2.2 写法二:直接继承 SystemService,内部匿名类创建 IBinder 对象

我们继续看一下 NotificationManagerService 的写法。
在这里插入图片描述
(1)这个类是直接继承自 SystemServer;
(2)通过匿名类的方式创建 IBinder 对象,具体实现接口中定义的方法。

334  /** {@hide} */
335  public class NotificationManagerService extends SystemService {
    
    
...
2437      public void onStart() {
    
    
...
2483          publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
2484                  DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL);
2485          publishLocalService(NotificationManagerInternal.class, mInternalService);
2486      }
2487  
...
   @VisibleForTesting
3176      final IBinder mService = new INotificationManager.Stub() {
    
    
...
3180          @Override
3181          public void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration,
3182                  int displayId, @Nullable ITransientNotificationCallback callback) {
    
    
3183              enqueueToast(pkg, token, text, null, duration, displayId, callback);
3184          }
...
11101      }
11102  }

2.3 写法三:直接继承 .stub,然后用另一个继承自 SystemServer 的类将其发布

这次看一下 AppWidget 相关的 AIDL 服务。
在这里插入图片描述
服务的实现类是 AppWidgetServiceImpl.java

17  package com.android.server.appwidget;
...
146  class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider,
147          OnCrossProfileWidgetProvidersChangeListener {
    
    
...
4940  }

我们发现这个类直接继承了 IAppWidgetService.Stub,实现了一些具体方法。但然后呢?我们发现,它并没有 IBinder 类型的对象,也没有发布 binder 服务。

这是怎么一回事,不慌,我们接着看看和它同包下的 AppWidgetService.java 这个类。
在这里插入图片描述
注释就首先吸引了我的目光,“SystemService that publishes an IAppWidgetService”。这个继承自 SystemService,组合了一个 AppWidgetServiceImpl 类型的对象,然后将其发布出去。

27  /**
28   * SystemService that publishes an IAppWidgetService.
29   */
30  public class AppWidgetService extends SystemService {
    
    
31      private final AppWidgetServiceImpl mImpl;
32  
33      public AppWidgetService(Context context) {
    
    
34          super(context);
35          mImpl = new AppWidgetServiceImpl(context);
36      }
37  
38      @Override
39      public void onStart() {
    
    
40          mImpl.onStart();
41          publishBinderService(Context.APPWIDGET_SERVICE, mImpl);
42          AppWidgetBackupBridge.register(mImpl);
43      }
...
62  }

2.4 服务实现和发布小结

方法的实现一定是在继承了 .Stub 的类中,方法的发布一定是在继承了 SystemServer 的类中,。总共有三种情形:

  • 首先是在同一个 Java 类中的情况
    1. 外部类继承 .Stub,内部类继承 SystemServer,此时 IBinder 对象是外部内的实例。方法的实现在外部类中,发布则在内部类中。这种方法写的比较死,适合整个服务就只实现一个 AIDL 服务的情形。
    2. 外部类继承 SystemServer,内部类继承 .Stub,此时 IBinder 对象就是内部内的实例。方法实现在内部内中,发布在外部内中。这种写法具有可拓展性,因为可以有多个内部类,所以可以同时发布多个 AIDL 服务。
  • 然后是写在两个 Java 类中的情况
    此时一个 java 类继承自 SystemServer,它的内部必须要维和一个继承了 .Stub 的类对象(也就是 IBinder 对象),这样才能发布相应服务。另一个 java 类继承 .Stub,只用来实现具体方法。同方法 2 一样,这种方法也具有较高的灵活性,当维护多个 IBinder对象时,也就能发布多个 AIDL 服务。

3 将服务封装到 AudioManager

这一层封装是为了方便客户端调用,客户端调用 AudioManager.java 中的方法就跟调用普通类中的方法没什么两样,因为系统已经做好了封装。这步不是必须的,调用 binder 服务的客户端自己也可以做。

看一下,isMasterMute() 这个方法,其实就是直接调用 AIDL 文件中定义的方法,细心的同学可能已经发现 manager 文件是与 .aidl 文件共包的。

/frameworks/base/media/java/android/media/AudioManager.java
17  package android.media;
...
90  /**
91   * AudioManager provides access to volume and ringer mode control.
92   */
93  @SystemService(Context.AUDIO_SERVICE)
94  public class AudioManager {
    
    
...
1460      public boolean isMasterMute() {
    
    
1461          final IAudioService service = getService();
1462          try {
    
    
1463              return service.isMasterMute(); //直接调用 AIDL 中的方法
1464          } catch (RemoteException e) {
    
    
1465              throw e.rethrowFromSystemServer();
1466          }
1467      }
...
7837  }

有必要关注一下上面代码里的 service 的获取,所以看一下 getService() 方法。

808      private static IAudioService getService()
809      {
    
    
810          if (sService != null) {
    
    
811              return sService;
812          }
813          IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
814          sService = IAudioService.Stub.asInterface(b);
815          return sService;
816      }

ServiceManager.getService(Context.AUDIO_SERVICE):当我们前面通过 publish 方法将服务发布出去后,就可以通过服务名获取该 binder 服务了,返回的是一个 IBinder 对象,getService 的具体实现也请看这篇 AIDL 服务的发布 publishBinderService 和 获取 getService
IAudioService.Stub.asInterface(b):同上一条语句一样,这也是一个固定写法。通过它我们就能将 IBinder 转化成对应服务的对象了。

4 总结

最后再概括一下, Frameworks 中实现 AIDL 系统服务的步骤:

  1. 在 IAudioService.aidl 中定义相关方法;
  2. 在 AudioService.java 中实现具体方法,该类或者其内部类必须要继承 IAudioService.stub,这样才能实例化一个 IBinder 对象;
  3. 通过 publishBinderService() 将服务发布出去,向系统注册,该方法第二个参数是步骤二中的 IBinder 对象,调用该方法的类要继承了 SystemServer。方法实现和 AIDL 发布的总结见 2.4 节;
  4. 最后在 AudioManager.java 类里封装好服务,方便客户端使用。这个封装也可以不做,让客户端调用的时候自己实现。

猜你喜欢

转载自blog.csdn.net/hejnhong/article/details/124531048