Android6.0之AMS啓動App下篇

前面已經分析App啓動的時候,進程是如何創建的了。也知道了App進程創建之後,首先執行的是ActivityThread類中的main方法。也就是說ActivityThread.main方法是App執行代碼的總入口點。

ActivityThread類

在AMS啓動App上篇中已經介紹過這個ActivityThread類了,這是一個非常重要的類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 * This manages the execution of the main thread in an
 * application process, scheduling and executing activities,
 * broadcasts, and other operations on it as the activity
 * manager requests.
 *
 * {@hide}
 */
public final class ActivityThread {
........
private ContextImpl mSystemContext;

static IPackageManager sPackageManager;
// 保存該app中所有的Activity
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
// 保存該app中所有的service
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
// 保存該app中所有的provider
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
        = new ArrayMap<ProviderKey, ProviderClientRecord>();
//管理應用的資源
private final ResourcesManager mResourcesManager;

// 存儲包含代碼,即dex文件的apk文件保存在該變量中
final ArrayMap<String, WeakReference<LoadedApk>> mPackages
        = new ArrayMap<String, WeakReference<LoadedApk>>();
// 不包含代碼,緊緊包含資源的apk放在該變量中
final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages

// 如果app中自己實現了Application的子類,並在清單文件中聲明瞭,那麼該變量就指向自己實現的那個子類對象
Application mInitialApplication;

AppBindData mBoundApplication;

// 用於binder通信,AMS通過它來調用應用的接口
final ApplicationThread mAppThread = new ApplicationThread();

// 主線程中的Handler
static Handler sMainThreadHandler;  // set once in main()

final Looper mLooper = Looper.myLooper();

// H繼承自Handler,mH用來發送和處理ApplicationThread通過binder接收的AMS請求
// 將binder轉換爲異步調用
final H mH = new H();

.........
}

ActivityThread類中定義的關鍵數據成員可以看出他的作用了:

  1. 負責執行AMS的請求

  2. 管理應用的資源

  3. 管理應用所有activity,service,provider

  4. 創建App主線程中的looper消息處理循環

其中mAppThread是ApplicationThread類型的,在App啓動上篇分析中已經介紹過它的作用了,這個類主要用來binder通信,AMS通過它來調用ActivityThread中的一些方法。而ActivityThread中負責調用Activity等組件的生命週期方法。也就是說AMS通過這個變量來控制App中Android 組件的生命週期。

H繼承自Handler,在AMS通過mAppThread的代理(實際上是通過binder)發送一些處理請求,mAppThread實體端通過mH將其轉換爲異步處理的消息,然後由ActivityThread執行,也就是App主線程執行。也可以理解爲將處理請求的代碼從binder線程切換到App主線程.可以參考《App啓動上篇》中對其的分析。

ActivityThread.main方法

這個main方法是Android app的入口點。ActivityThread的相關初始化,也是在main方法裏面完成的。

ActivityThread並沒有像其名字那樣是一個線程類,它僅僅是App主線程中使用的一個類而已。App主線程執行這個類的mian方法,其main方法是一個死循環:looper消息處理循環。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public static void main(String[] args) {
      Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
      SamplingProfilerIntegration.start();
      CloseGuard.setEnabled(false);

      // 環境初始化,主要是app運行過程中需要使用到的系統路徑
      // 比如外部存儲路徑等等
      Environment.initForCurrentUser();

      // Set the reporter for event logging in libcore
      EventLogger.setReporter(new EventLoggingReporter());
      //增加一個保存key的provider
      AndroidKeyStoreProvider.install();

      // 爲應用社會當前用戶的CA證書保存的位置
      final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
      TrustedCertificateStore.setDefaultUserDirectory(configDir);
      // 設置app進程的名字
      // 通過前面的分析可知,前面的過程中已經設置過名字了,這裏又改爲了“pre-initialized”,不知道爲啥,
      // 因爲後面還要在調用該方法,重新設置進程名字爲app 包名或者app指定的名字。
      Process.setArgV0("<pre-initialized>");
      // 創建主線程looper
      Looper.prepareMainLooper();
      // 創建ActivityThread對象。
      ActivityThread thread = new ActivityThread();
      // 將創建的ActivityThread附加到AMS中,這樣
      // AMS就可以控制這個app中組件的生命週期了
      thread.attach(false);

      if (sMainThreadHandler == null) {
          sMainThreadHandler = thread.getHandler();
      }

      if (false) {
          Looper.myLooper().setMessageLogging(new
                  LogPrinter(Log.DEBUG, "ActivityThread"));
      }

      // End of event ActivityThreadMain.
      Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
      //App主線程開始執行消息處理循環
      Looper.loop();

      throw new RuntimeException("Main thread loop unexpectedly exited");
  }
}

其構造方法:

1
2
3
ActivityThread() {
      mResourcesManager = ResourcesManager.getInstance();
  }

主要是創建資源管理對象,資源管理後續單獨分析其源碼,這裏不多說了。

當ActivityThread對象創建之後,就開始調用其attach()方法。這是一個很重要的方法,參數爲false表明是普通app進程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private void attach(boolean system)
{
        sCurrentActivityThread = this;
        mSystemThread = system;
        // app進程傳入fasle
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            // mAppThread是ApplicationThread對象;
            // 下面這個方法會把mAppThread放到RuntimeInit類中的靜態變量mApplicationObject中
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                // 執行AMS的attachApplication方法
                // 將mAppThread傳入AMS,這樣AMS就可以通過它來控制app了
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
              ............
            });
        } else {
          ..............
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
          .......
        });
    }

其中RuntimeInit.setApplicationObject方法如下:

1
2
3
4
5
6
7
/**
    * Set the object identifying this application/process, for reporting VM
    * errors.
    */
   public static final void setApplicationObject(IBinder app) {
       mApplicationObject = app;
   }

註釋已經說得很清楚了,主要是VM用來報告錯誤使用的。

AMS的attachApplication()方法

這個方法主要負App和AMS的綁定.

1
2
3
4
5
6
7
8
public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

attachApplication()方法內部又調用了attachApplicationLocked()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
              // 在創建startProcessLocked()方法中調用Process.start()方法創建進程後
              // 會以接收傳遞過來的進程號爲索引,將ProcessRecord加入到AMS的mPidsSelfLocked中
              // 這裏可以以進程號從mPidsSelfLocked中拿到ProcessRecord
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }
if (app == null) {
          ........
            return false;
        }
if (app.thread != null) {
       handleAppDiedLocked(app, true, true);
   }

   // 註冊app進程死亡通知處理機制,也就是創建監聽app死亡的對象
   // App進程死亡後,會調用AppDeathRecipient.binderDied()方法
   final String processName = app.processName;
   try {
       AppDeathRecipient adr = new AppDeathRecipient(
               app, pid, thread);
       thread.asBinder().linkToDeath(adr, 0);
       app.deathRecipient = adr;
   } catch (RemoteException e) {
       app.resetPackageList(mProcessStats);
       startProcessLocked(app, "link fail", processName);
       return false;
   }
   //調用ProcessStatsService開始記錄process的狀態
   //該方法中將thread賦值給app.thread
   app.makeActive(thread, mProcessStats);
   // 初始化App進程優先級等信息
   app.curAdj = app.setAdj = -100;
   app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
   app.forcingToForeground = null;
   updateProcessForegroundLocked(app, false, false);
   app.hasShownUi = false;
   app.debugging = false;
   app.cached = false;
   app.killedByAm = false;
   // 移除PROC_START_TIMEOUT_MSG消息
   // 前面在AMS.startProcessLocked方法中會在調用Process.start()方法之後,將這個消息放入消息隊列中
   // 如果沒有在規定的時間內將該消息移除消息隊列,那麼會導致進程啓動超時
   mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

   // mProcessesReady爲true
   boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
   // 拿到App的provider
   List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
   ........
   // If the app is being launched for restore or full backup, set it up specially
   boolean isRestrictedBackupMode = false;
   if (mBackupTarget != null && mBackupAppName.equals(processName)) {
       isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
               || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
               || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
   }
   // 判斷是否需要執行dex2oat命令
   // 在app安裝的時候,會執行一次dex2oat
   // 當生成的oat文件被破外或者刪除的時候,需要重新執行dex2oat
   ensurePackageDexOpt(app.instrumentationInfo != null
                    ? app.instrumentationInfo.packageName
                    : app.info.packageName);
    //  instrument app 技術先關
    // 比如Android studio  開發時,修改某些代碼時,沒必要重新安裝apk,即可查看之後的結果
    // 後續單獨在分析instrument技術
    if (app.instrumentationClass != null) {
          ensurePackageDexOpt(app.instrumentationClass.getPackageName());
    }
    ....
    // 調用ApplicationThread的bindApplication接口
    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                   profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                   app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                   isRestrictedBackupMode || !normalMode, app.persistent,
                   new Configuration(mConfiguration), app.compat,
                   getCommonServicesLocked(app.isolated),
                   mCoreSettingsObserver.getCoreSettingsLocked());
           updateLruProcessLocked(app, false, null);
           app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
       } catch (Exception e) {
          ............
           return false;
       }
    ....
    boolean badApp = false;
    boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
// 爲true
    if (normalMode) {
        try {
            // 執行ActivityStackSupervisor.attachApplicationLocked
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    // Find any services that should be running in this process...
    if (!badApp) {
        try {
            // 處理要運行這個進程中的service
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
            badApp = true;
        }
    }

    // Check if a next-broadcast receiver is in this process...
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        try {
            // 處理廣播
            didSomething |= sendPendingBroadcastsLocked(app);
        } catch (Exception e) {
            // If the app died trying to launch the receiver we declare it 'bad'
            Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
            badApp = true;
        }
    }
    ........
    if (!didSomething) {
           updateOomAdjLocked();
       }

       return true;
}

attachApplicationLocked函數比較長,首先以傳入的app進程號爲索引從AMS的mPidsSelfLocked中取出app進程的ProcessRecord對象.然後調用ProcessRecord對象的makeActive方法調用ProcessStatsService開始記錄process的狀態,接着將PROC_START_TIMEOUT_MSG消息,從消息循環中移除,檢查是否重新執行dex2oat生成app的oat文件。後面主要做了四件事情:

  1. 是調用ActivityThread的bindApplication方法去啓動Application;

  2. 是調用ActivityStackSupervisor的attachApplicationLocked()方法去啓動ActivityStack棧頂的Activity;

  3. 是ActiveServices調用的attachApplicationLocked()方法啓動在當前App進程中的service;

  4. 是檢查是否有廣播broadcast到這個application,如果有則廣播。

上面全部過程的時序圖如下:

ApplicationThread.bindApplication()方法

接下來重點分析bindApplication()方法.這個方法最終效果是調用了App的Application對象的onCreate方法.這是還還沒啓動activity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public final void bindApplication(
                String processName, //ProcessRecord中記錄的進程名字
                ApplicationInfo appInfo,
                List<ProviderInfo> providers, // app中的providers
                ComponentName instrumentationName,
                ProfilerInfo profilerInfo,
                Bundle instrumentationArgs, //測試相關
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
                Bundle coreSettings) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            // 發送SET_CORE_SETTINGS消息
            // 獲取系統的設定並設置到ActivityThread中
            setCoreSettings(coreSettings);

            // 拿到PMS
            IPackageManager pm = getPackageManager();
            android.content.pm.PackageInfo pi = null;
            try {
                // 以包名從PMS中獲得PackageInfo
                pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
            } catch (RemoteException e) {
            }
            if (pi != null) {
                // 該app是否設置了共享uid
                boolean sharedUserIdSet = (pi.sharedUserId != null);
                // app進程名字是否被設定爲與包名不一致
                // 默認情況下,app進程名字就是其包名
                // 當顯示設置process name 的時候可以執行進程的名字
                boolean processNameNotDefault =
                (pi.applicationInfo != null &&
                 !appInfo.packageName.equals(pi.applicationInfo.processName));

                // 如果設置了共享uid或者進程名字設置爲了其他名字,
                // 這就導致該app可能運行在一個已經運行的進程中
                boolean sharable = (sharedUserIdSet || processNameNotDefault);

                // 如果app是單獨的進程,那麼要想VM註冊相關信息
                // 是就上就在/data/dalvik-cache/profiles/創建一個以包名爲名字的空文件,另外兩個參數沒用到
                if (!sharable) {
                    VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
                                            appInfo.processName);
                }
            }
            // 創建兵初始化AppBindData對象
            // 在這裏設置了進程名字,app的provider,ApplicationInfo
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            // 測試相關
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableOpenGlTrace = enableOpenGlTrace;
            // 是否允許adb backup
            data.restrictedBackupMode = isRestrictedBackupMode;
            // 進程是否常駐內存,殺掉後,會被重啓
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            // 發送BIND_APPLICATION消息
            sendMessage(H.BIND_APPLICATION, data);
        }

bindApplication()方法要通過PMS檢查啓動的app是否設置了共享uid,以及檢查當前app進程的名字是否設定的與包名不一致.符合兩者中的任一種情況下,該app進程可能運行在另一個已經存在的進程中.這時不需要執行VMRuntime.registerAppInfo()向虛擬機註冊app信息.所謂的向虛擬機註冊信息,目前Android版本僅僅是在

1
/data/dalvik-cache/profiles/

中創建一個以包名爲名字的空文件而已.因爲該app和其他進程共享時,其進程名字肯定不是包名了,所以無需註冊.

bindApplication()方法主要是創建和初始化了AppBindData對象(這裏還沒有初始化AppBindData中的 LoadedApk info字段),併發送兩個消息,一個是SET_CORE_SETTINGS;另一個是BIND_APPLICATION。SET_CORE_SETTINGS主要是獲取系統的設定並設置到ActivityThread中。BIND_APPLICATION用於啓動App並安裝所有的provider,並回調App的oncreate方法BIND_APPLICATION消息.

ActivityThread.handleBindApplication()方法

ActivityThread中處理BIND_APPLICATION消息的方法是handleBindApplication():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
   .......

    // 設置進程的名字,因爲前面ActivityThread.main將其設置爲了"<pre-initialized>"
    Process.setArgV0(data.processName);
    // 設置app在ddms中顯示的進程名字
    android.ddm.DdmHandleAppName.setAppName(data.processName,
                                            UserHandle.myUserId());
    // 普通app進程,一般情況下爲false
    // 除非xml設置persistent爲true   
    // 帶有persistent標記的進程在低內存設備中部支持使用硬件加速                                 
    if (data.persistent) {
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(false);
        }
    }

    if (mProfiler.profileFd != null) {
        mProfiler.startProfiling();
    }

    // 根據app編譯時指定的sdk版本與當前系統sdk版本設置AsyncTask
    if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
        AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    Message.updateCheckRecycle(data.appInfo.targetSdkVersion);

    // 恢復時區和位置信息
    TimeZone.setDefault(null);
    Locale.setDefault(data.config.locale);
    // 資源管理初始化設置
    mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
    mCurDefaultDisplayDpi = data.config.densityDpi;
    applyCompatConfiguration(mCurDefaultDisplayDpi);

    // 設置AppBindData中LoadedApk info屬性字段
    // 這裏會根據傳入app的ActivityInfo和CompatibilityInfo創建一個LoadedApk對象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

    // 如果應用沒有指定使用設備的density,那麼默認使用mdpi
    if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
            == 0) {
        mDensityCompatMode = true;
        Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
    }
    updateDefaultDensity();
    // 創建ContextImpl上下文,裏面也設計到了資源管理相關的內容 ,如從LoadedApk中提取資源
    // 後續還需對其進行初始化
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    // 普通app啓動時,isIsolated爲false
    if (!Process.isIsolated()) {
        //在沙箱目錄中創建cache文件夾
        final File cacheDir = appContext.getCacheDir();

        if (cacheDir != null) {
            //將創建的cache文件夾與屬性"java.io.tmpdir"關聯
            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
        } else {
            Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property due to missing cache directory");
        }

        // Use codeCacheDir to store generated/compiled graphics code
        // 在沙箱目錄創建code-cache文件夾
        final File codeCacheDir = appContext.getCodeCacheDir();
        if (codeCacheDir != null) {
            setupGraphicsSupport(data.info, codeCacheDir);
        } else {
            Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
        }
    }

    // 設置時間格式
    final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
    DateFormat.set24HourTimePref(is24Hr);
    View.mDebugViewAttributes =
            mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;

    // 調試相關
    if ((data.appInfo.flags &
         (ApplicationInfo.FLAG_SYSTEM |
          ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
        StrictMode.conditionallyEnableDebugLogging();
    }

    if (data.appInfo.targetSdkVersion > 9) {
        StrictMode.enableDeathOnNetwork();
    }

    NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted(
            (data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0);

    if (data.debugMode != IApplicationThread.DEBUG_OFF) {
      ............
    }

    // Enable OpenGL tracing if required
    if (data.enableOpenGlTrace) {
        GLUtils.setTracingLevel(1);
    }

    // Allow application-generated systrace messages if we're debuggable.
    boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    Trace.setAppTracingAllowed(appTracingAllowed);

    /**
     * Initialize the default http proxy in this process for the reasons we set the time zone.
     */
    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    if (b != null) {
        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
        try {
          // 設置網絡代理
            final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
            Proxy.setHttpProxySystemProperty(proxyInfo);
        } catch (RemoteException e) {}
    }
    // 爲null
    if (data.instrumentationName != null) {
      ..........
    } else {
      // 創建Instrumentation對象
        mInstrumentation = new Instrumentation();
    }
    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    } else {
        dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
    }
    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
    try {
        // 創建app的Application對象
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        // don't bring up providers in restricted mode; they may depend on the
        // app's custom Application class
        if (!data.restrictedBackupMode) {
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                installContentProviders(app, providers);
                // For process that contains content providers, we want to
                // ensure that the JIT is enabled "at some point".
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }

        // Do this after providers, since instrumentation tests generally start their
        // test thread at this point, and we don't want that racing.
        try {
          // 執行instrumentation的onCreate()方法
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
          ................
        }
        // 執行Application的onCreate生命週期方法
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...............
        }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

handleBindApplication()方法中做了:

  1. 確定了進程的最終名字,以及其在ddms中顯示的進程名字

  2. 恢復進程的時區和位置信息

  3. 調用getPackageInfoNoCheck()創建LoadApk對象

  4. 創建ContextImpl對象,是AppContext

  5. 設置網絡代理

  6. 創建Instrumentation對象.

使用Instrumentation, 你可以在app啓動之前,創建模擬的系統對象,如Context;控制應用程序的多個生命週期;發送UI事件給應用程序;在執行期間檢查程序狀態。

  1. 創建app的Applicaition對象

  2. 執行Instrumentation.onCreate()方法

  3. 執行app的Application對象的onCreate()方法.

LoadedApk

LoadedApk類用來描述一個被被加載運行的APK,記錄其代碼,資源等信息.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public final class LoadedApk {

    private static final String TAG = "LoadedApk";

    private final ActivityThread mActivityThread; // App的ActivityThread對象
    private ApplicationInfo mApplicationInfo;   // 描述App信息的ApplicationInfo,如果App中重載了Application類,那麼其類名會被記錄在ApplicationInfo中
    final String mPackageName;// app的包名
    private final String mAppDir;// app在/data/app/<包名>路徑
    private final String mResDir;// 資源路徑
    private final String[] mSplitAppDirs;
    private final String[] mSplitResDirs;
    private final String[] mOverlayDirs;
    private final String[] mSharedLibraries;// 共享java庫
    private final String mDataDir;//數據沙箱目錄
    private final String mLibDir;// native so庫位置
    private final File mDataDirFile;
    private final ClassLoader mBaseClassLoader;//getPackageInfoNoCheck()創建的LoadedApk對象中該字段初始化爲null
    private final boolean mSecurityViolation;
    private final boolean mIncludeCode;// 這個apk是否包含dex
    private final boolean mRegisterPackage;
    private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
    Resources mResources;
    private ClassLoader mClassLoader;//
    private Application mApplication;// 這個app的Application對象,如果App繼承了Application,那麼爲其子類對象

    private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
        = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
    private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
        = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
    private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
        = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
    private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
        = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();

    int mClientCount = 0;

    Application getApplication() {
        return mApplication;
    }
    ...........

LoadedApk是一個非常重要的類,是一個運行的apk在AMS中的管理對象.要清楚地直到何時創建這個對象.

通過前面分析可知,是在handleBindApplication()方法中通過調用getPackageInfoNoCheck()方法創建LoadedApk對象的.

1
2
3
4
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
            CompatibilityInfo compatInfo) {
        return getPackageInfo(ai, compatInfo, null, false, true, false);
    }

可知實際上調用的是getPackageInfo()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private LoadedApk getPackageInfo(
            ApplicationInfo aInfo, // app的Application信息
            CompatibilityInfo compatInfo, // 兼容性
            ClassLoader baseLoader,// 傳入null
            boolean securityViolation,// 傳入false
            boolean includeCode,// 傳入true
            boolean registerPackage // 傳入false
            ) {
// 要啓動app的擁有者與當前系統用戶不一致
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
    WeakReference<LoadedApk> ref;
    if (differentUser) {
        ref = null;
    } else if (includeCode) {
        // 如果包含了dex,那麼從ActivityThread.mPackages中先查找是否已經有了apk對應的LoadedApk
        ref = mPackages.get(aInfo.packageName);
    } else {
      // 如果沒有包含了dex,那麼從ActivityThread.mResourcePackages中先查找是否已經有了apk對應的LoadedApk
        ref = mResourcePackages.get(aInfo.packageName);
    }
    // 如果前面已經從mPackages或者mResourcePackages中找到了apk對應的LoadedApk,那麼就可以直接返回了
    // 沒有找到的話,就要創建LoadedApk對象了
    if (packageInfo == null || (packageInfo.mResources != null
         && !packageInfo.mResources.getAssets().isUpToDate())) {

      // 創建LoadedApk對象
     packageInfo =
         new LoadedApk(this, aInfo, compatInfo, baseLoader,
                 securityViolation, includeCode &&
                 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

     if (mSystemThread && "android".equals(aInfo.packageName)) {
         packageInfo.installSystemApplicationInfo(aInfo,
                 getSystemContext().mPackageInfo.getClassLoader());
     }

     // 創建LoadedApk對象之後,將其加入對應的緩存列表中
     if (differentUser) {
         // Caching not supported across users
     } else if (includeCode) {
         mPackages.put(aInfo.packageName,
                 new WeakReference<LoadedApk>(packageInfo));
     } else {
         mResourcePackages.put(aInfo.packageName,
                 new WeakReference<LoadedApk>(packageInfo));
     }
  }
  return packageInfo;
}

}

由以上代碼可知,當要獲取一個LoadedApk對象時,先從ActivityThread的兩個緩存列表:mPackages和mResourcePackages中尋找,沒找到的話,纔會新建LoadedApk對象,然後將其加入對應的緩存列表中.

其構造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
            CompatibilityInfo compatInfo, ClassLoader baseLoader,// 傳入的爲null
            boolean securityViolation, boolean includeCode, boolean registerPackage) {
        final int myUid = Process.myUid();
        aInfo = adjustNativeLibraryPaths(aInfo);

        mActivityThread = activityThread;
        mApplicationInfo = aInfo;
        mPackageName = aInfo.packageName;
        mAppDir = aInfo.sourceDir;
        mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
        mSplitAppDirs = aInfo.splitSourceDirs;
        mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
        mOverlayDirs = aInfo.resourceDirs;
        mSharedLibraries = aInfo.sharedLibraryFiles;
        mDataDir = aInfo.dataDir;
        mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
        mLibDir = aInfo.nativeLibraryDir;
        mBaseClassLoader = baseLoader;//傳入的爲null
        mSecurityViolation = securityViolation;
        mIncludeCode = includeCode;
        mRegisterPackage = registerPackage;
        mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    }

ContextImpl

當找到apk對應的LoadedApk對象後,以此爲參數創建Application的Context:

1
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
     if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
     return new ContextImpl(null, mainThread,
             packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
 }

private ContextImpl(
        ContextImpl container, // 傳入null
        ActivityThread mainThread,// app的ActivityThread對象
        LoadedApk packageInfo, // apk對應的LoadedApk對象
        IBinder activityToken, // 傳入爲null
        UserHandle user, boolean restricted,
        Display display, Configuration overrideConfiguration, int createDisplayWithId) {
    mOuterContext = this;

    mMainThread = mainThread;
    mActivityToken = activityToken;
    mRestricted = restricted;

    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;
    // context中會記錄apk對應的LoadedApk對象
    mPackageInfo = packageInfo;
    // 資源管理相關,後續單獨開篇介紹
    mResourcesManager = ResourcesManager.getInstance();
    ..............

    Resources resources = packageInfo.getResources(mainThread);
    if (resources != null) {
        if (displayId != Display.DEFAULT_DISPLAY
                || overrideConfiguration != null
                || (compatInfo != null && compatInfo.applicationScale
                        != resources.getCompatibilityInfo().applicationScale)) {
            resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
                    packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
                    packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
                    overrideConfiguration, compatInfo);
        }
    }
    mResources = resources;

    if (container != null) {
        mBasePackageName = container.mBasePackageName;
        mOpPackageName = container.mOpPackageName;
    } else {
        // 記錄app包名
        mBasePackageName = packageInfo.mPackageName;
        ApplicationInfo ainfo = packageInfo.getApplicationInfo();
        if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
            mOpPackageName = ActivityThread.currentPackageName();
        } else {
            mOpPackageName = mBasePackageName;
        }
    }
    // 內容提供者相關
    mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}

Instrumentation.onCreate()方法

1
2
public void onCreate(Bundle arguments) {
    }

方法爲空.

Instrumentation.callApplicationOnCreate()方法

1
2
3
public void callApplicationOnCreate(Application app) {
        app.onCreate();
}

可知調用的是Application類的onCreate()方法,如果App實現了其子類,那麼調用的就是其子類中的onCreate()方法.

bindApplication()方法關鍵時序圖:

在這個方法中創建了Classloader,以及Application對象。然後執行Application對象的attach方法,這個方法中又會調用attachBaseContext()方法。也就是說Application對象首先被執行的方法不是onCreate()方法,而是attach()方法。

ActivityStackSupervisor.attachApplicationLocked()方法

從圖1中ActivityThread.main的整體執行時序圖中可知,啓動activity的是attachApplicationLocked()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = stacks.get(stackNdx);
            // 從 如何啓動app中篇之Task的管理 可知,此時mFocusedStack指向即將要運行的activity所在的ActivityStack
            // 下面這個方法就是爲了從衆多ActivityStack找到這個ActivityStack
            if (!isFrontStack(stack)) {
                continue;
            }
            // 找到了所需的ActivityStack
            // 然後找到其棧頂的Activity,實際就是mTaskHistory數組末端的Task的頂端Activity
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception in new application when starting activity "
                              + hr.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisibleLocked(null, 0);
    }
    return didSomething;
}

ActivityStackSupervisor.realStartActivityLocked()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
final boolean realStartActivityLocked(
        ActivityRecord r,// 要啓動的Activity
        ProcessRecord app, // Activity所要運行在的進程
        boolean andResume, // 傳入true
        boolean checkConfig)// 傳入true
        throws RemoteException {

  .................

    // 將代表activity運行的進程的ProcessRecord對象加入ActivityRecord.app
    r.app = app;
    app.waitingToKill = null;
    r.launchCount++;
    // 記錄啓動時間
    r.lastLaunchTime = SystemClock.uptimeMillis();

    if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

    // 將這個activity加入到ProcessRecord.activities中
    int idx = app.activities.indexOf(r);
    if (idx < 0) {
        app.activities.add(r);
    }
    // 更新進程優先級,後續單獨介紹進程管理
    mService.updateLruProcessLocked(app, true, null);
    mService.updateOomAdjLocked();

    ..............
    final ActivityStack stack = task.stack;
    try {
        .........
        List<ResultInfo> results = null;
        List<ReferrerIntent> newIntents = null;
        //
        if (andResume) {
            results = r.results;
            newIntents = r.newIntents;
        }
      ...........
        // 保證運行的app已經之興國dex2oat
        mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
        r.sleeping = false;
        r.forceNewConfig = false;
        mService.showAskCompatModeDialogLocked(r);
        // 得到Activity的兼容性信息
        r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
        ProfilerInfo profilerInfo = null;
        if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
          .................
        }

        if (andResume) {
            app.hasShownUi = true;
            app.pendingUiClean = true;
        }
        // 設置進程狀態爲ActivityManager.PROCESS_STATE_TOP
        app.forceProcessStateUpTo(mService.mTopProcessState);
        // 調用 ActivityThread.scheduleLaunchActivity加載activity
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

        if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
            ...............
        }

    } catch (RemoteException e) {
      ...............
    }

    r.launchFailed = false;
    // 更新activity在其ActivityStack.mLRUActivities中的位置
    // 移除之前存在的,將其重新插入mLRUActivities末尾
    if (stack.updateLRUListLocked(r)) {
        Slog.w(TAG, "Activity " + r
              + " being launched, but already in LRU list");
    }

    if (andResume) {
        // 該方法中將activity所在的task加入ActivityStack.mRecentTasks中
        stack.minimalResumeActivityLocked(r);
    } else {
    ..................
    }

    if (isFrontStack(stack)) {
       //啓動系統升級後(或者第一次開機新設備)時設置嚮導頁面
       // 只會運行一次
        mService.startSetupActivityLocked();
    }
    //進程中有activity了,要更新app進程綁定的service,說不定這些service關心客戶端進程中是否存在activity.
    // 實際上就是設置與之綁定的service進程的ProcessRecord.hasClientActivities爲true
    mService.mServices.updateServiceConnectionActivitiesLocked(r.app);

    return true;
}

這個方法主要方法調用時序圖如下所示:

ApplicationThread.scheduleLaunchActivity()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public final void scheduleLaunchActivity(
        Intent intent,//啓動這個activity的intent
        IBinder token,// window manager token
        int ident,// 與java.lang.Object.hashCode()一致
        ActivityInfo info,// 要啓動的activity的信息
        Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo,// 兼容性
        String referrer, // 啓動這個activity的activity的包名
        IVoiceInteractor voiceInteractor,
        int procState,// activity運行所在的進程上一次的狀態
        Bundle state, // 要啓動的activity上一次保存的狀態,如果是第一次啓動,則爲null
        PersistableBundle persistentState,//要啓動的activity上一次保存的持續信息的狀態,如果是第一次啓動,則爲null
        List<ResultInfo> pendingResults,//已經收到的待處返回的結果
        List<ReferrerIntent> pendingNewIntents,//ams中有可複用的activity,這時候會將新的intent設置到對應activityrecord的newintents屬性中
        boolean notResumed,// 傳入false
        boolean isForward, ProfilerInfo profilerInfo) {

    // 更新VM進程狀態
    updateProcessState(procState, false);

    // 創建ActivityClientRecord對象
    ActivityClientRecord r = new ActivityClientRecord();

    // 初始化ActivityClientRecord對象
    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    r.voiceInteractor = voiceInteractor;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.persistentState = persistentState;

    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;

    r.startsNotResumed = notResumed;
    r.isForward = isForward;

    r.profilerInfo = profilerInfo;

    r.overrideConfig = overrideConfig;
    updatePendingConfiguration(curConfig);

    // 發送LAUNCH_ACTIVITY消息
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

處理消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
            // 獲取LoadedApk
            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        ..........

ActivityThread.handleLaunchActivity()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ..................

    // Initialize before creating the activity
    WindowManagerGlobal.initialize();
    // 啓動activity
    // 主要是加載activity的class,並且實例化一個Activity對象
    Activity a = performLaunchActivity(r, customIntent);
    // 調用activity的onResume方法
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);

        if (!r.activity.mFinished && r.startsNotResumed) {
          ...........
        }
    } else {
        ................
    }
}

如下是執行過程:

執行完上面的過程後,返回AMS的attachApplicationLocked方法中,開始啓動運行在這個進程中的service。以及執行sendPendingBroadcastsLocked(),這些內容後續單獨分析。

發佈了14 篇原創文章 · 獲贊 26 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章