Android解析ActivityManagerService(一)AMS啟動流程和AMS家族

劉望舒發表於2017-08-09

相關文章
Android系統啟動流程系列
Android應用程式系列
Android深入四大元件系列

前言

此前在Android系統啟動流程、應用程式以及深入四大元件這三個系列文章中,都提及到了AMS,但都沒有系統的來講解它,本文就以AMS為主來進行講解,其中會有一些知識點與這些系列文章有所重合,這裡會儘量做到詳盡講解。閱讀此文章前,最好閱讀相關文章中列出的系列文章,否則我不敢保證這篇文章你能看的懂。

1.概述

AMS是系統的引導服務,應用程式的啟動、切換和排程、四大元件的啟動和管理都需要AMS的支援。從這裡可以看出AMS的功能會十分的繁多,當然它並不是一個類承擔這個重責,它有一些關聯類,這在文章後面會講到。AMS的涉及的知識點非常多,這篇文章主要會講解AMS的以下幾個知識點:

  • AMS的啟動流程。
  • AMS與程式啟動。
  • AMS家族。

2.AMS的啟動流程

AMS的啟動是在SyetemServer程式中啟動的,在Android系統啟動流程(三)解析SyetemServer程式啟動過程這篇文章中提及過,這裡從SyetemServer的main方法開始講起:
frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
       new SystemServer().run();
   }複製程式碼

main方法中只呼叫了SystemServer的run方法,如下所示。
frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {
       ...
           System.loadLibrary("android_servers");//1
       ...
           mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
           LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
       ...    
        try {
           Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
           startBootstrapServices();//3
           startCoreServices();//4
           startOtherServices();//5
       } catch (Throwable ex) {
           Slog.e("System", "******************************************");
           Slog.e("System", "************ Failure starting system services", ex);
           throw ex;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
       ...
   }複製程式碼

在註釋1處載入了動態庫libandroid_servers.so。接下來在註釋2處建立SystemServiceManager,它會對系統的服務進行建立、啟動和生命週期管理。在註釋3中的startBootstrapServices方法中用SystemServiceManager啟動了ActivityManagerService、PowerManagerService、PackageManagerService等服務。在註釋4處的startCoreServices方法中則啟動了BatteryService、UsageStatsService和WebViewUpdateService。註釋5處的startOtherServices方法中啟動了CameraService、AlarmManagerService、VrManagerService等服務。這些服務的父類均為SystemService。從註釋3、4、5的方法可以看出,官方把系統服務分為了三種型別,分別是引導服務、核心服務和其他服務,其中其他服務是一些非緊要和一些不需要立即啟動的服務。系統服務總共大約有80多個,我們主要來檢視引導服務AMS是如何啟動的,註釋3處的startBootstrapServices方法如下所示。

frameworks/base/services/java/com/android/server/SystemServer.java

   private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);
        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();//1
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
      ...
    }複製程式碼

在註釋1處呼叫了SystemServiceManager的startService方法,方法的引數是ActivityManagerService.Lifecycle.class:
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

  @SuppressWarnings("unchecked")
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
           ...
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);//1
                service = constructor.newInstance(mContext);//2
            } catch (InstantiationException ex) {
              ...
            }
            // Register it.
            mServices.add(service);//3
            // Start it.
            try {
                service.onStart();//4
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to start service " + name
                        + ": onStart threw an exception", ex);
            }
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }複製程式碼

startService方法傳入的引數是Lifecycle.class,Lifecycle繼承自SystemService。首先,通過反射來建立Lifecycle例項,註釋1處得到傳進來的Lifecycle的構造器constructor,在註釋2處呼叫constructor的newInstance方法來建立Lifecycle型別的service物件。接著在註釋3處將剛建立的service新增到ArrayList型別的mServices物件中來完成註冊。最後在註釋4處呼叫service的onStart方法來啟動service,並返回該service。Lifecycle是AMS的內部類,程式碼如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

   public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;
        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);//1
        }
        @Override
        public void onStart() {
            mService.start();//2
        }
        public ActivityManagerService getService() {
            return mService;//3
        }
    }複製程式碼

上面的程式碼結合SystemServiceManager的startService方法來分析,當通過反射來建立Lifecycle例項時,會呼叫註釋1處的方法建立AMS例項,當呼叫Lifecycle型別的service的onStart方法時,實際上是呼叫了註釋2處AMS的start方法。在SystemServer的startBootstrapServices方法的註釋1處,呼叫瞭如下程式碼:

 mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();複製程式碼

我們知道SystemServiceManager的startService方法最終會返回Lifecycle型別的物件,緊接著又呼叫了Lifecycle的getService方法,這個方法會返回AMS型別的mService物件,見註釋3處,這樣AMS例項就會被建立並且返回。

3.AMS與程式啟動

Android系統啟動流程(二)解析Zygote程式啟動過程這篇文章中,我提到了Zygote的Java框架層中,會建立一個Server端的Socket,這個Socket用來等待AMS來請求Zygote來建立新的應用程式程式。要啟動一個應用程式,首先要保證這個應用程式所需要的應用程式程式已經被啟動。AMS在啟動應用程式時會檢查這個應用程式需要的應用程式程式是否存在,不存在就會請求Zygote程式將需要的應用程式程式啟動。Service的啟動過程中會呼叫ActiveServices的bringUpServiceLocked方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
  ...
  final String procName = r.processName;//1
  ProcessRecord app;
  if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//2
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {//3
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode,
                    mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);//4
                    return null;
                } catch (TransactionTooLargeException e) {
              ...
            }
        } else {
            app = r.isolatedProc;
        }
 if (app == null && !permissionsReviewRequired) {//5
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {//6
              ...
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
 ...     
}複製程式碼

在註釋1處得到ServiceRecord的processName的值賦值給procName ,其中ServiceRecord用來描述Service的android:process屬性。註釋2處將procName和Service的uid傳入到AMS的getProcessRecordLocked方法中,來查詢是否存在一個與Service對應的ProcessRecord型別的物件app,ProcessRecord主要用來記錄執行的應用程式程式的資訊。註釋5處判斷Service對應的app為null則說明用來執行Service的應用程式程式不存在,則呼叫註釋6處的AMS的startProcessLocked方法來建立對應的應用程式程式,
具體的過程請檢視Android應用程式程式啟動過程(前篇)

4.AMS家族

ActivityManager是一個和AMS相關聯的類,它主要對執行中的Activity進行管理,這些管理工作並不是由ActivityManager來處理的,而是交由AMS來處理,ActivityManager中的方法會通過ActivityManagerNative(以後簡稱AMN)的getDefault方法來得到ActivityManagerProxy(以後簡稱AMP),通過AMP就可以和AMN進行通訊,而AMN是一個抽象類,它會將功能交由它的子類AMS來處理,因此,AMP就是AMS的代理類。AMS作為系統核心服務,很多API是不會暴露給ActivityManager的,因此ActivityManager並不算是AMS家族一份子。
為了講解AMS家族,這裡拿Activity的啟動過程舉例,Activity的啟動過程中會呼叫Instrumentation的execStartActivity方法,如下所示。
frameworks/base/core/java/android/app/Instrumentation.java

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
      ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }複製程式碼

execStartActivity方法中會呼叫AMN的getDefault來獲取AMS的代理類AMP。接著呼叫了AMP的startActivity方法,先來檢視AMN的getDefault方法做了什麼,如下所示。
frameworks/base/core/java/android/app/ActivityManagerNative.java

 static public IActivityManager getDefault() {
        return gDefault.get();
    }
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");//1
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);//2
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }+
    };
}複製程式碼

getDefault方法呼叫了gDefault的get方法,我們接著往下看,gDefault 是一個Singleton類。註釋1處得到名為”activity”的Service引用,也就是IBinder型別的AMS的引用。接著在註釋2處將它封裝成AMP型別物件,並將它儲存到gDefault中,此後呼叫AMN的getDefault方法就會直接獲得AMS的代理物件AMP。註釋2處的asInterface方法如下所示。
frameworks/base/core/java/android/app/ActivityManagerNative.java

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ActivityManagerProxy(obj);
}複製程式碼

asInterface方法的主要作用就是將IBinder型別的AMS引用封裝成AMP,AMP的構造方法如下所示。

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager
{
    public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }
...
 }複製程式碼

AMP的構造方法中將AMS的引用賦值給變數mRemote ,這樣在AMP中就可以使用AMS了。
其中IActivityManager是一個介面,AMN和AMP都實現了這個介面,用於實現代理模式和Binder通訊。
再回到Instrumentation的execStartActivity方法,來檢視AMP的startActivity方法,AMP是AMN的內部類,程式碼如下所示。
frameworks/base/core/java/android/app/ActivityManagerNative.java

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
           String resolvedType, IBinder resultTo, String resultWho, int requestCode,
           int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
     ...
       data.writeInt(requestCode);
       data.writeInt(startFlags);
     ...
       mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);//1
       reply.readException();+
       int result = reply.readInt();
       reply.recycle();
       data.recycle();
       return result;
   }複製程式碼

首先會將傳入的引數寫入到Parcel型別的data中。在註釋1處,通過IBinder型別物件mRemote(AMS的引用)向服務端的AMS傳送一個START_ACTIVITY_TRANSACTION型別的程式間通訊請求。那麼服務端AMS就會從Binder執行緒池中讀取我們客戶端發來的資料,最終會呼叫AMN的onTransact方法,如下所示。
frameworks/base/core/java/android/app/ActivityManagerNative.java

   @Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
           throws RemoteException {
       switch (code) {
       case START_ACTIVITY_TRANSACTION:
       {
       ...
           int result = startActivity(app, callingPackage, intent, resolvedType,
                   resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
           reply.writeNoException();
           reply.writeInt(result);
           return true;
       }
   }複製程式碼

onTransact中會呼叫AMS的startActivity方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

 @Override
 public final int startActivity(IApplicationThread caller, String callingPackage,
         Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
         int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
     return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
             resultWho, requestCode, startFlags, profilerInfo, bOptions,
             UserHandle.getCallingUserId());
 }複製程式碼

startActivity方法會最後return startActivityAsUser方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

 @Override
 public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
         Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
         int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
     enforceNotIsolatedCaller("startActivity");
     userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
             userId, false, ALLOW_FULL_ONLY, "startActivity", null);
     return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
             resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
             profilerInfo, null, null, bOptions, false, userId, null, null);
  }複製程式碼

startActivityAsUser方法最後會return ActivityStarter的startActivityMayWait方法,這一呼叫過程已經脫離了本節要講的AMS家族,因此這裡不做介紹了,具體的呼叫過程可以檢視Android深入四大元件(一)應用程式啟動過程(後篇)這篇文章。

在Activity的啟動過程中提到了AMP、AMN和AMS,它們共同組成了AMS家族的主要部分,如下圖所示。

AMP是AMN的內部類,它們都實現了IActivityManager介面,這樣它們就可以實現代理模式,具體來講是遠端代理:AMP和AMN是執行在兩個程式的,AMP是Client端,AMN則是Server端,而Server端中具體的功能都是由AMN的子類AMS來實現的,因此,AMP就是AMS在Client端的代理類。AMN又實現了Binder類,這樣AMP可以和AMS就可以通過Binder來進行程式間通訊。

ActivityManager通過AMN的getDefault方法得到AMP,通過AMP就可以和AMN進行通訊,也就是間接的與AMS進行通訊。除了ActivityManager,其他想要與AMS進行通訊的類都需要通過AMP,如下圖所示。

參考資料
[深入理解Android卷二 全文-第六章]深入理解ActivityManagerService
Framework原始碼分析(一):ActivityManagerService
ActivityManager與Proxy模式的運用


歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。

相關文章