【Android 進階必會】深刻了解系統 Services 機制

什麼是系統 Services?

從 Android 應用的角度來講,系統啓動以後,會在一個名爲 system_server 的進程中啓動一系列的 Services,以向每一個進程應用(Application Process)提供各式各樣的「服務」,每一個 Service 各思其職。好比,你們最熟悉的 Activity 以及其餘組件,其生命週期則是由 ActivityManagerService 這個服務來管理的。java

而對於開發者而言,在一個普通應用的開發過程當中,和系統機制有關的功能都是由這些系統服務來提供實現的。換句話說,咱們大部分時候所實現的功能本質上都是在和這些系統服務「打交道」。爲了方便開發者使用,Android SDK 內對每一個系統 Service 都作了必定程度的封裝,提供了必要的 API 來調用。android

好比,開發中經常使用到,設置一個定時鬧鐘任務:web

PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE); alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5 * 1000, pi); 複製代碼

在這裏,當前應用進程是經過 AlarmManager 來實現設置定時鬧鐘,其背後是調用了 AlarmManagerService 來實現相關操做。緩存

系統 Services 的總體流程

系統 Services 從建立到使用的總體流程示意以下:架構

其中,整個流程,可分爲如下四個步驟(分別對應上圖中的數字處):app

一、系統 Service 在 system_server 進程中建立、啓動;編輯器

二、系統 Service 發佈 Binder Service 至 Native Framework 的 ServiceManager 中;ide

三、在應用啓動的過程當中,ActivityManagerServiceServiceManager(native)中獲取其餘經常使用的服務(BinderProxy 對象),傳遞到應用進程的 ServiceManager(java) 中;學習

四、應用進程中建立各個使用服務的 Manager 對象,如 WindowManager 等,經過上下文 Context 調用使用。fetch

下面的部分會經過源碼示例的方式,把以上四個步驟具體流程、實現方式深刻分析一下,讀者可根據本身想要了解的部分自行跳轉閱讀,目錄在右側 👉 可找到 。

  • 涉及到的源碼文件有:
frameworks/base/services/java/com/android/sever/
 - SystemServer.java  - SystemServiceManager.java  - AlarmManagerService.java  - am/ActivityManagerService.java  frameworks/base/core/java/android/os/  - ServiceManager.java  - ServiceManagerNative.java  frameworks/base/core/java/android/app/  - ActivityThread.java  - ContextImpl.java  - SystemServiceRegistry.java  frameworks/native/libs/binder/  - IServiceManager.cpp  frameworks/native/cmds/servicemanager/  - ServiceManager.h  - ServiceManager.cpp 複製代碼

注:源碼部分用的 Android 10(Q)版本的,不一樣的 Android 系統版本在實現的方式存在必定的差別,但總體流程是同樣的。

系統 Services 的建立、啓動

system_server 進程建立後,在SystemServer 中的 main 方法爲入口,依次啓動各 Services。

  • SystemServer.java
···
// SystemServer 進程主方法入口 public static void main(String[] args) {  new SystemServer().run(); }  private void run() {  ···  // 建立 SystemServiceManager,用於後續管理系統 Services  mSystemServiceManager = new SystemServiceManager(mSystemContext);  mSystemServiceManager.setStartInfo(mRuntimeRestart,  mRuntimeStartElapsedTime, mRuntimeStartUptime);  LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);   ···  // Start services.  startBootstrapServices();  // 啓動系統電池、GPU 等核心服務  startCoreServices();  // 大部分應用直接所需的服務在此啓動  startOtherServices();  ··· }  private void startOtherServices() {  ···  // 啓動 AlarmManagerService  mSystemServiceManager.startService(new AlarmManagerService(context));  ···  // 啓動 ActivityManagerService  mActivityManagerService = ActivityManagerService.Lifecycle.startService(  mSystemServiceManager, atm);  // 啓動其餘的 Services  ··· } ··· 複製代碼

其中,不一樣的 Service 的建立過程會有必定的差別,有的是直接 new 出一個對象,有的經過反射的形式建立,有得須要註冊回調等,但核心的流程是同樣的

在 Service 對象建立以後,回調其父類 SystemService onStart 方法,這樣一個 Service 就算啓動了。

  • SystemServiceManager.java
···
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();  // 啓動系統服務 public void startService(@NonNull final SystemService service) {  // 添加 service 對象到一個 List 中  mServices.add(service);  ···  // 回調 onStart  try {  service.onStart();  } ··· } 複製代碼

註冊 Binder Service

到此,一個系統 Service 尚未真正的完成註冊。全部的 Services 對象是建立在 system_server 進程的,而後經過 Binder 與每個應用進程進行跨進程通訊(IPC),所以須要發佈一個 Binder Service,以 AlarmManagerService 爲例:

  • AlarmManagerService.java
class AlarmManagerService extends SystemService {
 ···  // 建立一個 IBinder Service 對象,用於實現 Binder 通訊  private final IBinder mService = new IAlarmManager.Stub() {   // 設置定時鬧鐘的接口實現  @Override  public void set(String callingPackage, int type, long triggerAtTime, ...) {  ···  setImpl(type, triggerAtTime, ...);  }  ···  }   // 設置定時鬧鐘真正方法入口  void setImpl(int type, long triggerAtTime, ...) {  ...  }   @Override  public void onStart() {  ···  // onStart 回調中發佈該 Binder Service  publishBinderService(Context.ALARM_SERVICE, mService);  }   // 經過 ServiceManager 添加 Binder Service  protected final void publishBinderService(String name, IBinder service,  boolean allowIsolated, int dumpPriority) {  ServiceManager.addService(name, service, allowIsolated, dumpPriority);  }  ··· } 複製代碼

ServiceManager 主要用於 Service 的添加與獲取。

  • ServiceManager.java
···
public static void addService(String name, IBinder service, boolean allowIsolated,  int dumpPriority) {  try {  // 添加一個 Service,這裏一樣是 IPC 通訊  getIServiceManager().addService(name, service, allowIsolated, dumpPriority);  } catch (RemoteException e) {  Log.e(TAG, "error in addService", e);  } }  private static IServiceManager getIServiceManager() {  if (sServiceManager != null) {  return sServiceManager;  }   // 找到 ServiceManager 對象  // BinderInternal.getContextObject() 爲 native 方法,  // 返回指向 IServiceManager 的 BinderProxy 對象  sServiceManager = ServiceManagerNative  .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));  return sServiceManager; } ··· 複製代碼

接着,往下看 ServiceManagerNative

  • ServiceManagerNative.java
public final class ServiceManagerNative {
 ···  public static IServiceManager asInterface(IBinder obj) {  if (obj == null) {  return null;  }   // ServiceManager 的代理對象  return new ServiceManagerProxy(obj);  }   // 這裏等同於 IServiceManager$Stub$Proxy  class ServiceManagerProxy implements IServiceManager {   public ServiceManagerProxy(IBinder remote) {  mRemote = remote;  mServiceManager = IServiceManager.Stub.asInterface(remote);  }   // 獲取服務  public IBinder getService(String name) throws RemoteException {  return mServiceManager.checkService(name);  }   // 添加服務  public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)  throws RemoteException {  mServiceManager.addService(name, service, allowIsolated, dumpPriority);  }  } } 複製代碼

從這裏能夠看到,發佈一個 Service 的過程自己也是 Binder IPC 的方式實現的,最終會傳遞到 servicemanager 進程中,在 IServiceManager.cpp 內:

  • IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager>
{ public:  explicit BpServiceManager(const sp<IBinder>& impl)  : BpInterface<IServiceManager>(impl),  mTheRealServiceManager(interface_cast<AidlServiceManager>(impl))  {  }   // 添加 Service 到 ServiceManager  status_t addService(const String16& name, const sp<IBinder>& service,  bool allowIsolated, int dumpsysPriority) override {  Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority);  return status.exceptionCode();  }  ... } 複製代碼

這裏,Native Framework 中的 ServiceManager 是整個 Binder IPC 架構的服務中心,全部大大小小的 service 都須要通過 ServiceManager 來管理

  • ServiceManager.h
···
private:  // 定義 Service 的結構體  struct Service {  sp<IBinder> binder; // not null  bool allowIsolated;  int32_t dumpPriority;  };   ···  using ServiceMap = std::map<std::string, Service>;   // 用於保存添加進來的 Services  ServiceMap mNameToService;  ··· }; 複製代碼
  • ServiceManager.cpp
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
 ···  // 添加 Service 到 mNameToService 中,完成 Binder Service 註冊過程  mNameToService[name] = Service {  .binder = binder,  .allowIsolated = allowIsolated,  .dumpPriority = dumpPriority,  };   auto it = mNameToCallback.find(name);  if (it != mNameToCallback.end()) {  for (const sp<IServiceCallback>& cb : it->second) {  // permission checked in registerForNotifications  cb->onRegistration(name, binder);  }  }   return Status::ok(); } 複製代碼

獲取並傳遞 Service 代理對象

在新啓動一個應用的過程當中,建立應用進程以後,ActivityManagerService 中會獲取並緩存經常使用的系統 Services,經過回調 IApplicationThread.bindApplication() 方法傳遞 Service 的 BinderProxy 對象到應用進程中去。

  • ActivityManagerService.java
// IActivityManager 的 server 端實現
@Override public final void attachApplication(IApplicationThread thread, long startSeq) {  synchronized (this) {  int callingPid = Binder.getCallingPid();  final int callingUid = Binder.getCallingUid();  final long origId = Binder.clearCallingIdentity();  // 這裏 thread 實際爲 IApplicationThread$Stub$Proxy 對象,  attachApplicationLocked(thread, callingPid, callingUid, startSeq);  Binder.restoreCallingIdentity(origId);  } }  @GuardedBy("this") private final boolean attachApplicationLocked(IApplicationThread thread,  int pid, int callingUid, long startSeq) {  ···  thread.bindApplication(processName, appInfo, providers,  ···  getCommonServicesLocked(app.isolated), // 獲取各經常使用服務  ···);  ···  return true; }  private ArrayMap<String, IBinder> getCommonServicesLocked(boolean isolated) {  ···  if (mAppBindArgs == null) {  mAppBindArgs = new ArrayMap<>();   // 添加經常使用的服務進一個 map 中  addServiceToMap(mAppBindArgs, "package");  addServiceToMap(mAppBindArgs, Context.WINDOW_SERVICE);  addServiceToMap(mAppBindArgs, Context.ALARM_SERVICE);  addServiceToMap(mAppBindArgs, Context.DISPLAY_SERVICE);  ···  }  return mAppBindArgs; }  private static void addServiceToMap(ArrayMap<String, IBinder> map, String name) {  // 經過 ServiceManager 獲取服務  final IBinder service = ServiceManager.getService(name);  if (service != null) {  map.put(name, service);  if (false) {  Log.i(TAG, "Adding " + name + " to the pre-loaded service cache.");  }  } } 複製代碼

經過 ServiceManager 來獲取 Service 的過程和添加一個 Service 的流程是同樣的,最終從 Native Framework 中的 ServiceManager 獲取到該服務的 BinderProxy 對象。

IApplicationThread 的 server 端實如今 ActivityThread 中:

  • ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler {
  ···  private class ApplicationThread extends IApplicationThread.Stub {   // 傳遞指向系統 Service 的 BinderProxy 對象  public final void bindApplication(···, Map services, ···) {  if (services != null) {  ···  // 添加進應用進程的 ServiceManager 中  ServiceManager.initServiceCache(services);  }  }  } } 複製代碼
  • ServiceManager.java
public static void initServiceCache(Map<String, IBinder> cache) {
 if (sCache.size() != 0) {  throw new IllegalStateException("setServiceCache may only be called once");  }  // 存進 cache  sCache.putAll(cache); } 複製代碼

使用系統 Services

Context 上下文提供了 getSystemService 接口調用,Context 的真正實現類是 ContextImpl

  • ContextImpl.java
···
@Override public Object getSystemService(String name) {  return SystemServiceRegistry.getSystemService(this, name); } 複製代碼

SystemServiceRegistry 負責根據 ServiceManager 中各 Service 的 BinderProxy 來建立 Binder 通訊的 client 端對象,並封裝在對應的 Manager 對象。

  • SystemServiceRegistry.java
// 管理{@link ContextImpl#getSystemService} 能夠返回的全部系統服務
final class SystemServiceRegistry {  ···  private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =  new ArrayMap<Class<?>, String>();  private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =  new ArrayMap<String, ServiceFetcher<?>>();   ···  // SystemServiceRegistry 類被加載時建立各 Manager 對象  static {  registerService(Context.ALARM_SERVICE, AlarmManager.class,  new CachedServiceFetcher<AlarmManager>() {  @Override  public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {  IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);  IAlarmManager service = IAlarmManager.Stub.asInterface(b);  return new AlarmManager(service, ctx);  }});  ···  registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,  new CachedServiceFetcher<ActivityManager>() {  @Override  public ActivityManager createService(ContextImpl ctx) {  return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());  }});  ···  }   private static <T> void registerService(String serviceName, Class<T> serviceClass,  ServiceFetcher<T> serviceFetcher) {  SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);  SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);  }   // 返回系統 Service 對應的 Manager 對象  public static Object getSystemService(ContextImpl ctx, String name) {  ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);  return fetcher != null ? fetcher.getService(ctx) : null;  } }  複製代碼
  • ServiceManager.java
public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
 final IBinder binder = getService(name);  if (binder != null) {  return binder;  } else {  throw new ServiceNotFoundException(name);  } }  public static IBinder getService(String name) {  try {  // 各經常使用服務的代理對象已放入緩存,直接從緩存中取  IBinder service = sCache.get(name);  if (service != null) {  return service;  } else {  // 其餘很是用服務則再 經過 Binder IPC 來獲取  return Binder.allowBlocking(rawGetService(name));  }  } catch (RemoteException e) {  Log.e(TAG, "error in getService", e);  }  return null; }  private static IBinder rawGetService(String name) throws RemoteException {  ···  final IBinder binder = getIServiceManager().getService(name);  ···  return binder; } 複製代碼

到此,整個系統 Services 的流程的代碼示例已經展現完。

總結 & 拓展

  • 系統 Services 是 Android Framework 中最爲重要、核心的部分,也是 Android 進階開發者必需要學習的部分。
  • 系統 Services 的總體相關流程可大體分爲 建立&啓動、註冊 Binder Service、獲取&傳遞代理對象、使用 Service 這四個步驟
  • 在每個層級的進程中,都會有一個 ServiceManager 對象來管理系統 Services(或代理對象),用戶進程和 system_server 進程中的爲 java 對象(對應同一個 ServiceManager.java), severmanager 進程則爲 native 對象( service_manager.cServiceManager.cpp),也是整個 Binder 架構的服務管理中心。
  • 總體流程中大量涉及到 Binder IPC 的運用,Binder 是 Android Framework 中最重要也是較難理解的 IPC 機制,對此有必定了解才能順利地閱讀相關代碼。
  • 本文介紹的系統 Services 表明的是 Java Framework 層所提供的 Services,嚴格意義上還有 C++ Framework 中提供的 Media 相關的服務,再也不本文的討論範圍內。
  • 每一個系統 Services 內都有各自衆多複雜機制的實現,可根據自身想要了解的部分再去深刻閱讀相關代碼。

本次的分享就到這啦,喜歡的話能夠點個贊 👍 或關注唄。若有錯誤的地方歡迎你們在評論裏指出。

相關文章
相關標籤/搜索